more package support
This commit is contained in:
parent
a60562b7fc
commit
9737746923
5 changed files with 283 additions and 11 deletions
87
krayt/bundles.py
Normal file
87
krayt/bundles.py
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
"""
|
||||
Bundles of packages available in most package managers.
|
||||
"""
|
||||
|
||||
basics = [
|
||||
"curl",
|
||||
"wget",
|
||||
"jq",
|
||||
"yq",
|
||||
"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",
|
||||
]
|
||||
|
||||
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(
|
||||
set(
|
||||
[
|
||||
*basics,
|
||||
*pretty,
|
||||
*networking,
|
||||
*database,
|
||||
*storage,
|
||||
*search,
|
||||
*monitoring,
|
||||
]
|
||||
)
|
||||
)
|
||||
|
|
@ -6,7 +6,7 @@ import os
|
|||
from pathlib import Path
|
||||
import time
|
||||
import typer
|
||||
from typing import Any, Optional
|
||||
from typing import Any, List, Optional
|
||||
import yaml
|
||||
|
||||
KRAYT_VERSION = "NIGHTLY"
|
||||
|
|
@ -324,6 +324,11 @@ def create_inspector_job(
|
|||
volumes: list,
|
||||
image: str = "alpine:latest",
|
||||
imagepullsecret: Optional[str] = None,
|
||||
additional_packages: Optional[List[str]] = None,
|
||||
pre_init_scripts: Optional[List[str]] = None,
|
||||
post_init_scripts: Optional[List[str]] = None,
|
||||
pre_init_hooks: Optional[List[str]] = None,
|
||||
post_init_hooks: Optional[List[str]] = None,
|
||||
):
|
||||
"""Create a Krayt inspector job with the given mounts"""
|
||||
timestamp = int(time.time())
|
||||
|
|
|
|||
166
krayt/package.py
Normal file
166
krayt/package.py
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
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
|
||||
|
||||
|
||||
SUPPORTED_KINDS = {
|
||||
"system",
|
||||
"uv",
|
||||
"installer",
|
||||
"i",
|
||||
"curlbash",
|
||||
"curlsh",
|
||||
"brew",
|
||||
"cargo",
|
||||
"pipx",
|
||||
"npm",
|
||||
"go",
|
||||
"gh",
|
||||
}
|
||||
|
||||
|
||||
def validate_kind(v):
|
||||
if v not in SUPPORTED_KINDS:
|
||||
raise ValueError(
|
||||
f"Unknown installer kind: {v}\n Supported kinds: {SUPPORTED_KINDS}\n "
|
||||
)
|
||||
return v
|
||||
|
||||
|
||||
class Package(BaseModel):
|
||||
"""
|
||||
Represents a package to be installed, either via system package manager
|
||||
or an alternative installer like uv, installer.sh, brew, etc.
|
||||
"""
|
||||
|
||||
kind: Annotated[
|
||||
Literal[
|
||||
"system",
|
||||
"uv",
|
||||
"i",
|
||||
"curlsh",
|
||||
"brew",
|
||||
"cargo",
|
||||
"pipx",
|
||||
"npm",
|
||||
"go",
|
||||
"gh",
|
||||
],
|
||||
BeforeValidator(validate_kind),
|
||||
] = "system"
|
||||
dependencies: Optional[List[str]] = None
|
||||
value: str
|
||||
|
||||
@classmethod
|
||||
def from_raw(cls, raw: str) -> "Package":
|
||||
"""
|
||||
Parse a raw input string like 'uv:copier' into a Package(kind='uv', value='copier')
|
||||
"""
|
||||
if ":" in raw:
|
||||
prefix, value = raw.split(":", 1)
|
||||
return cls(kind=prefix.strip(), value=value.strip())
|
||||
else:
|
||||
return cls(kind="system", value=raw.strip())
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_dependencies(self) -> Self:
|
||||
if self.dependencies:
|
||||
return self
|
||||
else:
|
||||
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):
|
||||
return f"{self.kind}:{self.value}" if self.kind != "system" else self.value
|
||||
|
||||
def is_system(self) -> bool:
|
||||
return self.kind == "system"
|
||||
|
||||
def install_command(self) -> str:
|
||||
"""
|
||||
Generate the bash install command snippet for this package.
|
||||
"""
|
||||
if self.kind == "system":
|
||||
return f"detect_package_manager_and_install {self.value}"
|
||||
elif self.kind == "uv":
|
||||
return f"uv tool install {self.value}"
|
||||
elif self.kind in ["i", "installer", "gh"]:
|
||||
return f"curl -fsSL https://i.jpillora.com/{self.value} | sh"
|
||||
elif self.kind == "curlsh":
|
||||
return f"curl -fsSL {self.value} | sh"
|
||||
elif self.kind == "curlbash":
|
||||
return f"curl -fsSL {self.value} | bash"
|
||||
elif self.kind == "brew":
|
||||
return f"brew install {self.value}"
|
||||
elif self.kind == "cargo":
|
||||
return f"cargo install {self.value}"
|
||||
elif self.kind == "pipx":
|
||||
return f"pipx install {self.value}"
|
||||
elif self.kind == "npm":
|
||||
return f"npm install -g {self.value}"
|
||||
elif self.kind == "go":
|
||||
return f"go install {self.value}@latest"
|
||||
else:
|
||||
raise ValueError(f"Unknown install method for kind={self.kind}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raw_inputs = [
|
||||
"curl",
|
||||
"wget",
|
||||
"uv:copier",
|
||||
"i:sharkdp/fd",
|
||||
"curlsh:https://example.com/install.sh",
|
||||
"brew:bat",
|
||||
]
|
||||
|
||||
packages = [Package.from_raw(raw) for raw in raw_inputs]
|
||||
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]
|
||||
print("\n".join(install for install in unique_everseen([*dependencies, *installs])))
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{% if additional_packages %}
|
||||
detect_package_manager_and_install_command() {
|
||||
detect_package_manager_and_install() {
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: detect_package_manager_and_install_command <package1> [package2] [...]"
|
||||
echo "Usage: detect_package_manager_and_install <package1> [package2] [...]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
|
@ -34,19 +34,32 @@ detect_package_manager_and_install_command() {
|
|||
return 2
|
||||
fi
|
||||
|
||||
PACKAGES="$*"
|
||||
echo "Using package manager: $PKG_MANAGER"
|
||||
|
||||
if [ -n "$UPDATE_CMD" ]; then
|
||||
echo "$UPDATE_CMD
|
||||
echo $INSTALL_CMD $PACKAGES"
|
||||
$UPDATE_CMD
|
||||
$INSTALL_CMD $PACKAGES
|
||||
echo "Running package manager update..."
|
||||
eval "$UPDATE_CMD"
|
||||
fi
|
||||
|
||||
FAILED_PKGS=()
|
||||
|
||||
for pkg in "$@"; do
|
||||
echo "Installing package: $pkg"
|
||||
if ! eval "$INSTALL_CMD $pkg"; then
|
||||
echo "⚠️ Warning: Failed to install package: $pkg"
|
||||
FAILED_PKGS+=("$pkg")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#FAILED_PKGS[@]} -ne 0 ]; then
|
||||
echo "⚠️ The following packages failed to install:"
|
||||
for failed_pkg in "${FAILED_PKGS[@]}"; do
|
||||
echo " - $failed_pkg"
|
||||
done
|
||||
else
|
||||
echo "$INSTALL_CMD $PACKAGES"
|
||||
$INSTALL_CMD $PACKAGES
|
||||
echo "✅ All requested packages installed successfully."
|
||||
fi
|
||||
}
|
||||
|
||||
detect_package_manager_and_install_command {% for package in additional_packages %}{{ package | trim }}{% if not loop.last %} {% endif %}{% endfor %}
|
||||
detect_package_manager_and_install {% for package in additional_packages %}{{ package | trim }}{% if not loop.last %} {% endif %}{% endfor %}
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ dependencies = [
|
|||
"InquirerPy",
|
||||
"jinja2",
|
||||
"iterfzf",
|
||||
"pydantic",
|
||||
]
|
||||
|
||||
[[project.authors]]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue