Example #1
0
def get_deck(ctx, deck_id: str):
    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($id: UUID) {
                deck(id: $id) {
                    id
                    title
                    environment {
                        id
                        type
                        valuesPath
                        namespace
                    }
                    project {
                        id
                        title
                        organization {
                            title
                        }
                    }
                }
            }
            """,
            query_variables={"id": deck_id},
        )
        deck = data["deck"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    return deck
Example #2
0
def compare_current_and_latest_versions():
    try:
        current_version = None
        try:
            path = Path(__file__).parent / "../VERSION"
            with path.open("r") as f:
                current_version = f.read()
        except (FileNotFoundError, PermissionError):
            console.debug("Could not read current version.")

        if not current_version:
            dist = pkg_resources.working_set.by_key.get("unikube")
            if dist:
                current_version = dist.version

        release = requests.get("https://api.github.com/repos/unikubehq/cli/releases/latest")
        if release.status_code == 403:
            console.info("Versions cannot be compared, as API rate limit was exceeded")
            return None
        latest_release_version = release.json()["tag_name"].replace("-", ".")
        if current_version != latest_release_version:
            console.info(
                f"You are using unikube version {current_version}; however, version {latest_release_version} is "
                f"available."
            )

        return current_version
    except pkg_resources.DistributionNotFound as e:
        console.warning(f"Version of the package could not be found: {e}")
    except Exception:
        import traceback

        console.info(f"Versions cannot be compared, because of error {traceback.format_exc()}")
Example #3
0
def organization_list(ctx) -> Union[None, str]:
    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query("""
            query {
                allOrganizations {
                    results {
                        id
                        title
                    }
                }
            }
            """)
        organization_list = data["allOrganizations"]["results"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    selection = console.list(
        message="Please select an organization",
        choices=[organization["title"] for organization in organization_list],
        identifiers=[organization["id"] for organization in organization_list],
        message_no_choices="No organizations available!",
    )
    if selection is None:
        return None

    # get identifier if available
    organization_argument = get_identifier_or_pass(selection)

    organization_id = convert_organization_argument_to_uuid(
        ctx.auth, argument_value=organization_argument)
    return organization_id
Example #4
0
def info(ctx, project=None, organization=None, **kwargs):
    """
    Displays the id, title and optional description of the selected project.
    """

    _ = ctx.auth.refresh()

    # context
    organization_id, project_id, _ = ctx.context.get_context_ids_from_arguments(
        organization_argument=organization, project_argument=project)

    # argument
    if not project_id:
        project_id = console.project_list(ctx, organization_id=organization_id)
        if not project_id:
            return None

    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($id: UUID!) {
                project(id: $id) {
                    id
                    title
                    description
                    specRepository
                    specRepositoryBranch
                    organization {
                        title
                    }
                }
            }
            """,
            query_variables={"id": project_id},
        )
        project_selected = data["project"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    # console
    if project_selected:
        project_selected["organization"] = project_selected.pop(
            "organization").get("title", "-")
        project_selected["repository"] = project_selected.pop("specRepository")
        project_selected["repository branch"] = project_selected.pop(
            "specRepositoryBranch")

        console.table(
            data={
                "key": [k for k in project_selected.keys()],
                "value": [v for v in project_selected.values()],
            },
            headers=["Key", "Value"],
        )
    else:
        console.error("Project does not exist.")
Example #5
0
def environment_type_from_string(environment_type: str):
    try:
        environment_type = EnvironmentType(environment_type)
    except Exception as e:
        console.debug(e)
        environment_type = None

    return environment_type
Example #6
0
    def __request(
        self,
        url,
        data,
        message_exception,
        message_200,
        message_400,
        message_500,
        headers=None,
    ) -> dict:
        # request
        try:
            req = requests.post(
                url,
                data,
                headers=headers,
                timeout=self.timeout,
            )
        except Exception as e:
            console.debug(e)
            return {
                "success": False,
                "message": message_exception,
                "response": None,
            }

        # return
        if req.status_code == 200:
            success = True
            message = message_200

        elif req.status_code in [400, 401, 404]:
            success = False
            message = message_400

        elif req.status_code in [500, 501, 502, 503]:
            success = False
            message = message_500

        else:
            success = False
            message = ""

        # get json response
        try:
            response = req.json()
        except Exception:
            response = None

        return {
            "success": success,
            "message": message,
            "response": response,
        }
Example #7
0
 def uninstall(self, deployment, namespace=None, silent=False):
     arguments = ["uninstall", "--agent", deployment]
     arguments.append(deployment)
     if namespace:
         arguments += ["-n", namespace]
     console.debug(arguments)
     process = self._execute(arguments)
     if not silent and process.returncode and process.returncode != 0:
         console.error(
             "There was an error with uninstalling the traffic agent, please find details above",
             _exit=False)
Example #8
0
File: app.py Project: unikubehq/cli
def get_deck_from_arguments(ctx, organization_id: str, project_id: str,
                            deck_id: str):
    # context
    organization_id, project_id, deck_id = ctx.context.get_context_ids_from_arguments(
        organization_argument=organization_id,
        project_argument=project_id,
        deck_argument=deck_id)

    # argument
    if not deck_id:
        deck_id = console.deck_list(ctx,
                                    organization_id=organization_id,
                                    project_id=project_id)
        if not deck_id:
            exit(1)

    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($id: UUID) {
                deck(id: $id) {
                    id
                    title
                    environment {
                        namespace
                    }
                    project {
                        id
                    }
                }
            }
            """,
            query_variables={"id": deck_id},
        )
        deck = data["deck"]
        project_id = deck["project"]["id"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    # cluster data
    cluster_list = ctx.cluster_manager.get_cluster_list(ready=True)
    if project_id not in [cluster.id for cluster in cluster_list]:
        console.info(
            f"The project cluster for '{project_id}' is not up or does not exist yet.",
            _exit=True)

    cluster_data = ctx.cluster_manager.get(id=project_id)
    if not cluster_data:
        console.error("The cluster could not be found.", _exit=True)

    return cluster_data, deck
Example #9
0
def prune(ctx, **kwargs):
    """
    Remove unused clusters.
    """

    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query("""
            query {
                allProjects {
                    results {
                        id
                    }
                }
            }
            """)
        projects = data["allProjects"]["results"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    # cluster
    cluster_list = ctx.cluster_manager.get_cluster_list()

    # select clusters to prune
    prune_clusters = []
    for cluster_data in cluster_list:
        if cluster_data.id not in [project["id"] for project in projects]:
            prune_clusters.append(cluster_data)

    for cluster_data in prune_clusters:
        console.info(
            f"It seems like the project for cluster '{cluster_data.name}' has been deleted."
        )

        # confirm question
        confirmed = console.confirm(
            question="Do want to remove the cluster? [N/y]: ")
        if not confirmed:
            console.info("No action taken.")
            continue

        # delete
        try:
            cluster = ctx.cluster_manager.select(cluster_data=cluster_data)
            success = cluster.delete()
            if success:
                console.success("The project was deleted successfully.")
                ctx.cluster_manager.delete(cluster.id)
        except Exception as e:
            console.debug(e)
            console.error("The cluster could not be deleted.")
Example #10
0
def project_list(ctx,
                 organization_id: str = None,
                 filter: List[str] = None,
                 excludes: List[str] = None) -> Union[None, str]:
    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($organization_id: UUID) {
                allProjects(organizationId: $organization_id) {
                    results {
                        title
                        id
                        organization {
                            id
                            title
                        }
                    }
                }
            }
            """,
            query_variables={
                "organization_id": organization_id,
            },
        )
        project_list = data["allProjects"]["results"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    selection = console.list(
        message="Please select a project",
        choices=[project["title"] for project in project_list],
        identifiers=[project["id"] for project in project_list],
        filter=filter,
        excludes=excludes,
        help_texts=[
            project["organization"]["title"] for project in project_list
        ],
        message_no_choices="No projects available!",
    )
    if selection is None:
        return None

    # get identifier if available
    project_argument = get_identifier_or_pass(selection)

    project_id = convert_project_argument_to_uuid(
        ctx.auth,
        argument_value=project_argument,
        organization_id=organization_id)
    return project_id
Example #11
0
 def leave(self, deployment, namespace=None, silent=False):
     arguments = ["leave", "--no-report"]
     if namespace:
         arguments.append(f"{deployment}-{namespace}")
     else:
         arguments.append(deployment)
     console.debug(arguments)
     process = self._execute(arguments)
     if not silent and process.returncode and process.returncode != 0:
         console.error(
             "There was an error with leaving the deployment, please find details above",
             _exit=False)
Example #12
0
def deck_list(ctx,
              organization_id: str = None,
              project_id: str = None) -> Union[None, str]:
    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($organization_id: UUID, $project_id: UUID) {
                allDecks(organizationId: $organization_id, projectId: $project_id) {
                    results {
                        title
                        id
                        project {
                            id
                            title
                            organization {
                                id
                            }
                        }
                    }
                }
            }
            """,
            query_variables={
                "organization_id": organization_id,
                "project_id": project_id,
            },
        )
        deck_list = data["allDecks"]["results"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    selection = console.list(
        message="Please select a deck",
        choices=[deck["title"] for deck in deck_list],
        identifiers=[deck["id"] for deck in deck_list],
        help_texts=[deck["project"]["title"] for deck in deck_list],
        message_no_choices="No decks available!",
    )
    if selection is None:
        return None

    # get identifier if available
    deck_argument = get_identifier_or_pass(selection)

    deck_id = convert_deck_argument_to_uuid(ctx.auth,
                                            argument_value=deck_argument,
                                            organization_id=organization_id,
                                            project_id=project_id)
    return deck_id
Example #13
0
def info(ctx, organization=None, project=None, deck=None, **kwargs):
    """
    Display further information of the selected deck.
    """

    # context
    organization_id, project_id, deck_id = ctx.context.get_context_ids_from_arguments(
        organization_argument=organization,
        project_argument=project,
        deck_argument=deck)

    # argument
    if not deck_id:
        deck_id = console.deck_list(ctx,
                                    organization_id=organization_id,
                                    project_id=project_id)
        if not deck_id:
            return None

    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($id: UUID) {
                deck(id: $id) {
                    id
                    title
                    description
                    namespace
                    type
                }
            }
            """,
            query_variables={"id": deck_id},
        )
        deck_selected = data["deck"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    # console
    if deck_selected:
        console.table(
            data={
                "key": [k for k in deck_selected.keys()],
                "value": [v for v in deck_selected.values()],
            },
            headers=["Key", "Value"],
        )
    else:
        console.error("Deck does not exist.")
Example #14
0
    def _decode_requesting_party_token(self, requesting_party_token: str) -> dict:
        # decode
        try:
            token = jwt.decode(
                requesting_party_token,
                algorithms=["RS256"],
                audience=settings.TOKEN_AUDIENCE,
                options={"verify_signature": False},
            )
        except Exception as e:
            console.debug(e)
            raise Exception("Requesting Party Token (RPT) could not be decoded.")

        return token
Example #15
0
    def swap(self,
             deployment,
             image_name,
             command=None,
             namespace=None,
             envs=None,
             mounts=None,
             port=None):
        arguments = ["intercept", "--no-report", deployment]
        if namespace:
            arguments = arguments + ["--namespace", namespace]

        arguments = arguments + [
            "--port", f"{port}:{port}", "--docker-run", "--"
        ]
        if platform.system() != "Darwin":
            arguments.append("--network=host")
        arguments += [
            f"--dns-search={namespace}",
            "--rm",
        ]
        if mounts:
            for mount in mounts:
                arguments = arguments + ["-v", f"{mount[0]}:{mount[1]}"]
        if envs:
            for env in envs:
                arguments = arguments + ["--env", f"{env[0]}={env[1]}"]

        # this name to be retrieved for "app shell" command
        arguments = arguments + ["--name", image_name.replace(":", "")]
        arguments.append(image_name)
        if command:
            arguments = arguments + ["sh", "-c"] + [f"{' '.join(command)}"]

        console.debug(arguments)
        try:
            process = self._execute_intercept(arguments)
            if process.returncode and (process.returncode != 0
                                       and not process.returncode != 137):
                console.error(
                    "There was an error with switching the deployment, please find details above",
                    _exit=False)
        except KeyboardInterrupt:
            pass
        console.info(
            "Stopping the switch operation. It takes a few seconds to reset the cluster."
        )
        self.leave(deployment, namespace, silent=True)
        self.uninstall(deployment, namespace, silent=True)
Example #16
0
    def verify_or_refresh(self) -> bool:
        # verify
        response = self.verify()
        if response["success"]:
            return True

        # refresh
        response = self.refresh()
        if response["success"]:
            return True

        # exception messsage
        console.debug(response["message"])

        return False
Example #17
0
    def intercept_count(self) -> Union[int, None]:
        arguments = ["status"]
        process = self._execute(arguments)
        status = process.stdout.readlines()

        # parse intercept count
        try:
            intercept_line = status[15]
            match = re.findall("[ ]{1,}Intercepts[ ]{1,}:(.*)[ ]{1,}total",
                               intercept_line)
            intercept_count = int(match[0])
        except Exception as e:
            console.debug(e)
            intercept_count = None

        return intercept_count
Example #18
0
def list(ctx, organization, **kwargs):
    """
    Display a table of all available project names alongside with the ids.
    """

    _ = ctx.auth.refresh()

    # context
    organization_id, _, _ = ctx.context.get_context_ids_from_arguments(
        organization_argument=organization)

    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($organization_id: UUID) {
                allProjects(organizationId: $organization_id) {
                    results {
                        title
                        id
                        description
                    }
                }
            }
            """,
            query_variables={"organization_id": organization_id},
        )
        project_list = data["allProjects"]["results"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    # console
    if len(project_list) < 1:
        console.info(
            "No projects available. Please go to https://app.unikube.io and create a project.",
            _exit=True)

    console.table(
        data={
            "id": [p["id"] for p in project_list],
            "title": [p["title"] for p in project_list],
            "description": [p["description"] for p in project_list],
        },
        headers=["id", "name", "description"],
    )
Example #19
0
def info(ctx, organization, **kwargs):
    """
    Display further information of the selected organization.
    """

    _ = ctx.auth.refresh()

    # context
    organization_id, _, _ = ctx.context.get_context_ids_from_arguments(organization_argument=organization)

    # argument
    if not organization_id:
        organization_id = console.organization_list(ctx)
        if not organization_id:
            return None

    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($id: UUID!) {
                organization(id: $id) {
                    id
                    title
                    description
                }
            }
            """,
            query_variables={"id": organization_id},
        )
        organization_selected = data["organization"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    # console
    if organization_selected:
        console.table(
            data={
                "key": [k for k in organization_selected.keys()],
                "value": [v for v in organization_selected.values()],
            },
            headers=["Key", "Value"],
        )
    else:
        console.error("Organization does not exist.")
Example #20
0
        def do_POST(self):
            POST = self.get_post_data()

            if POST["state"] != state:
                raise Exception(f"Invalid state: {POST['state']}")

            response = ctx.auth._get_requesting_party_token(
                POST["access_token"])

            login_file = open(
                os.path.join(os.path.dirname(os.path.realpath(__file__)),
                             "login.html"))
            text = login_file.read()
            login_file.close()

            # select response
            if not response["success"]:
                console.error("Login failed!")
                text = (
                    "Login failed! Could not retrieve requesting party token. "
                    "Please try again or contact your System administrator")
            else:
                try:
                    token = ctx.auth.token_from_response(response)
                except Exception as e:
                    console.debug(e)
                    console.debug(response)
                    console.error("Login failed!")
                    text = "Login failed! Your token does not match."
                else:
                    ctx.auth.general_data.authentication = AuthenticationData(
                        email=token["email"],
                        access_token=response["response"]["access_token"],
                        refresh_token=response["response"]["refresh_token"],
                        requesting_party_token=True,
                    )
                    ctx.auth.local_storage_general.set(ctx.auth.general_data)

                    if given_name := token.get("given_name", ""):
                        greeting = f"Hello {given_name}!"
                    else:
                        greeting = "Hello!"
Example #21
0
def password_flow(ctx, email, password):
    response = ctx.auth.login(
        email,
        password,
    )
    if response["success"]:
        try:
            token = ctx.auth.token_from_response(response)
        except Exception as e:
            console.debug(e)
            console.debug(response)
            console.error("Login failed. Your token does not match.")
            return False

        if token["given_name"]:
            console.success(f'Login successful. Hello {token["given_name"]}!')
        else:
            console.success("Login successful.")
    else:
        console.error("Login failed. Please check email and password.")
    return True
Example #22
0
    def get(self) -> ContextData:
        context = ContextData()

        for context_object in self.context_order:
            # get context variables from current context
            try:
                context_current = context_object.get(current_context=context)
            except Exception as e:
                console.debug(e)
                context_current = ContextData()

            # update context
            context_dict = context.dict()
            for key, value in context_current.dict().items():
                if context_dict[key] is None:
                    context_dict[key] = value
            context = ContextData(**context_dict)

            # check if all context variables have already been set
            if None not in context.dict().values():
                break

        return context
Example #23
0
def list(ctx, **kwargs):
    """
    List all your organizations.
    """

    _ = ctx.auth.refresh()
    context = ctx.context.get()

    # keycloak
    try:
        keycloak_permissions = KeycloakPermissions(authentication=ctx.auth)
        permission_list = keycloak_permissions.get_permissions_by_scope("organization:*")
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    # append "(active)"
    if context.organization_id:
        for permission in permission_list:
            if permission.rsid == context.organization_id:
                permission.rsid += " (active)"

    # console
    organization_list = [
        {
            "id": permission.rsid,
            "name": permission.rsname.replace("organization ", ""),
        }
        for permission in permission_list
    ]
    console.table(
        data=organization_list,
        headers={
            "id": "id",
            "name": "name",
        },
    )
Example #24
0
def organization_id_2_display_name(ctx, id: str = None) -> str:
    if not id:
        return "-"

    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($id: UUID!) {
                organization(id: $id) {
                    title
                }
            }
            """,
            query_variables={
                "id": id,
            },
        )
        title = data["organization"]["title"]
    except Exception as e:
        console.debug(e)
        title = "-"

    return f"{title} ({id})"
Example #25
0
    def select(
        self,
        cluster_data: K8sProviderData,
        cluster_provider_type: K8sProviderType = settings.
        UNIKUBE_DEFAULT_PROVIDER_TYPE,
    ) -> Union[AbstractK8sProvider, None]:
        # create config
        config = {
            "id": cluster_data.id,
        }

        if cluster_data.name:
            config["name"] = cluster_data.name

        # get selected kubernetes cluster from factory
        try:
            kubernetes_cluster = kubernetes_cluster_factory.get(
                cluster_provider_type,
                **config,
            )
            return kubernetes_cluster
        except Exception as e:
            console.debug(e)
            return None
Example #26
0
def list(ctx, organization=None, project=None, **kwargs):
    """
    List all decks.
    """

    # context
    organization_id, project_id, _ = ctx.context.get_context_ids_from_arguments(
        organization_argument=organization, project_argument=project)

    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($organization_id: UUID, $project_id: UUID) {
                allDecks(organizationId: $organization_id, projectId: $project_id) {
                    results {
                        id
                        title
                        project {
                            title
                            organization {
                                title
                            }
                        }
                    }
                }
            }
            """,
            query_variables={
                "organization_id": organization_id,
                "project_id": project_id,
            },
        )
        deck_list = data["allDecks"]["results"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    if not deck_list:
        console.warning(
            "No decks available. Please go to https://app.unikube.io and create a project.",
            _exit=True)

    # format list to table
    table_data = []
    for deck in deck_list:
        data = {}

        if not organization_id:
            data["organization"] = deck["project"]["organization"]["title"]

        if not project_id:
            data["project"] = deck["project"]["title"]

        data["id"] = deck["id"]
        data["title"] = deck["title"]
        table_data.append(data)

    # console
    console.table(data=table_data)
Example #27
0
File: app.py Project: unikubehq/cli
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()
Example #28
0
def up(ctx,
       project=None,
       organization=None,
       ingress=None,
       provider=None,
       workers=None,
       **kwargs):
    """
    This command starts or resumes a Kubernetes cluster for the specified project. As it is a selection command, the
    project can be specified and/or filtered in several ways:

    * as a positional argument, id or project title can be specified, or from a set context
    * as an interactive selection from available projects
    * via ``-o`` or ``--organization`` option, specifying an organisation to which a project belongs

    """

    _ = ctx.auth.refresh()

    if not Docker().daemon_active():
        console.error(
            "Docker is not running. Please start Docker before starting a project.",
            _exit=True)

    # context
    organization_id, project_id, _ = ctx.context.get_context_ids_from_arguments(
        organization_argument=organization, project_argument=project)

    # cluster information
    cluster_list = ctx.cluster_manager.get_cluster_list(ready=True)
    cluster_id_list = [item.id for item in cluster_list]

    # argument
    if not project_id:
        project_id = console.project_list(ctx,
                                          organization_id=organization_id,
                                          excludes=cluster_id_list)
        if not project_id:
            return None

    if project_id in cluster_id_list:
        console.info(
            f"Project '{project_id_2_display_name(ctx=ctx, id=project_id)}' is already up.",
            _exit=True)

    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query($id: UUID) {
                project(id: $id) {
                    title
                    id
                    organization {
                        id
                    }
                    clusterSettings {
                        id
                        port
                    }
                    organization {
                        title
                    }
                }
            }
            """,
            query_variables={
                "id": project_id,
            },
        )
        project_selected = data["project"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    if not project_selected:
        console.info(
            f"The project '{project_id_2_display_name(ctx=ctx, id=project_id)}' could not be found.",
            _exit=True)

    try:
        cluster_provider_type = K8sProviderType[provider]
    except KeyError:
        console.error(
            f"The provider '{provider}' is not supported. Please use "
            f"one of: {','.join(opt.name for opt in K8sProviderType)}",
            _exit=True,
        )

    check_running_cluster(ctx, cluster_provider_type, project_selected)

    # get project id
    if ingress is None:
        ingress = project_selected["clusterSettings"]["port"]

    if not_available_ports := check_ports([ingress]):
        console.error(
            "Following ports are currently busy, however needed to spin up the cluster: {}"
            .format(", ".join([str(port) for port in not_available_ports])),
            _exit=True,
        )
Example #29
0
def ps(ctx, **kwargs):
    """
    Displays the current process state.
    """

    # cluster
    cluster_list = ctx.cluster_manager.get_cluster_list(ready=True)
    cluster_id_list = [cluster.id for cluster in cluster_list]

    # GraphQL
    try:
        graph_ql = GraphQL(authentication=ctx.auth)
        data = graph_ql.query(
            """
            query {
                allProjects {
                    results {
                        title
                        id
                        description
                    }
                }
            }
            """, )
        project_list = data["allProjects"]["results"]
    except Exception as e:
        console.debug(e)
        console.exit_generic_error()

    cluster_data = []
    for project in project_list:
        if project["id"] in cluster_id_list:
            cluster_data.append(project)

    console.info("Project:")
    console.table(
        data={
            "id": [cluster["id"] for cluster in cluster_data],
            "title": [cluster["title"] for cluster in cluster_data],
            "description":
            [cluster["description"] for cluster in cluster_data],
        },
        headers=["cluster: id", "name", "description"],
    )
    console.echo("")

    # switch
    intercept_count = 0
    if cluster_data:
        cluster = get_cluster_or_exit(ctx, cluster_data[0]["id"])
        provider_data = cluster.storage.get()

        telepresence = Telepresence(provider_data)
        intercept_count = telepresence.intercept_count()

    if intercept_count == 0 or not intercept_count:
        console.info("No app switched!")
    else:
        console.info(f"Apps switched: #{intercept_count}")
    console.echo("")

    # context
    local_storage_user = get_local_storage_user()
    user_data = local_storage_user.get()
    show_context(ctx=ctx, context=user_data.context)