Compare commits

..

No commits in common. "main" and "v0.3.0" have entirely different histories.
main ... v0.3.0

10 changed files with 201 additions and 396 deletions

View file

@ -12,7 +12,7 @@ permissions:
packages: none packages: none
id-token: write id-token: write
jobs: jobs:
pypi-release-krayt: release-krayt:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -22,26 +22,3 @@ jobs:
env: env:
# required for gh release # required for gh release
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
- run: sudo rm -rf dist
- name: Install just
run: |
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
shell: bash
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/0.6.16/install.sh | sh
shell: bash
- name: Install hatch
run: |
uv tool install hatch
shell: bash
- name: Configure Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
shell: bash
- name: GitHub Release (just release)
run: just create-release
env:
GH_TOKEN: ${{ github.token }}
shell: bash

View file

@ -1,29 +1,3 @@
## 0.4.3
- working out binary release process
## 0.4.2
- working out binary release process
## 0.4.1
- Automated release for both pypi and github
## 0.4.0
- create now has --apply to apply the generated manifest to the cluster
- generic templates endpoint for cli
- better motd for volume mounts
## 0.3.0
- created pypi release
- updated releases to use pyapp
- all new package
- port forward support
- additional_packages support
## 0.2.0 ## 0.2.0
### Added ### Added

View file

@ -3,7 +3,7 @@ delete-tag:
set -euo pipefail set -euo pipefail
# Get the version # Get the version
VERSION=$(hatch version) VERSION=$(cat version)
# Delete the tag # Delete the tag
git tag -d "v$VERSION" git tag -d "v$VERSION"
@ -14,65 +14,83 @@ delete-release:
set -euo pipefail set -euo pipefail
# Get the version # Get the version
VERSION=$(hatch version) VERSION=$(cat version)
# Delete the release # Delete the release
gh release delete "v$VERSION" gh release delete "v$VERSION"
create-tag: create-tag:
#!/usr/bin/env bash #!/usr/bin/env bash
VERSION=$(hatch version) VERSION=$(cat version)
git tag -a "v$VERSION" -m "Release v$VERSION" git tag -a "v$VERSION" -m "Release v$VERSION"
git push origin "v$VERSION" git push origin "v$VERSION"
create-archives: create-archives:
#!/usr/bin/env bash #!/usr/bin/env bash
VERSION=$(hatch version) VERSION=$(cat version)
rm -rf dist build rm -rf dist build
hatch build -t binary mkdir -p dist
krayt_bin=dist/binary/krayt-${VERSION}
# Create the binary for each platform # Create the binary for each platform
for platform in "x86_64-unknown-linux-gnu" "aarch64-unknown-linux-gnu"; do for platform in "x86_64-unknown-linux-gnu" "aarch64-unknown-linux-gnu"; do
outbin="krayt-${VERSION}-${platform}" outdir="krayt-${VERSION}-${platform}"
mkdir -p "dist/${outdir}"
# Copy the Python script and update version # Copy the Python script and update version
cp ${krayt_bin} "dist/binary/${outbin}" cp krayt.py "dist/${outdir}/krayt.py"
sed -i "s/NIGHTLY/${VERSION}/" "dist/${outdir}/krayt.py"
cd dist
tar czf "${outdir}.tar.gz" "${outdir}"
sha256sum "${outdir}.tar.gz" > "${outdir}.tar.gz.sha256"
cd ..
done done
# Generate install.sh # Generate install.sh
# ./scripts/generate_install_script.py "$VERSION" ./scripts/generate_install_script.py "$VERSION"
# chmod +x dist/install.sh chmod +x dist/install.sh
create-release: create-tag create-archives create-release: create-tag create-archives
#!/usr/bin/env bash #!/usr/bin/env bash
VERSION=$(hatch version) VERSION=$(cat version)
./scripts/get_release_notes.py "$VERSION" > release_notes.tmp ./scripts/get_release_notes.py "$VERSION" > release_notes.tmp
gh release create "v$VERSION" \
# Check if release already exists --title "v$VERSION" \
if gh release view "v$VERSION" &>/dev/null; then --notes-file release_notes.tmp \
echo "Release v$VERSION already exists. Uploading binaries..." dist/krayt-${VERSION}-x86_64-unknown-linux-gnu.tar.gz \
# Upload binaries to existing release dist/krayt-${VERSION}-x86_64-unknown-linux-gnu.tar.gz.sha256 \
gh release upload "v$VERSION" \ dist/krayt-${VERSION}-aarch64-unknown-linux-gnu.tar.gz \
dist/binary/krayt-${VERSION} \ dist/krayt-${VERSION}-aarch64-unknown-linux-gnu.tar.gz.sha256 \
dist/binary/krayt-${VERSION}-aarch64-unknown-linux-gnu \ dist/install.sh
dist/binary/krayt-${VERSION}-x86_64-unknown-linux-gnu || true
else
echo "Creating new release v$VERSION"
# Create new release with binaries
gh release create "v$VERSION" \
--title "v$VERSION" \
--notes-file release_notes.tmp \
dist/binary/krayt-${VERSION} \
dist/binary/krayt-${VERSION}-aarch64-unknown-linux-gnu \
dist/binary/krayt-${VERSION}-x86_64-unknown-linux-gnu
fi
rm release_notes.tmp rm release_notes.tmp
preview-release-notes: preview-release-notes:
#!/usr/bin/env bash #!/usr/bin/env bash
VERSION=$(hatch version) VERSION=$(cat version)
./scripts/get_release_notes.py "$VERSION" | less -R ./scripts/get_release_notes.py "$VERSION" | less -R
release: create-release release: create-release
build-pyapp:
export PYAPP_PROJECT_NAME=krayt
export PYAPP_PROJECT_VERSION=`hatch version`
export PYAPP_DISTRIBUTION_SOURCE=~/git/krayt/dist/krayt-${PYAPP_PROJECT_VERSION}.tar.gz
export PYAPP_DISTRIBUTION_EMBED=true
echo "linting"
hatch run lint-format
echo "Building pyapp"
hatch build
echo "Uploading pyapp"
hatch publish
cd ~/git/pyapp
cargo build --release --quiet
echo "Done"

View file

@ -1 +1 @@
__version__ = "0.4.3" __version__ = "0.3.0"

View file

@ -6,7 +6,7 @@ from typer import Typer
app = Typer() app = Typer()
app.add_typer(templates_app, name="template", no_args_is_help=True) 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.add_typer(pod_app, name="pod", no_args_is_help=True)
app.command(name="create")(create) app.command(name="create")(create)
app.command(name="c")(create) app.command(name="c")(create)

View file

@ -1,6 +1,5 @@
import iterfzf import iterfzf
from krayt.templates import env from krayt.templates import env
from kubernetes.stream import stream
from kubernetes import client, config from kubernetes import client, config
import logging import logging
import os import os
@ -9,12 +8,6 @@ import typer
from typing import Any, List, Optional from typing import Any, List, Optional
import yaml import yaml
from krayt.__about__ import __version__ from krayt.__about__ import __version__
import sys
import tty
import termios
import select
import signal
import json
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
@ -42,8 +35,8 @@ def format_volume_mount(vm: client.V1VolumeMount) -> dict[str, Any]:
return clean_dict( return clean_dict(
{ {
"name": vm.name, "name": vm.name,
"mount_path": vm.mount_path, "mountPath": vm.mount_path,
"read_only": vm.read_only if vm.read_only else None, "readOnly": vm.read_only if vm.read_only else None,
} }
) )
@ -151,17 +144,6 @@ def get_pods(
raise typer.Exit(1) raise typer.Exit(1)
def get_namespaces(
namespace=None,
label_selector: str = "app=krayt",
):
config.load_kube_config()
api = client.CoreV1Api()
all_namespaces = [n.metadata.name for n in api.list_namespace().items]
return all_namespaces
def get_pod_spec(pod_name, namespace): def get_pod_spec(pod_name, namespace):
config.load_kube_config() config.load_kube_config()
v1 = client.CoreV1Api() v1 = client.CoreV1Api()
@ -278,81 +260,92 @@ def create_inspector_job(
pre_init_hooks: Optional[List[str]] = None, pre_init_hooks: Optional[List[str]] = None,
post_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()) timestamp = int(time.time())
job_name = f"{pod_name}-krayt-{timestamp}" job_name = f"{pod_name}-krayt-{timestamp}"
# Get environment variables and secret volumes from the target pod
env_vars, secret_volumes = get_env_vars_and_secret_volumes(api, namespace) env_vars, secret_volumes = get_env_vars_and_secret_volumes(api, namespace)
# Add secret volumes to our volumes list
volumes.extend(secret_volumes) volumes.extend(secret_volumes)
secret_mounts = [ # Create corresponding volume mounts for secrets
client.V1VolumeMount( secret_mounts = []
name=vol.name, for vol in secret_volumes:
mount_path=f"/mnt/secrets/{vol.secret.secret_name}", secret_mounts.append(
read_only=True, {
"name": vol.name,
"mountPath": f"/mnt/secrets/{vol.secret.secret_name}",
"readOnly": True,
}
) )
for vol in secret_volumes
]
# Convert volume mounts to dictionaries
formatted_mounts = [format_volume_mount(vm) for vm in volume_mounts] formatted_mounts = [format_volume_mount(vm) for vm in volume_mounts]
formatted_mounts = [client.V1VolumeMount(**vm) for vm in formatted_mounts if vm]
formatted_mounts.extend(secret_mounts) formatted_mounts.extend(secret_mounts)
pvc_info = [ # Format mount and PVC info for MOTD
f"{v.name}:{v.persistent_volume_claim.claim_name}" mount_info = []
for v in volumes for vm in formatted_mounts:
if hasattr(v, "persistent_volume_claim") and v.persistent_volume_claim if vm:
] mount_info.append(f"{vm['name']}:{vm['mountPath']}")
template = env.get_template("base.sh") pvc_info = []
for v in volumes:
if hasattr(v, "persistent_volume_claim") and v.persistent_volume_claim:
pvc_info.append(f"{v.name}:{v.persistent_volume_claim.claim_name}")
template_name = "base.sh"
template = env.get_template(template_name)
pvcs = None
pre_init_scripts = None
post_init_scripts = None
pre_init_hooks = None
post_init_hooks = None
command = template.render( command = template.render(
volumes=volumes, volumes=volumes,
pvcs=None, pvcs=pvcs,
additional_packages=additional_packages, additional_packages=additional_packages,
pre_init_scripts=None, pre_init_scripts=pre_init_scripts,
post_init_scripts=None, post_init_scripts=post_init_scripts,
pre_init_hooks=None, pre_init_hooks=pre_init_hooks,
post_init_hooks=None, post_init_hooks=post_init_hooks,
) )
container = client.V1Container( inspector_job = {
name="inspector", "apiVersion": "batch/v1",
image=image, "kind": "Job",
command=["sh", "-c", command], "metadata": {
env=env_vars, "name": job_name,
volume_mounts=formatted_mounts, "namespace": namespace,
) "labels": {"app": "krayt"},
"annotations": {"pvcs": ",".join(pvc_info) if pvc_info else "none"},
spec = client.V1PodSpec( },
containers=[container], "spec": {
volumes=[format_volume(v) for v in volumes if format_volume(v)], "ttlSecondsAfterFinished": 600,
restart_policy="Never", "template": {
image_pull_secrets=[client.V1LocalObjectReference(name=imagepullsecret)] "metadata": {"labels": {"app": "krayt"}},
if imagepullsecret "spec": {
else None, "containers": [
) {
"name": "inspector",
template = client.V1PodTemplateSpec( "image": image,
metadata=client.V1ObjectMeta(labels={"app": "krayt"}), spec=spec "command": ["sh", "-c", command],
) "env": env_vars,
"volumeMounts": formatted_mounts,
job_spec = client.V1JobSpec( }
template=template, ],
ttl_seconds_after_finished=600, "volumes": [format_volume(v) for v in volumes if format_volume(v)],
) "imagePullSecrets": [{"name": imagepullsecret}]
if imagepullsecret
job = client.V1Job( else None,
api_version="batch/v1", "restartPolicy": "Never",
kind="Job", },
metadata=client.V1ObjectMeta( },
name=job_name, },
namespace=namespace, }
labels={"app": "krayt"}, return inspector_job
annotations={"pvcs": ",".join(pvc_info) if pvc_info else "none"},
),
spec=job_spec,
)
return job
PROTECTED_NAMESPACES = { PROTECTED_NAMESPACES = {
@ -445,164 +438,32 @@ def get_pod(namespace: Optional[str] = None):
return pod_name, pod_namespace return pod_name, pod_namespace
def interactive_exec(pod_name: str, namespace: str):
# Load kubeconfig from local context (or use load_incluster_config if running inside the cluster)
print(f"Connecting to pod {pod_name} in namespace {namespace}...")
try:
config.load_kube_config()
except Exception as e:
print(f"Error loading kubeconfig: {e}", file=sys.stderr)
return
core_v1 = client.CoreV1Api()
command = ["/bin/bash", "-l"]
resp = None
# Save the current terminal settings
oldtty = termios.tcgetattr(sys.stdin)
# Function to handle window resize events
def handle_resize(signum, frame):
if resp and resp.is_open():
# Get the current terminal size
cols, rows = os.get_terminal_size()
# Send terminal resize command via websocket
# Format matches kubectl's resize message format
resize_msg = json.dumps({"Width": cols, "Height": rows})
resp.write_channel(4, resize_msg)
# Function to handle exit signals
def handle_exit(signum, frame):
if resp and resp.is_open():
# Send Ctrl+C to the remote process
resp.write_stdin("\x03")
try:
# Put terminal into raw mode but don't handle local echo ourselves
# Let the remote terminal handle echoing and control characters
tty.setraw(sys.stdin.fileno())
# Set up signal handlers
signal.signal(signal.SIGWINCH, handle_resize) # Window resize
signal.signal(signal.SIGINT, handle_exit) # Ctrl+C
# Create a TTY-enabled exec connection to the pod
try:
resp = stream(
core_v1.connect_get_namespaced_pod_exec,
pod_name,
namespace,
command=command,
stderr=True,
stdin=True,
stdout=True,
tty=True,
_preload_content=False,
)
print(f"Connected to {pod_name}")
except Exception as e:
print(f"\nError connecting to pod: {e}", file=sys.stderr)
return
# Wait for the connection to be ready
time.sleep(0.2)
# Send initial terminal size
cols, rows = os.get_terminal_size()
resize_msg = json.dumps({"Width": cols, "Height": rows})
resp.write_channel(4, resize_msg)
# Make sure the size is set by sending a resize event
handle_resize(None, None)
# Set up a simple select-based event loop to handle I/O
try:
while resp and resp.is_open():
# Update the websocket connection
resp.update(timeout=0.1)
# Handle output from the pod
if resp.peek_stdout():
sys.stdout.write(resp.read_stdout())
sys.stdout.flush()
if resp.peek_stderr():
sys.stderr.write(resp.read_stderr())
sys.stderr.flush()
# Check for input from the user
rlist, _, _ = select.select([sys.stdin], [], [], 0.01)
if sys.stdin in rlist:
# Read input and forward it to the pod without local echo
data = os.read(sys.stdin.fileno(), 1024)
if not data: # EOF (e.g., user pressed Ctrl+D)
break
resp.write_stdin(data.decode())
except Exception as e:
print(f"\nConnection error: {e}", file=sys.stderr)
except KeyboardInterrupt:
# Handle Ctrl+C gracefully
print("\nSession terminated by user", file=sys.stderr)
except Exception as e:
print(f"\nError in interactive session: {e}", file=sys.stderr)
finally:
# Reset signal handlers
signal.signal(signal.SIGWINCH, signal.SIG_DFL)
signal.signal(signal.SIGINT, signal.SIG_DFL)
# Close the connection if it's still open
if resp and resp.is_open():
try:
resp.close()
except Exception:
pass
# Always restore terminal settings
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
print("\nConnection closed", file=sys.stderr)
@app.command() @app.command()
def exec( def exec(
namespace: Optional[str] = typer.Option( namespace: Optional[str] = typer.Option(
None, None,
help="Kubernetes namespace. If not specified, will search for inspectors across all namespaces.", help="Kubernetes namespace. If not specified, will search for inspectors across all namespaces.",
), ),
shell: Optional[str] = typer.Option(
"/bin/bash",
"--shell",
"-s",
help="Shell to use for the inspector pod",
),
): ):
""" """
Enter the Krayt dragon's lair! Connect to a running inspector pod. Enter the Krayt dragon's lair! Connect to a running inspector pod.
If multiple inspectors are found, you'll get to choose which one to explore. If multiple inspectors are found, you'll get to choose which one to explore.
""" """
config.load_kube_config() # or config.load_incluster_config() if running inside a pod
client.CoreV1Api()
pod_name, pod_namespace = get_pod(namespace) pod_name, pod_namespace = get_pod(namespace)
exec_command = [
"kubectl",
"exec",
"-it",
"-n",
pod_namespace,
pod_name,
"--",
"/bin/bash",
"-l",
]
try: os.execvp("kubectl", exec_command)
pod_name, pod_namespace = get_pod(namespace)
exec_command = [
"kubectl",
"exec",
"-it",
"-n",
pod_namespace,
pod_name,
"--",
shell,
"-l",
]
os.execvp("kubectl", exec_command)
except Exception as e:
print(f"Error executing command with kubectl trying python api: {e}")
interactive_exec(pod_name, pod_namespace)
@app.command() @app.command()
@ -779,11 +640,6 @@ def create(
"--post-init-hooks", "--post-init-hooks",
help="additional hooks to execute at the start of container initialization", help="additional hooks to execute at the start of container initialization",
), ),
apply: bool = typer.Option(
False,
"--apply",
help="Automatically apply the changes instead of just echoing them.",
),
): ):
""" """
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.
@ -791,15 +647,16 @@ 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 = namespace selected_namespace = None
selected_pod = clone selected_pod = None
if namespace is None and clone is not None and "/" in clone: if namespace is None and clone is not None and "/" in clone:
selected_namespace, selected_pod = clone.split("/", 1) selected_namespace, selected_pod = clone.split("/", 1)
elif namespace is not None and clone is not None:
selected_namespace = namespace
selected_pod = clone
get_namespaces(namespace) pods = get_pods(namespace, label_selector=None)
pods = get_pods(namespace, label_selector="app!=krayt")
if not pods: if not pods:
typer.echo("No pods found.") typer.echo("No pods found.")
raise typer.Exit(1) raise typer.Exit(1)
@ -815,6 +672,9 @@ def create(
typer.echo("No pod selected.") typer.echo("No pod selected.")
raise typer.Exit(1) 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) 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)
@ -834,21 +694,7 @@ def create(
) )
# Output the job manifest # Output the job manifest
api_client = client.ApiClient() typer.echo(yaml.dump(clean_dict(inspector_job), sort_keys=False))
job_dict = api_client.sanitize_for_serialization(inspector_job)
job_yaml = yaml.dump(job_dict, sort_keys=False)
if apply:
batch_api = client.BatchV1Api()
job = batch_api.create_namespaced_job(
namespace=selected_namespace,
body=inspector_job,
)
print(f"Job {job.metadata.name} created.")
return job
else:
# Just echo the YAML
typer.echo(job_yaml)
@app.command() @app.command()
@ -916,10 +762,10 @@ def list_pods():
typer.echo(f"{pod} ({namespace})") typer.echo(f"{pod} ({namespace})")
# def main(): def main():
# setup_environment() setup_environment()
# app() app()
#
#
# if __name__ == "__main__": if __name__ == "__main__":
# main() main()

View file

@ -13,8 +13,7 @@ def list():
@app.command() @app.command()
def render( def base(
template_name: Optional[str] = typer.Option("base.sh", "--template-name", "-t"),
volumes: Optional[List[str]] = typer.Option( volumes: Optional[List[str]] = typer.Option(
None, None,
"--volume", "--volume",
@ -49,6 +48,7 @@ def render(
help="additional hooks to execute at the start of container initialization", help="additional hooks to execute at the start of container initialization",
), ),
): ):
template_name = "base.sh"
template = env.get_template(template_name) template = env.get_template(template_name)
rendered = template.render( rendered = template.render(
volumes=volumes, volumes=volumes,
@ -62,37 +62,37 @@ def render(
print(rendered) print(rendered)
# @app.command() @app.command()
# def install( def install(
# additional_packages: Optional[List[str]] = typer.Option( additional_packages: Optional[List[str]] = typer.Option(
# ..., "--additional-packages", "-ap" ..., "--additional-packages", "-ap"
# ), ),
# ): ):
# template_name = "install.sh" template_name = "install.sh"
# template = env.get_template(template_name) template = env.get_template(template_name)
# rendered = template.render(additional_packages=additional_packages) rendered = template.render(additional_packages=additional_packages)
# print(rendered) print(rendered)
#
#
# @app.command() @app.command()
# def motd( def motd(
# volumes: Optional[List[str]] = typer.Option( volumes: Optional[List[str]] = typer.Option(
# None, None,
# "--volume", "--volume",
# ), ),
# pvcs: Optional[List[str]] = typer.Option( pvcs: Optional[List[str]] = typer.Option(
# None, None,
# "--pvc", "--pvc",
# ), ),
# additional_packages: Optional[List[str]] = typer.Option( additional_packages: Optional[List[str]] = typer.Option(
# ..., "--additional-packages", "-ap" ..., "--additional-packages", "-ap"
# ), ),
# ): ):
# template_name = "motd.sh" template_name = "motd.sh"
# template = env.get_template(template_name) template = env.get_template(template_name)
# rendered = template.render( rendered = template.render(
# volumes=volumes, volumes=volumes,
# pvcs=pvcs, pvcs=pvcs,
# additional_packages=additional_packages, additional_packages=additional_packages,
# ) )
# print(rendered) print(rendered)

View file

@ -5,11 +5,11 @@ cat <<EOF >/etc/motd
└───────────────────────────────────┘ └───────────────────────────────────┘
"Inside every volume lies a pearl of wisdom waiting to be discovered." "Inside every volume lies a pearl of wisdom waiting to be discovered."
{%- if mounts %} {%- if volumes %}
Mounted Volumes: Mounted Volumes:
{%- for mount in mounts %} {%- for volume in volumes %}
- {{ mount.name }}:{{ mount.mount_path }} - {{ volume }}
{%- endfor %} {%- endfor %}
{%- endif %} {%- endif %}

View file

@ -21,11 +21,7 @@ def get_release_notes(version):
You can install krayt using one of these methods: You can install krayt using one of these methods:
## pypi > !krayt requires [uv](https://docs.astral.sh/uv/getting-started/installation/) to be installed
``` bash
pip install krayt
```
### Using i.jpillora.com (recommended) ### Using i.jpillora.com (recommended)
@ -41,8 +37,8 @@ curl -fsSL https://github.com/waylonwalker/krayt/releases/download/v{version}/in
### Manual download ### Manual download
You can also manually download the archive for your platform from the releases page: You can also manually download the archive for your platform from the releases page:
- [x86_64-unknown-linux-gnu](https://github.com/waylonwalker/krayt/releases/download/v{version}/krayt-{version}-x86_64-unknown-linux-gnu) - [x86_64-unknown-linux-gnu](https://github.com/waylonwalker/krayt/releases/download/v{version}/krayt-{version}-x86_64-unknown-linux-gnu.tar.gz)
- [aarch64-unknown-linux-gnu](https://github.com/waylonwalker/krayt/releases/download/v{version}/krayt-{version}-aarch64-unknown-linux-gnu)""" - [aarch64-unknown-linux-gnu](https://github.com/waylonwalker/krayt/releases/download/v{version}/krayt-{version}-aarch64-unknown-linux-gnu.tar.gz)"""
# Get help output for main command and all subcommands # Get help output for main command and all subcommands
try: try:
@ -50,23 +46,17 @@ You can also manually download the archive for your platform from the releases p
# Get main help output # Get main help output
main_help = subprocess.check_output( main_help = subprocess.check_output(
["krayt", "--help"], ["./krayt.py", "--help"],
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
universal_newlines=True, universal_newlines=True,
) )
help_outputs.append(("Main Command", main_help)) help_outputs.append(("Main Command", main_help))
# Get help for each subcommand # Get help for each subcommand
subcommands = [ subcommands = ["create", "exec", "clean", "version"]
"create",
"exec",
"clean",
"version",
"pod",
]
for cmd in subcommands: for cmd in subcommands:
cmd_help = subprocess.check_output( cmd_help = subprocess.check_output(
["krayt", cmd, "--help"], ["./krayt.py", cmd, "--help"],
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
universal_newlines=True, universal_newlines=True,
) )

View file

@ -148,11 +148,11 @@ function install {
FTYPE="" FTYPE=""
case "${OS}_${ARCH}" in case "${OS}_${ARCH}" in
"linux_amd64") "linux_amd64")
URL="https://github.com/WaylonWalker/krayt/releases/download/v${RELEASE}/krayt-${RELEASE}-x86_64-unknown-linux-gnu.tar.gz" URL="https://github.com/WaylonWalker/nvim-manager/releases/download/v${RELEASE}/nvim-manager-${RELEASE}-x86_64-unknown-linux-gnu.tar.gz"
FTYPE=".tar.gz" FTYPE=".tar.gz"
;; ;;
"linux_arm64") "linux_arm64")
URL="https://github.com/WaylonWalker/krayt/releases/download/v${RELEASE}/krayt-${RELEASE}-aarch64-unknown-linux-gnu.tar.gz" URL="https://github.com/WaylonWalker/nvim-manager/releases/download/v${RELEASE}/nvim-manager-${RELEASE}-aarch64-unknown-linux-gnu.tar.gz"
FTYPE=".tar.gz" FTYPE=".tar.gz"
;; ;;
*) fail "No asset for platform ${OS}-${ARCH}" ;; *) fail "No asset for platform ${OS}-${ARCH}" ;;
@ -193,7 +193,7 @@ function install {
unzip -o -qq tmp.zip || fail "unzip failed" unzip -o -qq tmp.zip || fail "unzip failed"
rm tmp.zip || fail "cleanup failed" rm tmp.zip || fail "cleanup failed"
elif [[ $FTYPE = ".bin" ]]; then elif [[ $FTYPE = ".bin" ]]; then
bash -c "$GET $URL" >"krayt_${OS}_${ARCH}" || fail "download failed" bash -c "$GET $URL" >"nvim-manager_${OS}_${ARCH}" || fail "download failed"
else else
fail "unknown file type: $FTYPE" fail "unknown file type: $FTYPE"
fi fi