diff --git a/abst/__version__.py b/abst/__version__.py index d86cca4..d9180eb 100644 --- a/abst/__version__.py +++ b/abst/__version__.py @@ -10,7 +10,7 @@ "CLI Command making OCI Bastion and kubernetes usage simple and fast" ) -__version__ = "2.3.3" +__version__ = "2.3.4" __author__ = "Jiri Otoupal" __author_email__ = "jiri-otoupal@ips-database.eu" __license__ = "MIT" diff --git a/abst/cli_commands/cp_cli/commands.py b/abst/cli_commands/cp_cli/commands.py index 2abb462..a9f3b9e 100644 --- a/abst/cli_commands/cp_cli/commands.py +++ b/abst/cli_commands/cp_cli/commands.py @@ -1,9 +1,13 @@ +import logging import os +import re +from subprocess import call import click import rich +from InquirerPy import inquirer -from abst.utils.misc_funcs import setup_calls +from abst.utils.misc_funcs import setup_calls, fetch_pods @click.group("cp", help="Copy commands for special usage") @@ -33,10 +37,68 @@ def cp_secret( setup_calls(debug) try: rich.print("Trying Copy secret") + kubectl_copy_secret_cmd = f"kubectl get secret {secret_name} --namespace={source_namespace} -o yaml | sed " \ + f"'s/namespace: .*/namespace: {target_namespace}/' | kubectl apply -f -" + logging.info(f"Executing {kubectl_copy_secret_cmd}") + os.system( - f"kubectl get secret {secret_name} --namespace={source_namespace} -o yaml | sed " - f"'s/namespace: .*/namespace: {target_namespace}/' | kubectl apply -f -" + kubectl_copy_secret_cmd ) except FileNotFoundError: rich.print("[red]kubectl not found on this machine[/red]") return + + +@cp.command("file", help="Will copy file into pod with containing string name") +@click.argument("pod_name") +@click.argument("local_path") +@click.argument("dest_path") +@click.option("--debug", is_flag=True, default=False) +def cp_to_pod(pod_name, local_path, dest_path, debug): + setup_calls(debug) + + try: + pod_lines = fetch_pods() + except FileNotFoundError: + rich.print("[red]kubectl not found on this machine[/red]") + return + + found = list(filter(lambda pod_line: pod_name in pod_line, pod_lines)) + + if len(found) > 1: + data = re.sub( + " +", + " ", + inquirer.select("Found more pods, choose one:", list(found)).execute(), + ).split(" ") + pod_name_precise = data[1] + elif len(found) == 1: + tmp = found.pop() + data = re.sub(" +", " ", tmp).split(" ") + pod_name_precise = data[1] + else: + rich.print(f"[red]No pods with name {pod_name} found[/red]") + return + + rich.print( + f"[green]Copying file {local_path} to {pod_name_precise}:{dest_path} in namespace: {data[0]}[/green]" + ) + kubectl_copy_cmd = f"kubectl cp {local_path} {data[0]}/{pod_name_precise}:{dest_path}" + logging.info(f"Executing {kubectl_copy_cmd}") + + exit_code = call( + kubectl_copy_cmd.split(" ") + ) + + if exit_code == 255: + rich.print("[red]Failed to copy using conventional kubectl cp, probably missing [yellow]tar[/yellow] " + "executable[/red]") + rich.print("[yellow]Trying alternative copy method...[/yellow]") + kubectl_alt_copy_cmd = (f"cat {local_path} |" + f" kubectl exec -i {pod_name_precise} -n {data[0]} -- tee {dest_path} > /dev/null") + logging.info(f"Executing {kubectl_alt_copy_cmd}") + exit_code = os.system(kubectl_alt_copy_cmd) + if exit_code == 0: + rich.print("[green]File successfully copied![/green]") + else: + rich.print("[red]Failed.[/red]") diff --git a/abst/cli_commands/kubectl_cli/commands.py b/abst/cli_commands/kubectl_cli/commands.py index 4f03861..79fca3f 100644 --- a/abst/cli_commands/kubectl_cli/commands.py +++ b/abst/cli_commands/kubectl_cli/commands.py @@ -1,3 +1,4 @@ +import logging import os import re import subprocess @@ -6,7 +7,7 @@ import rich from InquirerPy import inquirer -from abst.utils.misc_funcs import setup_calls +from abst.utils.misc_funcs import setup_calls, fetch_pods @click.command("ssh", help="Will SSH into pod with containing string name") @@ -16,12 +17,7 @@ def ssh_pod(pod_name, debug): setup_calls(debug) try: - rich.print("Fetching pods") - pod_lines = ( - subprocess.check_output(f"kubectl get pods -A".split(" ")) - .decode() - .split("\n") - ) + pod_lines = fetch_pods() except FileNotFoundError: rich.print("[red]kubectl not found on this machine[/red]") return @@ -46,8 +42,10 @@ def ssh_pod(pod_name, debug): rich.print( f"[green]Connecting to {pod_name_precise} in namespace: {data[0]}[/green]" ) + kubectl_ssh_cmd = f"kubectl exec -n {data[0]} --stdin --tty {pod_name_precise} -- /bin/bash" + logging.info(f"Executing {kubectl_ssh_cmd}") os.system( - f"kubectl exec -n {data[0]} --stdin --tty {pod_name_precise} -- /bin/bash" + kubectl_ssh_cmd ) @@ -88,6 +86,8 @@ def log_pod(pod_name, debug): rich.print( f"[green]Getting logs from {pod_name_precise} in namespace: {data[0]}[/green]" ) + kubectl_log_cmd = f"kubectl -n {data[0]} logs {pod_name_precise}" + logging.info(f"Executing {kubectl_log_cmd}") os.system( - f"kubectl -n {data[0]} logs {pod_name_precise}" + kubectl_log_cmd ) diff --git a/abst/utils/misc_funcs.py b/abst/utils/misc_funcs.py index d4ee565..8d566d7 100644 --- a/abst/utils/misc_funcs.py +++ b/abst/utils/misc_funcs.py @@ -1,5 +1,6 @@ import json import logging +import subprocess from pathlib import Path from typing import Optional @@ -52,3 +53,13 @@ def get_context_data(name) -> Optional[dict]: else: rich.print("[red]Context does not exists[/red]") return None + + +def fetch_pods(): + rich.print("Fetching pods") + pod_lines = ( + subprocess.check_output(f"kubectl get pods -A".split(" ")) + .decode() + .split("\n") + ) + return pod_lines