Exemple #1
0
    def get(self, **kwargs) -> ContextData:
        # get unikube file
        unikube_file = unikube_file_selector.get(
            path_unikube_file=self.path_unikube_file)

        # check if unikube file was loaded
        if not unikube_file:
            return ContextData()

        return unikube_file.get_context()
Exemple #2
0
 def test_version_latest(self):
     path_unikube_file = "tests/unikube_file/unikube_version_latest.yaml"
     unikube_file = unikube_file_selector.get(path_unikube_file)
     self.assertEqual("latest", unikube_file.version)
Exemple #3
0
 def setUp(self) -> None:
     path_unikube_file = "tests/unikube_file/unikube.yaml"
     unikube_file = unikube_file_selector.get(path_unikube_file)
     self.unikube_file_app = unikube_file.get_app()
Exemple #4
0
    def test_get_app_default(self):
        path_unikube_file = "tests/unikube_file/unikube_apps_default.yaml"
        unikube_file = unikube_file_selector.get(path_unikube_file)

        unikube_file_app = unikube_file.get_app()
        self.assertEqual("default", unikube_file_app.name)
Exemple #5
0
    def test_get_app_name(self):
        path_unikube_file = "tests/unikube_file/unikube.yaml"
        unikube_file = unikube_file_selector.get(path_unikube_file)

        unikube_file_app = unikube_file.get_app(name="your-app-01")
        self.assertEqual("your-app-01", unikube_file_app.name)
Exemple #6
0
 def test_apps_invalid(self):
     path_unikube_file = "tests/unikube_file/unikube_apps_invalid.yaml"
     with self.assertRaises(UnikubeFileError):
         _ = unikube_file_selector.get(path_unikube_file)
Exemple #7
0
def switch(ctx,
           app,
           organization,
           project,
           deck,
           deployment,
           unikubefile: str = None,
           no_build: bool = False,
           **kwargs):
    """
    Switch a running deployment with a local Docker container.
    """

    cluster_data, deck = get_deck_from_arguments(ctx, organization, project,
                                                 deck)

    # get cluster
    cluster = get_cluster_or_exit(ctx, cluster_data.id)

    # unikube file input
    try:
        unikube_file = unikube_file_selector.get(path_unikube_file=unikubefile)
        unikube_file_app = unikube_file.get_app(name=app)
    except Exception as e:
        console.debug(e)
        console.error("Invalid 'app' argument.", _exit=True)

    # 2: Get a deployment
    # 2.1.a Check the deployment identifier
    if not deployment and unikube_file_app:
        # 1.1.b check the unikubefile
        deployment = unikube_file_app.get_deployment()
        if not deployment:
            console.error(
                "Please specify the 'deployment' key of your app in your unikube.yaml.",
                _exit=True)
    else:
        console.error(
            "Please specify the deployment either using the '--deployment' option or in the unikube.yaml. "
            "Run 'unikube app switch' in a directory containing the unikube.yaml file.",
            _exit=True,
        )

    # 2.2 Fetch available "deployment:", deployments
    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($id: UUID) {
                deck(id: $id) {
                    deployments(level: "local") {
                        id
                        title
                        description
                        ports
                        isSwitchable
                    }
                    environment {
                        id
                        type
                        valuesPath
                        namespace
                    }
                }
            }
            """,
            query_variables={
                "id": deck["id"],
            },
        )
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    target_deployment = None
    for _deployment in data["deck"]["deployments"]:
        if _deployment["title"] == deployment:
            target_deployment = _deployment

    # 2.3 Check and select deployment data
    if target_deployment is None:
        console.error(
            f"The deployment '{deployment}' you specified could not be found.",
            _exit=True,
        )

    ports = target_deployment["ports"].split(",")
    deployment = target_deployment["title"]
    namespace = deck["environment"][0]["namespace"]

    console.info("Please wait while unikube prepares the switch.")
    with click_spinner.spinner(beep=False,
                               disable=False,
                               force=False,
                               stream=sys.stdout):
        # check telepresence
        provider_data = cluster.storage.get()
        telepresence = Telepresence(provider_data)

        available_deployments = telepresence.list(namespace, flat=True)
        if deployment not in available_deployments:
            console.error(
                "The given deployment cannot be switched. "
                f"You may have to run 'unikube deck install {deck}' first.",
                _exit=True,
            )

        is_swapped = telepresence.is_swapped(deployment, namespace)

        k8s = KubeAPI(provider_data, deck)
        # service account token, service cert
        service_account_tokens = k8s.get_serviceaccount_tokens(deployment)

    # 3: Build an new Docker image
    # 3.1 Grab the docker file
    context, dockerfile, target = unikube_file_app.get_docker_build()
    if not target:
        target = ""
    console.debug(f"{context}, {dockerfile}, {target}")

    # 3.2 Set an image name
    image_name = settings.TELEPRESENCE_DOCKER_IMAGE_FORMAT.format(
        project=cluster_data.name.replace(" ", "").lower(),
        deck=deck["title"],
        name=deployment)

    docker = Docker()

    if is_swapped:
        console.warning(
            "It seems this app is already switched in another process. ")
        if click.confirm("Do you want to kill it and switch here?"):
            telepresence.leave(deployment, namespace, silent=True)
            if docker.check_running(image_name):
                docker.kill(name=image_name)
        else:
            sys.exit(0)

    # 3.3 Build image
    if not docker.image_exists(image_name) or not no_build:
        if no_build:
            console.warning(
                f"Ignoring --no-build since the required image '{image_name}' does not exist"
            )
        console.info(
            f"Building a Docker image for {dockerfile} with context {context}")
        with click_spinner.spinner(beep=False,
                                   disable=False,
                                   force=False,
                                   stream=sys.stdout):
            status, msg = docker.build(image_name, context, dockerfile, target)
        if not status:
            console.debug(msg)
            console.error("Failed to build Docker image.", _exit=True)

        console.info(f"Docker image successfully built: {image_name}")

    # 4. Start the Telepresence session
    # 4.1 Set the right intercept port
    port = unikube_file_app.get_port()
    if port is None:
        port = str(ports[0])
        if len(ports) > 1:
            console.warning(
                f"No port specified although there are multiple ports available: {ports}. "
                f"Defaulting to port {port} which might not be correct.")
    if port not in ports:
        console.error(
            f"The specified port {port} is not in the rage of available options: {ports}",
            _exit=True)
    if not _is_local_port_free(port):
        console.error(
            f"The local port {port} is busy. Please stop the application running on "
            f"this port and try again.",
            _exit=True,
        )

    # 4.2 See if there are volume mounts
    mounts = unikube_file_app.get_mounts()
    console.debug(f"Volumes requested: {mounts}")
    # mount service tokens
    if service_account_tokens:
        tmp_sa_token = tempfile.NamedTemporaryFile(delete=True)
        tmp_sa_cert = tempfile.NamedTemporaryFile(delete=True)
        tmp_sa_token.write(service_account_tokens[0].encode())
        tmp_sa_cert.write(service_account_tokens[1].encode())
        tmp_sa_token.flush()
        tmp_sa_cert.flush()
        mounts.append((tmp_sa_token.name, settings.SERVICE_TOKEN_FILENAME))
        mounts.append((tmp_sa_cert.name, settings.SERVICE_CERT_FILENAME))
    else:
        tmp_sa_token = None
        tmp_sa_cert = None

    # 4.3 See if there special env variables
    envs = unikube_file_app.get_environment()
    console.debug(f"Envs requested: {envs}")

    # 4.4 See if there is a run command to be executed
    command = unikube_file_app.get_command(port=port)
    console.debug(f"Run command: {command}")

    console.info(
        "Starting your container, this may take a while to become effective")

    telepresence.swap(deployment, image_name, command, namespace, envs, mounts,
                      port)
    if docker.check_running(image_name):
        docker.kill(name=image_name)
    if tmp_sa_token:
        tmp_sa_token.close()
        tmp_sa_cert.close()