@@ -55,21 +55,28 @@ var (
5555
5656type Driver struct {
5757 * drivers.BaseDriver
58- clientFactory func () Ec2Client
59- awsCredentials awsCredentials
60- Id string
61- AccessKey string
62- SecretKey string
63- SessionToken string
64- Region string
65- AMI string
66- SSHKeyID int
67- KeyName string
68- InstanceId string
69- InstanceType string
70- PrivateIPAddress string
71- SecurityGroupId string
72- SecurityGroupName string
58+ clientFactory func () Ec2Client
59+ awsCredentials awsCredentials
60+ Id string
61+ AccessKey string
62+ SecretKey string
63+ SessionToken string
64+ Region string
65+ AMI string
66+ SSHKeyID int
67+ KeyName string
68+ InstanceId string
69+ InstanceType string
70+ PrivateIPAddress string
71+
72+ // NB: SecurityGroupId expanded from single value to slice on 26 Feb 2016 - we maintain both for host storage backwards compatibility.
73+ SecurityGroupId string
74+ SecurityGroupIds []string
75+
76+ // NB: SecurityGroupName expanded from single value to slice on 26 Feb 2016 - we maintain both for host storage backwards compatibility.
77+ SecurityGroupName string
78+ SecurityGroupNames []string
79+
7380 Tags string
7481 ReservationId string
7582 DeviceName string
@@ -138,10 +145,10 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
138145 Usage : "AWS VPC subnet id" ,
139146 EnvVar : "AWS_SUBNET_ID" ,
140147 },
141- mcnflag.StringFlag {
148+ mcnflag.StringSliceFlag {
142149 Name : "amazonec2-security-group" ,
143150 Usage : "AWS VPC security group" ,
144- Value : defaultSecurityGroup ,
151+ Value : [] string { defaultSecurityGroup } ,
145152 EnvVar : "AWS_SECURITY_GROUP" ,
146153 },
147154 mcnflag.StringFlag {
@@ -225,14 +232,14 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
225232func NewDriver (hostName , storePath string ) * Driver {
226233 id := generateId ()
227234 driver := & Driver {
228- Id : id ,
229- AMI : defaultAmiId ,
230- Region : defaultRegion ,
231- InstanceType : defaultInstanceType ,
232- RootSize : defaultRootSize ,
233- Zone : defaultZone ,
234- SecurityGroupName : defaultSecurityGroup ,
235- SpotPrice : defaultSpotPrice ,
235+ Id : id ,
236+ AMI : defaultAmiId ,
237+ Region : defaultRegion ,
238+ InstanceType : defaultInstanceType ,
239+ RootSize : defaultRootSize ,
240+ Zone : defaultZone ,
241+ SecurityGroupNames : [] string { defaultSecurityGroup } ,
242+ SpotPrice : defaultSpotPrice ,
236243 BaseDriver : & drivers.BaseDriver {
237244 SSHUser : defaultSSHUser ,
238245 MachineName : hostName ,
@@ -282,7 +289,7 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
282289 d .InstanceType = flags .String ("amazonec2-instance-type" )
283290 d .VpcId = flags .String ("amazonec2-vpc-id" )
284291 d .SubnetId = flags .String ("amazonec2-subnet-id" )
285- d .SecurityGroupName = flags .String ("amazonec2-security-group" )
292+ d .SecurityGroupNames = flags .StringSlice ("amazonec2-security-group" )
286293 d .Tags = flags .String ("amazonec2-tags" )
287294 zone := flags .String ("amazonec2-zone" )
288295 d .Zone = zone [:]
@@ -448,6 +455,31 @@ func (d *Driver) instanceIpAvailable() bool {
448455 return false
449456}
450457
458+ func makePointerSlice (stackSlice []string ) []* string {
459+ pointerSlice := []* string {}
460+ for i := range stackSlice {
461+ pointerSlice = append (pointerSlice , & stackSlice [i ])
462+ }
463+ return pointerSlice
464+ }
465+
466+ // Support migrating single string Driver fields to slices.
467+ func migrateStringToSlice (value string , values []string ) (result []string ) {
468+ if value != "" {
469+ result = append (result , value )
470+ }
471+ result = append (result , values ... )
472+ return
473+ }
474+
475+ func (d * Driver ) securityGroupNames () (ids []string ) {
476+ return migrateStringToSlice (d .SecurityGroupName , d .SecurityGroupNames )
477+ }
478+
479+ func (d * Driver ) securityGroupIds () (ids []string ) {
480+ return migrateStringToSlice (d .SecurityGroupId , d .SecurityGroupIds )
481+ }
482+
451483func (d * Driver ) Create () error {
452484 if err := d .checkPrereqs (); err != nil {
453485 return err
@@ -459,7 +491,7 @@ func (d *Driver) Create() error {
459491 return fmt .Errorf ("unable to create key pair: %s" , err )
460492 }
461493
462- if err := d .configureSecurityGroup (d .SecurityGroupName ); err != nil {
494+ if err := d .configureSecurityGroups (d .securityGroupNames () ); err != nil {
463495 return err
464496 }
465497
@@ -473,7 +505,7 @@ func (d *Driver) Create() error {
473505 }
474506 netSpecs := []* ec2.InstanceNetworkInterfaceSpecification {{
475507 DeviceIndex : aws .Int64 (0 ), // eth0
476- Groups : [] * string { & d . SecurityGroupId } ,
508+ Groups : makePointerSlice ( d . securityGroupIds ()) ,
477509 SubnetId : & d .SubnetId ,
478510 AssociatePublicIpAddress : aws .Bool (! d .PrivateIPOnly ),
479511 }}
@@ -866,14 +898,18 @@ func (d *Driver) configureTags(tagGroups string) error {
866898 return nil
867899}
868900
869- func (d * Driver ) configureSecurityGroup (groupName string ) error {
870- log .Debugf ("configuring security group in %s" , d .VpcId )
901+ func (d * Driver ) configureSecurityGroups (groupNames []string ) error {
902+ if len (groupNames ) == 0 {
903+ log .Debugf ("no security groups to configure in %s" , d .VpcId )
904+ return nil
905+ }
906+
907+ log .Debugf ("configuring security groups in %s" , d .VpcId )
871908
872- var group * ec2.SecurityGroup
873909 filters := []* ec2.Filter {
874910 {
875911 Name : aws .String ("group-name" ),
876- Values : [] * string { & groupName } ,
912+ Values : makePointerSlice ( groupNames ) ,
877913 },
878914 {
879915 Name : aws .String ("vpc-id" ),
@@ -887,47 +923,52 @@ func (d *Driver) configureSecurityGroup(groupName string) error {
887923 return err
888924 }
889925
890- if len ( groups . SecurityGroups ) > 0 {
891- log . Debugf ( "found existing security group (%s) in %s" , groupName , d . VpcId )
892- group = groups . SecurityGroups [ 0 ]
926+ var groupsByName = make ( map [ string ] * ec2. SecurityGroup )
927+ for _ , securityGroup := range groups . SecurityGroups {
928+ groupsByName [ * securityGroup . GroupName ] = securityGroup
893929 }
894930
895- // if not found, create
896- if group == nil {
897- log .Debugf ("creating security group (%s) in %s" , groupName , d .VpcId )
898- groupResp , err := d .getClient ().CreateSecurityGroup (& ec2.CreateSecurityGroupInput {
899- GroupName : & groupName ,
900- Description : aws .String ("Docker Machine" ),
901- VpcId : & d .VpcId ,
902- })
903- if err != nil {
904- return err
905- }
906- // Manually translate into the security group construct
907- group = & ec2.SecurityGroup {
908- GroupId : groupResp .GroupId ,
909- VpcId : aws .String (d .VpcId ),
910- GroupName : aws .String (groupName ),
911- }
912- // wait until created (dat eventual consistency)
913- log .Debugf ("waiting for group (%s) to become available" , * group .GroupId )
914- if err := mcnutils .WaitFor (d .securityGroupAvailableFunc (* group .GroupId )); err != nil {
915- return err
931+ for _ , groupName := range groupNames {
932+ var group * ec2.SecurityGroup
933+ securityGroup , ok := groupsByName [groupName ]
934+ if ok {
935+ log .Debugf ("found existing security group (%s) in %s" , groupName , d .VpcId )
936+ group = securityGroup
937+ } else {
938+ log .Debugf ("creating security group (%s) in %s" , groupName , d .VpcId )
939+ groupResp , err := d .getClient ().CreateSecurityGroup (& ec2.CreateSecurityGroupInput {
940+ GroupName : aws .String (groupName ),
941+ Description : aws .String ("Docker Machine" ),
942+ VpcId : aws .String (d .VpcId ),
943+ })
944+ if err != nil {
945+ return err
946+ }
947+ // Manually translate into the security group construct
948+ group = & ec2.SecurityGroup {
949+ GroupId : groupResp .GroupId ,
950+ VpcId : aws .String (d .VpcId ),
951+ GroupName : aws .String (groupName ),
952+ }
953+ // wait until created (dat eventual consistency)
954+ log .Debugf ("waiting for group (%s) to become available" , * group .GroupId )
955+ if err := mcnutils .WaitFor (d .securityGroupAvailableFunc (* group .GroupId )); err != nil {
956+ return err
957+ }
916958 }
917- }
918-
919- d .SecurityGroupId = * group .GroupId
959+ d .SecurityGroupIds = append (d .SecurityGroupIds , * group .GroupId )
920960
921- perms := d .configureSecurityGroupPermissions (group )
961+ perms := d .configureSecurityGroupPermissions (group )
922962
923- if len (perms ) != 0 {
924- log .Debugf ("authorizing group %s with permissions: %v" , groupName , perms )
925- _ , err := d .getClient ().AuthorizeSecurityGroupIngress (& ec2.AuthorizeSecurityGroupIngressInput {
926- GroupId : group .GroupId ,
927- IpPermissions : perms ,
928- })
929- if err != nil {
930- return err
963+ if len (perms ) != 0 {
964+ log .Debugf ("authorizing group %s with permissions: %v" , groupNames , perms )
965+ _ , err := d .getClient ().AuthorizeSecurityGroupIngress (& ec2.AuthorizeSecurityGroupIngressInput {
966+ GroupId : group .GroupId ,
967+ IpPermissions : perms ,
968+ })
969+ if err != nil {
970+ return err
971+ }
931972 }
932973 }
933974
@@ -985,19 +1026,6 @@ func (d *Driver) configureSecurityGroupPermissions(group *ec2.SecurityGroup) []*
9851026 return perms
9861027}
9871028
988- func (d * Driver ) deleteSecurityGroup () error {
989- log .Debugf ("deleting security group %s" , d .SecurityGroupId )
990-
991- _ , err := d .getClient ().DeleteSecurityGroup (& ec2.DeleteSecurityGroupInput {
992- GroupId : & d .SecurityGroupId ,
993- })
994- if err != nil {
995- return err
996- }
997-
998- return nil
999- }
1000-
10011029func (d * Driver ) deleteKeyPair () error {
10021030 log .Debugf ("deleting key pair: %s" , d .KeyName )
10031031
0 commit comments