wip
This commit is contained in:
parent
9737746923
commit
378744632f
7 changed files with 208 additions and 173 deletions
|
|
@ -11,7 +11,7 @@ basics = [
|
||||||
"coreutils",
|
"coreutils",
|
||||||
]
|
]
|
||||||
pretty = [
|
pretty = [
|
||||||
*basics
|
*basics,
|
||||||
"starship",
|
"starship",
|
||||||
"atuin",
|
"atuin",
|
||||||
"bash",
|
"bash",
|
||||||
|
|
@ -21,7 +21,7 @@ pretty = [
|
||||||
"eza",
|
"eza",
|
||||||
]
|
]
|
||||||
networking = [
|
networking = [
|
||||||
*basics
|
*basics,
|
||||||
"mtr",
|
"mtr",
|
||||||
"bind-tools",
|
"bind-tools",
|
||||||
"aws-cli",
|
"aws-cli",
|
||||||
|
|
@ -34,7 +34,7 @@ networking = [
|
||||||
]
|
]
|
||||||
|
|
||||||
database = [
|
database = [
|
||||||
*basics
|
*basics,
|
||||||
"sqlite",
|
"sqlite",
|
||||||
"sqlite-dev",
|
"sqlite-dev",
|
||||||
"sqlite-libs",
|
"sqlite-libs",
|
||||||
|
|
@ -46,7 +46,7 @@ database = [
|
||||||
]
|
]
|
||||||
|
|
||||||
storage = [
|
storage = [
|
||||||
*basics
|
*basics,
|
||||||
"ncdu",
|
"ncdu",
|
||||||
"dust",
|
"dust",
|
||||||
"file",
|
"file",
|
||||||
|
|
@ -58,7 +58,7 @@ storage = [
|
||||||
]
|
]
|
||||||
|
|
||||||
search = [
|
search = [
|
||||||
*basics
|
*basics,
|
||||||
"ripgrep",
|
"ripgrep",
|
||||||
"fd",
|
"fd",
|
||||||
"fzf",
|
"fzf",
|
||||||
|
|
@ -66,7 +66,7 @@ search = [
|
||||||
]
|
]
|
||||||
|
|
||||||
monitoring = [
|
monitoring = [
|
||||||
*basics
|
*basics,
|
||||||
"htop",
|
"htop",
|
||||||
"bottom",
|
"bottom",
|
||||||
"mtr",
|
"mtr",
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
from krayt import __version__
|
from krayt import __version__
|
||||||
from krayt.cli.create import app as create_app
|
from krayt.cli.bundles import app as bundles_app
|
||||||
|
from krayt.cli.pod import app as pod_app, create, exec, logs
|
||||||
from krayt.cli.templates import app as templates_app
|
from krayt.cli.templates import app as templates_app
|
||||||
from typer import Typer
|
from typer import Typer
|
||||||
|
|
||||||
app = Typer()
|
app = Typer()
|
||||||
|
|
||||||
app.add_typer(templates_app, name="templates")
|
app.add_typer(templates_app, name="templates", no_args_is_help=True)
|
||||||
app.add_typer(create_app, name="create")
|
app.add_typer(pod_app, name="pod", no_args_is_help=True)
|
||||||
|
app.command(name="create")(create)
|
||||||
|
app.command(name="c")(create)
|
||||||
|
app.command(name="exec")(exec)
|
||||||
|
app.command(name="logs")(logs)
|
||||||
|
app.add_typer(bundles_app, name="bundles", no_args_is_help=True)
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
|
|
|
||||||
25
krayt/cli/bundles.py
Normal file
25
krayt/cli/bundles.py
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
from krayt import bundles
|
||||||
|
import typer
|
||||||
|
|
||||||
|
app = typer.Typer()
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def list(
|
||||||
|
verbose: bool = typer.Option(
|
||||||
|
False,
|
||||||
|
"--verbose",
|
||||||
|
"-v",
|
||||||
|
help="Verbose output",
|
||||||
|
),
|
||||||
|
):
|
||||||
|
"""List available bundles"""
|
||||||
|
typer.echo("Available bundles:")
|
||||||
|
# get all variables from bundles
|
||||||
|
for bundle in bundles.__dict__.keys():
|
||||||
|
if bundle.startswith("__"):
|
||||||
|
continue
|
||||||
|
typer.echo(bundle)
|
||||||
|
if verbose:
|
||||||
|
for package in bundles.__dict__[bundle]:
|
||||||
|
typer.echo(f" - {package}")
|
||||||
|
|
@ -1,16 +1,13 @@
|
||||||
from iterfzf import iterfzf
|
import iterfzf
|
||||||
from krayt.templates import env
|
from krayt.templates import env
|
||||||
from kubernetes import client, config
|
from kubernetes import client, config
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
|
||||||
import time
|
import time
|
||||||
import typer
|
import typer
|
||||||
from typing import Any, List, Optional
|
from typing import Any, List, Optional
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
KRAYT_VERSION = "NIGHTLY"
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.WARNING)
|
logging.basicConfig(level=logging.WARNING)
|
||||||
|
|
||||||
app = typer.Typer()
|
app = typer.Typer()
|
||||||
|
|
@ -92,7 +89,15 @@ def fuzzy_select(items):
|
||||||
|
|
||||||
# Use fzf for selection
|
# Use fzf for selection
|
||||||
try:
|
try:
|
||||||
selected = iterfzf(formatted_items)
|
# selected = inquirer.fuzzy(
|
||||||
|
# message="Select a pod to clone:", choices=formatted_items
|
||||||
|
# ).execute()
|
||||||
|
|
||||||
|
selected = iterfzf.iterfzf(
|
||||||
|
formatted_items,
|
||||||
|
prompt="Select a pod to clone:",
|
||||||
|
preview='''kubectl describe pod "$(echo {} | awk -F'[(|)]' '{gsub(/\x1b\[[0-9;]*m/, "", $1); print $1}' | xargs)" -n "$(echo {} | awk -F'[(|)]' '{gsub(/\x1b\[[0-9;]*m/, "", $2); print $2}' | xargs)"''',
|
||||||
|
)
|
||||||
if not selected:
|
if not selected:
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
|
|
@ -239,83 +244,6 @@ def get_env_vars_and_secret_volumes(api, namespace: str):
|
||||||
return env_vars, volumes
|
return env_vars, volumes
|
||||||
|
|
||||||
|
|
||||||
def get_init_scripts():
|
|
||||||
"""Get the contents of init scripts to be run in the pod"""
|
|
||||||
init_dir = Path.home() / ".config" / "krayt" / "init.d"
|
|
||||||
if not init_dir.exists():
|
|
||||||
logging.debug("No init.d directory found at %s", init_dir)
|
|
||||||
return ""
|
|
||||||
|
|
||||||
scripts = sorted(init_dir.glob("*.sh"))
|
|
||||||
if not scripts:
|
|
||||||
logging.debug("No init scripts found in %s", init_dir)
|
|
||||||
return ""
|
|
||||||
|
|
||||||
# Create a combined script that will run all init scripts
|
|
||||||
init_script = "#!/bin/bash\n\n"
|
|
||||||
init_script += "exec 2>&1 # Redirect stderr to stdout for proper logging\n"
|
|
||||||
init_script += "set -e # Exit on error\n\n"
|
|
||||||
init_script += "echo 'Running initialization scripts...' | tee /tmp/init.log\n\n"
|
|
||||||
init_script += "mkdir -p /tmp/init.d\n\n" # Create directory once at the start
|
|
||||||
|
|
||||||
for script in scripts:
|
|
||||||
try:
|
|
||||||
with open(script, "r") as f:
|
|
||||||
script_content = f.read()
|
|
||||||
if not script_content.strip():
|
|
||||||
logging.debug("Skipping empty script %s", script)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Use a unique heredoc delimiter for each script to avoid nesting issues
|
|
||||||
delimiter = f"EOF_SCRIPT_{script.stem.upper()}"
|
|
||||||
|
|
||||||
init_script += (
|
|
||||||
f"echo '=== Running {script.name} ===' | tee -a /tmp/init.log\n"
|
|
||||||
)
|
|
||||||
init_script += f"cat > /tmp/init.d/{script.name} << '{delimiter}'\n"
|
|
||||||
init_script += script_content
|
|
||||||
if not script_content.endswith("\n"):
|
|
||||||
init_script += "\n"
|
|
||||||
init_script += f"{delimiter}\n"
|
|
||||||
init_script += f"chmod +x /tmp/init.d/{script.name}\n"
|
|
||||||
init_script += f'cd /tmp/init.d && ./{script.name} 2>&1 | tee -a /tmp/init.log || {{ echo "Failed to run {script.name}"; exit 1; }}\n'
|
|
||||||
init_script += (
|
|
||||||
f"echo '=== Finished {script.name} ===' | tee -a /tmp/init.log\n\n"
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(f"Failed to load init script {script}: {e}")
|
|
||||||
|
|
||||||
init_script += "echo 'Initialization scripts complete.' | tee -a /tmp/init.log\n"
|
|
||||||
return init_script
|
|
||||||
|
|
||||||
|
|
||||||
def get_motd_script(mount_info, pvc_info):
|
|
||||||
"""Generate the MOTD script with proper escaping"""
|
|
||||||
return f"""
|
|
||||||
# Create MOTD
|
|
||||||
cat << EOF > /etc/motd
|
|
||||||
====================================
|
|
||||||
Krayt Dragon's Lair
|
|
||||||
A safe haven for volume inspection
|
|
||||||
====================================
|
|
||||||
|
|
||||||
"Inside every volume lies a pearl of wisdom waiting to be discovered."
|
|
||||||
|
|
||||||
Mounted Volumes:
|
|
||||||
$(echo "{",".join(mount_info)}" | tr ',' '\\n' | sed 's/^/- /')
|
|
||||||
|
|
||||||
Persistent Volume Claims:
|
|
||||||
$(echo "{",".join(pvc_info)}" | tr ',' '\\n' | sed 's/^/- /')
|
|
||||||
|
|
||||||
Mounted Secrets:
|
|
||||||
$(for d in /mnt/secrets/*; do if [ -d "$d" ]; then echo "- $(basename $d)"; fi; done)
|
|
||||||
|
|
||||||
Init Script Status:
|
|
||||||
$(if [ -f /tmp/init.log ]; then echo "View initialization log at /tmp/init.log"; fi)
|
|
||||||
EOF
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def create_inspector_job(
|
def create_inspector_job(
|
||||||
api,
|
api,
|
||||||
namespace: str,
|
namespace: str,
|
||||||
|
|
@ -418,6 +346,7 @@ def create_inspector_job(
|
||||||
"annotations": {"pvcs": ",".join(pvc_info) if pvc_info else "none"},
|
"annotations": {"pvcs": ",".join(pvc_info) if pvc_info else "none"},
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
|
"ttlSecondsAfterFinished": 600,
|
||||||
"template": {
|
"template": {
|
||||||
"metadata": {"labels": {"app": "krayt"}},
|
"metadata": {"labels": {"app": "krayt"}},
|
||||||
"spec": {
|
"spec": {
|
||||||
|
|
@ -459,24 +388,6 @@ PROTECTED_NAMESPACES = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def load_init_scripts():
|
|
||||||
"""Load and execute initialization scripts from ~/.config/krayt/scripts/"""
|
|
||||||
init_dir = Path.home() / ".config" / "krayt" / "scripts"
|
|
||||||
if not init_dir.exists():
|
|
||||||
return
|
|
||||||
|
|
||||||
# Sort scripts to ensure consistent execution order
|
|
||||||
scripts = sorted(init_dir.glob("*.py"))
|
|
||||||
|
|
||||||
for script in scripts:
|
|
||||||
try:
|
|
||||||
with open(script, "r") as f:
|
|
||||||
exec(f.read(), globals())
|
|
||||||
logging.debug(f"Loaded init script: {script}")
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(f"Failed to load init script {script}: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
def setup_environment():
|
def setup_environment():
|
||||||
"""Set up the environment with proxy settings and other configurations"""
|
"""Set up the environment with proxy settings and other configurations"""
|
||||||
# Load environment variables for proxies
|
# Load environment variables for proxies
|
||||||
|
|
@ -657,8 +568,16 @@ def clean(
|
||||||
def create(
|
def create(
|
||||||
namespace: Optional[str] = typer.Option(
|
namespace: Optional[str] = typer.Option(
|
||||||
None,
|
None,
|
||||||
|
"--namespace",
|
||||||
|
"-n",
|
||||||
help="Kubernetes namespace. If not specified, will search for pods across all namespaces.",
|
help="Kubernetes namespace. If not specified, will search for pods across all namespaces.",
|
||||||
),
|
),
|
||||||
|
clone: Optional[str] = typer.Option(
|
||||||
|
None,
|
||||||
|
"--clone",
|
||||||
|
"-c",
|
||||||
|
help="Clone an existing pod",
|
||||||
|
),
|
||||||
image: str = typer.Option(
|
image: str = typer.Option(
|
||||||
"alpine:latest",
|
"alpine:latest",
|
||||||
"--image",
|
"--image",
|
||||||
|
|
@ -670,6 +589,39 @@ def create(
|
||||||
"--imagepullsecret",
|
"--imagepullsecret",
|
||||||
help="Name of the image pull secret to use for pulling private images",
|
help="Name of the image pull secret to use for pulling private images",
|
||||||
),
|
),
|
||||||
|
additional_packages: Optional[List[str]] = typer.Option(
|
||||||
|
None,
|
||||||
|
"--additional-packages",
|
||||||
|
"-ap",
|
||||||
|
help="additional packages to install in the inspector pod",
|
||||||
|
),
|
||||||
|
additional_package_bundles: Optional[List[str]] = typer.Option(
|
||||||
|
None,
|
||||||
|
"--additional-package-bundles",
|
||||||
|
"-ab",
|
||||||
|
help="additional packages to install in the inspector pod",
|
||||||
|
),
|
||||||
|
pre_init_scripts: Optional[List[str]] = typer.Option(
|
||||||
|
None,
|
||||||
|
"--pre-init-scripts",
|
||||||
|
help="additional scripts to execute at the end of container initialization",
|
||||||
|
),
|
||||||
|
post_init_scripts: Optional[List[str]] = typer.Option(
|
||||||
|
None,
|
||||||
|
"--post-init-scripts",
|
||||||
|
"--init-scripts",
|
||||||
|
help="additional scripts to execute at the start of container initialization",
|
||||||
|
),
|
||||||
|
pre_init_hooks: Optional[List[str]] = typer.Option(
|
||||||
|
None,
|
||||||
|
"--pre-init-hooks",
|
||||||
|
help="additional hooks to execute at the end of container initialization",
|
||||||
|
),
|
||||||
|
post_init_hooks: Optional[List[str]] = typer.Option(
|
||||||
|
None,
|
||||||
|
"--post-init-hooks",
|
||||||
|
help="additional hooks to execute at the start of container initialization",
|
||||||
|
),
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Krack open a Krayt dragon! Create an inspector pod to explore what's inside your volumes.
|
Krack open a Krayt dragon! Create an inspector pod to explore what's inside your volumes.
|
||||||
|
|
@ -677,15 +629,36 @@ def create(
|
||||||
The inspector will be created in the same namespace as the selected pod.
|
The inspector will be created in the same namespace as the selected pod.
|
||||||
"""
|
"""
|
||||||
# For create, we want to list all pods, not just Krayt pods
|
# For create, we want to list all pods, not just Krayt pods
|
||||||
|
selected_namespace = None
|
||||||
|
selected_pod = None
|
||||||
|
typer.echo(namespace)
|
||||||
|
typer.echo(clone)
|
||||||
|
|
||||||
|
if namespace is None and clone is not None and "/" in clone:
|
||||||
|
selected_namespace, selected_pod = clone.split("/", 1)
|
||||||
|
elif namespace is not None and clone is not None:
|
||||||
|
selected_namespace = namespace
|
||||||
|
selected_pod = clone
|
||||||
|
|
||||||
pods = get_pods(namespace, label_selector=None)
|
pods = get_pods(namespace, label_selector=None)
|
||||||
if not pods:
|
if not pods:
|
||||||
typer.echo("No pods found.")
|
typer.echo("No pods found.")
|
||||||
raise typer.Exit(1)
|
raise typer.Exit(1)
|
||||||
|
|
||||||
selected_pod, selected_namespace = fuzzy_select(pods)
|
if selected_pod not in (p[0] for p in pods) or selected_pod is None:
|
||||||
if not selected_pod:
|
if selected_pod is not None:
|
||||||
typer.echo("No pod selected.")
|
pods = [p for p in pods if selected_pod in p[0]]
|
||||||
raise typer.Exit(1)
|
if len(pods) == 1:
|
||||||
|
selected_pod, selected_namespace = pods[0]
|
||||||
|
else:
|
||||||
|
selected_pod, selected_namespace = fuzzy_select(pods)
|
||||||
|
if not selected_pod:
|
||||||
|
typer.echo("No pod selected.")
|
||||||
|
raise typer.Exit(1)
|
||||||
|
|
||||||
|
typer.echo(f"Selected pod exists: {selected_pod in (p[0] for p in pods)}")
|
||||||
|
typer.echo(f"Selected pod: {selected_pod} ({selected_namespace})")
|
||||||
|
raise typer.Exit(1)
|
||||||
|
|
||||||
pod_spec = get_pod_spec(selected_pod, selected_namespace)
|
pod_spec = get_pod_spec(selected_pod, selected_namespace)
|
||||||
volume_mounts, volumes = get_pod_volumes_and_mounts(pod_spec)
|
volume_mounts, volumes = get_pod_volumes_and_mounts(pod_spec)
|
||||||
|
|
@ -758,9 +731,19 @@ def logs(
|
||||||
raise typer.Exit(1)
|
raise typer.Exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
@app.command("list")
|
||||||
|
def list_pods():
|
||||||
|
pods = get_pods()
|
||||||
|
if not pods:
|
||||||
|
typer.echo("No pods found.")
|
||||||
|
raise typer.Exit(1)
|
||||||
|
|
||||||
|
for pod, namespace in pods:
|
||||||
|
typer.echo(f"{pod} ({namespace})")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
setup_environment()
|
setup_environment()
|
||||||
load_init_scripts()
|
|
||||||
app()
|
app()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2,7 +2,25 @@ from krayt.templates import env
|
||||||
import typer
|
import typer
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
app = typer.Typer()
|
# app = typer.Typer()
|
||||||
|
app = typer.Typer(
|
||||||
|
context_settings={
|
||||||
|
"auto_envvar_prefix": "KRAYT",
|
||||||
|
"help_option_names": ["-h", "--help"],
|
||||||
|
"show_default": True,
|
||||||
|
"allow_interspersed_args": True,
|
||||||
|
"ignore_unknown_options": False,
|
||||||
|
"max_content_width": None,
|
||||||
|
"suggest_command": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def list():
|
||||||
|
typer.echo("Available templates:")
|
||||||
|
for template in env.list_templates():
|
||||||
|
typer.echo(template)
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
|
|
|
||||||
116
krayt/package.py
116
krayt/package.py
|
|
@ -40,6 +40,7 @@ class Package(BaseModel):
|
||||||
"uv",
|
"uv",
|
||||||
"i",
|
"i",
|
||||||
"curlsh",
|
"curlsh",
|
||||||
|
"curlbash",
|
||||||
"brew",
|
"brew",
|
||||||
"cargo",
|
"cargo",
|
||||||
"pipx",
|
"pipx",
|
||||||
|
|
@ -49,8 +50,10 @@ class Package(BaseModel):
|
||||||
],
|
],
|
||||||
BeforeValidator(validate_kind),
|
BeforeValidator(validate_kind),
|
||||||
] = "system"
|
] = "system"
|
||||||
dependencies: Optional[List[str]] = None
|
|
||||||
value: str
|
value: str
|
||||||
|
dependencies: Optional[List["Package"]] = None
|
||||||
|
pre_install_hook: Optional[str] = None
|
||||||
|
post_install_hook: Optional[str] = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_raw(cls, raw: str) -> "Package":
|
def from_raw(cls, raw: str) -> "Package":
|
||||||
|
|
@ -67,52 +70,37 @@ class Package(BaseModel):
|
||||||
def validate_dependencies(self) -> Self:
|
def validate_dependencies(self) -> Self:
|
||||||
if self.dependencies:
|
if self.dependencies:
|
||||||
return self
|
return self
|
||||||
else:
|
dependencies = []
|
||||||
if self.kind == "system":
|
|
||||||
return self
|
|
||||||
dependencies = []
|
|
||||||
if self.kind in ["uv", "i", "installer", "curlbash", "curlsh", "gh"]:
|
|
||||||
dependencies.extend(
|
|
||||||
[
|
|
||||||
Package.from_raw("curl"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
if self.kind == "brew":
|
|
||||||
dependencies.extend(
|
|
||||||
[
|
|
||||||
Package.from_raw("brew"),
|
|
||||||
Package.from_raw("git"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
if self.kind == "cargo":
|
|
||||||
dependencies.extend(
|
|
||||||
[
|
|
||||||
Package.from_raw("cargo"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
if self.kind == "pipx":
|
|
||||||
dependencies.extend(
|
|
||||||
[
|
|
||||||
Package.from_raw("pipx"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
if self.kind == "npm":
|
|
||||||
dependencies.extend(
|
|
||||||
[
|
|
||||||
Package.from_raw("npm"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
if self.kind == "go":
|
|
||||||
dependencies.extend(
|
|
||||||
[
|
|
||||||
Package.from_raw("go"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
self.dependencies = dependencies
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __str__(self):
|
if self.kind in ["uv", "i", "installer", "curlbash", "curlsh", "gh"]:
|
||||||
return f"{self.kind}:{self.value}" if self.kind != "system" else self.value
|
dependencies.append(Package.from_raw("curl"))
|
||||||
|
if self.kind == "brew":
|
||||||
|
dependencies.append(Package.from_raw("git"))
|
||||||
|
dependencies.append(Package.from_raw("curl"))
|
||||||
|
self.pre_install_hook = "NONINTERACTIVE=1"
|
||||||
|
self.post_install_hook = """
|
||||||
|
# Setup Homebrew PATH
|
||||||
|
if [ -f /home/linuxbrew/.linuxbrew/bin/brew ]; then
|
||||||
|
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
|
||||||
|
elif [ -f /opt/homebrew/bin/brew ]; then
|
||||||
|
eval "$(/opt/homebrew/.linuxbrew/bin/brew shellenv)"
|
||||||
|
elif [ -f /usr/local/bin/brew ]; then
|
||||||
|
eval "$(/usr/local/bin/brew shellenv)"
|
||||||
|
else
|
||||||
|
echo "⚠️ Brew installed but binary location unknown."
|
||||||
|
fi
|
||||||
|
"""
|
||||||
|
if self.kind == "cargo":
|
||||||
|
dependencies.append(Package.from_raw("cargo"))
|
||||||
|
if self.kind == "pipx":
|
||||||
|
dependencies.append(Package.from_raw("pipx"))
|
||||||
|
if self.kind == "npm":
|
||||||
|
dependencies.append(Package.from_raw("npm"))
|
||||||
|
if self.kind == "go":
|
||||||
|
dependencies.append(Package.from_raw("go"))
|
||||||
|
|
||||||
|
self.dependencies = dependencies
|
||||||
|
return self
|
||||||
|
|
||||||
def is_system(self) -> bool:
|
def is_system(self) -> bool:
|
||||||
return self.kind == "system"
|
return self.kind == "system"
|
||||||
|
|
@ -121,29 +109,36 @@ class Package(BaseModel):
|
||||||
"""
|
"""
|
||||||
Generate the bash install command snippet for this package.
|
Generate the bash install command snippet for this package.
|
||||||
"""
|
"""
|
||||||
|
cmd = ""
|
||||||
if self.kind == "system":
|
if self.kind == "system":
|
||||||
return f"detect_package_manager_and_install {self.value}"
|
cmd = f"detect_package_manager_and_install {self.value}"
|
||||||
elif self.kind == "uv":
|
elif self.kind == "uv":
|
||||||
return f"uv tool install {self.value}"
|
cmd = f"uv tool install {self.value}"
|
||||||
elif self.kind in ["i", "installer", "gh"]:
|
elif self.kind in ["i", "installer", "gh"]:
|
||||||
return f"curl -fsSL https://i.jpillora.com/{self.value} | sh"
|
cmd = f"curl -fsSL https://i.jpillora.com/{self.value} | sh"
|
||||||
elif self.kind == "curlsh":
|
elif self.kind == "curlsh":
|
||||||
return f"curl -fsSL {self.value} | sh"
|
cmd = f"curl -fsSL {self.value} | sh"
|
||||||
elif self.kind == "curlbash":
|
elif self.kind == "curlbash":
|
||||||
return f"curl -fsSL {self.value} | bash"
|
cmd = f"curl -fsSL {self.value} | bash"
|
||||||
elif self.kind == "brew":
|
elif self.kind == "brew":
|
||||||
return f"brew install {self.value}"
|
cmd = "curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | bash"
|
||||||
elif self.kind == "cargo":
|
elif self.kind == "cargo":
|
||||||
return f"cargo install {self.value}"
|
cmd = f"cargo install {self.value}"
|
||||||
elif self.kind == "pipx":
|
elif self.kind == "pipx":
|
||||||
return f"pipx install {self.value}"
|
cmd = f"pipx install {self.value}"
|
||||||
elif self.kind == "npm":
|
elif self.kind == "npm":
|
||||||
return f"npm install -g {self.value}"
|
cmd = f"npm install -g {self.value}"
|
||||||
elif self.kind == "go":
|
elif self.kind == "go":
|
||||||
return f"go install {self.value}@latest"
|
cmd = f"go install {self.value}@latest"
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unknown install method for kind={self.kind}")
|
raise ValueError(f"Unknown install method for kind={self.kind}")
|
||||||
|
|
||||||
|
# Add pre-install hook if necessary
|
||||||
|
if self.pre_install_hook:
|
||||||
|
return f"{self.pre_install_hook} {cmd}"
|
||||||
|
else:
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
raw_inputs = [
|
raw_inputs = [
|
||||||
|
|
@ -163,4 +158,11 @@ if __name__ == "__main__":
|
||||||
[dependency.install_command() for dependency in package.dependencies]
|
[dependency.install_command() for dependency in package.dependencies]
|
||||||
)
|
)
|
||||||
installs = [package.install_command() for package in packages]
|
installs = [package.install_command() for package in packages]
|
||||||
print("\n".join(install for install in unique_everseen([*dependencies, *installs])))
|
post_hooks = []
|
||||||
|
for package in packages:
|
||||||
|
if package.post_install_hook:
|
||||||
|
post_hooks.append(package.post_install_hook.strip())
|
||||||
|
|
||||||
|
# Final full script
|
||||||
|
full_script = list(unique_everseen([*dependencies, *installs, *post_hooks]))
|
||||||
|
print("\n".join(full_script))
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ classifiers = [
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"typer",
|
"typer",
|
||||||
"kubernetes",
|
"kubernetes",
|
||||||
"InquirerPy",
|
"inquirerPy",
|
||||||
|
"inquirer",
|
||||||
"jinja2",
|
"jinja2",
|
||||||
"iterfzf",
|
"iterfzf",
|
||||||
"pydantic",
|
"pydantic",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue