def delete_image_instance(name): conn = connect.cf() stacks = [stack for stack in conn.describe_stacks() if stack.stack_name == name] if len(stacks) == 0: logger.info("Image instance is already deleted.") return conn.delete_stack(name) logger.info("Waiting for image instance to delete...") formations.wait_until_terminated(name) logger.info("Image instance deleted.")
def decommission(env): conn = connect.cf() app = config.APP_NAME stack_name = name.stack(app, env) stacks = [stack for stack in conn.describe_stacks() if stack.stack_name == stack_name] if len(stacks) == 0: logger.info("Infrastructure is already decommissioned.") return logger.info("Decommissioning...") conn.delete_stack(stack_name) manage.formations.wait_until_terminated(stack_name) logger.info("Decommissioning complete.") notify.notify("Decommissioning for [{0}] complete.".format(env))
def get_stack(name): """ Get a stack by name. This does not retrieve deleted stacks. For that, use `connect.cf().list_stacks()`, though this returns minimal info about each stack (only `stack.stack_name` and `stack.stack_status`) Stack names are unique per AWS account, so we only expect to get one. """ conn = connect.cf() stacks = [stack for stack in conn.describe_stacks() if stack.stack_name == name] if len(stacks) == 0: return None return stacks[0]
def create_image_instance(name, base_ami_id, key_name): conn = connect.cf() if formations.get_stack(name) is not None: logger.info("Image instance already exists.") return image_template = open("formations/image.json", "rb").read() logger.info("Creating image instance ({0})...".format(name)) conn.create_stack( name, image_template, parameters=[("ImageId", base_ami_id), ("InstanceName", name), ("KeyName", key_name)] ) logger.info("Waiting for image instance to launch...") try: formations.wait_until_ready(name) logger.info("Image instance has launched.") except formations.FormationError as e: logger.error("There was an error creating the image instance: {0}".format(e.message)) logger.error( "If the image instance was rolled back, it is likely due to an error with the image instance template." ) logger.info("Cleaning up...") delete_image_instance(name) raise Exception("Image instance creation failed.") stack = formations.get_stack(name) instance_ip = formations.get_output(stack, "PublicIP") instance_host = formations.get_output(stack, "PublicDNSName") logger.info("Instance up at {0} ({1}).".format(instance_host, instance_ip)) logger.info("Waiting for SSH to become active...") sleep(120) # Need to add the instance to known hosts. logger.info("Adding instance to known hosts...") command.add_to_known_hosts([instance_ip, instance_host]) logger.info("Image instance successfully created.")
def update( env, min_size=1, max_size=4, instance_type=DEFAULT_INSTANCE_TYPE, db_instance_type="db.m1.medium", knowledge_instance_type="m3.large", collector_instance_type="c3.large", db_size=250, ): conn = connect.cf() app = config.APP_NAME stack_name = name.stack(app, env) img_name = name.image(app) logger.info( "Updating application cloud (app={0}, stack_name={1}, image_name={2})...".format(app, stack_name, img_name) ) stacks = [stack for stack in conn.describe_stacks() if stack.stack_name == stack_name] if len(stacks) == 0: logger.info("Infrastructure doesn't exist yet. Please commission it first.") return app_ami_id = get_or_create_image(img_name) logger.info("UPDATING INFRASTRUCTURE ===================================================") logger.info("Merging individual templates: {0}".format(TEMPLATES)) template = manage.formations.build_template(TEMPLATES) parameters = build_parameters( env, app, app_ami_id, instance_type, knowledge_instance_type, collector_instance_type, db_size, db_instance_type ) logger.info("Updating the infrastructure...") logger.info( "You can see its progress (and debug issues more easily) by checking out [https://console.aws.amazon.com/cloudformation/]" ) try: conn.update_stack(stack_name, template, parameters=parameters) except BotoServerError as e: if e.message == "No updates are to be performed.": logger.info( "There are no updates to make! If you wish to deploy non-infrastructural updates, use the `deploy` command." ) return else: raise e try: manage.formations.wait_until_ready(stack_name) except manage.formations.FormationError as e: logger.info("There was an error updating the infrastructure: {0}".format(e.message)) logger.info("If the stack was rolled back, it is likely due to an error with the template.") logger.info("Cleaning up...") manage.formations.wait_until_rolled_back(stack_name) return # Return the output from the stack creation. stack = manage.formations.get_stack(stack_name) logger.info("Stack output: {0}".format(stack.outputs)) logger.info("UPDATING INFRASTRUCTURE =================================================== DONE") logger.info("CONFIGURING INFRASTRUCTURE ================================================") logger.info("Adding instances to known hosts...") targets = [ manage.formations.get_output(stack, key) for key in [ "KnowledgePublicIP", "KnowledgePublicDNS", "APIServerPublicIP", "APIServerPublicDNS", "FrontServerPublicIP", "FrontServerPublicDNS", "CollectorPublicIP", "CollectorPublicDNS", ] ] print(targets) command.add_to_known_hosts(targets) deploy(env) logger.info("CONFIGURING INFRASTRUCTURE ================================================ DONE") logger.info("Stack output: {0}".format(stack.outputs)) logger.info("Updating complete.") notify.notify("Updating for [{0}] complete.".format(env)) return stack.outputs
def commission( env, min_size=1, max_size=4, instance_type=DEFAULT_INSTANCE_TYPE, db_instance_type="db.m1.medium", knowledge_instance_type="m3.large", collector_instance_type="c3.large", db_size=250, ): conn = connect.cf() app = config.APP_NAME stack_name = name.stack(app, env) img_name = name.image(app) logger.info( "Commissioning new application cloud (app={0}, stack_name={1}, image_name={2})...".format( app, stack_name, img_name ) ) app_ami_id = get_or_create_image(img_name) logger.info("SPAWNING INFRASTRUCTURE ===================================================") if manage.formations.get_stack(stack_name) is not None: logger.info("Infrastructure for the environment [{0}] already exists.".format(env)) else: logger.info("Merging individual templates: {0}".format(TEMPLATES)) template = manage.formations.build_template(TEMPLATES) parameters = build_parameters( env, app, app_ami_id, instance_type, knowledge_instance_type, collector_instance_type, db_size, db_instance_type, ) logger.info("Creating the infrastructure...") logger.info( "You can see its progress (and debug issues more easily) by checking out [https://console.aws.amazon.com/cloudformation/]" ) conn.create_stack(stack_name, template, parameters=parameters) try: manage.formations.wait_until_ready(stack_name) except manage.formations.FormationError as e: logger.info("There was an error creating the infrastructure: {0}".format(e.message)) logger.info("If the stack was rolled back, it is likely due to an error with the template.") logger.info("Cleaning up...") manage.formations.wait_until_rolled_back(stack_name) decommission(stack_name) return # Return the output from the stack creation. stack = manage.formations.get_stack(stack_name) logger.info("Stack output: {0}".format(stack.outputs)) logger.info("SPAWNING INFRASTRUCTURE =================================================== DONE") logger.info("CONFIGURING INFRASTRUCTURE ================================================") logger.info("Adding instances to known hosts...") targets = [ manage.formations.get_output(stack, key) for key in [ "KnowledgePublicIP", "KnowledgePublicDNS", "APIServerPublicIP", "APIServerPublicDNS", "FrontServerPublicIP", "FrontServerPublicDNS", "CollectorPublicIP", "CollectorPublicDNS", ] ] command.add_to_known_hosts(targets) deploy(env) logger.info("CONFIGURING INFRASTRUCTURE ================================================ DONE") logger.info("Stack output: {0}".format(stack.outputs)) logger.info("Commissioning complete.") notify.notify("Commissioning for [{0}] complete.".format(env)) return stack.outputs