its working!
This commit is contained in:
parent
0d913f7656
commit
2899ee23eb
10 changed files with 680 additions and 334 deletions
139
krayt/bundles.py
139
krayt/bundles.py
|
|
@ -10,78 +10,79 @@ basics = [
|
|||
"bash",
|
||||
"coreutils",
|
||||
]
|
||||
pretty = [
|
||||
*basics,
|
||||
"starship",
|
||||
"atuin",
|
||||
"bash",
|
||||
"zsh",
|
||||
"fish",
|
||||
"bat",
|
||||
"eza",
|
||||
]
|
||||
networking = [
|
||||
*basics,
|
||||
"mtr",
|
||||
"bind-tools",
|
||||
"aws-cli",
|
||||
"curl",
|
||||
"wget",
|
||||
"iperf3",
|
||||
"nmap",
|
||||
"traceroute",
|
||||
"netcat-openbsd",
|
||||
]
|
||||
bundles = {
|
||||
"basics": [
|
||||
*basics,
|
||||
],
|
||||
"pretty": [
|
||||
*basics,
|
||||
"starship",
|
||||
"atuin",
|
||||
"bash",
|
||||
"zsh",
|
||||
"fish",
|
||||
"bat",
|
||||
"eza",
|
||||
],
|
||||
"networking": [
|
||||
*basics,
|
||||
"mtr",
|
||||
"bind-tools",
|
||||
"aws-cli",
|
||||
"curl",
|
||||
"wget",
|
||||
"iperf3",
|
||||
"nmap",
|
||||
"traceroute",
|
||||
"netcat-openbsd",
|
||||
],
|
||||
"database": [
|
||||
*basics,
|
||||
"sqlite",
|
||||
"sqlite-dev",
|
||||
"sqlite-libs",
|
||||
"postgresql",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"redis",
|
||||
"mongodb",
|
||||
],
|
||||
"storage": [
|
||||
*basics,
|
||||
"ncdu",
|
||||
"dust",
|
||||
"file",
|
||||
"hexyl",
|
||||
"ripgrep",
|
||||
"fd",
|
||||
"fzf",
|
||||
"difftastic",
|
||||
],
|
||||
"search": [
|
||||
*basics,
|
||||
"ripgrep",
|
||||
"fd",
|
||||
"fzf",
|
||||
"difftastic",
|
||||
],
|
||||
"monitoring": [
|
||||
*basics,
|
||||
"htop",
|
||||
"bottom",
|
||||
"mtr",
|
||||
],
|
||||
}
|
||||
|
||||
database = [
|
||||
*basics,
|
||||
"sqlite",
|
||||
"sqlite-dev",
|
||||
"sqlite-libs",
|
||||
"postgresql",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"redis",
|
||||
"mongodb",
|
||||
]
|
||||
|
||||
storage = [
|
||||
*basics,
|
||||
"ncdu",
|
||||
"dust",
|
||||
"file",
|
||||
"hexyl",
|
||||
"ripgrep",
|
||||
"fd",
|
||||
"fzf",
|
||||
"difftastic",
|
||||
]
|
||||
|
||||
search = [
|
||||
*basics,
|
||||
"ripgrep",
|
||||
"fd",
|
||||
"fzf",
|
||||
"difftastic",
|
||||
]
|
||||
|
||||
monitoring = [
|
||||
*basics,
|
||||
"htop",
|
||||
"bottom",
|
||||
"mtr",
|
||||
]
|
||||
|
||||
all = list(
|
||||
bundles["all"] = list(
|
||||
set(
|
||||
[
|
||||
*basics,
|
||||
*pretty,
|
||||
*networking,
|
||||
*database,
|
||||
*storage,
|
||||
*search,
|
||||
*monitoring,
|
||||
*bundles["basics"],
|
||||
*bundles["pretty"],
|
||||
*bundles["networking"],
|
||||
*bundles["database"],
|
||||
*bundles["storage"],
|
||||
*bundles["search"],
|
||||
*bundles["monitoring"],
|
||||
]
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from krayt import __version__
|
||||
from krayt.cli.bundles import app as bundles_app
|
||||
from krayt.cli.pod import app as pod_app, create, exec, logs
|
||||
from krayt.cli.pod import app as pod_app, create, exec, logs, clean
|
||||
from krayt.cli.templates import app as templates_app
|
||||
from typer import Typer
|
||||
|
||||
|
|
@ -10,6 +10,7 @@ app.add_typer(templates_app, name="templates", no_args_is_help=True)
|
|||
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="clean")(clean)
|
||||
app.command(name="exec")(exec)
|
||||
app.command(name="logs")(logs)
|
||||
app.add_typer(bundles_app, name="bundles", no_args_is_help=True)
|
||||
|
|
|
|||
|
|
@ -296,31 +296,6 @@ def create_inspector_job(
|
|||
|
||||
template_name = "base.sh"
|
||||
template = env.get_template(template_name)
|
||||
additional_packages = [
|
||||
"ripgrep",
|
||||
"exa",
|
||||
"ncdu",
|
||||
"dust",
|
||||
"file",
|
||||
"hexyl",
|
||||
"jq",
|
||||
"yq",
|
||||
"bat",
|
||||
"fd",
|
||||
"fzf",
|
||||
"htop",
|
||||
"bottom",
|
||||
"difftastic",
|
||||
"mtr",
|
||||
"bind-tools",
|
||||
"aws-cli",
|
||||
"sqlite",
|
||||
"sqlite-dev",
|
||||
"sqlite-libs",
|
||||
"bash",
|
||||
"neovim",
|
||||
"starship",
|
||||
]
|
||||
pvcs = None
|
||||
pre_init_scripts = None
|
||||
post_init_scripts = None
|
||||
|
|
@ -631,8 +606,6 @@ def create(
|
|||
# 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)
|
||||
|
|
@ -656,9 +629,8 @@ def create(
|
|||
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)
|
||||
# typer.echo(f"Selected pod exists: {selected_pod in (p[0] for p in pods)}")
|
||||
# typer.echo(f"Selected pod: {selected_pod} ({selected_namespace})")
|
||||
|
||||
pod_spec = get_pod_spec(selected_pod, selected_namespace)
|
||||
volume_mounts, volumes = get_pod_volumes_and_mounts(pod_spec)
|
||||
|
|
@ -671,6 +643,11 @@ def create(
|
|||
volumes,
|
||||
image=image,
|
||||
imagepullsecret=imagepullsecret,
|
||||
additional_packages=additional_packages,
|
||||
pre_init_scripts=pre_init_scripts,
|
||||
post_init_scripts=post_init_scripts,
|
||||
pre_init_hooks=pre_init_hooks,
|
||||
post_init_hooks=post_init_hooks,
|
||||
)
|
||||
|
||||
# Output the job manifest
|
||||
|
|
|
|||
|
|
@ -2,18 +2,7 @@ from krayt.templates import env
|
|||
import typer
|
||||
from typing import List, Optional
|
||||
|
||||
# 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 = typer.Typer()
|
||||
|
||||
|
||||
@app.command()
|
||||
|
|
@ -103,6 +92,8 @@ def motd(
|
|||
template_name = "motd.sh"
|
||||
template = env.get_template(template_name)
|
||||
rendered = template.render(
|
||||
volumes=volumes, pvcs=pvcs, additional_packages=additional_packages
|
||||
volumes=volumes,
|
||||
pvcs=pvcs,
|
||||
additional_packages=additional_packages,
|
||||
)
|
||||
print(rendered)
|
||||
|
|
|
|||
152
krayt/package.py
152
krayt/package.py
|
|
@ -1,7 +1,7 @@
|
|||
from krayt.bundles import bundles
|
||||
from more_itertools import unique_everseen
|
||||
from pydantic import BaseModel, BeforeValidator, model_validator
|
||||
from typing import Annotated, List, Literal, Optional
|
||||
from typing_extensions import Self
|
||||
from pydantic import BaseModel, BeforeValidator
|
||||
from typing import Annotated, List, Literal, Optional, Union
|
||||
|
||||
|
||||
SUPPORTED_KINDS = {
|
||||
|
|
@ -16,6 +16,26 @@ SUPPORTED_KINDS = {
|
|||
"npm",
|
||||
"go",
|
||||
"gh",
|
||||
"group",
|
||||
"bundle",
|
||||
}
|
||||
|
||||
DEPENDENCIES = {
|
||||
"uv": [
|
||||
"curl",
|
||||
"curlsh:https://astral.sh/uv/install.sh",
|
||||
],
|
||||
"installer": [
|
||||
"curl",
|
||||
],
|
||||
"i": ["curl"],
|
||||
"curlbash": ["curl"],
|
||||
"curlsh": ["curl"],
|
||||
"cargo": ["cargo"],
|
||||
"pipx": ["pipx"],
|
||||
"npm": ["npm"],
|
||||
"go": ["go"],
|
||||
"gh": ["gh"],
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -34,22 +54,11 @@ class Package(BaseModel):
|
|||
"""
|
||||
|
||||
kind: Annotated[
|
||||
Literal[
|
||||
"system",
|
||||
"uv",
|
||||
"i",
|
||||
"curlsh",
|
||||
"curlbash",
|
||||
"cargo",
|
||||
"pipx",
|
||||
"npm",
|
||||
"go",
|
||||
"gh",
|
||||
],
|
||||
Literal[*SUPPORTED_KINDS],
|
||||
BeforeValidator(validate_kind),
|
||||
] = "system"
|
||||
value: str
|
||||
dependencies: Optional[List["Package"]] = None
|
||||
# dependencies: Optional[List["Package"]] = None
|
||||
pre_install_hook: Optional[str] = None
|
||||
post_install_hook: Optional[str] = None
|
||||
|
||||
|
|
@ -64,26 +73,29 @@ class Package(BaseModel):
|
|||
else:
|
||||
return cls(kind="system", value=raw.strip())
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_dependencies(self) -> Self:
|
||||
if self.dependencies:
|
||||
return self
|
||||
dependencies = []
|
||||
|
||||
if self.kind in ["uv", "i", "installer", "curlbash", "curlsh", "gh"]:
|
||||
dependencies.append(Package.from_raw("curl"))
|
||||
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
|
||||
|
||||
# @model_validator(mode="after")
|
||||
# def validate_dependencies(self) -> Self:
|
||||
# if self.dependencies:
|
||||
# return self
|
||||
# dependencies = []
|
||||
#
|
||||
# if self.kind in ["uv", "i", "installer", "curlbash", "curlsh", "gh"]:
|
||||
# dependencies.append(Package.from_raw("curl"))
|
||||
# dependencies.append(
|
||||
# Package.from_raw("curlsh:https://astral.sh/uv/install.sh")
|
||||
# )
|
||||
# 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:
|
||||
return self.kind == "system"
|
||||
|
||||
|
|
@ -92,12 +104,14 @@ class Package(BaseModel):
|
|||
Generate the bash install command snippet for this package.
|
||||
"""
|
||||
cmd = ""
|
||||
if self.kind == "system":
|
||||
if self.kind in ["bundle", "group"]:
|
||||
cmd = ""
|
||||
elif self.kind == "system":
|
||||
cmd = f"detect_package_manager_and_install {self.value}"
|
||||
elif self.kind == "uv":
|
||||
cmd = f"uv tool install {self.value}"
|
||||
elif self.kind in ["i", "installer", "gh"]:
|
||||
cmd = f"curl -fsSL https://i.jpillora.com/{self.value} | sh"
|
||||
cmd = f"installer {self.value}"
|
||||
elif self.kind == "curlsh":
|
||||
cmd = f"curl -fsSL {self.value} | sh"
|
||||
elif self.kind == "curlbash":
|
||||
|
|
@ -120,28 +134,58 @@ class Package(BaseModel):
|
|||
return cmd
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raw_inputs = [
|
||||
"curl",
|
||||
"wget",
|
||||
"uv:copier",
|
||||
"i:sharkdp/fd",
|
||||
"curlsh:https://example.com/install.sh",
|
||||
]
|
||||
|
||||
packages = [Package.from_raw(raw) for raw in raw_inputs]
|
||||
dependencies = []
|
||||
def get_install_script(packages: Union[str, List[str]]) -> str:
|
||||
if packages is None:
|
||||
return []
|
||||
if isinstance(packages, str):
|
||||
packages = [packages]
|
||||
bundled_packages = []
|
||||
for package in packages:
|
||||
if package.dependencies:
|
||||
dependencies.extend(
|
||||
[dependency.install_command() for dependency in package.dependencies]
|
||||
)
|
||||
if package.startswith("bundle:") or package.startswith("group:"):
|
||||
_package = package.split(":")[1].strip()
|
||||
bundled_packages.extend(bundles.get(_package, []))
|
||||
packages = list(unique_everseen([*bundled_packages, *packages]))
|
||||
|
||||
packages = [Package.from_raw(raw) for raw in packages]
|
||||
kinds_used = [package.kind for package in packages]
|
||||
dependencies = []
|
||||
for kind in kinds_used:
|
||||
dependencies.extend(DEPENDENCIES.get(kind, []))
|
||||
dependencies = list(
|
||||
unique_everseen(
|
||||
[Package.from_raw(raw).install_command() for raw in dependencies]
|
||||
)
|
||||
)
|
||||
# for package in packages:
|
||||
# if package.dependencies:
|
||||
# dependencies.extend(
|
||||
# [dependency.install_command() for dependency in package.dependencies]
|
||||
# )
|
||||
installs = [package.install_command() for package in packages]
|
||||
post_hooks = []
|
||||
for package in packages:
|
||||
if package.post_install_hook:
|
||||
post_hooks.append(package.post_install_hook.strip())
|
||||
pre_hooks = []
|
||||
for package in packages:
|
||||
if package.pre_install_hook:
|
||||
pre_hooks.append(package.pre_install_hook.strip())
|
||||
|
||||
# Final full script
|
||||
full_script = list(unique_everseen([*dependencies, *installs, *post_hooks]))
|
||||
full_script = list(
|
||||
unique_everseen([*pre_hooks, *dependencies, *installs, *post_hooks])
|
||||
)
|
||||
return "\n".join(full_script) if full_script else full_script
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raw_inputs = [
|
||||
"bundle:storage",
|
||||
"wget",
|
||||
"uv:copier",
|
||||
"i:sharkdp/fd",
|
||||
"curlsh:https://example.com/install.sh",
|
||||
]
|
||||
full_script = get_install_script(raw_inputs)
|
||||
|
||||
print("\n".join(full_script))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from jinja2 import Environment, FileSystemLoader
|
||||
from krayt.package import get_install_script
|
||||
from pathlib import Path
|
||||
|
||||
# Get the two template directories
|
||||
|
|
@ -9,3 +10,4 @@ template_dirs = [
|
|||
|
||||
# Create the Jinja environment
|
||||
env = Environment(loader=FileSystemLoader([str(path) for path in template_dirs]))
|
||||
env.globals["get_install_script"] = get_install_script
|
||||
|
|
|
|||
|
|
@ -1,65 +1,88 @@
|
|||
{% if additional_packages %}
|
||||
# Detect package manager
|
||||
if command -v apt >/dev/null 2>&1; then
|
||||
PKG_MANAGER="apt"
|
||||
UPDATE_CMD="apt update"
|
||||
INSTALL_CMD="apt install -y"
|
||||
elif command -v dnf >/dev/null 2>&1; then
|
||||
PKG_MANAGER="dnf"
|
||||
UPDATE_CMD=""
|
||||
INSTALL_CMD="dnf install -y"
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
PKG_MANAGER="yum"
|
||||
UPDATE_CMD=""
|
||||
INSTALL_CMD="yum install -y"
|
||||
elif command -v pacman >/dev/null 2>&1; then
|
||||
PKG_MANAGER="pacman"
|
||||
UPDATE_CMD=""
|
||||
INSTALL_CMD="pacman -Sy --noconfirm"
|
||||
elif command -v zypper >/dev/null 2>&1; then
|
||||
PKG_MANAGER="zypper"
|
||||
UPDATE_CMD=""
|
||||
INSTALL_CMD="zypper install -y"
|
||||
elif command -v apk >/dev/null 2>&1; then
|
||||
PKG_MANAGER="apk"
|
||||
UPDATE_CMD=""
|
||||
INSTALL_CMD="apk add"
|
||||
else
|
||||
echo "No supported package manager found."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "Using package manager: $PKG_MANAGER"
|
||||
|
||||
# Run update once if needed
|
||||
if [ -n "$UPDATE_CMD" ]; then
|
||||
echo "Running package manager update..."
|
||||
eval "$UPDATE_CMD"
|
||||
fi
|
||||
|
||||
detect_package_manager_and_install() {
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: detect_package_manager_and_install <package1> [package2] [...]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if command -v apt >/dev/null 2>&1; then
|
||||
PKG_MANAGER="apt"
|
||||
UPDATE_CMD="apt update &&"
|
||||
INSTALL_CMD="apt install -y"
|
||||
elif command -v dnf >/dev/null 2>&1; then
|
||||
PKG_MANAGER="dnf"
|
||||
UPDATE_CMD=""
|
||||
INSTALL_CMD="dnf install -y"
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
PKG_MANAGER="yum"
|
||||
UPDATE_CMD=""
|
||||
INSTALL_CMD="yum install -y"
|
||||
elif command -v pacman >/dev/null 2>&1; then
|
||||
PKG_MANAGER="pacman"
|
||||
UPDATE_CMD=""
|
||||
INSTALL_CMD="pacman -Sy --noconfirm"
|
||||
elif command -v zypper >/dev/null 2>&1; then
|
||||
PKG_MANAGER="zypper"
|
||||
UPDATE_CMD=""
|
||||
INSTALL_CMD="zypper install -y"
|
||||
elif command -v apk >/dev/null 2>&1; then
|
||||
PKG_MANAGER="apk"
|
||||
UPDATE_CMD=""
|
||||
INSTALL_CMD="apk add"
|
||||
else
|
||||
echo "No supported package manager found."
|
||||
return 2
|
||||
fi
|
||||
|
||||
echo "Using package manager: $PKG_MANAGER"
|
||||
|
||||
if [ -n "$UPDATE_CMD" ]; then
|
||||
echo "Running package manager update..."
|
||||
eval "$UPDATE_CMD"
|
||||
fi
|
||||
|
||||
FAILED_PKGS=()
|
||||
FAILED_PKGS=""
|
||||
|
||||
for pkg in "$@"; do
|
||||
echo "Installing package: $pkg"
|
||||
if ! eval "$INSTALL_CMD $pkg"; then
|
||||
if ! $INSTALL_CMD $pkg; then
|
||||
echo "⚠️ Warning: Failed to install package: $pkg"
|
||||
FAILED_PKGS+=("$pkg")
|
||||
FAILED_PKGS="$FAILED_PKGS $pkg"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#FAILED_PKGS[@]} -ne 0 ]; then
|
||||
{% raw %}
|
||||
if [ -n "$FAILED_PKGS" ]; then
|
||||
echo "⚠️ The following packages failed to install:"
|
||||
for failed_pkg in "${FAILED_PKGS[@]}"; do
|
||||
for failed_pkg in $FAILED_PKGS; do
|
||||
echo " - $failed_pkg"
|
||||
done
|
||||
else
|
||||
echo "✅ All requested packages installed successfully."
|
||||
fi
|
||||
{% endraw %}
|
||||
}
|
||||
|
||||
detect_package_manager_and_install {% for package in additional_packages %}{{ package | trim }}{% if not loop.last %} {% endif %}{% endfor %}
|
||||
installer() {
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: installer <package1> [package2] [...]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
for pkg in "$@"; do
|
||||
echo "Installing package with installer: $pkg"
|
||||
(
|
||||
orig_dir="$(pwd)"
|
||||
cd /usr/local/bin || exit 1
|
||||
curl -fsSL https://i.jpillora.com/${pkg} | sh
|
||||
cd "$orig_dir" || exit 1
|
||||
)
|
||||
done
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
{% if additional_packages %}
|
||||
{{ get_install_script(additional_packages) | safe }}
|
||||
{% endif %}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue