def active_ami_for_edp(env, dep, play): """ Given an environment, deployment, and play, find the base AMI id used for the active deployment. Arguments: env (str): Environment to check (stage, prod, loadtest, etc.) dep (str): Deployment to check (edx, edge, mckinsey, etc.) play (str): Play to check (edxapp, discovery, ecommerce, etc.) Returns: str: Base AMI id of current active deployment for the EDP. Raises: MultipleImagesFoundException: If multiple AMI IDs are found within the EDP's ELB. ImageNotFoundException: If no AMI IDs are found for the EDP. """ LOG.info("Looking up AMI for {}-{}-{}...".format(env, dep, play)) edp = EDP(env, dep, play) ec2_conn = boto.connect_ec2() asg_conn = boto.connect_autoscale() all_elbs = get_all_load_balancers() LOG.info("Found {} load balancers.".format(len(all_elbs))) edp_filter = { "tag:environment": env, "tag:deployment": dep, "tag:play": play, } reservations = ec2_conn.get_all_reservations(filters=edp_filter) LOG.info("{} reservations found for EDP {}-{}-{}".format( len(reservations), env, dep, play)) amis = set() instances_by_id = {} for reservation in reservations: for instance in reservation.instances: # Need to build up instances_by_id for code below instances_by_id[instance.id] = instance asgs = asg_conn.get_all_groups(names=asgs_for_edp(edp)) for asg in asgs: for asg_inst in asg.instances: instance = instances_by_id[asg_inst.instance_id] asg_enabled = len(asg.suspended_processes) == 0 if instance.state == 'running' and asg_enabled: amis.add(instance.image_id) LOG.info("AMI found in ASG {} for {}-{}-{}: {}".format( asg.name, env, dep, play, instance.image_id)) else: LOG.info("Instance {} state: {} - asg {} enabled: {}".format( instance.id, instance.state, asg.name, asg_enabled)) if len(amis) > 1: msg = "Multiple AMIs found for {}-{}-{}, should have only one.".format( env, dep, play) raise MultipleImagesFoundException(msg) if not amis: msg = "No AMIs found for {}-{}-{}.".format(env, dep, play) raise ImageNotFoundException(msg) return amis.pop()
def asgs_for_edp(edp, filter_asgs_pending_delete=True): """ All AutoScalingGroups that have the tags of this play. A play is made up of many auto_scaling groups. Arguments: EDP Named Tuple: The edp tags for the ASGs you want. Returns: list: list of ASG names that match the EDP. eg. [ u'edxapp-v018', u'sandbox-edx-hacking-ASG', u'sandbox-edx-insights-ASG', u'test-edx-ecomapp', u'test-edx-edxapp-v007', u'test2-edx-certificates', ] """ all_groups = get_all_autoscale_groups() matching_groups = [] LOG.info("Found {} ASGs".format(len(all_groups))) for group in all_groups: LOG.debug("Checking group {}".format(group)) tags = {tag.key: tag.value for tag in group.tags} LOG.debug("Tags for asg {}: {}".format(group.name, tags)) if filter_asgs_pending_delete and ASG_DELETE_TAG_KEY in tags.keys(): LOG.info( "filtering ASG: {0} because it is tagged for deletion on: {1}". format(group.name, tags[ASG_DELETE_TAG_KEY])) continue edp_keys = ['environment', 'deployment', 'play'] if all([tag in tags for tag in edp_keys]): group_env = tags['environment'] group_deployment = tags['deployment'] group_play = tags['play'] group_edp = EDP(group_env, group_deployment, group_play) if group_edp == edp: matching_groups.append(group.name) LOG.info("Returning %s ASGs for EDP %s-%s-%s.", len(matching_groups), edp.environment, edp.deployment, edp.play) return matching_groups
def test_asgs_for_edp(self, params): asgs, expected_returned_count, expected_asg_names_list = params edp = EDP("foo", "bar", "baz") for name, tags in six.viewitems(asgs): create_asg_with_tags(name, tags) asgs = ec2.asgs_for_edp(edp) self.assertIsInstance(asgs, list) self.assertEqual(len(asgs), expected_returned_count) self.assertTrue( all(asg_name in asgs for asg_name in expected_asg_names_list))
def edp_for_ami(ami_id): """ Look up the EDP tags for an AMI. Arguments: ami_id (str): An AMI Id. Returns: EDP Named Tuple: The EDP tags for this AMI. Raises: ImageNotFoundException: No image found with this ami ID. MissingTagException: AMI is missing one or more of the expected tags. """ tags = tags_for_ami(ami_id) try: edp = EDP(tags['environment'], tags['deployment'], tags['play']) except KeyError as key_err: missing_key = key_err.args[0] msg = "{} is missing the {} tag.".format(ami_id, missing_key) raise MissingTagException(msg) LOG.debug("Got EDP for {}: {}".format(ami_id, edp)) return edp
def test_edp2_for_tagged_ami(self): actual_edp = ec2.edp_for_ami(self._make_fake_ami()) expected_edp = EDP("foo", "bar", "baz") # Happy Path self.assertEqual(expected_edp, actual_edp)