Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit 17cf5d2

Browse files
Cluster Management Improvements (#614)
* Add new admin create cluster command to create a cluster and enable cert bundle injection * Add support for more Kind and Minikube backends * Fix cluster creation * Add ability to get clusters * Improve cluster list output * Add connectivity checks to cluster list * Tweak connectivity checks * Remove connectivity checks and allow single cluster get * Remove cluster management from jmp admin install command * Add jumpstarter-cli-admin tests * Migrate tests to cluster module and fix remaining tests * Fix broken docs build * Fix cluster creation and Jumpstarter version * Fix cluster detection logic * Fix lint errors * Update docs * Tweak docs * Fix issues and improve tests * Increase test coverage * Fix click exception handling for get_cluster * Fix remaining issues and nitpicks * Fix line length * Add support for passing values files for the Helm install (supports E2E tests) * Fix lint errors * Fix remaining issues * Fix double nodes issue in YAML --------- Co-authored-by: Miguel Angel Ajo Pelayo <majopela@redhat.com>
1 parent 41d932b commit 17cf5d2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+6477
-1530
lines changed

docs/source/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import os
1111
import sys
1212

13-
from jumpstarter_cli_admin.controller import get_latest_compatible_controller_version
13+
from jumpstarter_kubernetes.controller import get_latest_compatible_controller_version
1414

1515
os.environ["TERM"] = "dumb"
1616

@@ -32,7 +32,7 @@
3232
"sphinx_click",
3333
"sphinx_substitution_extensions",
3434
"sphinx_copybutton",
35-
"sphinx_inline_tabs"
35+
"sphinx_inline_tabs",
3636
]
3737

3838
templates_path = ["_templates"]

docs/source/getting-started/installation/service/service-local.md

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@ Before installing locally, ensure you have:
1313

1414
## Install with Jumpstarter CLI
1515

16-
The Jumpstarter CLI provides the `jmp admin install` command to automatically
17-
run Helm with the correct arguments, simplifying installation in your Kubernetes
18-
cluster. This is the recommended approach for getting started quickly.
16+
The Jumpstarter CLI provides convenient commands for local demo/test cluster management and Jumpstarter installation:
17+
18+
- `jmp admin create cluster` - Creates a local cluster and installs Jumpstarter (recommended for getting started quickly)
19+
- `jmp admin delete cluster` - Deletes a local cluster completely
20+
- `jmp admin get clusters` - Get local clusters from a Kubeconfig
21+
- `jmp admin install` - Installs Jumpstarter on an existing cluster
22+
- `jmp admin uninstall` - Removes Jumpstarter from a cluster (but keeps the cluster)
1923

2024
```{warning}
2125
Sometimes the automatic IP address detection for will not work correctly, to check if Jumpstarter can determine your IP address, run `jmp admin ip`. If the IP address cannot be determined, use the `--ip` argument to manually set your IP address.
@@ -27,44 +31,65 @@ If you want to test Jumpstarter locally with more control over the setup, you ca
2731

2832
[**kind**](https://kind.sigs.k8s.io/docs/user/quick-start/) (Kubernetes in Docker) is a tool for running local Kubernetes clusters using Docker or Podman containerized "nodes". It's lightweight and fast to start, making it excellent for CI/CD pipelines and quick local testing.
2933

30-
[**minikube**](https://minikube.sigs.k8s.io/docs/start/) runs local Kubernetes clusters using VMs or container "nodes". It works across several platforms and supports different hypervisors, making it ideal for local development and testing. It's particularly useful in environments requiring untrusted certificates.
34+
[**minikube**](https://minikube.sigs.k8s.io/docs/start/) runs local Kubernetes clusters using VMs or container "nodes". It works across several platforms and supports different hypervisors, making it ideal for local development and testing. Minikube works better if you don't have a local Docker/Podman installation.
35+
36+
The admin CLI can automatically create a local cluster and install Jumpstarter with a single command:
37+
38+
By default, Jumpstarter will try to detect which local cluster tools are installed:
3139

3240
```{tip}
33-
Consider minikube for environments requiring [untrusted certificates](https://minikube.sigs.k8s.io/docs/handbook/untrusted_certs/).
41+
By default, Jumpstarter will use `kind` if available, use the `--minikube` argument to force Jumpstarter to use minikube instead.
3442
```
3543

36-
The admin CLI can automatically create a local cluster and install Jumpstarter with a single command:
44+
```{code-block} console
45+
$ jmp admin create cluster
46+
```
47+
48+
However, you can also explicitly specify a local cluster tool:
3749

3850
````{tab} kind
3951
```{code-block} console
40-
$ jmp admin install --kind --create-cluster
52+
$ jmp admin create cluster --kind
4153
```
54+
55+
Additional options for cluster creation:
56+
57+
- Custom cluster name: Specify as the first argument (default: `jumpstarter-lab`)
58+
- `--kind <PATH>`: Path to the kind binary to use for cluster management
59+
- `--helm <PATH>`: Path to the Helm binary to install the Jumpstarter service with
60+
- `--force-recreate`: Force recreate the cluster if it already exists (destroys all data)
61+
- `--kind-extra-args`: Pass additional arguments to kind cluster creation
62+
- `--skip-install`: Create the cluster without installing Jumpstarter
63+
- `--extra-certs <PATH>`: Path to custom CA certificate bundle file to inject into the cluster
4264
````
4365

4466
````{tab} minikube
4567
```{code-block} console
46-
$ jmp admin install --minikube --create-cluster
68+
$ jmp admin create cluster --minikube
4769
```
48-
````
4970
5071
Additional options for cluster creation:
5172
52-
- `--cluster-name`: Specify a custom cluster name (default: `jumpstarter-lab`)
53-
- `--force-recreate-cluster`: Force recreate the cluster if it already exists (destroys all data)
54-
- `--kind-extra-args`: Pass additional arguments to kind cluster creation
73+
- Custom cluster name: Specify as the first argument (default: `jumpstarter-lab`)
74+
- `--minikube <PATH>`: Path to the minikube binary to use for cluster management
75+
- `--helm <PATH>`: Path to the Helm binary to install the Jumpstarter service with
76+
- `--force-recreate`: Force recreate the cluster if it already exists (destroys all data)
5577
- `--minikube-extra-args`: Pass additional arguments to minikube cluster creation
78+
- `--skip-install`: Create the cluster without installing Jumpstarter
79+
- `--extra-certs <PATH>`: Path to custom CA certificate bundle file to inject into the cluster
80+
````
5681

5782
To set a custom cluster name:
5883

5984
````{tab} kind
6085
```{code-block} console
61-
$ jmp admin install --kind --create-cluster --cluster-name my-jumpstarter-cluster
86+
$ jmp admin create cluster my-jumpstarter-cluster --kind
6287
```
6388
````
6489

6590
````{tab} minikube
6691
```{code-block} console
67-
$ jmp admin install --minikube --create-cluster --cluster-name my-jumpstarter-cluster
92+
$ jmp admin create cluster my-jumpstarter-cluster --minikube
6893
```
6994
````
7095

@@ -90,28 +115,41 @@ $ jmp admin install --minikube
90115

91116
### Uninstall Jumpstarter
92117

93-
Uninstall Jumpstarter with the CLI:
118+
Uninstall Jumpstarter from the cluster with the CLI:
94119

95120
```{code-block} console
96121
$ jmp admin uninstall
97122
```
98123

99-
To delete the local cluster when uninstalling, use the `--delete-cluster` flag:
124+
To delete the local cluster completely, use the cluster delete command:
125+
126+
````{tab} kind
127+
```{code-block} console
128+
$ jmp admin delete cluster --kind
129+
```
130+
````
131+
132+
````{tab} minikube
133+
```{code-block} console
134+
$ jmp admin delete cluster --minikube
135+
```
136+
````
137+
138+
To delete a cluster with a custom name:
100139

101140
````{tab} kind
102141
```{code-block} console
103-
$ jmp admin uninstall --kind --delete-cluster
142+
$ jmp admin delete cluster my-jumpstarter-cluster --kind
104143
```
105144
````
106145

107146
````{tab} minikube
108147
```{code-block} console
109-
$ jmp admin uninstall --minikube --delete-cluster
148+
$ jmp admin delete cluster my-jumpstarter-cluster --minikube
110149
```
111150
````
112151

113-
For complete documentation of the `jmp admin install` command and all available
114-
options, see the [MAN pages](../../../reference/man-pages/jmp.md).
152+
For complete documentation of the `jmp admin create cluster`, `jmp admin delete cluster`, `jmp admin get clusters`, and `jmp admin install` commands and all available options, see the [MAN pages](../../../reference/man-pages/jmp.md).
115153

116154
## Manual Local Cluster Install
117155

packages/jumpstarter-cli-admin/jumpstarter_cli_admin/controller.py

Lines changed: 0 additions & 55 deletions
This file was deleted.

packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import click
44
from jumpstarter_cli_common.alias import AliasedGroup
55
from jumpstarter_cli_common.blocking import blocking
6+
from jumpstarter_cli_common.callbacks import ClickCallback
67
from jumpstarter_cli_common.opt import (
78
OutputType,
89
confirm_insecure_tls,
@@ -15,7 +16,13 @@
1516
opt_output_all,
1617
)
1718
from jumpstarter_cli_common.print import model_print
18-
from jumpstarter_kubernetes import ClientsV1Alpha1Api, ExportersV1Alpha1Api
19+
from jumpstarter_kubernetes import (
20+
ClientsV1Alpha1Api,
21+
ExportersV1Alpha1Api,
22+
create_cluster_and_install,
23+
validate_cluster_type_selection,
24+
)
25+
from jumpstarter_kubernetes.exceptions import JumpstarterKubernetesError
1926
from kubernetes_asyncio.client.exceptions import ApiException
2027
from kubernetes_asyncio.config.config_exception import ConfigException
2128

@@ -178,3 +185,141 @@ async def create_exporter(
178185
handle_k8s_api_exception(e)
179186
except ConfigException as e:
180187
handle_k8s_config_exception(e)
188+
189+
190+
@create.command("cluster")
191+
@click.argument("name", type=str, required=False, default="jumpstarter-lab")
192+
@click.option("--kind", is_flag=False, flag_value="kind", default=None, help="Create a local Kind cluster")
193+
@click.option(
194+
"--minikube",
195+
is_flag=False,
196+
flag_value="minikube",
197+
default=None,
198+
help="Create a local Minikube cluster",
199+
)
200+
@click.option(
201+
"--force-recreate",
202+
is_flag=True,
203+
help="Force recreate the cluster if it already exists (WARNING: This will destroy all data in the cluster)",
204+
)
205+
@click.option("--kind-extra-args", type=str, help="Extra arguments for the Kind cluster creation", default="")
206+
@click.option("--minikube-extra-args", type=str, help="Extra arguments for the Minikube cluster creation", default="")
207+
@click.option(
208+
"--extra-certs",
209+
type=click.Path(exists=True, readable=True, dir_okay=False, resolve_path=True),
210+
help="Path to custom CA certificate bundle file to inject into the cluster",
211+
)
212+
@click.option(
213+
"--skip-install",
214+
is_flag=True,
215+
help="Skip installing Jumpstarter after creating the cluster",
216+
)
217+
@click.option("--helm", type=str, help="Path or name of a helm executable", default="helm")
218+
@click.option(
219+
"--chart",
220+
type=str,
221+
help="The URL of a Jumpstarter helm chart to install",
222+
default="oci://quay.io/jumpstarter-dev/helm/jumpstarter",
223+
)
224+
@click.option("--chart-name", type=str, help="The name of the chart installation", default="jumpstarter")
225+
@click.option(
226+
"-n", "--namespace", type=str, help="Namespace to install Jumpstarter components in", default="jumpstarter-lab"
227+
)
228+
@click.option("-i", "--ip", type=str, help="IP address of your host machine", default=None)
229+
@click.option("-b", "--basedomain", type=str, help="Base domain of the Jumpstarter service", default=None)
230+
@click.option("-g", "--grpc-endpoint", type=str, help="The gRPC endpoint to use for the Jumpstarter API", default=None)
231+
@click.option("-r", "--router-endpoint", type=str, help="The gRPC endpoint to use for the router", default=None)
232+
@click.option("-v", "--version", help="The version of the service to install", default=None)
233+
@click.option(
234+
"-f",
235+
"--values-file",
236+
"values_files",
237+
type=click.Path(exists=True, readable=True, dir_okay=False, resolve_path=True),
238+
multiple=True,
239+
help="Path to custom helm values file (can be specified multiple times)",
240+
)
241+
@opt_kubeconfig
242+
@opt_context
243+
@opt_nointeractive
244+
@opt_output_all
245+
@blocking
246+
async def create_cluster(
247+
name: str,
248+
kind: Optional[str],
249+
minikube: Optional[str],
250+
force_recreate: bool,
251+
kind_extra_args: str,
252+
minikube_extra_args: str,
253+
extra_certs: Optional[str],
254+
skip_install: bool,
255+
helm: str,
256+
chart: str,
257+
chart_name: str,
258+
namespace: str,
259+
ip: Optional[str],
260+
basedomain: Optional[str],
261+
grpc_endpoint: Optional[str],
262+
router_endpoint: Optional[str],
263+
version: Optional[str],
264+
values_files: tuple[str, ...],
265+
kubeconfig: Optional[str],
266+
context: Optional[str],
267+
nointeractive: bool,
268+
output: OutputType,
269+
):
270+
"""Create a Kubernetes cluster for running Jumpstarter"""
271+
cluster_type = validate_cluster_type_selection(kind, minikube)
272+
273+
if output is None:
274+
if kind is None and minikube is None:
275+
click.echo(f"Auto-detected {cluster_type} as the cluster type")
276+
if skip_install:
277+
click.echo(f'Creating {cluster_type} cluster "{name}"...')
278+
else:
279+
click.echo(f'Creating {cluster_type} cluster "{name}" and installing Jumpstarter...')
280+
281+
# Auto-detect version if not specified and installing Jumpstarter
282+
if not skip_install and version is None:
283+
from jumpstarter_cli_common.version import get_client_version
284+
from jumpstarter_kubernetes import get_latest_compatible_controller_version
285+
286+
version = await get_latest_compatible_controller_version(get_client_version())
287+
288+
# Create callback for library functions
289+
# Use silent mode when JSON/YAML output is requested
290+
callback = ClickCallback(silent=(output is not None))
291+
292+
try:
293+
await create_cluster_and_install(
294+
cluster_type,
295+
force_recreate,
296+
name,
297+
kind_extra_args,
298+
minikube_extra_args,
299+
kind or "kind",
300+
minikube or "minikube",
301+
extra_certs,
302+
install_jumpstarter=not skip_install,
303+
helm=helm,
304+
chart=chart,
305+
chart_name=chart_name,
306+
namespace=namespace,
307+
version=version,
308+
kubeconfig=kubeconfig,
309+
context=context,
310+
ip=ip,
311+
basedomain=basedomain,
312+
grpc_endpoint=grpc_endpoint,
313+
router_endpoint=router_endpoint,
314+
callback=callback,
315+
values_files=list(values_files) if values_files else None,
316+
)
317+
except JumpstarterKubernetesError as e:
318+
# Convert library exceptions to CLI exceptions
319+
raise click.ClickException(str(e)) from e
320+
321+
if output is None:
322+
if skip_install:
323+
click.echo(f'Cluster "{name}" is ready for Jumpstarter installation.')
324+
else:
325+
click.echo(f'Cluster "{name}" created and Jumpstarter installed successfully!')

0 commit comments

Comments
 (0)