Example #1
0
    def load_balancers(self, load_balancer_cfg):
        """Build ELB load balancers."""
        for lb_name, lb_cfg in load_balancer_cfg.items():

            lb_fullname = '{}-{}'.format(self.evpc.name, lb_name)
            self.log.emit('creating {} load_balancer ...'.format(lb_fullname))

            # make list of security group ids.
            security_groups = map(self.evpc.get_security_group,
                                  lb_cfg.get('security_groups', []))
            sg_ids = get_ids(security_groups)

            # make list of subnet ids.
            subnets = map(self.evpc.get_subnet, lb_cfg.get('subnets', []))
            sn_ids = get_ids(subnets)

            scheme = 'internet-facing'
            if lb_cfg.get('internal', False):
                scheme = 'internal'

            listeners = self.evpc.elb.format_listeners(
                lb_cfg.get('listeners', []))

            self.evpc.elb.create_load_balancer(
                LoadBalancerName=lb_fullname,
                Subnets=sn_ids,
                SecurityGroups=sg_ids,
                Scheme=scheme,
                Tags=[
                    {
                        'Key': 'vpc_name',
                        'Value': self.evpc.vpc_name
                    },
                    {
                        'Key': 'role',
                        'Value': lb_cfg['instance_role']
                    },
                ],
                Listeners=listeners,
            )

            self.log.emit('created {} load_balancer ...'.format(lb_fullname))

            asg_name = '{}-{}'.format(self.evpc.name, lb_cfg['instance_role'])
            if asg_name in self.evpc.autoscaling.get_related_autoscaling_group_names(
            ):
                self.log.emit(
                    'attaching {} load balancer to {} autoscaling group ...'.
                    format(lb_fullname, asg_name))
                self.evpc.autoscaling.attach_load_balancers(
                    AutoScalingGroupName=asg_name,
                    LoadBalancerNames=[lb_fullname],
                )
            else:
                self.log.emit(
                    'registering {} role to {} load balancer ...'.format(
                        lb_cfg['instance_role'], lb_fullname))
                self.evpc.elb.register_role_with_load_balancer(
                    lb_fullname, lb_cfg['instance_role'])
Example #2
0
    def autoscaling_instance_role(self, role_name, role_data, desired_count):
        if role_data.get('autoscaling', False) != True:
            # exit early if this instance_role is not autoscaling.
            return None

        long_role_name = '{}-{}'.format(self.evpc.name, role_name)

        ami = self.amis[role_data['ami']][self.evpc.region_name]

        key_pair = self.evpc.key_pair.get_key_pair(
                       role_data.get('key_pair', 'default')
                   )

        security_groups = map(
            self.evpc.get_security_group,
            role_data.get('security_groups', [])
        )

        subnets = map(
            self.evpc.get_subnet,
            role_data.get('subnets', [])
        )

        block_device_map = get_block_device_map_from_role_config(role_data)

        kwargs = {
          'LaunchConfigurationName' : long_role_name,
          'ImageId'             : ami,
          'InstanceType'        : role_data.get('instance_type'),
          'KeyName'             : key_pair.name,
          'SecurityGroups'      : get_ids(security_groups),
          'BlockDeviceMappings' : block_device_map,
          'UserData'            : role_data.get('userdata', ''),
        }

        profile_name = role_data.get('instance_profile_name', None)
        if profile_name:
            # only add profile if set. Empty string causes error.
            kwargs['IamInstanceProfile'] = profile_name
            self.wait_for_instance_profile(profile_name)

        self.log.emit('creating launch configuration for role: {}'.format(long_role_name))
        self.evpc.autoscaling.create_launch_configuration(**kwargs)

        self.log.emit('creating autoscaling group for role: {}'.format(long_role_name))
        self.evpc.autoscaling.create_auto_scaling_group(
            AutoScalingGroupName = long_role_name,
            LaunchConfigurationName = long_role_name,
            MinSize = desired_count,
            MaxSize = desired_count,
            DesiredCapacity = desired_count,
            VPCZoneIdentifier = ','.join(get_ids(subnets)),
            Tags = [
              { 'Key' : 'role', 'Value' : role_name, 'PropagateAtLaunch' : True, },
            ]
        )
Example #3
0
    def autoscaling_instance_role(self, role_name, role_data, desired_count):
        if role_data.get('autoscaling', False) != True:
            # exit early if this instance_role is not autoscaling.
            return None

        long_role_name = '{}-{}'.format(self.evpc.name, role_name)

        ami = self.amis[role_data['ami']][self.evpc.region_name]

        key_pair = self.evpc.key_pair.get_key_pair(
            role_data.get('key_pair', 'default'))

        security_groups = map_filter_false(
            self.evpc.get_security_group, role_data.get('security_groups', []))

        subnets = map_filter_false(self.evpc.get_subnet,
                                   role_data.get('subnets', []))

        block_device_map = get_block_device_map_from_role_config(role_data)

        kwargs = {
            'LaunchConfigurationName': long_role_name,
            'ImageId': ami,
            'InstanceType': role_data.get('instance_type'),
            'KeyName': key_pair.name,
            'SecurityGroups': get_ids(security_groups),
            'BlockDeviceMappings': block_device_map,
            'UserData': role_data.get('userdata', ''),
        }

        profile_name = role_data.get('instance_profile_name', None)
        if profile_name:
            # only add profile if set. Empty string causes error.
            kwargs['IamInstanceProfile'] = profile_name
            self.wait_for_instance_profile(profile_name)

        self.log.emit('creating launch configuration for role: {}'.format(
            long_role_name))
        self.evpc.autoscaling.create_launch_configuration(**kwargs)

        self.log.emit(
            'creating autoscaling group for role: {}'.format(long_role_name))
        self.evpc.autoscaling.create_auto_scaling_group(
            AutoScalingGroupName=long_role_name,
            LaunchConfigurationName=long_role_name,
            MinSize=desired_count,
            MaxSize=desired_count,
            DesiredCapacity=desired_count,
            VPCZoneIdentifier=','.join(get_ids(subnets)),
            Tags=[
                {
                    'Key': 'role',
                    'Value': role_name,
                    'PropagateAtLaunch': True,
                },
            ])
Example #4
0
    def db_instances(self, db_instance_cfg):
        """Build RDS DB Instances."""
        existing_rds_names = self.evpc.rds.get_related_db_ids()

        for rds_name, db_cfg in db_instance_cfg.items():

            if rds_name in existing_rds_names:
                msg = "skipping RDS db_instance: {} (it already exists)"
                self.log.emit(msg.format(rds_name), "debug")
                continue

            self.log.emit("creating {} RDS db_instance ...".format(rds_name))

            # make list of security group ids.
            security_groups = map_filter_false(
                self.evpc.get_security_group, db_cfg.get("security_groups", [])
            )
            sg_ids = get_ids(security_groups)

            # make list of subnet ids.
            subnets = map_filter_false(self.evpc.get_subnet, db_cfg.get("subnets", []))
            sn_ids = get_ids(subnets)

            self.evpc.rds.create_db_subnet_group(
                DBSubnetGroupName=rds_name,
                DBSubnetGroupDescription=db_cfg.get("description", ""),
                SubnetIds=sn_ids,
            )

            self.evpc.rds.create_db_instance(
                DBInstanceIdentifier=rds_name,
                DBSubnetGroupName=rds_name,
                DBName=db_cfg.get("name", rds_name),
                VpcSecurityGroupIds=sg_ids,
                DBInstanceClass=db_cfg.get("class", "db.t2.medium"),
                AllocatedStorage=db_cfg.get("allocated_storage", 100),
                Engine=db_cfg.get("engine"),
                EngineVersion=db_cfg.get("engine_version", ""),
                Iops=db_cfg.get("iops", 0),
                MultiAZ=db_cfg.get("multi_az", False),
                MasterUsername=db_cfg.get("master_username"),
                MasterUserPassword=generate_password(16),
                BackupRetentionPeriod=db_cfg.get("backup_retention_period", 0),
                StorageType=db_cfg.get("storage_type", "standard"),  # 'gp2'
                StorageEncrypted=db_cfg.get("storage_encryption", False),
                Tags=[{"Key": "vpc_name", "Value": self.evpc.vpc_name}],
            )
Example #5
0
    def db_instances(self, db_instance_cfg):
        """Build RDS DB Instances."""

        for rds_name, db_cfg in db_instance_cfg.items():

            self.log.emit('creating {} RDS db_instance ...'.format(rds_name))

            # make list of security group ids.
            security_groups = map(
                self.evpc.get_security_group,
                db_cfg.get('security_groups', [])
            )
            sg_ids = get_ids(security_groups)

            # make list of subnet ids.
            subnets = map(
                self.evpc.get_subnet,
                db_cfg.get('subnets', [])
            )
            sn_ids = get_ids(subnets)

            self.evpc.rds.create_db_subnet_group(
              DBSubnetGroupName = rds_name,
              DBSubnetGroupDescription = db_cfg.get('description',''),
              SubnetIds = sn_ids,
            )

            self.evpc.rds.create_db_instance(
              DBInstanceIdentifier = rds_name,
              DBSubnetGroupName    = rds_name,
              DBName = db_cfg.get('name', rds_name),
              VpcSecurityGroupIds   = sg_ids,
              DBInstanceClass       = db_cfg.get('class', 'db.t2.medium'),
              AllocatedStorage      = db_cfg.get('allocated_storage', 100),
              Engine                = db_cfg.get('engine'),
              EngineVersion         = db_cfg.get('engine_version', ''),
              Iops                  = db_cfg.get('iops', 0),
              MultiAZ               = db_cfg.get('multi_az', False),
              MasterUsername        = db_cfg.get('master_username'),
              MasterUserPassword    = generate_password(16),
              BackupRetentionPeriod = db_cfg.get('backup_retention_period', 0),
              Tags = [ { 'Key' : 'vpc_name', 'Value' : self.evpc.vpc_name } ],
            )
Example #6
0
    def db_instances(self, db_instance_cfg):
        """Build RDS DB Instances."""

        for rds_name, db_cfg in db_instance_cfg.items():

            self.log.emit('creating {} RDS db_instance ...'.format(rds_name))

            # make list of security group ids.
            security_groups = map_filter_false(
                self.evpc.get_security_group,
                db_cfg.get('security_groups', []))
            sg_ids = get_ids(security_groups)

            # make list of subnet ids.
            subnets = map_filter_false(self.evpc.get_subnet,
                                       db_cfg.get('subnets', []))
            sn_ids = get_ids(subnets)

            self.evpc.rds.create_db_subnet_group(
                DBSubnetGroupName=rds_name,
                DBSubnetGroupDescription=db_cfg.get('description', ''),
                SubnetIds=sn_ids,
            )

            self.evpc.rds.create_db_instance(
                DBInstanceIdentifier=rds_name,
                DBSubnetGroupName=rds_name,
                DBName=db_cfg.get('name', rds_name),
                VpcSecurityGroupIds=sg_ids,
                DBInstanceClass=db_cfg.get('class', 'db.t2.medium'),
                AllocatedStorage=db_cfg.get('allocated_storage', 100),
                Engine=db_cfg.get('engine'),
                EngineVersion=db_cfg.get('engine_version', ''),
                Iops=db_cfg.get('iops', 0),
                MultiAZ=db_cfg.get('multi_az', False),
                MasterUsername=db_cfg.get('master_username'),
                MasterUserPassword=generate_password(16),
                BackupRetentionPeriod=db_cfg.get('backup_retention_period', 0),
                Tags=[{
                    'Key': 'vpc_name',
                    'Value': self.evpc.vpc_name
                }],
            )
Example #7
0
 def create_all(self, route_table_names):
     """Accept route table names, create all endpoints for route tables."""
     route_tables = map(self.evpc.get_route_table, route_table_names)
     for endpoint in self.services():
         self.evpc.boto.ec2_client.create_vpc_endpoint(
             VpcId=self.evpc.id,
             ServiceName=endpoint,
             RouteTableIds=get_ids(route_tables),
             # PolicyDocument = 'string',
             # ClientToken = 'string'
         )
Example #8
0
 def create_all(self, route_table_names):
     """Accept route table names, create all endpoints for route tables."""
     route_tables = map(self.evpc.get_route_table, route_table_names)
     for endpoint in self.services():
         self.evpc.boto.ec2_client.create_vpc_endpoint(
           VpcId = self.evpc.id,
           ServiceName = endpoint,
           RouteTableIds = get_ids(route_tables),
           #PolicyDocument = 'string',
           #ClientToken = 'string'
         )
Example #9
0
    def load_balancers(self, load_balancer_cfg):
        """Build ELB load balancers."""
        existing_elb_names = self.evpc.elb.get_related_elb_names()

        for lb_name, lb_cfg in load_balancer_cfg.items():

            lb_fullname = "{}-{}".format(self.evpc.name, lb_name)

            if lb_fullname in existing_elb_names:
                msg = "skipping load_balancer: {} (it already exists)"
                self.log.emit(msg.format(lb_fullname), "debug")
                continue

            self.log.emit("creating {} load_balancer ...".format(lb_fullname))

            # make list of security group ids.
            security_groups = map_filter_false(
                self.evpc.get_security_group, lb_cfg.get("security_groups", [])
            )
            sg_ids = get_ids(security_groups)

            # make list of subnet ids.
            subnets = map_filter_false(self.evpc.get_subnet, lb_cfg.get("subnets", []))
            sn_ids = get_ids(subnets)

            scheme = "internet-facing"
            if lb_cfg.get("internal", False):
                scheme = "internal"

            listeners = lb_cfg.get("listeners", [])

            self.evpc.elb.create_load_balancer(
                LoadBalancerName=lb_fullname,
                Subnets=sn_ids,
                SecurityGroups=sg_ids,
                Scheme=scheme,
                Tags=[
                    {"Key": "vpc_name", "Value": self.evpc.vpc_name},
                    {"Key": "role", "Value": lb_cfg["instance_role"]},
                ],
                Listeners=self.evpc.elb.format_listeners(listeners),
            )

            self.log.emit("created {} load_balancer ...".format(lb_fullname))

            self.log.emit(
                "Configure Health Check for {} load_balancer ...".format(lb_fullname)
            )

            hc_cfg = lb_cfg.get("healthcheck", {})

            hc_default_target = "TCP:{}".format(listeners[0][1])

            self.evpc.elb.configure_health_check(
                LoadBalancerName=lb_fullname,
                HealthCheck={
                    "Target": hc_cfg.get("target", hc_default_target),
                    "Interval": hc_cfg.get("interval", 15),
                    "Timeout": hc_cfg.get("timeout", 5),
                    "UnhealthyThreshold": hc_cfg.get("unhealthy_threshold", 4),
                    "HealthyThreshold": hc_cfg.get("healthy_threshold", 4),
                },
            )

            self.log.emit(
                "Configured Health Check for {} load_balancer ...".format(lb_fullname)
            )

            asg_name = "{}-{}".format(self.evpc.name, lb_cfg["instance_role"])
            if asg_name in self.evpc.autoscaling.get_related_autoscaling_group_names():
                self.log.emit(
                    "attaching {} load balancer to {} autoscaling group ...".format(
                        lb_fullname, asg_name
                    )
                )
                self.evpc.autoscaling.attach_load_balancers(
                    AutoScalingGroupName=asg_name, LoadBalancerNames=[lb_fullname]
                )
            else:
                self.log.emit(
                    "registering {} role to {} load balancer ...".format(
                        lb_cfg["instance_role"], lb_fullname
                    )
                )
                self.evpc.elb.register_role_with_load_balancer(
                    lb_fullname, lb_cfg["instance_role"]
                )
Example #10
0
    def instance_role(self, role_name, role_data, desired_count):
        self.log.emit('creating role: {}'.format(role_name))
        ami = self.amis[role_data['ami']][self.evpc.region_name]

        key_pair = self.evpc.key_pair.get_key_pair(
                       role_data.get('key_pair', 'default')
                   )

        security_groups = map(
            self.evpc.get_security_group,
            role_data.get('security_groups', [])
        )

        subnets = map(
            self.evpc.get_subnet,
            role_data.get('subnets', [])
        )

        if len(subnets) == 0:
            self.log.emit(
                'no subnets found for role: {}'.format(role_name), 'warning'
            )
            # exit early.
            return None

        # sort by subnets by amount of instances, smallest first.
        subnets = sorted(
                      subnets,
                      key = lambda sn : collection_len(sn.instances),
                  )

        # determine the count of this role's existing instances.
        # Note: we look for role in all subnets, not just the listed subnets.
        existing_count = len(self.evpc.get_role(role_name))

        if existing_count >= desired_count:
            # for now we exit early, maybe terminate extras...
            self.log.emit(existing_count + ' ' + desired_count, 'debug')
            return None

        # determine count of additional instances needed to reach desired_count.
        needed_count      = desired_count - existing_count
        needed_per_subnet = needed_count / len(subnets)
        needed_remainder  = needed_count % len(subnets)

        role_instances = []

        for subnet in subnets:
            # ensure Run_Instance_Idempotency.html#client-tokens
            client_token = str(uuid4())

            # figure out how many instances this subnet needs to create ...
            existing_in_subnet = len(self.evpc.get_role(role_name, subnet.instances.all()))
            count = needed_per_subnet - existing_in_subnet
            if needed_remainder != 0:
                needed_remainder -= 1
                count += 1

            if count == 0:
                # skip this subnet, it doesn't need to launch any instances.
                continue

            subnet_name = make_tag_dict(subnet)['Name']
            msg = '{} instances of role {} launching into {}'
            self.log.emit(msg.format(count, role_name, subnet_name))

            # create a batch of instances in subnet!
            instances = subnet.create_instances(
                       ImageId           = ami,
                       InstanceType      = role_data.get('instance_type'),
                       MinCount          = count,
                       MaxCount          = count,
                       KeyName           = key_pair.name,
                       SecurityGroupIds  = get_ids(security_groups),
                       ClientToken       = client_token,
            )
            # accumulate all new instances into a single list.
            role_instances += instances

        # cast role Instance objets to EnrichedInstance objects.
        role_instances = self.evpc.get_instances(role_instances)

        self.tag_instances(role_name, role_instances)

        return role_instances
Example #11
0
    def load_balancers(self, load_balancer_cfg):
        """Build ELB load balancers."""
        for lb_name, lb_cfg in load_balancer_cfg.items():

            lb_fullname = '{}-{}'.format(self.evpc.name, lb_name)
            self.log.emit('creating {} load_balancer ...'.format(lb_fullname))

            # make list of security group ids.
            security_groups = map_filter_false(
                self.evpc.get_security_group,
                lb_cfg.get('security_groups', []))
            sg_ids = get_ids(security_groups)

            # make list of subnet ids.
            subnets = map_filter_false(self.evpc.get_subnet,
                                       lb_cfg.get('subnets', []))
            sn_ids = get_ids(subnets)

            scheme = 'internet-facing'
            if lb_cfg.get('internal', False):
                scheme = 'internal'

            listeners = lb_cfg.get('listeners', [])

            self.evpc.elb.create_load_balancer(
                LoadBalancerName=lb_fullname,
                Subnets=sn_ids,
                SecurityGroups=sg_ids,
                Scheme=scheme,
                Tags=[
                    {
                        'Key': 'vpc_name',
                        'Value': self.evpc.vpc_name
                    },
                    {
                        'Key': 'role',
                        'Value': lb_cfg['instance_role']
                    },
                ],
                Listeners=self.evpc.elb.format_listeners(listeners),
            )

            self.log.emit('created {} load_balancer ...'.format(lb_fullname))

            self.log.emit(
                'Configure Health Check for {} load_balancer ...'.format(
                    lb_fullname))

            hc_cfg = lb_cfg.get('healthcheck', {})

            hc_default_target = 'TCP:{}'.format(listeners[0][1])

            self.evpc.elb.configure_health_check(
                LoadBalancerName=lb_fullname,
                HealthCheck={
                    'Target': hc_cfg.get('target', hc_default_target),
                    'Interval': hc_cfg.get('interval', 15),
                    'Timeout': hc_cfg.get('timeout', 5),
                    'UnhealthyThreshold': hc_cfg.get('unhealthy_threshold', 4),
                    'HealthyThreshold': hc_cfg.get('healthy_threshold', 4)
                })

            self.log.emit(
                'Configured Health Check for {} load_balancer ...'.format(
                    lb_fullname))

            asg_name = '{}-{}'.format(self.evpc.name, lb_cfg['instance_role'])
            if asg_name in self.evpc.autoscaling.get_related_autoscaling_group_names(
            ):
                self.log.emit(
                    'attaching {} load balancer to {} autoscaling group ...'.
                    format(lb_fullname, asg_name))
                self.evpc.autoscaling.attach_load_balancers(
                    AutoScalingGroupName=asg_name,
                    LoadBalancerNames=[lb_fullname],
                )
            else:
                self.log.emit(
                    'registering {} role to {} load balancer ...'.format(
                        lb_cfg['instance_role'], lb_fullname))
                self.evpc.elb.register_role_with_load_balancer(
                    lb_fullname, lb_cfg['instance_role'])
Example #12
0
    def instance_role(self, role_name, role_data, desired_count):

        if role_data.get('autoscaling', False) == True:
            # exit early if this instance_role is autoscaling.
            return []

        self.log.emit('creating role: {}'.format(role_name))
        ami = self.amis[role_data['ami']][self.evpc.region_name]

        key_pair = self.evpc.key_pair.get_key_pair(
                       role_data.get('key_pair', 'default')
                   )

        security_groups = map(
            self.evpc.get_security_group,
            role_data.get('security_groups', [])
        )

        subnets = map(
            self.evpc.get_subnet,
            role_data.get('subnets', [])
        )

        if len(subnets) == 0:
            self.log.emit(
                'no subnets found for role: {}'.format(role_name), 'warning'
            )
            # exit early.
            return None

        # sort by subnets by amount of instances, smallest first.
        subnets = sorted(
                      subnets,
                      key = lambda sn : collection_len(sn.instances),
                  )

        # determine the count of this role's existing instances.
        # Note: we look for role in all subnets, not just the listed subnets.
        existing_count = len(self.evpc.get_role(role_name))

        if existing_count >= desired_count:
            # for now we exit early, maybe terminate extras...
            self.log.emit('{} {}'.format(existing_count, desired_count), 'debug')
            return None

        # determine count of additional instances needed to reach desired_count.
        needed_count      = desired_count - existing_count
        needed_per_subnet = desired_count / len(subnets)
        needed_remainder  = desired_count % len(subnets)

        block_device_map = get_block_device_map_from_role_config(role_data)

        role_instances = []

        kwargs = {
          'ImageId'             : ami,
          'InstanceType'        : role_data.get('instance_type'),
          'KeyName'             : key_pair.name,
          'SecurityGroupIds'    : get_ids(security_groups),
          'BlockDeviceMappings' : block_device_map,
          'UserData'            : role_data.get('userdata', ''),
          'IamInstanceProfile'  : {},
        }

        profile_name = role_data.get('instance_profile_name', None)
        if profile_name:
            kwargs['IamInstanceProfile'] = { 'Name' : profile_name }

        for subnet in subnets:
            # ensure Run_Instance_Idempotency.html#client-tokens
            kwargs['ClientToken'] = str(uuid4())

            # figure out how many instances this subnet needs to create ...
            existing_in_subnet = len(self.evpc.get_role(role_name, subnet.instances.all()))
            count = needed_per_subnet - existing_in_subnet

            if needed_remainder != 0:
                needed_remainder -= 1
                count += 1

            if count == 0:
                # skip this subnet, it doesn't need to launch any instances.
                continue

            subnet_name = make_tag_dict(subnet)['Name']
            msg = '{} instances of role {} launching into {} subnet'
            self.log.emit(msg.format(count, role_name, subnet_name))

            # create a batch of instances in subnet!
            kwargs['MinCount'] = kwargs['MaxCount'] = count
            instances = self._create_instances(subnet, **kwargs)

            # accumulate all new instances into a single list.
            role_instances += instances

        # add role tag to each instance.
        for instance in role_instances:
            update_tags(instance, role = role_name)
Example #13
0
    def instance_role(self, role_name, role_data, desired_count):

        if role_data.get('autoscaling', False) == True:
            # exit early if this instance_role is autoscaling.
            return None

        self.log.emit('creating role: {}'.format(role_name))
        ami = self.amis[role_data['ami']][self.evpc.region_name]

        key_pair = self.evpc.key_pair.get_key_pair(
            role_data.get('key_pair', 'default'))

        security_groups = map_filter_false(
            self.evpc.get_security_group, role_data.get('security_groups', []))

        subnets = map_filter_false(self.evpc.get_subnet,
                                   role_data.get('subnets', []))

        if len(subnets) == 0:
            self.log.emit('no subnets found for role: {}'.format(role_name),
                          'warning')
            # exit early.
            return None

        # sort by subnets by amount of instances, smallest first.
        subnets = sorted(
            subnets,
            key=lambda sn: collection_len(sn.instances),
        )

        # determine the count of this role's existing instances.
        # Note: we look for role in all subnets, not just the listed subnets.
        existing_count = len(self.evpc.get_role(role_name))

        if existing_count >= desired_count:
            # for now we exit early, maybe terminate extras...
            msg = 'skipping role: {} (existing_count {} is greater than or equal to {})'
            self.log.emit(msg.format(role_name, existing_count, desired_count),
                          'debug')
            return None

        # determine count of additional instances needed to reach desired_count.
        needed_count = desired_count - existing_count
        needed_per_subnet = desired_count / len(subnets)
        needed_remainder = desired_count % len(subnets)

        block_device_map = get_block_device_map_from_role_config(role_data)

        role_instances = []

        kwargs = {
            'ImageId': ami,
            'InstanceType': role_data.get('instance_type'),
            'KeyName': key_pair.name,
            'SecurityGroupIds': get_ids(security_groups),
            'BlockDeviceMappings': block_device_map,
            'UserData': role_data.get('userdata', ''),
            'IamInstanceProfile': {},
        }

        profile_name = role_data.get('instance_profile_name', None)
        if profile_name:
            kwargs['IamInstanceProfile'] = {'Name': profile_name}

        for subnet in subnets:
            # ensure Run_Instance_Idempotency.html#client-tokens
            kwargs['ClientToken'] = str(uuid4())

            # figure out how many instances this subnet needs to create ...
            existing_in_subnet = len(
                self.evpc.get_role(role_name, subnet.instances.all()))
            count = needed_per_subnet - existing_in_subnet

            if needed_remainder != 0:
                needed_remainder -= 1
                count += 1

            if count == 0:
                # skip this subnet, it doesn't need to launch any instances.
                continue

            subnet_name = make_tag_dict(subnet)['Name']
            msg = '{} instances of role {} launching into {} subnet'
            self.log.emit(msg.format(count, role_name, subnet_name))

            # create a batch of instances in subnet!
            kwargs['MinCount'] = kwargs['MaxCount'] = count
            instances = self._create_instances(subnet, **kwargs)

            # accumulate all new instances into a single list.
            role_instances += instances

        # add role tag to each instance.
        for instance in role_instances:
            update_tags(instance, role=role_name)
Example #14
0
    def instance_role(self, role_name, role_data, desired_count):
        self.log.emit('creating role: {}'.format(role_name))
        ami = self.amis[role_data['ami']][self.evpc.region_name]

        key_pair = self.evpc.key_pair.get_key_pair(
                       role_data.get('key_pair', 'default')
                   )

        security_groups = map(
            self.evpc.get_security_group,
            role_data.get('security_groups', [])
        )

        subnets = map(
            self.evpc.get_subnet,
            role_data.get('subnets', [])
        )

        if len(subnets) == 0:
            self.log.emit(
                'no subnets found for role: {}'.format(role_name), 'warning'
            )
            # exit early.
            return None

        # sort by subnets by amount of instances, smallest first.
        subnets = sorted(
                      subnets,
                      key = lambda sn : collection_len(sn.instances),
                  )

        # determine the count of this role's existing instances.
        # Note: we look for role in all subnets, not just the listed subnets.
        existing_count = len(self.evpc.get_role(role_name))

        if existing_count >= desired_count:
            # for now we exit early, maybe terminate extras...
            self.log.emit(existing_count + ' ' + desired_count, 'debug')
            return None

        # determine count of additional instances needed to reach desired_count.
        needed_count      = desired_count - existing_count
        needed_per_subnet = needed_count / len(subnets)
        needed_remainder  = needed_count % len(subnets)

        role_instances = []

        for subnet in subnets:
            # ensure Run_Instance_Idempotency.html#client-tokens
            client_token = str(uuid4())

            # figure out how many instances this subnet needs to create ...
            existing_in_subnet = len(self.evpc.get_role(role_name, subnet.instances.all()))
            count = needed_per_subnet - existing_in_subnet
            if needed_remainder != 0:
                needed_remainder -= 1
                count += 1

            if count == 0:
                # skip this subnet, it doesn't need to launch any instances.
                continue

            subnet_name = make_tag_dict(subnet)['Name']
            msg = '{} instances of role {} launching into {}'
            self.log.emit(msg.format(count, role_name, subnet_name))

            # create a batch of instances in subnet!
            instances = subnet.create_instances(
                       ImageId           = ami,
                       InstanceType      = role_data.get('instance_type'),
                       MinCount          = count,
                       MaxCount          = count,
                       KeyName           = key_pair.name,
                       SecurityGroupIds  = get_ids(security_groups),
                       ClientToken       = client_token,
            )
            # accumulate all new instances into a single list.
            role_instances += instances

        # cast role Instance objets to EnrichedInstance objects.
        role_instances = self.evpc.get_instances(role_instances)

        self.tag_instances(role_name, role_instances)

        return role_instances
Example #15
0
    def load_balancers(self, load_balancer_cfg):
        """Build ELB load balancers."""
        for lb_name, lb_cfg in load_balancer_cfg.items():

            lb_fullname = '{}-{}'.format(self.evpc.name, lb_name)
            self.log.emit('creating {} load_balancer ...'.format(lb_fullname))

            # make list of security group ids.
            security_groups = map(
                self.evpc.get_security_group,
                lb_cfg.get('security_groups', [])
            )
            sg_ids = get_ids(security_groups)

            # make list of subnet ids.
            subnets = map(
                self.evpc.get_subnet,
                lb_cfg.get('subnets', [])
            )
            sn_ids = get_ids(subnets)

            scheme = 'internet-facing'
            if lb_cfg.get('internal', False):
                scheme = 'internal'

            listeners = lb_cfg.get('listeners', [])

            self.evpc.elb.create_load_balancer(
              LoadBalancerName = lb_fullname,
              Subnets = sn_ids,
              SecurityGroups = sg_ids,
              Scheme = scheme,
              Tags = [
                { 'Key' : 'vpc_name', 'Value' : self.evpc.vpc_name },
                { 'Key' : 'role', 'Value' : lb_cfg['instance_role'] },
              ],
              Listeners = self.evpc.elb.format_listeners(listeners),
            )

            self.log.emit('created {} load_balancer ...'.format(lb_fullname))
            
            self.log.emit('Configure Health Check for {} load_balancer ...'.format(lb_fullname))

            hc_cfg = lb_cfg.get('healthcheck', {})
            
            hc_default_target = 'TCP:{}'.format(listeners[0][1])
            
            self.evpc.elb.configure_health_check(
                LoadBalancerName= lb_fullname,
                HealthCheck={
                    'Target': hc_cfg.get('target',hc_default_target),
                    'Interval': hc_cfg.get('interval',15),
                    'Timeout': hc_cfg.get('timeout',5),
                    'UnhealthyThreshold': hc_cfg.get('unhealthy_threshold',4),
                    'HealthyThreshold': hc_cfg.get('healthy_threshold',4)
                }
            )

            self.log.emit('Configured Health Check for {} load_balancer ...'.format(lb_fullname))
            
            asg_name  = '{}-{}'.format(self.evpc.name, lb_cfg['instance_role'])
            if asg_name in self.evpc.autoscaling.get_related_autoscaling_group_names():
                self.log.emit('attaching {} load balancer to {} autoscaling group ...'.format(lb_fullname, asg_name))
                self.evpc.autoscaling.attach_load_balancers(
                  AutoScalingGroupName = asg_name,
                  LoadBalancerNames = [lb_fullname],
                )
            else:
                self.log.emit('registering {} role to {} load balancer ...'.format(lb_cfg['instance_role'], lb_fullname))
                self.evpc.elb.register_role_with_load_balancer(lb_fullname, lb_cfg['instance_role'])
Example #16
0
    def autoscaling_instance_role(self, role_name, role_data, desired_count):
        if role_data.get("autoscaling", False) != True:
            # exit early if this instance_role is not autoscaling.
            return None

        long_role_name = "{}-{}".format(self.evpc.name, role_name)

        if (
            long_role_name
            in self.evpc.autoscaling.get_related_autoscaling_group_names()
        ):
            msg = "skipping autoscaling group: {} (it already exists)"
            self.log.emit(msg.format(long_role_name), "debug")
            return None

        ami = self.amis[role_data["ami"]][self.evpc.region_name]

        key_pair = self.evpc.key_pair.get_key_pair(role_data.get("key_pair", "default"))

        security_groups = map_filter_false(
            self.evpc.get_security_group, role_data.get("security_groups", [])
        )

        subnets = map_filter_false(self.evpc.get_subnet, role_data.get("subnets", []))

        block_device_map = get_block_device_map_from_role_config(role_data)

        kwargs = {
            "LaunchConfigurationName": long_role_name,
            "ImageId": ami,
            "InstanceType": role_data.get("instance_type"),
            "KeyName": key_pair.name,
            "SecurityGroups": get_ids(security_groups),
            "BlockDeviceMappings": block_device_map,
            "UserData": role_data.get("userdata", ""),
        }

        profile_name = role_data.get("instance_profile_name", None)
        if profile_name:
            # only add profile if set. Empty string causes error.
            kwargs["IamInstanceProfile"] = profile_name
            self.wait_for_instance_profile(profile_name)

        self.log.emit(
            "creating launch configuration for role: {}".format(long_role_name)
        )
        self.evpc.autoscaling.create_launch_configuration(**kwargs)

        self.log.emit("creating autoscaling group for role: {}".format(long_role_name))
        self.evpc.autoscaling.create_auto_scaling_group(
            AutoScalingGroupName=long_role_name,
            LaunchConfigurationName=long_role_name,
            MinSize=desired_count,
            MaxSize=desired_count,
            DesiredCapacity=desired_count,
            VPCZoneIdentifier=",".join(get_ids(subnets)),
            Tags=[
                {
                    "Key": "role",
                    "Value": role_name,
                    "Key": "Name",
                    "Value": long_role_name,
                    "PropagateAtLaunch": True,
                }
            ],
        )
Example #17
0
    def instance_role(self, role_name, role_data, desired_count):

        if role_data.get("autoscaling", False) == True:
            # exit early if this instance_role is autoscaling.
            return None

        self.log.emit("creating role: {}".format(role_name))
        ami = self.amis[role_data["ami"]][self.evpc.region_name]

        key_pair = self.evpc.key_pair.get_key_pair(role_data.get("key_pair", "default"))

        security_groups = map_filter_false(
            self.evpc.get_security_group, role_data.get("security_groups", [])
        )

        subnets = map_filter_false(self.evpc.get_subnet, role_data.get("subnets", []))

        if len(subnets) == 0:
            self.log.emit("no subnets found for role: {}".format(role_name), "warning")
            # exit early.
            return None

        # sort by subnets by amount of instances, smallest first.
        subnets = sorted(subnets, key=lambda sn: collection_len(sn.instances))

        # determine the count of this role's existing instances.
        # Note: we look for role in all subnets, not just the listed subnets.
        existing_count = len(self.evpc.get_role(role_name))

        if existing_count >= desired_count:
            # for now we exit early, maybe terminate extras...
            msg = "skipping role: {} (existing_count {} is greater than or equal to {})"
            self.log.emit(msg.format(role_name, existing_count, desired_count), "debug")
            return None

        # determine count of additional instances needed to reach desired_count.
        needed_count = desired_count - existing_count
        needed_per_subnet = desired_count / len(subnets)
        needed_remainder = desired_count % len(subnets)

        block_device_map = get_block_device_map_from_role_config(role_data)

        role_instances = []

        kwargs = {
            "ImageId": ami,
            "InstanceType": role_data.get("instance_type"),
            "KeyName": key_pair.name,
            "SecurityGroupIds": get_ids(security_groups),
            "BlockDeviceMappings": block_device_map,
            "UserData": role_data.get("userdata", ""),
            "IamInstanceProfile": {},
        }

        profile_name = role_data.get("instance_profile_name", None)
        if profile_name:
            kwargs["IamInstanceProfile"] = {"Name": profile_name}

        private_ip_address = role_data.get("private_ip_address", None)
        if private_ip_address:
            kwargs["PrivateIpAddress"] = private_ip_address

        for subnet in subnets:
            # ensure Run_Instance_Idempotency.html#client-tokens
            kwargs["ClientToken"] = str(uuid4())

            # figure out how many instances this subnet needs to create ...
            existing_in_subnet = len(
                self.evpc.get_role(role_name, subnet.instances.all())
            )
            count = needed_per_subnet - existing_in_subnet

            if needed_remainder != 0:
                needed_remainder -= 1
                count += 1

            if count == 0:
                # skip this subnet, it doesn't need to launch any instances.
                continue

            subnet_name = make_tag_dict(subnet)["Name"]
            msg = "{} instances of role {} launching into {} subnet"
            self.log.emit(msg.format(count, role_name, subnet_name))

            # create a batch of instances in subnet!
            kwargs["MinCount"] = kwargs["MaxCount"] = count
            instances = self._create_instances(subnet, **kwargs)

            # accumulate all new instances into a single list.
            role_instances += instances

        # add role tag to each instance.
        for instance in role_instances:
            update_tags(instance, role=role_name)