def promote_db_instance(module, conn): main_logger.log(30, "promote_db_instance called") params = select_parameters_meta(module, conn, 'PromoteReadReplica') instance_id = module.params.get('db_instance_identifier') result = get_db_instance(conn, instance_id) if not result: module.fail_json(msg="DB Instance %s does not exist" % instance_id) if result.get('replication_source'): if module.check_mode: module.exit_json(changed=True, promote_read_replica_params=params) try: response = conn.promote_read_replica(**params) instance = response['DBInstance'] changed = True except botocore.exceptions.ClientError as e: module.fail_json(msg="Failed to promote replica instance: %s " % str(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) else: changed = False if module.params.get('wait'): instance = await_resource(conn, instance_id, 'available', module) else: instance = get_db_instance(conn, instance_id) return dict(changed=changed, instance=instance)
def restore_db_instance(module, conn): main_logger.log(30, "resore_db_instance called") params = select_parameters_meta(module, conn, 'RestoreDBInstanceFromDBSnapshot') instance_id = module.params.get('db_instance_identifier') changed = False instance = get_db_instance(conn, instance_id) if not instance: if module.check_mode: module.exit_json( changed=True, restore_db_instance_from_db_snapshot_params=params) try: response = conn.restore_db_instance_from_db_snapshot(**params) instance = response['DBInstance'] changed = True except botocore.exceptions.ClientError as e: module.fail_json(msg="Failed to restore instance: %s " % str(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) if module.params.get('wait'): instance = await_resource(conn, instance_id, 'available', module) else: instance = get_db_instance(conn, instance_id) return dict(changed=changed, instance=instance)
def create_db_instance(module, conn): main_logger.log(30, "create_db_instance called") params = select_parameters_meta(module, conn, 'CreateDBInstance') instance_id = module.params.get('db_instance_identifier') params['DBInstanceIdentifier'] = instance_id changed = False instance = get_db_instance(conn, instance_id) if instance is None: if module.check_mode: module.exit_json(changed=True, create_db_instance_params=params) try: response = conn.create_db_instance(**params) instance = get_db_instance(conn, instance_id) changed = True except Exception as e: module.fail_json_aws(e, msg="trying to create instance") if module.params.get('wait'): resource = await_resource(conn, instance_id, 'available', module) else: resource = get_db_instance(conn, instance_id) return dict(changed=changed, instance=resource, response=response)
def await_resource(conn, instance_id, status, module, await_pending=None): wait_timeout = module.params.get('wait_timeout') + time.time() # Refresh the resource immediately in case we just changed it's state; # should we sleep first? assert instance_id is not None resource = get_db_instance(conn, instance_id) main_logger.log(50, "await_resource called for " + instance_id) main_logger.log( 40, "wait is {0} {1} await_pending is {2} status is {3}".format( str(wait_timeout), str(time.time()), str(await_pending), str(resource['DBInstanceStatus']))) rdat = resource["PendingModifiedValues"] while ((await_pending and rdat) or resource['DBInstanceStatus'] != status ) and wait_timeout > time.time(): main_logger.log(70, "waiting with resource{} ".format(str(resource))) time.sleep(5) # Temporary until all the rds2 commands have their responses parsed current_id = resource.get('DBInstanceIdentifier') if current_id is None: module.fail_json( msg="There was a problem waiting for RDS instance %s" % resource.instance) resource = get_db_instance(conn, current_id) if resource is None: break rdat = resource["PendingModifiedValues"] # resource will be none if it has actually been removed - e.g. we were waiting for deleted # status; maybe that should be an error in other situations? if wait_timeout <= time.time( ) and resource is not None and resource['DBInstanceStatus'] != status: module.fail_json( msg="Timeout waiting for RDS resource %s status is %s should be %s" % (resource.get('DBInstanceIdentifier'), resource['DBInstanceStatus'], status)) return resource
def wait_for_new_instance_id(conn, after_instance_id): # Wait until the new instance name is valid after_instance = None while not after_instance: # FIXME: Timeout!!! after_instance = get_db_instance(conn, after_instance_id) time.sleep(5) return after_instance
def get_instance_to_work_on(module, conn): instance_id = module.params.get('db_instance_identifier') old_instance_id = module.params.get('old_db_instance_identifier') before_instance = None if old_instance_id is not None: before_instance = get_db_instance(conn, old_instance_id) if before_instance is not None: if get_db_instance(conn, instance_id): module.fail_json( msg= "both old and new instance exist so can't act safely; please clean up one", exception=traceback.format_exc()) instance = before_instance else: instance = get_db_instance(conn, instance_id) return instance
def test_diff_should_compare_important_rds_attributes(self): conn = FakeResource() db_inst = instance_to_facts(get_db_instance(conn, "fakeDBIDstring")) assert len(instance_facts_diff(db_inst, db_inst) ) == 0, "comparison of identical instances shows difference!" assert not (instance_facts_diff(db_inst, db_inst) ), "comparsion of identical instances is not false!" bigger_inst = copy.deepcopy(db_inst) bigger_inst["allocated_storage"] = db_inst["allocated_storage"] + 5 assert len(instance_facts_diff(db_inst, bigger_inst) ) > 0, "comparison of differing instances is empty!"
def replicate_db_instance(module, conn): """if the database doesn't exist, create it as a replica of an existing instance """ main_logger.log(30, "replicate_db_instance called") params = select_parameters_meta(module, conn, 'CreateDBInstanceReadReplica') instance_id = module.params.get('db_instance_identifier') instance = get_db_instance(conn, instance_id) if instance: instance_source = instance.get('SourceDBInstanceIdentifier') if not instance_source: module.fail_json( msg="instance %s already exists; cannot overwrite with replica" % instance_id) if instance_source != params('SourceDBInstanceIdentifier'): module.fail_json( msg= "instance %s already exists with wrong source %s cannot overwrite" % (instance_id, params('SourceDBInstanceIdentifier'))) changed = False else: if module.check_mode: module.exit_json(changed=True, create_db_instance_read_replica_params=params) try: response = conn.create_db_instance_read_replica(**params) instance = get_db_instance(conn, instance_id) changed = True except Exception as e: module.fail_json_aws( e, msg="trying to create read replica of instance") if module.params.get('wait'): resource = await_resource(conn, instance_id, 'available', module) else: resource = get_db_instance(conn, instance_id) return dict(changed=changed, instance=resource, response=response)
def delete_db_instance(module, conn): main_logger.log(30, "delete_db_instance called") try: del (module.params['storage_type']) except KeyError: pass params = select_parameters_meta(module, conn, 'DeleteDBInstance') instance_id = module.params.get('db_instance_identifier') snapshot = module.params.get('final_db_snapshot_identifier') result = get_db_instance(conn, instance_id) if not result: return dict(changed=False) if result['DBInstanceStatus'] == 'deleting': return dict(changed=False) if snapshot: params["SkipFinalSnapshot"] = False params["FinalDBSnapshotIdentifier"] = snapshot del (module.params['snapshot']) else: params["SkipFinalSnapshot"] = True if module.check_mode: module.exit_json(changed=True, delete_db_instance_params=params) # FIXME: it's possible to get "trying to delete instance: An error occurred # (InvalidDBInstanceState) when calling the DeleteDBInstance operation: # Cannot delete DB Instance with a read replica still creating", # our call should retry here. try: response = conn.delete_db_instance(**params) instance = result except Exception as e: module.fail_json_aws(e, msg="trying to delete instance") # If we're not waiting for a delete to complete then we're all done # so just return if not module.params.get('wait'): return dict(changed=True, response=response) try: instance = await_resource(conn, instance_id, 'deleted', module) except botocore.exceptions.ClientError as e: if e.code == 'DBInstanceNotFound': return dict(changed=True) else: module.fail_json_aws(e, msg="waiting for rds deletion to complete") except Exception as e: module.fail_json_aws(e, msg="waiting for rds deletion to complete") return dict(changed=True, response=response, instance=instance)
def test_instance_facts_gives_sensible_values(self): conn = FakeResource() db_facts = instance_to_facts(get_db_instance(conn, "fakeDBIDstring")) assert db_facts[db_id_key] == "fakeDBIDstring"
def test_get_db_instance_should_return_camel_dict(self): conn = FakeResource() db_inst = get_db_instance(conn, "fakeDBIDstring") assert db_id_key not in db_inst assert db_inst["DBInstanceIdentifier"] == "fakeDBIDstring"