Example #1
0
def install_config(ctx=None, output_path=None, **kwargs):
    """Install config file.

    Agrs:
        ctx (object): Click Context object.
        output_path (path): Path to place conf file.
    """
    if not ctx:  # Using API. Else handled by cli.
        _set_init_vars(kwargs.get("cwd"), kwargs.get("tmpdir"))

    if not output_path:
        output_path = get_env_var("cwd")
    path = os.path.join(output_path, "%s.conf" % PROJECT_NAME)

    if os.path.exists(path):
        utils.abort("%s.conf already esists." % PROJECT_NAME)
    else:
        with open(path, "w") as f:
            f.write("""\
[up]
provider = virtualbox
box = ubuntu/bionic64
sync_dirs = [["saltstack/etc", "/etc/salt"], ["saltstack/srv", "/srv"]]
""")
        utils.echo("Created config at %s" % path)
Example #2
0
def install_gitignore(ctx=None, output_path=None, **kwargs):
    """Install config file.

    Agrs:
        ctx (object): Click Context object.
        output_path (path): Path to place conf file.
    """
    if not ctx:  # Using API. Else handled by cli.
        _set_init_vars(kwargs.get("cwd"), kwargs.get("tmpdir"))

    if not output_path:
        output_path = get_env_var("cwd")
    path = os.path.join(output_path, ".gitignore")

    if os.path.exists(path):
        pass
    else:
        with open(path, "w") as f:
            f.write("""\
.rambo-tmp/
.vagrant/
my_rambo.conf
auth/
""")
        utils.echo("Created .gitignore")
Example #3
0
def createproject(project_name, cwd, tmpdir, config_only=None, ctx=None):
    """Create project with basic configuration files.

    Agrs:
        project_name (path): Place to create a new project. Must be non-existing dir.
        config_only (bool): Determins if we should only place a conf file in the new project.
    """
    # initialize paths
    _set_env()
    cwd = _set_cwd(cwd)
    path = os.path.join(cwd, project_name)
    _set_tmpdir(path)

    # create new project dir
    try:
        os.makedirs(path)  # Make parent dirs if needed.
    except FileExistsError:
        utils.abort("Directory already exists.")
    utils.echo('Created %s project "%s" in %s.' %
               (PROJECT_NAME.capitalize(), project_name, path))

    # Fill project dir with basic configs.
    install_config(ctx, output_path=path)
    install_gitignore(ctx, output_path=path)
    if not config_only:
        export("saltstack", path)
        install_auth(ctx, output_path=path)
Example #4
0
def export(resource=None, export_path=None, force=None):
    """Drop default code in the CWD / user defined space. Operate on saltstack
    and vagrant resources.

    Agrs:
        resource (str): Resource to export: saltstack or vagrant.
        export_path (path): Dir to export resources to.
        force (bool): Determins if we should overwrite and merge conflicting files in the target path.
    """
    if export_path:
        output_dir = os.path.normpath(export_path)
    else:
        output_dir = os.getcwd()

    if resource in ("vagrant", "saltstack"):
        srcs = [os.path.normpath(os.path.join(PROJECT_LOCATION, resource))]
        dsts = [os.path.join(output_dir, resource)]

    if resource == "vagrant":
        srcs.append(
            os.path.normpath(os.path.join(PROJECT_LOCATION, "settings.json")))
        srcs.append(
            os.path.normpath(os.path.join(PROJECT_LOCATION, "Vagrantfile")))
        dsts.append(os.path.join(output_dir, "settings.json"))
        dsts.append(os.path.join(output_dir, "Vagrantfile"))

    if not force:
        try:
            for path in dsts:
                if os.path.exists(path):
                    click.confirm(
                        "One or more destination files or directories in "
                        "'%s' already exists. Attempt to merge and "
                        "overwrite?" % dsts,
                        abort=True,
                    )
                    break  # We only need general confirmation of an overwrite once.
        except UnboundLocalError:  # dsts referenced before assignement
            utils.abort("The resource '%s' is not a valid option." % resource)

    for src, dst in zip(srcs, dsts):
        try:
            copy_tree(src, dst)  # Merge copy tree with overwrites.
        except DistutilsFileError:  # It's a file, not a dir.
            try:
                shutil.copy(src, dst)  # Copy file with overwrites.
            except FileNotFoundError:
                os.makedirs(
                    os.path.dirname(dst),
                    exist_ok=True)  # Make parent dirs if needed. # Py 3.2+
                shutil.copy(src, dst)  # Copy file with overwrites.

    utils.echo("Done exporting %s code." % resource)
Example #5
0
def _invoke_vagrant(cmd=None):
    """Pass a command to vagrant. This outputs in near real-time,
    logs both stderr and stdout in a combined file, and detects stderr for
    our own error handling.

    Returns returncode (exitcode) of the command.

    Args:
        cmd (str): The cmd string that is appended to `vagrant ...`,
                   passed to the shell and executed.
    """
    masters, slaves = zip(pty.openpty(), pty.openpty())
    cmd = " ".join(["vagrant", cmd]).split()

    with Popen(cmd, stdin=slaves[0], stdout=slaves[0], stderr=slaves[1]) as p:
        for fd in slaves:
            os.close(fd)  # no input
            readable = {
                masters[0]: sys.stdout.buffer,  # store buffers seperately
                masters[1]: sys.stderr.buffer,
            }
        while readable:
            for fd in select(readable, [], [])[0]:
                try:
                    data = os.read(fd, 1024)  # read available
                except OSError as e:
                    if e.errno != errno.EIO:
                        raise  # XXX cleanup
                    del readable[fd]  # EIO means EOF on some systems
                else:
                    if not data:  # EOF
                        del readable[fd]
                    else:
                        if fd == masters[0]:  # We caught stdout
                            utils.echo(data.rstrip())
                            utils.write_to_log(data)
                        else:  # We caught stderr
                            utils.echo(data.rstrip(), err=True)
                            utils.write_to_log(data, "stderr")
                        readable[fd].flush()
    for fd in masters:
        os.close(fd)
    return p.returncode
Example #6
0
def install_auth(ctx=None, output_path=None, **kwargs):
    """Install auth directory.

    Agrs:
        ctx (object): Click Context object.
        output_path (path): Path to place auth dir.
    """
    if not ctx:  # Using API. Else handled by cli.
        _set_init_vars(kwargs.get("cwd"), kwargs.get("tmpdir"))

    if not output_path:
        output_path = get_env_var("cwd")
    license_dir = os.path.join(output_path, "auth/licenses")
    try:
        os.makedirs(license_dir)
    except FileExistsError:
        pass  # Dir already created. Moving on.
    utils.echo(
        "Any (license) files you put in %s will be synced into your VM." %
        license_dir)

    for filename in os.listdir(
            os.path.join(get_env_var("env"), "auth/env_scripts")):
        dst_dir = os.path.join(output_path, "auth/keys")
        dst = os.path.join(dst_dir, os.path.splitext(filename)[0])
        if not os.path.isfile(dst):
            os.makedirs(dst_dir,
                        exist_ok=True)  # Make parent dirs if needed. # Py 3.2+
            shutil.copy(
                os.path.join(get_env_var("env"), "auth/env_scripts", filename),
                dst)
            utils.echo("Added template key loading scripts %s to auth/keys." %
                       filename)
        else:
            utils.echo("File %s exists. Leaving it." % dst)
Example #7
0
def install_plugins(force=None, plugins=("all", )):
    """Install all of the vagrant plugins needed for all plugins

    Agrs:
        force (bool): Forces bypassing of reinstallation prompt.
        plugins (tuple): Names of vagrant plugins to install.
    """
    host_system = platform.system()
    for plugin in plugins:
        if plugin == "all":
            utils.echo("Installing all default plugins.")
            for plugin in SETTINGS["PLUGINS"][host_system]:
                _invoke_vagrant("plugin install %s" % plugin)
        elif plugin in SETTINGS["PLUGINS"][host_system]:
            _invoke_vagrant("plugin install %s" % plugin)
        else:
            if not force:
                click.confirm(
                    'The plugin "%s" is not in our list of plugins. Attempt '
                    "to install anyway?" % plugin,
                    abort=True,
                )
            vagrant_general_command("plugin install %s" % plugin)
Example #8
0
def destroy(ctx=None, **params):
    """Destroy a VM / container and all its metadata. Default leaves logs.
    All str args can also be set as an environment variable; arg takes precedence.

    Agrs:
        ctx (object): Click Context object.
        vagrant_cwd (path): Location of `Vagrantfile`. Used if invoked with API only.
        vagrant_dotfile_path (path): Location of `.vagrant` metadata directory. Used if invoked with API only.
    """
    # TODO add finding and deleting of all VMs registered to this installation.
    # TODO (optional) add finding and deleting of all VMs across all installations.
    # TODO add an --all flag to delete the whole .rambo-tmp dir. Default leaves logs.

    if not ctx:  # Using API. Else handled by cli.
        _set_init_vars(params.get("cwd"), params.get("tmpdir"))
        _set_vagrant_vars(params.get("vagrant_cwd"),
                          params.get("vagrant_dotfile_path"))

    destroy_cmd = vagrant_general_command("destroy --force")

    # If there's any error code from Vagrant, don't delete the metadata.
    if not destroy_cmd:  # I.e. we succeeded - ret code == 0
        utils.file_delete(os.path.join(get_env_var("TMPDIR"), "provider"))
        utils.file_delete(os.path.join(get_env_var("TMPDIR"), "random_tag"))
        utils.dir_delete(os.environ.get("VAGRANT_DOTFILE_PATH"))
        utils.echo("Temporary files removed")

        if params.get("vm_name"):  # Additionally remove the box if we can.
            utils.echo(
                f"Now removing base VirtualBox data for VM {params['vm_name']}."
            )
            os.system(f"vboxmanage controlvm {params['vm_name']} poweroff")
            os.system(f"vboxmanage unregistervm {params['vm_name']} --delete")

        utils.echo("Destroy complete.")
    else:
        utils.echo("We received an error. Destroy may not be complete.")