def wait_for_pod_ready(config: Config, service: str) -> None: fmt.echo_info(f"Waiting for a {service} pod to be ready...") utils.kubectl( "wait", *resource_selector(config, f"app.kubernetes.io/name={service}"), "--for=condition=ContainersReady", "--timeout=600s", "pod", )
def scale(context: K8sContext, deployment: str, replicas: int) -> None: config = tutor_config.load(context.root) utils.kubectl( "scale", # Note that we don't use the full resource selector because selectors # are not compatible with the deployment/<name> argument. *resource_namespace_selector(config, ), f"--replicas={replicas}", f"deployment/{deployment}", )
def delete(context: K8sContext, yes: bool) -> None: if not yes: click.confirm( "Are you sure you want to delete the platform? All data will be removed.", abort=True, ) utils.kubectl( "delete", "-k", tutor_env.pathjoin(context.root), "--ignore-not-found=true", "--wait", )
def logs(context: K8sContext, container: str, follow: bool, tail: bool, service: str) -> None: config = tutor_config.load(context.root) command = ["logs"] selectors = ["app.kubernetes.io/name=" + service] if service else [] command += resource_selector(config, *selectors) if container: command += ["-c", container] if follow: command += ["--follow"] if tail is not None: command += ["--tail", str(tail)] utils.kubectl(*command)
def delete_resources(config: Config, resources: Optional[List[str]] = None, name: Optional[str] = None) -> None: """ Delete resources by type and name. The load balancer is never deleted. """ resources = resources or ["deployments", "services", "configmaps", "jobs"] not_lb_selector = "app.kubernetes.io/component!=loadbalancer" name_selector = [f"app.kubernetes.io/name={name}"] if name else [] utils.kubectl( "delete", *resource_selector(config, not_lb_selector, *name_selector), ",".join(resources), )
def start(context: K8sContext, names: List[str]) -> None: config = tutor_config.load(context.root) # Create namespace, if necessary # Note that this step should not be run for some users, in particular those # who do not have permission to edit the namespace. try: utils.kubectl("get", "namespaces", k8s_namespace(config)) fmt.echo_info("Namespace already exists: skipping creation.") except exceptions.TutorError: fmt.echo_info("Namespace does not exist: now creating it...") kubectl_apply( context.root, "--wait", "--selector", "app.kubernetes.io/component=namespace", ) names = names or ["all"] for name in names: if name == "all": # Create volumes kubectl_apply( context.root, "--wait", "--selector", "app.kubernetes.io/component=volume", ) # Create everything else except jobs kubectl_apply( context.root, "--selector", "app.kubernetes.io/component notin (job,volume,namespace)", ) else: kubectl_apply( context.root, "--selector", f"app.kubernetes.io/name={name}", )
def kubectl_exec(config: Config, service: str, command: List[str]) -> int: selector = f"app.kubernetes.io/name={service}" pods = K8sClients.instance().core_api.list_namespaced_pod( namespace=k8s_namespace(config), label_selector=selector) if not pods.items: raise exceptions.TutorError( f"Could not find an active pod for the {service} service") pod_name = pods.items[0].metadata.name # Run command return utils.kubectl( "exec", "--stdin", "--tty", "--namespace", k8s_namespace(config), pod_name, "--", *command, )
def status(context: K8sContext) -> int: config = tutor_config.load(context.root) return utils.kubectl("get", "all", *resource_namespace_selector(config))
def kubectl_apply(root: str, *args: str) -> None: utils.kubectl("apply", "--kustomize", tutor_env.pathjoin(root), *args)