Esempio n. 1
0
def up_command(_args: argparse.Namespace, _unknow_args: [str]):
    printer = StepPrinter()
    try:
        printer.start_step("Finding Docker Container")
        docker_manager = DockerManager()
        printer.end_step()

        if not docker_manager.connection_ok():
            docker_manager.print_connection_err()
            return

        compose_path = ENVY_CONFIG.get_services_compose_path()
        if compose_path:
            printer.start_step("Starting Sidecar Services")
            ComposeManager(compose_path).up()
            printer.end_step()

        if not ENVY_STATE.get_container_id():
            printer.start_step("Creating ENVy environment")
            docker_manager.create_container()
            create_directory_if_not_exists()
            printer.end_step()

        printer.start_step("Starting Container")
        container = docker_manager.ensure_container()
        container.ensure_running()
        printer.end_step()

        if ENVY_CONFIG.should_x_forward():
            printer.start_step("Setting up X forwarding")

            if platform.system() == "Darwin":
                x_error = "WARNING: failed to set up X forwarding. X applications will likely fail. Is XQuartz installed and running?"
            else:
                x_error = "WARNING: failed to set up X forwarding. X applications will likely fail. Do you have an X server running?"

            if os.path.exists("/tmp/.X11-unix/X0"):
                try:
                    subprocess.run(["xhost", "+", "localhost"],
                                   check=True,
                                   capture_output=True)
                except subprocess.SubprocessError:
                    print(x_error)
            else:
                print(x_error)
            printer.end_step()

        step_builder = Builder(container, printer)
        step_builder.build()

    except ContainerError as err:
        printer.error(err.code)
Esempio n. 2
0
    def create_container(self) -> ContainerManager:
        """ Creates an ENVy container. Requires that the container does not already exist, and that the image already exists.

        Raises:
            ContainerExists: The container ID specified in ENVY_STATE already exists.

        Returns:
            ContainerManager -- A container manager for the newly created container
        """
        if self.get_container():
            raise ContainerExists()

        image = ENVY_CONFIG.get_base_image()
        if ":" not in image:
            image += ":latest"

        try:
            self.docker_client.images.get(image)
        except docker.errors.ImageNotFound:
            print("Pulling base image, this may take a while...")

        self.docker_client.images.pull(image)

        container_manager = ContainerManager.create(self.docker_client, image)

        ENVY_STATE.set_container_id(container_manager.container_id)

        return container_manager
Esempio n. 3
0
def down_command(_args: argparse.Namespace, _unknown_args: [str]):
    printer = StepPrinter()
    try:
        printer.start_step("Connecting to Docker")
        docker_manager = DockerManager()
        printer.end_step()

        if not docker_manager.connection_ok():
            docker_manager.print_connection_err()
            return

        printer.start_step("Finding Docker Container")
        container = docker_manager.get_container()
        printer.end_step()

        if container:
            printer.start_step("Stopping Docker Container")
            container.ensure_stopped()
            printer.end_step()

        compose_path = ENVY_CONFIG.get_services_compose_path()
        if compose_path:
            printer.start_step("Stopping Sidecar Services")
            ComposeManager(compose_path).down()
            printer.end_step()
    except ContainerError as err:
        printer.error(err.code)
Esempio n. 4
0
def main():
    parser = get_parser(ENVY_CONFIG.get_actions())
    args, unknown = parser.parse_known_args()
    if args.subparser_name:
        args.func(args, unknown)
    else:
        parser.print_help()
Esempio n. 5
0
    def __create_steps(self):
        for m in ENVY_CONFIG.get_setup_steps():
            # Create step
            name = m["name"]
            label = m["label"]
            if m["type"] == "script":
                step = ScriptSetupStep(
                    name, label, self.container, m["run"], m["as_user"]
                )
            elif m["type"] == "remote":
                step = RemoteSetupStep(name, label, self.container, m["url"])

            # Create and register triggers
            if m["triggers"] == "always":
                trigger = triggers.TriggerAlways()
            else:
                trigger_list = []
                for t in m["triggers"]["system-packages"]:
                    trigger_list.append(
                        triggers.TriggerSystemPackage(t, self.system_package_step)
                    )
                for t in m["triggers"]["files"]:
                    trigger_list.append(triggers.TriggerWatchfile(t))
                for t in m["triggers"]["steps"]:
                    trigger_list.append(triggers.TriggerStep(self.steps[t]))

                trigger = triggers.TriggerGroup(trigger_list)

            step.set_trigger(trigger)

            # Add step to dict
            self.steps[name] = step
Esempio n. 6
0
    def create(docker_client: DockerClient,
               image_id: str) -> "ContainerManager":
        """ Creates a container with the given image id

        Arguments:
            docker_client {DockerClient} -- A docker client
            image_id {str} -- the ID of the image to use

        Returns:
            ContainerManager -- a container manager for the created container
        """
        print("Creating ENVy container")

        environment = {}
        mounts = [
            Mount(
                ENVY_CONFIG.get_project_mount_path(),
                str(ENVY_PROJECT_DIR),
                type="bind",
            ),
            Mount("/var/run/docker.sock", "/var/run/docker.sock", type="bind"),
        ]

        if ENVY_CONFIG.should_x_forward():
            mounts += [Mount("/tmp/.X11-unix", "/tmp/.X11-unix", type="bind")]
            if platform.system() == "Darwin":
                environment["DISPLAY"] = "host.docker.internal:0"
            else:
                environment["DISPLAY"] = ":0"

        container = docker_client.containers.create(
            image_id,
            "tail -f /dev/null",
            name=ContainerManager.__generate_container_name(),
            network=ENVY_CONFIG.get_network(),
            network_mode=ENVY_CONFIG.get_network_mode(),
            ports=ENVY_CONFIG.get_ports(),
            mounts=mounts,
            environment=environment,
        )

        return ContainerManager(docker_client, container.id)
Esempio n. 7
0
    def exec(self, command: str, as_user: bool = False, relpath: str = None):
        """ Executes the command in the container

        Arguments:
            command {str} -- The command to run. Usually /bin/bash <>
            relpath {str} -- Relative path to project root to enter before executing. Optional, defaults to none.
        Raises:
            ContainerNotFound: The container was not found
            ContainerNotRunning: The container was not running
        """
        if not self.is_running():
            raise ContainerNotRunning()

        cdto = ENVY_CONFIG.get_project_mount_path()
        if relpath is not None:
            cdto = Path(ENVY_CONFIG.get_project_mount_path(), relpath)

        command_inside_project = "/bin/bash -c 'cd {}; {}'".format(
            cdto, command.replace("'", "'\\''"))

        if as_user:
            groups = ",".join(str(x) for x in os.getgroups())
            userspec = str(os.getuid()) + ":" + str(os.getgid())
            command_inside_project = "/usr/sbin/chroot --groups={} --userspec={} / /bin/bash -c 'export HOME=/uhome; cd {}; {}'".format(
                groups,
                userspec,
                ENVY_CONFIG.get_project_mount_path(),
                command.replace("'", "'\\''"),
            )

        exit_code = dockerpty.exec_command(self.docker_client,
                                           self.container_id,
                                           command_inside_project)

        if exit_code != 0:
            raise ContainerError(exit_code)
Esempio n. 8
0
def nuke_command(_args: argparse.Namespace, _unknown_args: [str]):
    printer = StepPrinter()
    try:
        printer.start_step("Destroying ENVy Environment")
        docker_manager = DockerManager()

        if not docker_manager.connection_ok():
            docker_manager.print_connection_err()
            return

        docker_manager.nuke()
        ENVY_STATE.nuke()

        compose_path = ENVY_CONFIG.get_services_compose_path()
        if compose_path:
            ComposeManager(compose_path).nuke()

        printer.end_step()
    except ContainerError as err:
        printer.error(err.code)
Esempio n. 9
0
 def __create_system_packages_step(self):
     self.system_package_step = AptPackageManagerStep(
         self.container, ENVY_CONFIG.get_system_packages()
     )
     self.steps[self.system_package_step.name] = self.system_package_step