def handle_next_to(args): command_dirs = get_command_dirs_from_config(Dodo.get()) command_map = get_command_map(command_dirs) if args.next_to: item = command_map.get(args.next_to) if not item: raise CommandError("Script not found: %s" % args.next_to) dest_path = os.path.join(os.path.dirname(item.filename), args.name + ".py") if os.path.exists(dest_path) and not args.force: raise CommandError("Destination already exists: %s" % dest_path) with open(dest_path, "w") as f: f.write( script_py.format(parser_args_str="", params_str="", description="", args_str="")) print(dest_path) else: print( script_py.format(parser_args_str="", params_str="", description="", args_str=""))
def _copy_extra_dirs(local_dir, extra_dirs): # todo: convert extra dirs config mapping into a list of key=val for extra_dir in extra_dirs or []: extra_dir_name, extra_dir_path = extra_dir.split("=") local_path = os.path.join(local_dir, extra_dir_name) if os.path.exists(local_path): raise CommandError("Cannot copy to existing path: " + local_path) if not os.path.exists(extra_dir_path): raise CommandError("Cannot copy from non-existing path: " + extra_dir_path) Dodo.run(["cp", "-rf", extra_dir_path, local_path]) if os.path.abspath(local_dir).startswith(os.path.abspath(extra_dir_path)): rp = os.path.relpath(local_dir, extra_dir_path) dead_path = os.path.join(local_path, rp) if os.path.exists(dead_path): Dodo.run(["rm", "-rf", dead_path])
def init(self, env, use_latest): self.global_config = load_global_config_parser() if not self.global_config.has_section("recent"): self.global_config.add_section("recent") self.latest_env = global_config_get(self.global_config, "recent", "latest_env") self.shell = args.shell or global_config_get( self.global_config, "settings", "shell", "bash" ) if env == "-": env = global_config_get(self.global_config, "recent", "previous_env") if not env: raise CommandError("There is no previous environment") if use_latest: if env: self._report("Options --latest and <env> are mutually exclusive\n") return False env = self.latest_env if not env: self._report("There is no latest environment\n") return False self.env = env self.env_dir = Paths().env_dir(self.env) if self.env else None return True
def _remove_package(package, only_from_defaults=False): """Install the dir with the default commands.""" if not only_from_defaults: dest_dir = os.path.join(Paths().global_commands_dir(), package) if not os.path.exists(dest_dir): raise CommandError("Not installed: %s" % dest_dir) Dodo.run(["rm", "-rf", dest_dir]) defaults_dest_dir = os.path.join(Paths().default_commands_dir(), package) if os.path.exists(defaults_dest_dir): Dodo.run(["rm", defaults_dest_dir])
def create_python_env(python, python_env_dir, env): try: plumbum.local["virtualenv"]("--version") except: # noqa raise CommandError( "Could not find virtualenv, please install it first.") plumbum.local["virtualenv"]("-p", python, python_env_dir, "--prompt", env) symlink( os.path.realpath(os.path.dirname(dodo_commands.__file__)), os.path.join(site_packages_dir(python_env_dir), "dodo_commands"), )
def _clone(args, src_dir): if os.path.exists(src_dir): raise CommandError("Cannot clone into %s, path already exists" % src_dir) Dodo.run( ["git", "clone", args.git_url, os.path.basename(src_dir)] + (["--depth", args.depth] if args.depth else []), cwd=os.path.dirname(src_dir), ) if args.branch: Dodo.run(["git", "checkout", args.branch], cwd=src_dir)
def _args(): # Create the parser parser = ArgumentParser(description="") parser.add_argument("--functions", action="store_true") # Use the parser to create the command arguments args = Dodo.parse_args(parser, config_args=[]) args.cwd = Dodo.get("/ROOT/project_dir") # Raise an error if something is not right if False: raise CommandError("Oops") return args
def _add_docker_volume_list(cls, docker_config, root_node): volume_list = docker_config.get("volume_list", []) volume_map = docker_config.get("volume_map", {}) volume_map_strict = docker_config.get("volume_map_strict", {}) for key, val in volume_map_strict.items(): if not os.path.exists(key): raise CommandError("Path in volume_map_strict not found: %s" % key) volume_map[key] = val options = ["--volume=%s:%s" % (x, x) for x in volume_list] + [ "--volume=%s:%s" % key_val for key_val in volume_map.items() ] for x in options: root_node["volume"].append(x)
def _args(): parser = ArgumentParser(description="Runs node") parser.add_argument("--inspect", action="store_true") parser.add_argument("--inspect-brk", action="store_true") parser.add_argument("--shell", action="store_true") args = Dodo.parse_args(parser) args.cwd = Dodo.get_config("/NODE/cwd") args.node = Dodo.get_config("/NODE/node", "node") args.entrypoint = Dodo.get_config("/NODE/entrypoint", "index.js") # Raise an error if something is not right if False: raise CommandError("Oops") return args
def _args(): parser = ArgumentParser(description="Publish own npm packages") parser.add_argument("--login", action="store_true") # Add arguments to the parser here # Parse the arguments. args = Dodo.parse_args(parser, config_args=[]) args.cwd = Dodo.get("/ROOT/project_dir") args.npm_dir = "/npm" args.src_sub_dirs = Dodo.get("/TSC/src_dir_map").keys() # Raise an error if something is not right if False: raise CommandError("Oops") return args
def _args(): parser = ArgumentParser(description=("Edit the dodo configuration files")) parser.add_argument( "--key", help="Only edit this key. Used in conjunction with --val") parser.add_argument( "--val", help="The value to be used in conjunction with the --key option") args = Dodo.parse_args(parser) if args.key or args.val: if not args.key and args.val: raise CommandError( "The options --key and --val should always be used together") args.editor = load_global_config_parser().get("settings", "config_editor") args.config_dir = Dodo.get("/ROOT/config_dir") return args
def _args(): Dodo.parser.description = "Runs make" Dodo.parser.add_argument("make_args", nargs="?") Dodo.parser.add_argument("--cat", action="store_true") Dodo.parser.add_argument("--edit", action="store_true") args = Dodo.parse_args() args.cwd = Dodo.get_config("/MAKE/cwd") args.file = Dodo.get_config("/MAKE/file", "Makefile") global_config = load_global_config_parser() args.editor = global_config_get(global_config, "settings", "editor") # Raise an error if something is not right if False: raise CommandError("Oops") return args
def install(self): parser = ArgumentParser(add_help=False) self.add_arguments(parser) known_args, args = parser.parse_known_args() if known_args.confirm and known_args.confirm > 1: local.env["__DODO_UNIVERSAL_CONFIRM__"] = "1" if known_args.echo and not Dodo.safe: raise CommandError( "The --echo option is not supported for unsafe commands.\n" + "Since this command is marked as unsafe, some operations will " + "be performed directly, instead of echoed to the console. " + "Use --confirm if you wish to execute with visual feedback. ") if known_args.confirm and not Dodo.safe: if not query_yes_no( "Since this command is marked as unsafe, some operations will " + "be performed without asking for confirmation. Continue?", default="no", ): sys.exit(1)
def _args(): # noqa parser = ArgumentParser( description=('Deploys a ansible script to a ssh server')) parser.add_argument( "--bash", action="store_true", help='Drop into a bash shell instead of calling ansible') args = Dodo.parse_args(parser) args.playbook = Dodo.get_config('/ANSIBLE/playbook') args.ansible_src_dir = Dodo.get_config('/ANSIBLE/src_dir') args.target_docker_image = Dodo.get_config('/ANSIBLE/target_docker_image', None) args.host_name = Dodo.get_config('/ANSIBLE/host_name', None) if args.host_name and args.target_docker_image: raise CommandError('Both host_name and target_docker_image supplied') if args.target_docker_image: args.ssh_public_key = os.path.expandvars( '$HOME/.ssh/%s.pub' % Dodo.get_config('/SSH/key_name')) return args
def _copy_defaults(args, shared_config_dir): config_dir = os.path.join(args.project_dir, ".dodo_commands") has_printed_header = False for filename in glob.glob(os.path.join(shared_config_dir, "*")): dest_path = os.path.join(config_dir, os.path.basename(filename)) if os.path.exists(dest_path): if args.confirm: if not has_printed_header: has_printed_header = True print( "\nCopying shared environment files to your local environment...\n" ) print( "Warning, destination path already exists: %s. Overwrite it?" % dest_path) elif args.use_force: print("Overwriting existing path: %s" % dest_path) else: raise CommandError( "Destination path %s already exists. " % dest_path + "Use the --confirm or --force flag to overwrite it.") Dodo.run(["cp", "-rf", filename, dest_path])
def kubectl_node(cls, get_config, command_name, cwd): merged = cls.merged_options(get_config, command_name) container_name = merged.get("container_name") kubectl = local["kubectl"] if container_name: full_container_name = kubectl( "get", "pods", "-l=app.kubernetes.io/name=" + container_name, "-o", 'jsonpath="{.items[0].metadata.name}"', ) return ArgsTreeNode( "kubectl", args=[ "kubectl", "exec", "-it", full_container_name[1:-1], "--" ], ) else: raise CommandError( "No kubernetes container name in /KUBERNETES for command %s" % command_name)
def _args(): Dodo.parser.add_argument("env", nargs="?") group = Dodo.parser.add_mutually_exclusive_group() group.add_argument("--create-python-env", action="store_true") group.add_argument("--use-python-env") group.add_argument( "--shell", help="Use this shell value instead of the global settings.shell value", ) group = Dodo.parser.add_mutually_exclusive_group() group.add_argument("--latest", action="store_true", dest="use_latest") group.add_argument("--create", action="store_true") group.add_argument("--init", action="store_true") group.add_argument("--forget", action="store_true") args = Dodo.parse_args() if args.create_python_env and not (args.create or args.init): raise CommandError( "The --create-python-env flag should be used together with" + " --init or --create" ) return args
def _args(): parser = ArgumentParser( description='A new command that runs in the project\'s "res" directory' ) # Add arguments to the parser here group = parser.add_mutually_exclusive_group() hooks = _all_hooks() precommit_hooks = hooks['pre-commit'].keys() parser.add_argument('name', choices=precommit_hooks) group.add_argument('--on') group.add_argument('--off') args = Dodo.parse_args(parser, config_args=[ConfigArg('/ROOT/src_dir', '--cwd')]) args.git_hooks_dir = os.path.join(args.cwd, '.git', 'hooks') if not os.path.exists(args.git_hooks_dir): raise CommandError('Git hooks dir not found: %s' % args.git_hooks_dir) args.hooks = hooks return args
'docker', 'run', '--rm', '--volumes-from=ssh-agent', '-it', args.ssh_agent_image_name, 'ssh-add', '-D' ], quiet=True) # noqa Dodo.run(['docker', 'rm', '-f', container_id]) if args.command in ('stop', ): sys.exit(0) elif args.command == 'status': print("running" if container_id else "stopped") elif args.command in ('start', 'restart'): # If container is already running, exit. if container_id: raise CommandError( "A container named 'ssh-agent' is already running.") # Run ssh-agent Dodo.run([ 'docker', 'run', '-d', '--name=ssh-agent', args.ssh_agent_image_name ], ) # Add ssh keys to the ssh-agent container ssh_host_dir = os.path.expandvars('$HOME/.ssh') for key in args.ssh_agent_key_name: Dodo.run([ 'docker', 'run', '--rm', '--volumes-from=ssh-agent', '-v', '%s:/.ssh' % ssh_host_dir, '-it',
if Dodo.is_main(__name__, safe=False): args = _args() config = ConfigIO().load() if args.layer == False: # noqa filtered_layers = _layers(config, filter_abs_paths=True) for layer in filtered_layers: name = _layer_name(layer) if name: value = _layer_value(filtered_layers, name) if value: print(name + ": " + _layer_value(filtered_layers, name)) sys.exit(0) layers = _layers(config) if args.value == False: # noqa print(_layer_value(layers, args.layer)) sys.exit(0) layer_file = os.path.join( Dodo.get("/ROOT/config_dir"), "%s.%s.yaml" % (args.layer, args.value) ) if not args.force and not os.path.exists(layer_file): raise CommandError("Layer file %s does not exist" % layer_file) config["LAYERS"] = _update_list_of_layers(layers, args.layer, args.value) ConfigIO().save(config)
def run(self, init, create, create_python_env, use_python_env, forget): if create: project_dir = os.path.expanduser( os.path.join( self.global_config.get("settings", "projects_dir"), self.env ) ) elif init or create_python_env: project_dir = os.path.abspath(local.cwd) elif forget: pass else: if not os.path.exists(self.env_dir): raise CommandError( "Environment not found: %s. Use the --create flag to create it\n" % self.env ) undo_steps = [] with undo(undo_steps): if create or init: if os.path.exists(self.env_dir): self._report( "Cannot create an environment because the " + "directory already exists: %s\n" % self.env_dir ) return False verb = "Creating" if create else "Initializing in existing" self._report("%s project directory %s ..." % (verb, project_dir)) config_dir = self._config_dir(project_dir) register_env( self.env, project_dir, config_dir, self._python_env_dir( create_python_env, use_python_env, project_dir ), undo_steps, ) if create_python_env: register_python_env( self.global_config.get("settings", "python_interpreter"), self.env, self._python_env_dir( create_python_env, use_python_env, project_dir ), undo_steps, ) if forget: forget_env(self.env) self.env = "default" if create or init or create_python_env: self._report(" done\n") if self.env != self.latest_env: self.global_config.set("recent", "previous_env", self.latest_env) self.global_config.set("recent", "latest_env", self.env) write_global_config_parser(self.global_config) activate_filename = os.path.join(self.env_dir, "activate.%s" % self.shell) if not forget: sys.stdout.write("source %s\n" % activate_filename)
package_name = os.path.basename(item) drop_src_dir = default_drop_src_dir or _read_dot_drop_path( dot_drop_path) _register_drop_dir(drop_dir_by_package_name, package_name, drop_src_dir) return drop_dir_by_package_name if Dodo.is_main(__name__, safe=True): args = _args() drop_src_dir = _drop_dir_by_package_name().get(args.package) if not drop_src_dir: raise CommandError("No drop-in found for package %s" % args.package) if not os.path.isdir(drop_src_dir): raise CommandError("The drop-in directory does not exist: %s" % drop_src_dir) config_dir = Dodo.get("/ROOT/config_dir") drops_target_dir = os.path.join(config_dir, "drops") if not os.path.exists(drops_target_dir): Dodo.run(["mkdir", drops_target_dir]) target_dir = os.path.join(drops_target_dir, args.package) if os.path.exists(target_dir): msg = "" msg += "Target directory already exists: %s\n" % target_dir msg += "\nThis probably means that %s has been already dropped into %s.\n" % (
self.env = "default" if create or init or create_python_env: self._report(" done\n") if self.env != self.latest_env: self.global_config.set("recent", "previous_env", self.latest_env) self.global_config.set("recent", "latest_env", self.env) write_global_config_parser(self.global_config) activate_filename = os.path.join(self.env_dir, "activate.%s" % self.shell) if not forget: sys.stdout.write("source %s\n" % activate_filename) if Dodo.is_main(__name__, safe=False): args = _args() if not args.env and not args.use_latest: raise CommandError("No environment was specified") activator = Activator() if activator.init(args.env, args.use_latest): activator.run( args.init, args.create, args.create_python_env, args.use_python_env, args.forget, )
parser.add_argument("file", nargs="?", help="Show diff for this file") parser.add_argument( "--env-name", help="Compare to files from an alternative environment") args = Dodo.parse_args(parser) return args def _diff_tool(): return load_global_config_parser().get("settings", "diff_tool") if Dodo.is_main(__name__): args = _args() file = args.file or "." project_dir = Paths().project_dir() if not project_dir: raise CommandError("No active dodo commands project") if args.env_name: ref_project_dir = os.path.abspath( os.path.join(project_dir, "..", args.env_name)) original_file = os.path.join(ref_project_dir, file) copied_file = os.path.join(project_dir, file) else: shared_config_dir = Dodo.get("/ROOT/shared_config_dir") original_file = os.path.realpath(os.path.join(shared_config_dir, file)) copied_file = os.path.join(Paths().config_dir(), file) Dodo.run([_diff_tool(), original_file, copied_file])
def docker_node(cls, get_config, command_name, cwd): merged = cls.merged_options(get_config, command_name) image, container = merged.get("image"), merged.get("container") if image: docker_node = ArgsTreeNode("docker", args=["docker", "run"]) docker_node.add_child(ArgsTreeNode("name")) docker_node.add_child(ArgsTreeNode("basic")) docker_node.add_child(ArgsTreeNode("link")) docker_node.add_child(ArgsTreeNode("publish")) docker_node.add_child(ArgsTreeNode("volume", is_horizontal=False)) docker_node.add_child(ArgsTreeNode("volumes-from")) docker_node.add_child(ArgsTreeNode("env", is_horizontal=False)) docker_node.add_child(ArgsTreeNode("other")) docker_node.add_child(ArgsTreeNode("workdir")) docker_node.add_child(ArgsTreeNode("image")) cls._add_linked_container_list(merged, docker_node) cls._add_docker_publish_list(merged, docker_node) cls._add_docker_volume_list(merged, docker_node) cls._add_docker_volumes_from_list(merged, docker_node) cls._add_docker_variable_list(merged, docker_node) cls._add_workdir(merged, docker_node, cwd) cls._add_interactive(merged, docker_node) cls._add_user(merged, docker_node) cls._add_environment_vars(get_config, merged, docker_node) cls._add_extra_options(merged, docker_node) if merged.get("rm", True): docker_node["basic"].append("--rm") if merged.get("is_daemon", False): docker_node["basic"].append("-d") name = merged.get("name", command_name) if name: docker_node["name"].append("--name=%s" % name) docker_node["image"].append(image) elif container: docker_node = ArgsTreeNode("docker", args=["docker", "exec"]) docker_node.add_child(ArgsTreeNode("basic")) docker_node.add_child(ArgsTreeNode("env", is_horizontal=False)) docker_node.add_child(ArgsTreeNode("other")) docker_node.add_child(ArgsTreeNode("workdir")) docker_node.add_child(ArgsTreeNode("container")) cls._add_interactive(merged, docker_node) cls._add_docker_variable_list(merged, docker_node) cls._add_workdir(merged, docker_node, cwd) cls._add_user(merged, docker_node) cls._add_environment_vars(get_config, merged, docker_node) cls._add_extra_options(merged, docker_node) docker_node["container"].append(container) else: raise CommandError( "No docker image or container found in /DOCKER_OPTIONS for command %s" % command_name) return docker_node, image
from dodo_commands import Dodo, CommandError from dodo_commands.framework.global_config import ( load_global_config_parser, write_global_config_parser, ) def _args(): parser = ArgumentParser( description="Write a value of the global Dodo Command configuration" ) parser.add_argument("key") parser.add_argument("val", nargs="?") args = Dodo.parse_args(parser) return args if Dodo.is_main(__name__, safe=False): args = _args() config = load_global_config_parser() if args.key.count(".") != 1: raise CommandError("The key should have the format <section>.<value>") section, key = args.key.split(".") if args.val: config.set(section, key, args.val) write_global_config_parser(config) else: print(config.get(section, key))
def _containers(): return [x for x in docker("ps", "--format", "{{.Names}}").split("\n") if x] if Dodo.is_main(__name__): args = _args() if args.find: args.name = None for container in _containers(): if args.find in container: args.name = container break if not args.name: raise CommandError("Container not found: %s" % args.find) elif not args.name: containers = _containers() print("0 - exit") for idx, container in enumerate(containers): print("%d - %s" % (idx + 1, container)) print("\nSelect a container: ") choice = int(raw_input()) - 1 if choice == -1: sys.exit(0) args.name = containers[choice] if not args.cmd:
def on_invalid_index(self, index): if index == 0: sys.exit(0) picker = Picker(commands, allow_free_text=allow_free_text, labels=labels) picker.pick() return [picker.free_text] if picker.free_text else picker.get_choices() if Dodo.is_main(__name__): args = _args() commands, labels = _get_commands_and_labels(args.command_map, args.category) if not commands: raise CommandError( "No commands were found in the /MENU configuration key") if args.list: print() for label in labels: print(label) elif args.tmux: if not exe_exists("tmux"): raise CommandError("Tmux is not installed on this sytem.") has_session = False try: sessions = tmux("ls") for session in sessions.split("\n"): has_session = has_session or session.startswith( "%s:" % args.session_id)
if args.key or args.val: if not args.key and args.val: raise CommandError( "The options --key and --val should always be used together") args.editor = load_global_config_parser().get("settings", "config_editor") args.config_dir = Dodo.get("/ROOT/config_dir") return args if Dodo.is_main(__name__, safe=("--key" not in sys.argv)): try: args = _args() except configparser.NoOptionError as e: raise CommandError("{error}. Please check {filename}".format( error=str(e), filename=Paths().global_config_filename())) config = ConfigIO().load() if args.key and args.val: key = Key(config, args.key) key.set(args.val) ConfigIO().save(config) sys.exit(0) def add_global_config_filename(layer_paths): return R.concat(layer_paths, [Paths().global_config_filename()]) x = Dodo.get_container().layers.get_ordered_layer_paths() x = add_global_config_filename(x) yaml_filenames = x
return True def _clone_git_repo(repo_path): tmp_dir = tempfile.mkdtemp() Dodo.run(["git", "clone", repo_path], cwd=tmp_dir) package = os.listdir(tmp_dir)[0] return tmp_dir, package if Dodo.is_main(__name__): args = _args() if args.pip and not is_using_system_dodo(): raise CommandError( "Please activate the default environment first by running 'dodo env default'." ) if args.make_default: _install_package(args.make_default, None, lambda: True, True) sys.exit(0) if args.remove_default: _remove_package(args.remove_default, only_from_defaults=True) sys.exit(0) if args.paths: for path in args.paths: package = os.path.basename(path) if args.remove: _remove_package(package)