oks-cli 1.14__tar.gz → 1.15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {oks_cli-1.14 → oks_cli-1.15}/PKG-INFO +14 -19
- {oks_cli-1.14 → oks_cli-1.15}/README.md +13 -18
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli/cache.py +5 -5
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli/cluster.py +29 -25
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli/main.py +4 -4
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli/profile.py +57 -15
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli/project.py +24 -13
- oks_cli-1.15/oks_cli/quotas.py +21 -0
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli/utils.py +136 -24
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli.egg-info/PKG-INFO +14 -19
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli.egg-info/SOURCES.txt +2 -1
- {oks_cli-1.14 → oks_cli-1.15}/setup.py +1 -1
- oks_cli-1.15/tests/test_cluster.py +404 -0
- {oks_cli-1.14 → oks_cli-1.15}/tests/test_nodepool.py +1 -1
- oks_cli-1.15/tests/test_profile.py +58 -0
- oks_cli-1.15/tests/test_project.py +457 -0
- oks_cli-1.15/tests/test_quota.py +27 -0
- oks_cli-1.15/tests/test_shell_completion.py +104 -0
- oks_cli-1.14/oks_cli/quotas.py +0 -14
- oks_cli-1.14/tests/test_cluster.py +0 -158
- oks_cli-1.14/tests/test_profile.py +0 -30
- oks_cli-1.14/tests/test_project.py +0 -102
- oks_cli-1.14/tests/test_quota.py +0 -15
- {oks_cli-1.14 → oks_cli-1.15}/LICENSE +0 -0
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli/__init__.py +0 -0
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli.egg-info/dependency_links.txt +0 -0
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli.egg-info/entry_points.txt +0 -0
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli.egg-info/requires.txt +0 -0
- {oks_cli-1.14 → oks_cli-1.15}/oks_cli.egg-info/top_level.txt +0 -0
- {oks_cli-1.14 → oks_cli-1.15}/setup.cfg +0 -0
- {oks_cli-1.14 → oks_cli-1.15}/tests/test_cache.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oks-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.15
|
|
4
4
|
Author: Outscale SAS
|
|
5
5
|
Author-email: opensource@outscale.com
|
|
6
6
|
License: BSD
|
|
@@ -102,31 +102,17 @@ Dynamic: requires-dist
|
|
|
102
102
|
### Standard Installation
|
|
103
103
|
|
|
104
104
|
```bash
|
|
105
|
-
# Clone the repository
|
|
106
|
-
git clone https://github.com/outscale/oks-cli.git
|
|
107
|
-
cd oks-cli
|
|
108
|
-
|
|
109
105
|
# Create and activate a virtual environment
|
|
110
106
|
python -m venv venv
|
|
111
107
|
source venv/bin/activate
|
|
112
108
|
|
|
113
|
-
# Install
|
|
114
|
-
pip install -
|
|
115
|
-
|
|
116
|
-
# Install the CLI in editable mode
|
|
117
|
-
pip install -e .
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### User Installation
|
|
109
|
+
# Install the CLI
|
|
110
|
+
pip install oks-cli
|
|
121
111
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
```bash
|
|
125
|
-
pip3.11 install -e --user .
|
|
112
|
+
# Check version of oks-cli
|
|
113
|
+
oks-cli version
|
|
126
114
|
```
|
|
127
115
|
|
|
128
|
-
> **Note:** Ensure `~/Library/Python/3.11/bin` (macOS) or the equivalent path is in your `PATH`.
|
|
129
|
-
|
|
130
116
|
---
|
|
131
117
|
|
|
132
118
|
## 🚀 Usage
|
|
@@ -207,6 +193,15 @@ oks-cli project login --project-name my-project
|
|
|
207
193
|
Install the CLI in editable mode with development dependencies
|
|
208
194
|
|
|
209
195
|
```bash
|
|
196
|
+
# Clone the repository
|
|
197
|
+
git clone https://github.com/outscale/oks-cli.git
|
|
198
|
+
cd oks-cli
|
|
199
|
+
|
|
200
|
+
# Create and activate a virtual environment
|
|
201
|
+
python -m venv venv
|
|
202
|
+
source venv/bin/activate
|
|
203
|
+
|
|
204
|
+
# CLI in editable mode
|
|
210
205
|
pip install -e ".[dev]"
|
|
211
206
|
```
|
|
212
207
|
|
|
@@ -59,31 +59,17 @@
|
|
|
59
59
|
### Standard Installation
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
# Clone the repository
|
|
63
|
-
git clone https://github.com/outscale/oks-cli.git
|
|
64
|
-
cd oks-cli
|
|
65
|
-
|
|
66
62
|
# Create and activate a virtual environment
|
|
67
63
|
python -m venv venv
|
|
68
64
|
source venv/bin/activate
|
|
69
65
|
|
|
70
|
-
# Install
|
|
71
|
-
pip install -
|
|
72
|
-
|
|
73
|
-
# Install the CLI in editable mode
|
|
74
|
-
pip install -e .
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### User Installation
|
|
66
|
+
# Install the CLI
|
|
67
|
+
pip install oks-cli
|
|
78
68
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
pip3.11 install -e --user .
|
|
69
|
+
# Check version of oks-cli
|
|
70
|
+
oks-cli version
|
|
83
71
|
```
|
|
84
72
|
|
|
85
|
-
> **Note:** Ensure `~/Library/Python/3.11/bin` (macOS) or the equivalent path is in your `PATH`.
|
|
86
|
-
|
|
87
73
|
---
|
|
88
74
|
|
|
89
75
|
## 🚀 Usage
|
|
@@ -164,6 +150,15 @@ oks-cli project login --project-name my-project
|
|
|
164
150
|
Install the CLI in editable mode with development dependencies
|
|
165
151
|
|
|
166
152
|
```bash
|
|
153
|
+
# Clone the repository
|
|
154
|
+
git clone https://github.com/outscale/oks-cli.git
|
|
155
|
+
cd oks-cli
|
|
156
|
+
|
|
157
|
+
# Create and activate a virtual environment
|
|
158
|
+
python -m venv venv
|
|
159
|
+
source venv/bin/activate
|
|
160
|
+
|
|
161
|
+
# CLI in editable mode
|
|
167
162
|
pip install -e ".[dev]"
|
|
168
163
|
```
|
|
169
164
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import click
|
|
2
|
-
from .utils import clear_cache, find_project_id_by_name, find_cluster_id_by_name, get_all_cache, get_expiration_date, ctx_update, login_profile, profile_completer
|
|
2
|
+
from .utils import clear_cache, find_project_id_by_name, find_cluster_id_by_name, get_all_cache, get_expiration_date, ctx_update, login_profile, profile_completer, cluster_completer, project_completer
|
|
3
3
|
import prettytable
|
|
4
4
|
|
|
5
5
|
# DEFINE THE CACHE COMMAND GROUP
|
|
6
6
|
@click.group(help="Cache related commands.")
|
|
7
|
-
@click.option('--project-name', '-p', required = False, help="Project Name")
|
|
8
|
-
@click.option('--cluster-name', '-c', required = False, help="Cluster Name")
|
|
7
|
+
@click.option('--project-name', '-p', required = False, help="Project Name", shell_complete=project_completer)
|
|
8
|
+
@click.option('--cluster-name', '-c', required = False, help="Cluster Name", shell_complete=cluster_completer)
|
|
9
9
|
@click.option("--profile", help="Configuration profile to use", shell_complete=profile_completer)
|
|
10
10
|
@click.pass_context
|
|
11
11
|
def cache(ctx, project_name, cluster_name, profile):
|
|
@@ -20,8 +20,8 @@ def delete_cache(force):
|
|
|
20
20
|
clear_cache()
|
|
21
21
|
|
|
22
22
|
@cache.command('kubeconfigs', help="List cached kubeconfigs")
|
|
23
|
-
@click.option('--project-name', '-p', required=False, help="Project Name")
|
|
24
|
-
@click.option('--cluster-name', '-c', required=False, help="Cluster Name")
|
|
23
|
+
@click.option('--project-name', '-p', required=False, help="Project Name", shell_complete=project_completer)
|
|
24
|
+
@click.option('--cluster-name', '-c', required=False, help="Cluster Name", shell_complete=cluster_completer)
|
|
25
25
|
@click.option('--plain', is_flag=True, help="Plain table format")
|
|
26
26
|
@click.option('--msword', is_flag=True, help="Microsoft Word table format")
|
|
27
27
|
@click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer)
|
|
@@ -12,7 +12,7 @@ import human_readable
|
|
|
12
12
|
import prettytable
|
|
13
13
|
import logging
|
|
14
14
|
|
|
15
|
-
from .utils import do_request, print_output, find_project_id_by_name, find_cluster_id_by_name, get_cache, save_cache, detect_and_parse_input, verify_certificate, shell_completions, transform_tuple, profile_list, login_profile, cluster_create_in_background, ctx_update, set_cluster_id, get_cluster_id, get_project_id, get_template, get_cluster_name, format_changed_row, is_interesting_status, profile_completer
|
|
15
|
+
from .utils import cluster_completer, do_request, print_output, find_project_id_by_name, find_cluster_id_by_name, get_cache, save_cache, detect_and_parse_input, verify_certificate, shell_completions, transform_tuple, profile_list, login_profile, cluster_create_in_background, ctx_update, set_cluster_id, get_cluster_id, get_project_id, get_template, get_cluster_name, format_changed_row, is_interesting_status, profile_completer, project_completer
|
|
16
16
|
|
|
17
17
|
from .profile import add_profile
|
|
18
18
|
from .project import project_create, project_login
|
|
@@ -20,9 +20,9 @@ from .project import project_create, project_login
|
|
|
20
20
|
# DEFINE THE CLUSTER GROUP
|
|
21
21
|
@click.group(help="Cluster related commands.")
|
|
22
22
|
@click.option('--project', 'project_name', required = False, help="Project Name")
|
|
23
|
-
@click.option('--project-name', '-p', required = False, help="Project Name")
|
|
23
|
+
@click.option('--project-name', '-p', required = False, help="Project Name", shell_complete=project_completer)
|
|
24
24
|
@click.option('--name', 'cluster_name', required = False, help="Cluster Name")
|
|
25
|
-
@click.option('--cluster-name', '-c', required = False, help="Cluster Name")
|
|
25
|
+
@click.option('--cluster-name', '-c', required = False, help="Cluster Name", shell_complete=cluster_completer)
|
|
26
26
|
@click.option("--profile", help="Configuration profile to use", shell_complete=profile_completer)
|
|
27
27
|
@click.pass_context
|
|
28
28
|
def cluster(ctx, project_name, cluster_name, profile):
|
|
@@ -31,7 +31,7 @@ def cluster(ctx, project_name, cluster_name, profile):
|
|
|
31
31
|
|
|
32
32
|
# LOGIN ON CLUSTER
|
|
33
33
|
@cluster.command('login', help="Set a default cluster")
|
|
34
|
-
@click.option('--cluster-name', '-c', required=False, help="Name of cluster")
|
|
34
|
+
@click.option('--cluster-name', '-c', required=False, help="Name of cluster", shell_complete=cluster_completer)
|
|
35
35
|
@click.option("--profile", help="Configuration profile to use", shell_complete=profile_completer)
|
|
36
36
|
@click.pass_context
|
|
37
37
|
def cluster_login(ctx, cluster_name, profile):
|
|
@@ -70,9 +70,9 @@ def cluster_logout(ctx, profile):
|
|
|
70
70
|
|
|
71
71
|
# LIST CLUSTERS
|
|
72
72
|
@cluster.command('list', help="List all clusters")
|
|
73
|
-
@click.option('--project-name', '-p', required=False, help="Project Name")
|
|
73
|
+
@click.option('--project-name', '-p', required=False, help="Project Name", shell_complete=project_completer)
|
|
74
74
|
@click.option('--name', 'cluster_name', required = False, help="Cluster Name")
|
|
75
|
-
@click.option('--cluster-name', '-c', required = False, help="Cluster Name")
|
|
75
|
+
@click.option('--cluster-name', '-c', required = False, help="Cluster Name", shell_complete=cluster_completer)
|
|
76
76
|
@click.option('--deleted', is_flag=True, help="List deleted clusters")
|
|
77
77
|
@click.option('--plain', is_flag=True, help="Plain table format")
|
|
78
78
|
@click.option('--msword', is_flag=True, help="Microsoft Word table format")
|
|
@@ -215,9 +215,9 @@ def cluster_list(ctx, project_name, cluster_name, deleted, plain, msword, watch,
|
|
|
215
215
|
|
|
216
216
|
# GET CLUSTER BY NAME
|
|
217
217
|
@cluster.command('get', help="Get a cluster by name")
|
|
218
|
-
@click.option('--project-name', '-p', required = False, help="Project Name")
|
|
219
|
-
@click.option('--name', 'cluster_name', required=False, help="Cluster Name")
|
|
220
|
-
@click.option('--cluster-name', '-c', required=False, help="Cluster Name")
|
|
218
|
+
@click.option('--project-name', '-p', required = False, help="Project Name", shell_complete=project_completer)
|
|
219
|
+
@click.option('--name', 'cluster_name', required=False, help="Cluster Name", shell_complete=cluster_completer)
|
|
220
|
+
@click.option('--cluster-name', '-c', required=False, help="Cluster Name", shell_complete=cluster_completer)
|
|
221
221
|
@click.option('-o', '--output', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json")
|
|
222
222
|
@click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer)
|
|
223
223
|
@click.pass_context
|
|
@@ -311,8 +311,8 @@ def _create_cluster(project_name, cluster_config, output):
|
|
|
311
311
|
|
|
312
312
|
# CLUSTER CREATE BY NAME
|
|
313
313
|
@cluster.command('create', help="Create a new cluster")
|
|
314
|
-
@click.option('--project-name', '-p', required=False, help="Project Name")
|
|
315
|
-
@click.option('--cluster-name', '--name', '-c', required=False, help="Cluster Name")
|
|
314
|
+
@click.option('--project-name', '-p', required=False, help="Project Name", shell_complete=project_completer)
|
|
315
|
+
@click.option('--cluster-name', '--name', '-c', required=False, help="Cluster Name", shell_complete=cluster_completer)
|
|
316
316
|
@click.option('--description', help="Description of the cluster")
|
|
317
317
|
@click.option('--admin', help="Admin Whitelist")
|
|
318
318
|
@click.option('--version', shell_complete=shell_completions, help="Kubernetes version")
|
|
@@ -325,12 +325,13 @@ def _create_cluster(project_name, cluster_config, output):
|
|
|
325
325
|
@click.option('--quirk', multiple=True, help="Quirk")
|
|
326
326
|
@click.option('--tags', help="Comma-separated list of tags, example: 'key1=value1,key2=value2'")
|
|
327
327
|
@click.option('--disable-api-termination', type=click.BOOL, help="Disable delete action by API")
|
|
328
|
+
@click.option('--cp-multi-az', is_flag=True, help="enable control plane multi az")
|
|
328
329
|
@click.option('--dry-run', is_flag=True, help="Client dry-run, only print the object that would be sent, without sending it")
|
|
329
330
|
@click.option('-o', '--output', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json")
|
|
330
331
|
@click.option('-f', '--filename', type=click.File("r"), help="Path to file to use to create the cluster ")
|
|
331
332
|
@click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer)
|
|
332
333
|
@click.pass_context
|
|
333
|
-
def cluster_create_command(ctx, project_name, cluster_name, description, admin, version, cidr_pods, cidr_service, control_plane, zone, enable_admission_plugins, disable_admission_plugins, quirk, tags, disable_api_termination, dry_run, output, filename, profile):
|
|
334
|
+
def cluster_create_command(ctx, project_name, cluster_name, description, admin, version, cidr_pods, cidr_service, control_plane, zone, enable_admission_plugins, disable_admission_plugins, quirk, tags, disable_api_termination, cp_multi_az, dry_run, output, filename, profile):
|
|
334
335
|
"""CLI command to create a new Kubernetes cluster with optional configuration parameters."""
|
|
335
336
|
project_name, cluster_name, profile = ctx_update(ctx, project_name, cluster_name, profile)
|
|
336
337
|
login_profile(profile)
|
|
@@ -397,6 +398,9 @@ def cluster_create_command(ctx, project_name, cluster_name, description, admin,
|
|
|
397
398
|
|
|
398
399
|
if disable_api_termination is not None:
|
|
399
400
|
cluster_config["disable_api_termination"] = disable_api_termination
|
|
401
|
+
|
|
402
|
+
if cp_multi_az is not None:
|
|
403
|
+
cluster_config["cp_multi_az"] = cp_multi_az
|
|
400
404
|
|
|
401
405
|
if not dry_run:
|
|
402
406
|
_create_cluster(project_name, cluster_config, output)
|
|
@@ -407,9 +411,9 @@ def cluster_create_command(ctx, project_name, cluster_name, description, admin,
|
|
|
407
411
|
|
|
408
412
|
# UPDATE CLUSTER
|
|
409
413
|
@cluster.command('update', help="Update a cluster by name")
|
|
410
|
-
@click.option('--project-name', '-p', required=False, help="Project name")
|
|
414
|
+
@click.option('--project-name', '-p', required=False, help="Project name", shell_complete=project_completer)
|
|
411
415
|
@click.option('--name', 'cluster_name', required=False, help="Cluster name")
|
|
412
|
-
@click.option('--cluster-name', '-c', required=False, help="Cluster name")
|
|
416
|
+
@click.option('--cluster-name', '-c', required=False, help="Cluster name", shell_complete=cluster_completer)
|
|
413
417
|
@click.option('--description', help="Description of the cluster")
|
|
414
418
|
@click.option('--admin', help="Admin Whitelist")
|
|
415
419
|
@click.option('--version', shell_complete=shell_completions, help="Kubernetes version")
|
|
@@ -495,9 +499,9 @@ def cluster_update_command(ctx, project_name, cluster_name, description, admin,
|
|
|
495
499
|
|
|
496
500
|
# UPGRADE CLUSTER
|
|
497
501
|
@cluster.command('upgrade', help="Upgrade a cluster by name")
|
|
498
|
-
@click.option('--project-name', '-p', required=False, help="Project name")
|
|
502
|
+
@click.option('--project-name', '-p', required=False, help="Project name", shell_complete=project_completer)
|
|
499
503
|
@click.option('--name', 'cluster_name', required=False, help="Cluster name")
|
|
500
|
-
@click.option('--cluster-name', '-c', required=False, help="Cluster name")
|
|
504
|
+
@click.option('--cluster-name', '-c', required=False, help="Cluster name", shell_complete=cluster_completer)
|
|
501
505
|
@click.option('-o', '--output', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json")
|
|
502
506
|
@click.option('--force', is_flag=True, help="Force upgrade")
|
|
503
507
|
@click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer)
|
|
@@ -517,9 +521,9 @@ def cluster_update_command(ctx, project_name, cluster_name, output, force, profi
|
|
|
517
521
|
|
|
518
522
|
# DELETE CLUSTER BY NAME
|
|
519
523
|
@cluster.command('delete', help="Delete a cluster by name")
|
|
520
|
-
@click.option('--project-name', '-p', required=False, help="Project name")
|
|
524
|
+
@click.option('--project-name', '-p', required=False, help="Project name", shell_complete=project_completer)
|
|
521
525
|
@click.option('--name', 'cluster_name', required=False, help="Cluster name")
|
|
522
|
-
@click.option('--cluster-name', '-c', required=False, help="Cluster name")
|
|
526
|
+
@click.option('--cluster-name', '-c', required=False, help="Cluster name", shell_complete=cluster_completer)
|
|
523
527
|
@click.option('-o', '--output', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json")
|
|
524
528
|
@click.option('--dry-run', is_flag=True, help="Run without any action")
|
|
525
529
|
@click.option('--force', is_flag=True, help="Force deletion without confirmation")
|
|
@@ -549,9 +553,9 @@ def cluster_delete_command(ctx, project_name, cluster_name, output, dry_run, for
|
|
|
549
553
|
|
|
550
554
|
# GET KUBECONFIG
|
|
551
555
|
@cluster.command('kubeconfig', help="Fetch the kubeconfig for a cluster")
|
|
552
|
-
@click.option('--project-name', '-p', required=False, help="Project Name")
|
|
556
|
+
@click.option('--project-name', '-p', required=False, help="Project Name", shell_complete=project_completer)
|
|
553
557
|
@click.option('--name', 'cluster_name', required=False, help="Cluster name")
|
|
554
|
-
@click.option('--cluster-name', '-c', required=False, help="Cluster Name")
|
|
558
|
+
@click.option('--cluster-name', '-c', required=False, help="Cluster Name", shell_complete=cluster_completer)
|
|
555
559
|
@click.option('--print-path', is_flag=True, help="Print path to saved kubeconfig")
|
|
556
560
|
@click.option('--refresh', '--force', is_flag=True, help="Force refresh saved kubeconfig")
|
|
557
561
|
@click.option('--nacl', is_flag=True, help="Use public key encryption on wire (require api support)")
|
|
@@ -659,8 +663,8 @@ def _run_kubectl(project_id, cluster_id, user, group, args, input=None):
|
|
|
659
663
|
|
|
660
664
|
|
|
661
665
|
@cluster.command('kubectl', help='Fetch the kubeconfig for a cluster and run kubectl against it', context_settings={"ignore_unknown_options": True})
|
|
662
|
-
@click.option('--project-name', '-p', required=False, help="Project Name")
|
|
663
|
-
@click.option('--cluster-name', '-c', required=False, help="Cluster Name")
|
|
666
|
+
@click.option('--project-name', '-p', required=False, help="Project Name", shell_complete=project_completer)
|
|
667
|
+
@click.option('--cluster-name', '-c', required=False, help="Cluster Name", shell_complete=cluster_completer)
|
|
664
668
|
@click.option('--user', type=click.STRING, help="User")
|
|
665
669
|
@click.option('--group', type=click.STRING, help="Group")
|
|
666
670
|
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
|
|
@@ -678,8 +682,8 @@ def cluster_kubectl_command(ctx, project_name, cluster_name, user, group, args,
|
|
|
678
682
|
|
|
679
683
|
|
|
680
684
|
@click.group(help="nodepool related commands.")
|
|
681
|
-
@click.option('--project-name', '-p', required=False, help="Project Name")
|
|
682
|
-
@click.option('--cluster-name', '-c', required=False, help="Cluster Name")
|
|
685
|
+
@click.option('--project-name', '-p', required=False, help="Project Name", shell_complete=project_completer)
|
|
686
|
+
@click.option('--cluster-name', '-c', required=False, help="Cluster Name", shell_complete=cluster_completer)
|
|
683
687
|
@click.option('--user', type=click.STRING, help="User")
|
|
684
688
|
@click.option('--group', type=click.STRING, help="Group")
|
|
685
689
|
@click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer)
|
|
@@ -711,7 +715,7 @@ def nodepool_list(ctx):
|
|
|
711
715
|
@click.option('--nodepool-name', '-n', default="nodepool01", help="Nodepool Name")
|
|
712
716
|
@click.option('--count', default=2, help="Count of nodes")
|
|
713
717
|
@click.option('--type', 'vmtype', default="tinav6.c2r4p3", help="Type of VMs")
|
|
714
|
-
@click.option('--zone',
|
|
718
|
+
@click.option('--zone', multiple=True, required=True, help="Provide zone")
|
|
715
719
|
@click.option('-o', '--output', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json")
|
|
716
720
|
@click.option('--dry-run', is_flag=True, help="Run without any action")
|
|
717
721
|
@click.option('-f', '--filename', type=click.File("r"), help="Path to file to use to create the Nodepool ")
|
|
@@ -9,13 +9,13 @@ from .profile import profile
|
|
|
9
9
|
from .cache import cache
|
|
10
10
|
from .quotas import quotas
|
|
11
11
|
|
|
12
|
-
from .utils import ctx_update, login_profile, install_completions, profile_completer
|
|
12
|
+
from .utils import ctx_update, login_profile, install_completions, profile_completer, cluster_completer, project_completer
|
|
13
13
|
|
|
14
14
|
# Main CLI entry point
|
|
15
15
|
@click.group(invoke_without_command=True)
|
|
16
16
|
@click.option("--profile", help="Configuration profile to use", shell_complete=profile_completer)
|
|
17
|
-
@click.option('--project-name', '-p', required = False, help="Project Name")
|
|
18
|
-
@click.option('--cluster-name', '-c', required = False, help="Cluster Name")
|
|
17
|
+
@click.option('--project-name', '-p', required = False, help="Project Name", shell_complete=project_completer)
|
|
18
|
+
@click.option('--cluster-name', '-c', required = False, help="Cluster Name", shell_complete=cluster_completer)
|
|
19
19
|
@click.option('-v', '--verbose', count=True)
|
|
20
20
|
@click.pass_context
|
|
21
21
|
def cli(ctx, project_name, cluster_name, profile, verbose):
|
|
@@ -82,7 +82,7 @@ def version():
|
|
|
82
82
|
print(importlib.metadata.version(__package__))
|
|
83
83
|
|
|
84
84
|
@cli.command("install-completion", help="Install shell completion scripts.")
|
|
85
|
-
@click.option('--type', help="Shell")
|
|
85
|
+
@click.option('--type', help="Shell, supported [bash,zsh]")
|
|
86
86
|
def install_completion(type):
|
|
87
87
|
"""Install shell completion scripts for the CLI."""
|
|
88
88
|
install_completions(type)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import click
|
|
2
|
-
|
|
2
|
+
import prettytable
|
|
3
|
+
from .utils import set_profile, remove_profile, profile_list, DEFAULT_API_URL, get_profiles, print_output, print_table
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
# DEFINE THE PROFILE COMMAND GROUP
|
|
@@ -62,15 +63,18 @@ def add_profile(profile_name, access_key, secret_key, username, password, region
|
|
|
62
63
|
|
|
63
64
|
@profile.command('update', help="Update an existing profile")
|
|
64
65
|
@click.option('--profile-name', required=True, help="Name of profile", type=click.STRING)
|
|
66
|
+
@click.option('--new-name', required=False, help="Update profile name with new one, USE IT WITH CAUTION", type=click.STRING)
|
|
65
67
|
@click.option('--region', required=False, help="Region name", type=click.Choice(['eu-west-2', 'cloudgouv-eu-west-1']))
|
|
66
68
|
@click.option('--endpoint', required=False, help="API endpoint", type=click.STRING)
|
|
67
69
|
@click.option('--jwt', required=False, help="Enable jwt, by default is false", type=click.BOOL)
|
|
68
|
-
|
|
70
|
+
@click.option('--force', is_flag=True, help="Force update profile name without confirmation")
|
|
71
|
+
def update_profile(profile_name, region, endpoint, jwt, new_name, force):
|
|
69
72
|
"""Update configuration settings for an existing profile."""
|
|
70
73
|
profiles = profile_list()
|
|
71
74
|
if profile_name not in profiles:
|
|
72
|
-
raise click.ClickException(f"There no profile with name: {profile_name}")
|
|
75
|
+
raise click.ClickException(f"There is no profile with name: {profile_name}")
|
|
73
76
|
|
|
77
|
+
msg = f"Profile {profile_name} has been successfully updated"
|
|
74
78
|
profile = profiles[profile_name]
|
|
75
79
|
if region:
|
|
76
80
|
profile["region_name"] = region
|
|
@@ -81,11 +85,17 @@ def update_profile(profile_name, region, endpoint, jwt):
|
|
|
81
85
|
if jwt is not None:
|
|
82
86
|
profile["jwt"] = jwt
|
|
83
87
|
|
|
84
|
-
|
|
88
|
+
if new_name is not None:
|
|
89
|
+
old_profile = click.style(profile_name, bold=True)
|
|
90
|
+
new_profile = click.style(new_name, bold=True)
|
|
91
|
+
if force or click.confirm(f"Are you sure you want to update the profile {old_profile} with new name {new_profile}?", abort=True):
|
|
92
|
+
remove_profile(profile_name)
|
|
93
|
+
profile_name = new_name
|
|
94
|
+
msg = f"Profile {old_profile} has been successfully updated with new name {new_profile}"
|
|
85
95
|
|
|
96
|
+
set_profile(profile_name, profile)
|
|
86
97
|
profile_name = click.style(profile_name, bold=True)
|
|
87
|
-
|
|
88
|
-
click.echo(f"Profile {profile_name} has been successfully updated")
|
|
98
|
+
click.echo(msg)
|
|
89
99
|
|
|
90
100
|
@profile.command('delete', help="Delete a profile by name")
|
|
91
101
|
@click.option('--profile-name', required=True, help="Name of profile", type=click.STRING)
|
|
@@ -103,7 +113,8 @@ def delete_profile(profile_name, force):
|
|
|
103
113
|
click.echo(f"Profile {profile_name_bold} has been successfully deleted")
|
|
104
114
|
|
|
105
115
|
@profile.command('list', help="List existing profiles")
|
|
106
|
-
|
|
116
|
+
@click.option('-o', '--output', type=click.Choice(["json", "yaml", "table", "wide"]), help="Specify output format, by default is wide")
|
|
117
|
+
def list_profiles(output):
|
|
107
118
|
"""Display all configured profiles with their settings."""
|
|
108
119
|
profiles = profile_list()
|
|
109
120
|
|
|
@@ -111,18 +122,49 @@ def list_profiles():
|
|
|
111
122
|
return click.echo("There are no profiles")
|
|
112
123
|
|
|
113
124
|
profiles_keys = list(profiles.keys())
|
|
125
|
+
lines = list()
|
|
114
126
|
|
|
115
127
|
for key in profiles_keys:
|
|
116
128
|
if 'endpoint' not in profiles[key]:
|
|
117
129
|
if 'region_name' in profiles[key]:
|
|
118
|
-
endpoint =
|
|
130
|
+
endpoint = DEFAULT_API_URL.format(region=profiles[key]['region_name'])
|
|
119
131
|
else:
|
|
120
132
|
endpoint = None
|
|
121
133
|
else:
|
|
122
|
-
endpoint =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
134
|
+
endpoint = profiles[key]["endpoint"]
|
|
135
|
+
|
|
136
|
+
name = key
|
|
137
|
+
account_type = profiles[key]["type"]
|
|
138
|
+
region = profiles[key]["region_name"]
|
|
139
|
+
jwt = profiles[key].get("jwt", False)
|
|
140
|
+
# Remove credentials keys from profiles
|
|
141
|
+
profiles[key].pop('access_key', None)
|
|
142
|
+
profiles[key].pop('secret_key', None)
|
|
143
|
+
profiles[key].pop('username', None)
|
|
144
|
+
profiles[key].pop('password', None)
|
|
145
|
+
# Add endpoint and JWT to dict
|
|
146
|
+
profiles[key].update({'endpoint': endpoint})
|
|
147
|
+
profiles[key].update({'jwt': jwt})
|
|
148
|
+
|
|
149
|
+
if output == 'wide' or output is None:
|
|
150
|
+
lines.append("Profile: {} Account type: {} Region: {} Endpoint: {} Enabled JWT auth: {}".format(
|
|
151
|
+
click.style(name, bold=True),
|
|
152
|
+
click.style(account_type, bold=True),
|
|
153
|
+
click.style(region, bold=True),
|
|
154
|
+
click.style(endpoint, bold=True),
|
|
155
|
+
click.style(jwt, bold=True)))
|
|
156
|
+
else:
|
|
157
|
+
lines.append({"name": name, "account_type": account_type, "region": region, "endpoint": endpoint, "jwt": jwt})
|
|
158
|
+
|
|
159
|
+
if output == "table":
|
|
160
|
+
print_table(lines, [["Profile", "name"],
|
|
161
|
+
["Account type", "account_type"],
|
|
162
|
+
["Region", "region"],
|
|
163
|
+
["Endpoint", "endpoint"],
|
|
164
|
+
["JWT enabled", "jwt"]])
|
|
165
|
+
elif output in ["json", "yaml"]:
|
|
166
|
+
print_output(profiles, output)
|
|
167
|
+
else:
|
|
168
|
+
for line in lines:
|
|
169
|
+
click.echo(line)
|
|
170
|
+
return
|
|
@@ -6,12 +6,12 @@ import human_readable
|
|
|
6
6
|
import prettytable
|
|
7
7
|
import os
|
|
8
8
|
|
|
9
|
-
from .utils import do_request, print_output, find_project_id_by_name, get_project_id, set_project_id, detect_and_parse_input, transform_tuple, ctx_update, set_cluster_id, get_template, get_project_name, format_changed_row, is_interesting_status, login_profile, profile_completer
|
|
9
|
+
from .utils import do_request, print_output, print_table, find_project_id_by_name, get_project_id, set_project_id, detect_and_parse_input, transform_tuple, ctx_update, set_cluster_id, get_template, get_project_name, format_changed_row, is_interesting_status, login_profile, profile_completer, project_completer
|
|
10
10
|
|
|
11
11
|
# DEIFNE THE PROJECT COMMAND GROUP
|
|
12
12
|
@click.group(help="Project related commands.")
|
|
13
13
|
@click.option('--project', 'project_name', required = False, help="Project Name")
|
|
14
|
-
@click.option('--project-name', '-p', required = False, help="Project Name")
|
|
14
|
+
@click.option('--project-name', '-p', required = False, help="Project Name", shell_complete=project_completer)
|
|
15
15
|
@click.option("--profile", help="Configuration profile to use", shell_complete=profile_completer)
|
|
16
16
|
@click.pass_context
|
|
17
17
|
def project(ctx, project_name, profile):
|
|
@@ -20,7 +20,7 @@ def project(ctx, project_name, profile):
|
|
|
20
20
|
|
|
21
21
|
# LOGIN ON PROJECT
|
|
22
22
|
@project.command('login', help="Set a default project by name")
|
|
23
|
-
@click.option('--project-name', '-p', required=False, help="Name of project", type=click.STRING)
|
|
23
|
+
@click.option('--project-name', '-p', required=False, help="Name of project", type=click.STRING, shell_complete=project_completer)
|
|
24
24
|
@click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer)
|
|
25
25
|
@click.pass_context
|
|
26
26
|
def project_login(ctx, project_name, profile):
|
|
@@ -58,7 +58,7 @@ def project_logout(ctx, profile):
|
|
|
58
58
|
|
|
59
59
|
# LIST PROJECTS
|
|
60
60
|
@project.command('list', help="List all projects")
|
|
61
|
-
@click.option('--project-name', '-p', help="Name of project", type=click.STRING)
|
|
61
|
+
@click.option('--project-name', '-p', help="Name of project", type=click.STRING, shell_complete=project_completer)
|
|
62
62
|
@click.option('--deleted', is_flag=True, help="List deleted projects")
|
|
63
63
|
@click.option('--plain', is_flag=True, help="Plain table format")
|
|
64
64
|
@click.option('--msword', is_flag=True, help="Microsoft Word table format")
|
|
@@ -193,7 +193,7 @@ def project_list(ctx, project_name, deleted, plain, msword, uuid, watch, output,
|
|
|
193
193
|
|
|
194
194
|
# CREATE PROJECT BY NAME
|
|
195
195
|
@project.command('create', help="Create a new project")
|
|
196
|
-
@click.option('--project-name', '-p', help="Name of the project")
|
|
196
|
+
@click.option('--project-name', '-p', help="Name of the project", shell_complete=project_completer)
|
|
197
197
|
@click.option('--description', help="Description of the project")
|
|
198
198
|
@click.option('--cidr', help='CIDR for the project')
|
|
199
199
|
@click.option('--quirk', multiple=True, help="Quirk")
|
|
@@ -254,7 +254,7 @@ def project_create(ctx, project_name, description, cidr, quirk, tags, disable_ap
|
|
|
254
254
|
|
|
255
255
|
# GET PROJECT BY NAME
|
|
256
256
|
@project.command('get', help="Get default project or the project by name")
|
|
257
|
-
@click.option('--project-name', '-p', help="Name of the project")
|
|
257
|
+
@click.option('--project-name', '-p', help="Name of the project", shell_complete=project_completer)
|
|
258
258
|
@click.option('-o', '--output', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json")
|
|
259
259
|
@click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer)
|
|
260
260
|
@click.pass_context
|
|
@@ -270,7 +270,7 @@ def project_get(ctx, project_name, output, profile):
|
|
|
270
270
|
|
|
271
271
|
# DELETE PROJECT BY NAME
|
|
272
272
|
@project.command('delete', help="Delete a project by name")
|
|
273
|
-
@click.option('--project-name', '-p', required=False, help="Project Name")
|
|
273
|
+
@click.option('--project-name', '-p', required=False, help="Project Name", shell_complete=project_completer)
|
|
274
274
|
@click.option('-o', '--output', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json")
|
|
275
275
|
@click.option('--dry-run', is_flag=True, help="Run without any action")
|
|
276
276
|
@click.option('--force', is_flag=True, help="Force deletion without confirmation")
|
|
@@ -302,7 +302,7 @@ def project_delete_command(ctx, project_name, output, dry_run, force, profile):
|
|
|
302
302
|
|
|
303
303
|
# UPDATE PROJECT BY NAME
|
|
304
304
|
@project.command('update', help="Update a project by name")
|
|
305
|
-
@click.option('--project-name', '-p', required=False, help="Project Name")
|
|
305
|
+
@click.option('--project-name', '-p', required=False, help="Project Name", shell_complete=project_completer)
|
|
306
306
|
@click.option('--description', help="Description of the project")
|
|
307
307
|
@click.option('--quirk', multiple=True, help="Quirk")
|
|
308
308
|
@click.option('--tags', help="Comma-separated list of tags, example: 'key1=value1,key2=value2'")
|
|
@@ -350,8 +350,8 @@ def project_update_command(ctx, project_name, description, quirk, tags, disable_
|
|
|
350
350
|
|
|
351
351
|
# GET PROJECT QUOTAS BY PROJECT NAME
|
|
352
352
|
@project.command('quotas', help="Get project quotas")
|
|
353
|
-
@click.option('--project-name', '-p', help="Name of the project")
|
|
354
|
-
@click.option('-o', '--output', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json")
|
|
353
|
+
@click.option('--project-name', '-p', help="Name of the project", shell_complete=project_completer)
|
|
354
|
+
@click.option('-o', '--output', type=click.Choice(["json", "yaml", "table"]), help="Specify output format, by default is json")
|
|
355
355
|
@click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer)
|
|
356
356
|
@click.pass_context
|
|
357
357
|
def project_get_quotas(ctx, project_name, output, profile):
|
|
@@ -362,12 +362,23 @@ def project_get_quotas(ctx, project_name, output, profile):
|
|
|
362
362
|
project_id = find_project_id_by_name(project_name)
|
|
363
363
|
|
|
364
364
|
data = do_request("GET", f'projects/{project_id}/quotas')["data"]
|
|
365
|
-
|
|
365
|
+
if output == "table":
|
|
366
|
+
print_table(data["quotas"], [["Name", "Name"],
|
|
367
|
+
["Collection", "QuotaCollection"],
|
|
368
|
+
["Description", "ShortDescription"],
|
|
369
|
+
["Max Value", "MaxValue"],
|
|
370
|
+
["Used Value", "UsedValue"]])
|
|
371
|
+
print_table(data["subregions"], [["Region", "RegionName"],
|
|
372
|
+
["Availability Zone", "SubregionName"],
|
|
373
|
+
["State", "State"]])
|
|
374
|
+
|
|
375
|
+
else:
|
|
376
|
+
print_output(data, output)
|
|
366
377
|
|
|
367
378
|
|
|
368
379
|
# GET PROJECT SNAPSHOTS BY PROJECT NAME
|
|
369
380
|
@project.command('snapshots', help="Get project snapshots")
|
|
370
|
-
@click.option('--project-name', '-p', help="Name of the project")
|
|
381
|
+
@click.option('--project-name', '-p', help="Name of the project", shell_complete=project_completer)
|
|
371
382
|
@click.option('-o', '--output', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json")
|
|
372
383
|
@click.option('--profile', help="Configuration profile to use", shell_complete=profile_completer)
|
|
373
384
|
@click.pass_context
|
|
@@ -383,7 +394,7 @@ def project_get(ctx, project_name, output, profile):
|
|
|
383
394
|
|
|
384
395
|
# GET PUBLIC IPS BY PROJECT NAME
|
|
385
396
|
@project.command('publicips', help="Get project public ips")
|
|
386
|
-
@click.option('--project-name', '-p', help="Name of the project")
|
|
397
|
+
@click.option('--project-name', '-p', help="Name of the project", shell_complete=project_completer)
|
|
387
398
|
@click.option('-o', '--output', type=click.Choice(["json", "yaml"]), help="Specify output format, by default is json")
|
|
388
399
|
@click.option('--profile', help="Configuration profile to use")
|
|
389
400
|
@click.pass_context
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import prettytable
|
|
3
|
+
from .utils import do_request, print_output, print_table, ctx_update, login_profile, profile_completer
|
|
4
|
+
|
|
5
|
+
@click.command(help="Get Quotas")
|
|
6
|
+
@click.option("--profile", help="Configuration profile to use", shell_complete=profile_completer)
|
|
7
|
+
@click.option('-o', '--output', type=click.Choice(["json", "yaml", "table"]), help="Specify output format, by default is json")
|
|
8
|
+
@click.pass_context
|
|
9
|
+
def quotas(ctx, profile, output):
|
|
10
|
+
"""Retrieve global quotas across all projects for the given profile."""
|
|
11
|
+
_, _, profile = ctx_update(ctx, None, None, profile)
|
|
12
|
+
login_profile(profile)
|
|
13
|
+
|
|
14
|
+
data = do_request("GET", 'quotas')
|
|
15
|
+
if output == "table":
|
|
16
|
+
print_table([data], [["Projects", "Projects"],
|
|
17
|
+
["Clusters per project", "ClustersPerProject"],
|
|
18
|
+
["Kubernetes versions", "KubeVersions"],
|
|
19
|
+
["Control plane subregions", "CPSubregions"]])
|
|
20
|
+
else:
|
|
21
|
+
print_output(data, output)
|