def check_secrets(docker_compose_path: str, no_prompt: bool = False): log.info("Checking Coral secrets...") required_secrets = swarmadmin.get_objs_from_compose( "secret", docker_compose_path) missing_secrets = list( filter(lambda x: not swarmadmin.obj_exists("secret", x), required_secrets)) if len(missing_secrets) > 0: log.info("Some required secrets are missing") if no_prompt: raise Exception( "When running in test mode, all secrets must be manually created beforehand." ) else: prompt_secrets(missing_secrets) else: if not no_prompt: question = "All required secrets are defined. Do you wish to redefine them? (y/n) " answer = fish.valid_answer_from_prompt( question, valid_answers=settings.get("prompt_boolean_answers")) log_file.info(question + answer) if fish.user_prompt_yes(answer): manage.remove_coral_objects("secret", silent=True, list_found_objs=False, prompt=False) prompt_secrets(required_secrets)
def remove_coral_objects(obj_type: str, silent: bool = False, list_found_objs: bool = True, prompt: bool = True, is_dep: bool = False): if not silent: log.info( f"Removing{' dependent ' if is_dep else ' '}Coral {obj_type}s...") cleanup_params = settings.get("cleanup_params")[obj_type] rm_confirmation_msg, all_, quiet, format_, filters, force = [ value for value in cleanup_params.values() ] obj_list = get_coral_objs(obj_type, all_=all_, quiet=quiet, format_=f"\"{format_}\"", filters=filters) if obj_list: bullets_obj_list = "\n".join( [f"- {line}" for line in obj_list.split("\n")]) if list_found_objs and not silent: log.info( f"The following Coral {obj_type}s were found:\n{bullets_obj_list}" ) log_stdout.info("") if prompt: question = f"{rm_confirmation_msg}\nAre you sure you want to remove these {obj_type}s? (y/n) " answer = fish.valid_answer_from_prompt( question, valid_answers=settings.get("prompt_boolean_answers")) log_file.info(question.replace("\n", " ") + answer) if not prompt or fish.user_prompt_yes(answer): remove_coral_obj_dependencies(obj_type, silent=silent) obj_ids = [ i for i, j in (obj.split("\t") for obj in obj_list.split("\n")) ] if not silent: log.info(f"Removing {obj_type}s...") res = swarmadmin.rm(obj_type, obj_ids, force=force, suppress_stdout=silent) fish.handle(res) if not silent: log.info(f"Done!") else: if not silent: log.info(f"No Coral {obj_type}s were found. Skipping...")
def update(): question = "Coral will be stopped in order to perform the update. Do you wish to continue? (y/n) " answer = fish.valid_answer_from_prompt( question, valid_answers=settings.get("prompt_boolean_answers")) log_file.info(question + answer) if fish.user_prompt_yes(answer): docker_compose_path = settings.get("compose_path") original_compose_file = None log.info("Updating Coral Docker images...") # check if a current deployment is using dev images curr_depl_conf = deploy.get_curr_depl_config() if curr_depl_conf is not None: original_compose_file = fish.read_file(docker_compose_path) dev = curr_depl_conf["advanced"]["dev_images"] if dev: deploy.switch_to_dev_images( docker_compose_path) # switch to dev images try: registry_login() pull_coral_images(docker_compose_path) finally: if original_compose_file is not None: fish.write_file(original_compose_file, docker_compose_path) log_stdout.info("") log.info("Coral Docker images successfully updated!") curr_depl_conf = deploy.get_curr_depl_config() if (curr_depl_conf is None): log.info("Cannot start Coral. Please deploy first.") else: domain = curr_depl_conf["basic"][ "domain"] # needed for logs after deployment deploy.prepare(skip_depl_config=True, is_update=True, docker_compose_path=docker_compose_path, domain=domain, email=None, cert_type=None, stack_name=None, no_prompt=True)
def check_skip_depl_config(no_prompt: bool = False): curr_depl_conf = get_curr_depl_config() if curr_depl_conf is None: return False curr_depl_conf = json.dumps(curr_depl_conf, indent=2) log.info( "Previous deployment configuration found:\n{0}".format(curr_depl_conf)) if no_prompt: return True else: question = f"Do you wish to reuse the configuration above? (y/n) " answer = fish.valid_answer_from_prompt( question, valid_answers=settings.get("prompt_boolean_answers")) log_file.info(question + answer) return fish.user_prompt_yes(answer)
def check_central_mon(env_file_path: str, no_prompt: bool = False): log.info("Checking for central monitoring configuration...") central_mon_url = get_central_monitor_url() if (len(central_mon_url["value"]) == 0): log.warn( f"A central monitoring URL has not been defined in {env_file_path}, line {str(central_mon_url['index'] + 1)}.\nThe monitoring features described in the 'Coral Monitor Stack' section of README.md will be disabled." ) if not no_prompt: question = "Do you wish to continue? (y/n) " answer = fish.valid_answer_from_prompt( question, valid_answers=settings.get("prompt_boolean_answers")) log_file.info(question + answer) if fish.user_prompt_no(answer): sys.exit(0) return False else: log.info(f"Using {central_mon_url['value']} for central monitoring...") return True
def exec_cmd_live(cmd, print_stdout=True, print_stderr=False, filter_stdout=False, overlay_keyword=None, timeout=None): # use file as pipe to allow for live printing of stdout/stderr with io.open("stdout.tmp", 'wb') as stdout_writer,\ io.open("stderr.tmp", 'wb') as stderr_writer,\ io.open("stdout.tmp", 'rb', 1) as stdout_reader,\ io.open("stderr.tmp", 'rb', 1) as stderr_reader: prev_stdout = "" process = subprocess.Popen(cmd.split(" "), stdout=stdout_writer, stderr=stderr_writer) exit_code = None time_step = 0.5 elapsed_time = 0 while process.poll() is None: stdout = stdout_reader.read().decode('utf-8') stderr = stderr_reader.read().decode('utf-8') # filter out empty or duplicate lines if print_stdout and filter_stdout: if "\n" in stdout: stdout = list(filter(lambda x: x not in ["", "\n"], stdout.split("\n"))) if stdout and stdout[0] != prev_stdout: stdout = stdout[0] prev_stdout = stdout if overlay_keyword is not None and overlay_keyword in stdout: sys.stdout.write(stdout + "\r") # overlay on top of previous line else: sys.stdout.write(stdout + "\n") # log stdout to file (excluding overlayed lines) if overlay_keyword not in stdout: log_file.info(stdout) else: if print_stdout: sys.stdout.write(stdout) if print_stderr: sys.stdout.write(stderr) time.sleep(time_step) elapsed_time += time_step if timeout and elapsed_time >= timeout: exit_code = 124 break else: exit_code = process.returncode # read any remaining outpout if print_stdout: sys.stdout.write(stdout_reader.read().decode('utf-8')) result = { "cmd": cmd, "exit_code": exit_code, "stdout": stdout_reader.read().decode('utf-8'), "stderr": stderr_reader.read().decode('utf-8') } for file_ in glob.glob("*.tmp"): os.remove(file_) return result
def signal_handler(sig, frame): msg = "Cancelled by user. Exiting..." log_stdout.info("\n" + msg) log_file.info(msg) sys.exit(0)
status = manage.start() elif parsed_args.stop: status = manage.stop() elif parsed_args.restart: status = manage.restart() if status == 1: log.info( "No Coral services were found (Coral stack is not currently deployed)" ) if __name__ == "__main__": try: log_stdout.info(settings.get_intro()) log_file.info("EXEC: [ {0} ]".format(", ".join(sys.argv))) signal.signal(signal.SIGINT, signal_handler) skip_depl_config = False if "--deploy" in sys.argv: skip_depl_config = deploy.check_skip_depl_config( "--test" in sys.argv) parser = config_arg_parser() parsed_args = parse_args(parser, skip_depl_config) main(parsed_args, skip_depl_config) except (Exception, SystemExit) as e: e_name = type(e).__name__ if e_name == "SystemExit": if e == 1: log_file.exception(e_name) else: