drove-cli 0.0.3__tar.gz → 0.0.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drove-cli
3
- Version: 0.0.3
3
+ Version: 0.0.4
4
4
  Summary: Drove Command Line Interface
5
5
  License: Apache-2.0
6
6
  Keywords: container,docker,podman,distributed-systems,container-orchestrator
@@ -118,12 +118,11 @@ To see basic help:
118
118
 
119
119
  $ drove -h
120
120
 
121
- usage: drove [-h] [--file FILE] [--cluster CLUSTER] [--endpoint ENDPOINT] [--auth-header AUTH_HEADER] [--insecure] [--username USERNAME] [--password PASSWORD] [--debug]
122
- {lsinstances,executor,cluster,apps,appinstances,tasks,localservices} ...
123
-
121
+ usage: drove [-h] [--file FILE] [--cluster CLUSTER] [--endpoint ENDPOINT] [--auth-header AUTH_HEADER] [--insecure INSECURE] [--username USERNAME] [--password PASSWORD] [--debug]
122
+ {executor,cluster,apps,appinstances,tasks,config} ...
124
123
 
125
124
  positional arguments:
126
- {lsinstances,executor,cluster,apps,appinstances,tasks,localservices}
125
+ {executor,cluster,apps,appinstances,tasks,config}
127
126
  Available plugins
128
127
  lsinstances Drove local service instance related commands
129
128
  executor Drove cluster executor related commands
@@ -131,7 +130,7 @@ positional arguments:
131
130
  apps Drove application related commands
132
131
  appinstances Drove application instance related commands
133
132
  tasks Drove task related commands
134
- localservices Drove local service related commands
133
+ config Manage drove cluster configurations
135
134
 
136
135
  options:
137
136
  -h, --help show this help message and exit
@@ -220,6 +219,21 @@ auth_header = %(prod_token)s
220
219
  ..
221
220
  ```
222
221
 
222
+ ### Setting a Default Cluster
223
+ You can set a default cluster so you don't need to specify `-c cluster` on every command:
224
+
225
+ ```ini
226
+ [DEFAULT]
227
+ current_cluster = local
228
+ ...
229
+ ```
230
+
231
+ When `current_cluster` is set, commands will automatically use that cluster unless overridden with `-c`.
232
+
233
+ Priority order for cluster selection:
234
+
235
+ `-c cluster` command line flag >`current_cluster` in `[DEFAULT]` section > `DEFAULT` section endpoint
236
+
223
237
  The `DEFAULT` section can be used to define common variables like Insecure etc. The `local`, `stage`, `production` etc are names for individual clusters and these sections can be used to define configuration for individual clusters. Cluster name is referred to in the command line by using the `-c` command line option.\
224
238
  *Interpolation* of values is supported and can be achieved by using `%(variable_name)s` references.
225
239
 
@@ -274,8 +288,8 @@ $ drove -e http://localhost:10000 -u guest -p guest ...
274
288
  The following CLI format is followed:
275
289
 
276
290
  ```
277
- usage: drove [-h] [--file FILE] [--cluster CLUSTER] [--endpoint ENDPOINT] [--auth-header AUTH_HEADER] [--insecure] [--username USERNAME] [--password PASSWORD] [--debug]
278
- {executor,cluster,apps,appinstances,tasks} ...
291
+ usage: drove [-h] [--file FILE] [--cluster CLUSTER] [--endpoint ENDPOINT] [--auth-header AUTH_HEADER] [--insecure INSECURE] [--username USERNAME] [--password PASSWORD] [--debug]
292
+ {executor,cluster,apps,appinstances,tasks,config} ...
279
293
  ```
280
294
  ### Basic Arguments
281
295
  ```
@@ -1114,5 +1128,156 @@ drove lsinstances kill [-h] [--parallelism PARALLELISM] [--timeout TIMEOUT] serv
1114
1128
  --wait, -w Wait to ensure all instances are killed
1115
1129
  ```
1116
1130
 
1131
+ ### config
1132
+ ---
1133
+ Manage drove cluster configurations (similar to kubectl config). These commands do not require an active cluster connection.
1134
+
1135
+ ```shell
1136
+ drove config [-h] {get-clusters,current-cluster,use-cluster,view,init,add-cluster,delete-cluster} ...
1137
+ ```
1138
+
1139
+ #### Sub-commands
1140
+
1141
+ ##### get-clusters
1142
+
1143
+ List all configured clusters
1144
+
1145
+ ```shell
1146
+ drove config get-clusters [-h]
1147
+ ```
1148
+
1149
+ Example output:
1150
+ ```
1151
+ CURRENT NAME ENDPOINT AUTH INSECURE
1152
+ -----------------------------------------------------------------------------------------------
1153
+ * local http://localhost:4000 yes no
1154
+ stage http://stage.drove.com:4000 yes no
1155
+
1156
+ Current cluster: local
1157
+ ```
1158
+
1159
+ ##### current-cluster
1160
+
1161
+ Show the current default cluster
1162
+
1163
+ ```shell
1164
+ drove config current-cluster [-h]
1165
+ ```
1166
+
1167
+ ##### use-cluster
1168
+
1169
+ Set the default cluster. After setting, all commands will use this cluster unless overridden with `-c`.
1170
+
1171
+ ```shell
1172
+ drove config use-cluster [-h] cluster-name
1173
+ ```
1174
+
1175
+ ###### Positional Arguments
1176
+
1177
+ `cluster-name` - Name of the cluster to set as default
1178
+
1179
+ Example:
1180
+ ```shell
1181
+ $ drove config use-cluster stage
1182
+ Switched to cluster "stage".
1183
+ ```
1184
+
1185
+ ##### view
1186
+
1187
+ Display the full configuration file
1188
+
1189
+ ```shell
1190
+ drove config view [-h] [--raw]
1191
+ ```
1192
+
1193
+ ###### Named Arguments
1194
+
1195
+ ```
1196
+ --raw, -r Show raw config file content instead of formatted output
1197
+ ```
1198
+
1199
+ ##### init
1200
+
1201
+ Initialize a new `~/.drove` config file. Will fail if the file already exists.
1202
+
1203
+ ```shell
1204
+ drove config init [-h] --endpoint ENDPOINT [--name NAME] [--username USERNAME] [--password PASSWORD] [--auth-header AUTH_HEADER] [--insecure]
1205
+ ```
1206
+
1207
+ ###### Named Arguments
1208
+
1209
+ ```
1210
+ --endpoint ENDPOINT, -e ENDPOINT
1211
+ Drove endpoint URL (required)
1212
+ --name NAME, -n NAME Cluster name (default: "default")
1213
+ --username USERNAME, -u USERNAME
1214
+ Username for basic auth
1215
+ --password PASSWORD, -p PASSWORD
1216
+ Password for basic auth
1217
+ --auth-header AUTH_HEADER, -t AUTH_HEADER
1218
+ Authorization header value
1219
+ --insecure, -i Skip SSL verification
1220
+ ```
1221
+
1222
+ Example:
1223
+ ```shell
1224
+ $ drove config init -e http://localhost:4000 -n local -u admin -p admin
1225
+ Config initialized at: /home/user/.drove
1226
+ Current cluster set to: local
1227
+ ```
1228
+
1229
+ ##### add-cluster
1230
+
1231
+ Add a new cluster to the config file
1232
+
1233
+ ```shell
1234
+ drove config add-cluster [-h] --endpoint ENDPOINT [--username USERNAME] [--password PASSWORD] [--auth-header AUTH_HEADER] [--insecure] cluster-name
1235
+ ```
1236
+
1237
+ ###### Positional Arguments
1238
+
1239
+ `cluster-name` - Name for this cluster
1240
+
1241
+ ###### Named Arguments
1242
+
1243
+ ```
1244
+ --endpoint ENDPOINT, -e ENDPOINT
1245
+ Drove endpoint URL (required)
1246
+ --username USERNAME, -u USERNAME
1247
+ Username for basic auth
1248
+ --password PASSWORD, -p PASSWORD
1249
+ Password for basic auth
1250
+ --auth-header AUTH_HEADER, -t AUTH_HEADER
1251
+ Authorization header value
1252
+ --insecure, -i Skip SSL verification
1253
+ ```
1254
+
1255
+ Example:
1256
+ ```shell
1257
+ $ drove config add-cluster production -e https://prod.drove.com -t "Bearer <token>"
1258
+ Cluster 'production' added to /home/user/.drove
1259
+ ```
1260
+
1261
+ ##### delete-cluster
1262
+
1263
+ Remove a cluster from the config file
1264
+
1265
+ ```shell
1266
+ drove config delete-cluster [-h] cluster-name
1267
+ ```
1268
+
1269
+ ###### Positional Arguments
1270
+
1271
+ `cluster-name` - Name of the cluster to remove
1272
+
1273
+ Example:
1274
+ ```shell
1275
+ $ drove config delete-cluster stage
1276
+
1277
+ Cluster 'staging' deleted from /home/user/.drove
1278
+ ```
1279
+
1280
+ > **Note:** If you delete the current default cluster, it will be unset and you'll need to use `drove config use-cluster` to set a new default.
1281
+
1117
1282
  ©2024, Santanu Sinha.
1118
1283
 
@@ -85,12 +85,11 @@ To see basic help:
85
85
 
86
86
  $ drove -h
87
87
 
88
- usage: drove [-h] [--file FILE] [--cluster CLUSTER] [--endpoint ENDPOINT] [--auth-header AUTH_HEADER] [--insecure] [--username USERNAME] [--password PASSWORD] [--debug]
89
- {lsinstances,executor,cluster,apps,appinstances,tasks,localservices} ...
90
-
88
+ usage: drove [-h] [--file FILE] [--cluster CLUSTER] [--endpoint ENDPOINT] [--auth-header AUTH_HEADER] [--insecure INSECURE] [--username USERNAME] [--password PASSWORD] [--debug]
89
+ {executor,cluster,apps,appinstances,tasks,config} ...
91
90
 
92
91
  positional arguments:
93
- {lsinstances,executor,cluster,apps,appinstances,tasks,localservices}
92
+ {executor,cluster,apps,appinstances,tasks,config}
94
93
  Available plugins
95
94
  lsinstances Drove local service instance related commands
96
95
  executor Drove cluster executor related commands
@@ -98,7 +97,7 @@ positional arguments:
98
97
  apps Drove application related commands
99
98
  appinstances Drove application instance related commands
100
99
  tasks Drove task related commands
101
- localservices Drove local service related commands
100
+ config Manage drove cluster configurations
102
101
 
103
102
  options:
104
103
  -h, --help show this help message and exit
@@ -187,6 +186,21 @@ auth_header = %(prod_token)s
187
186
  ..
188
187
  ```
189
188
 
189
+ ### Setting a Default Cluster
190
+ You can set a default cluster so you don't need to specify `-c cluster` on every command:
191
+
192
+ ```ini
193
+ [DEFAULT]
194
+ current_cluster = local
195
+ ...
196
+ ```
197
+
198
+ When `current_cluster` is set, commands will automatically use that cluster unless overridden with `-c`.
199
+
200
+ Priority order for cluster selection:
201
+
202
+ `-c cluster` command line flag >`current_cluster` in `[DEFAULT]` section > `DEFAULT` section endpoint
203
+
190
204
  The `DEFAULT` section can be used to define common variables like Insecure etc. The `local`, `stage`, `production` etc are names for individual clusters and these sections can be used to define configuration for individual clusters. Cluster name is referred to in the command line by using the `-c` command line option.\
191
205
  *Interpolation* of values is supported and can be achieved by using `%(variable_name)s` references.
192
206
 
@@ -241,8 +255,8 @@ $ drove -e http://localhost:10000 -u guest -p guest ...
241
255
  The following CLI format is followed:
242
256
 
243
257
  ```
244
- usage: drove [-h] [--file FILE] [--cluster CLUSTER] [--endpoint ENDPOINT] [--auth-header AUTH_HEADER] [--insecure] [--username USERNAME] [--password PASSWORD] [--debug]
245
- {executor,cluster,apps,appinstances,tasks} ...
258
+ usage: drove [-h] [--file FILE] [--cluster CLUSTER] [--endpoint ENDPOINT] [--auth-header AUTH_HEADER] [--insecure INSECURE] [--username USERNAME] [--password PASSWORD] [--debug]
259
+ {executor,cluster,apps,appinstances,tasks,config} ...
246
260
  ```
247
261
  ### Basic Arguments
248
262
  ```
@@ -1081,4 +1095,155 @@ drove lsinstances kill [-h] [--parallelism PARALLELISM] [--timeout TIMEOUT] serv
1081
1095
  --wait, -w Wait to ensure all instances are killed
1082
1096
  ```
1083
1097
 
1098
+ ### config
1099
+ ---
1100
+ Manage drove cluster configurations (similar to kubectl config). These commands do not require an active cluster connection.
1101
+
1102
+ ```shell
1103
+ drove config [-h] {get-clusters,current-cluster,use-cluster,view,init,add-cluster,delete-cluster} ...
1104
+ ```
1105
+
1106
+ #### Sub-commands
1107
+
1108
+ ##### get-clusters
1109
+
1110
+ List all configured clusters
1111
+
1112
+ ```shell
1113
+ drove config get-clusters [-h]
1114
+ ```
1115
+
1116
+ Example output:
1117
+ ```
1118
+ CURRENT NAME ENDPOINT AUTH INSECURE
1119
+ -----------------------------------------------------------------------------------------------
1120
+ * local http://localhost:4000 yes no
1121
+ stage http://stage.drove.com:4000 yes no
1122
+
1123
+ Current cluster: local
1124
+ ```
1125
+
1126
+ ##### current-cluster
1127
+
1128
+ Show the current default cluster
1129
+
1130
+ ```shell
1131
+ drove config current-cluster [-h]
1132
+ ```
1133
+
1134
+ ##### use-cluster
1135
+
1136
+ Set the default cluster. After setting, all commands will use this cluster unless overridden with `-c`.
1137
+
1138
+ ```shell
1139
+ drove config use-cluster [-h] cluster-name
1140
+ ```
1141
+
1142
+ ###### Positional Arguments
1143
+
1144
+ `cluster-name` - Name of the cluster to set as default
1145
+
1146
+ Example:
1147
+ ```shell
1148
+ $ drove config use-cluster stage
1149
+ Switched to cluster "stage".
1150
+ ```
1151
+
1152
+ ##### view
1153
+
1154
+ Display the full configuration file
1155
+
1156
+ ```shell
1157
+ drove config view [-h] [--raw]
1158
+ ```
1159
+
1160
+ ###### Named Arguments
1161
+
1162
+ ```
1163
+ --raw, -r Show raw config file content instead of formatted output
1164
+ ```
1165
+
1166
+ ##### init
1167
+
1168
+ Initialize a new `~/.drove` config file. Will fail if the file already exists.
1169
+
1170
+ ```shell
1171
+ drove config init [-h] --endpoint ENDPOINT [--name NAME] [--username USERNAME] [--password PASSWORD] [--auth-header AUTH_HEADER] [--insecure]
1172
+ ```
1173
+
1174
+ ###### Named Arguments
1175
+
1176
+ ```
1177
+ --endpoint ENDPOINT, -e ENDPOINT
1178
+ Drove endpoint URL (required)
1179
+ --name NAME, -n NAME Cluster name (default: "default")
1180
+ --username USERNAME, -u USERNAME
1181
+ Username for basic auth
1182
+ --password PASSWORD, -p PASSWORD
1183
+ Password for basic auth
1184
+ --auth-header AUTH_HEADER, -t AUTH_HEADER
1185
+ Authorization header value
1186
+ --insecure, -i Skip SSL verification
1187
+ ```
1188
+
1189
+ Example:
1190
+ ```shell
1191
+ $ drove config init -e http://localhost:4000 -n local -u admin -p admin
1192
+ Config initialized at: /home/user/.drove
1193
+ Current cluster set to: local
1194
+ ```
1195
+
1196
+ ##### add-cluster
1197
+
1198
+ Add a new cluster to the config file
1199
+
1200
+ ```shell
1201
+ drove config add-cluster [-h] --endpoint ENDPOINT [--username USERNAME] [--password PASSWORD] [--auth-header AUTH_HEADER] [--insecure] cluster-name
1202
+ ```
1203
+
1204
+ ###### Positional Arguments
1205
+
1206
+ `cluster-name` - Name for this cluster
1207
+
1208
+ ###### Named Arguments
1209
+
1210
+ ```
1211
+ --endpoint ENDPOINT, -e ENDPOINT
1212
+ Drove endpoint URL (required)
1213
+ --username USERNAME, -u USERNAME
1214
+ Username for basic auth
1215
+ --password PASSWORD, -p PASSWORD
1216
+ Password for basic auth
1217
+ --auth-header AUTH_HEADER, -t AUTH_HEADER
1218
+ Authorization header value
1219
+ --insecure, -i Skip SSL verification
1220
+ ```
1221
+
1222
+ Example:
1223
+ ```shell
1224
+ $ drove config add-cluster production -e https://prod.drove.com -t "Bearer <token>"
1225
+ Cluster 'production' added to /home/user/.drove
1226
+ ```
1227
+
1228
+ ##### delete-cluster
1229
+
1230
+ Remove a cluster from the config file
1231
+
1232
+ ```shell
1233
+ drove config delete-cluster [-h] cluster-name
1234
+ ```
1235
+
1236
+ ###### Positional Arguments
1237
+
1238
+ `cluster-name` - Name of the cluster to remove
1239
+
1240
+ Example:
1241
+ ```shell
1242
+ $ drove config delete-cluster stage
1243
+
1244
+ Cluster 'staging' deleted from /home/user/.drove
1245
+ ```
1246
+
1247
+ > **Note:** If you delete the current default cluster, it will be unset and you'll need to use `drove config use-cluster` to set a new default.
1248
+
1084
1249
  ©2024, Santanu Sinha.
@@ -173,12 +173,19 @@ def build_drove_client(drove_client: DroveClient, args: SimpleNamespace):
173
173
  with open(config_file) as stream:
174
174
  config_parser.read_string(stream.read())
175
175
  drove_config = config_parser['DEFAULT']
176
- if args.cluster is not None:
177
- if args.cluster in config_parser:
178
- drove_config = config_parser[args.cluster]
176
+
177
+ # Determine which cluster to use (priority: -c flag > current_cluster in config > DEFAULT)
178
+ cluster_to_use = args.cluster
179
+ if cluster_to_use is None:
180
+ cluster_to_use = config_parser.defaults().get('current_cluster')
181
+
182
+ if cluster_to_use is not None and cluster_to_use != 'DEFAULT':
183
+ if cluster_to_use in config_parser:
184
+ drove_config = config_parser[cluster_to_use]
179
185
  else:
180
- print("error: No cluster definition found for {cluster} in config {config_file}".format(config_file=config_file, cluster=args.cluster))
186
+ print("error: No cluster definition found for {cluster} in config {config_file}".format(config_file=config_file, cluster=cluster_to_use))
181
187
  return None
188
+
182
189
  endpoint = drove_config.get("endpoint")
183
190
  username = drove_config.get("username")
184
191
  password = drove_config.get("password")
@@ -0,0 +1,314 @@
1
+ """
2
+ Config plugin for drove-cli - cluster configuration management.
3
+
4
+ This plugin adds 'drove config' commands for managing clusters, largely inspired by kubectl context management.
5
+ - drove config current-cluster : Show current default cluster
6
+ - drove config get-clusters : List all configured clusters
7
+ - drove config use-cluster <name> : Set default cluster
8
+ - drove config view : Show full config file
9
+ - drove config init : Initialize a new config file
10
+ - drove config add-cluster <name> : Add a new cluster to config
11
+ - drove config delete-cluster <name> : Remove a cluster from config
12
+
13
+
14
+ Usage:
15
+ drove config use-cluster local
16
+ """
17
+
18
+ import argparse
19
+ import configparser
20
+ import os
21
+ import plugins
22
+
23
+ from pathlib import Path
24
+ from types import SimpleNamespace
25
+
26
+
27
+ def get_config_file_path() -> str:
28
+ return str(Path.home()) + "/.drove"
29
+
30
+
31
+ def read_config() -> configparser.ConfigParser:
32
+ config_file = get_config_file_path()
33
+ config = configparser.ConfigParser()
34
+
35
+ if os.path.isfile(config_file) and os.access(config_file, os.R_OK):
36
+ with open(config_file) as stream:
37
+ config.read_string(stream.read())
38
+
39
+ return config
40
+
41
+
42
+ def write_config(config: configparser.ConfigParser) -> None:
43
+ config_file = get_config_file_path()
44
+ with open(config_file, 'w') as f:
45
+ config.write(f)
46
+
47
+
48
+ def get_current_cluster() -> str:
49
+ config = read_config()
50
+ return config.defaults().get('current_cluster')
51
+
52
+
53
+ def set_current_cluster(cluster_name: str) -> None:
54
+ config = read_config()
55
+ config.set('DEFAULT', 'current_cluster', cluster_name)
56
+ write_config(config)
57
+
58
+
59
+ def get_clusters_from_config(config: configparser.ConfigParser) -> list:
60
+ clusters = []
61
+ for section in config.sections():
62
+ endpoint = config[section].get('endpoint', '')
63
+ if endpoint:
64
+ clusters.append({
65
+ 'name': section,
66
+ 'endpoint': endpoint,
67
+ 'has_auth': bool(config[section].get('username') or config[section].get('auth_header')),
68
+ 'insecure': config[section].get('insecure', 'false').lower() == 'true'
69
+ })
70
+
71
+ if config.defaults().get('endpoint'):
72
+ clusters.insert(0, {
73
+ 'name': 'DEFAULT',
74
+ 'endpoint': config.defaults().get('endpoint'),
75
+ 'has_auth': bool(config.defaults().get('username') or config.defaults().get('auth_header')),
76
+ 'insecure': config.defaults().get('insecure', 'false').lower() == 'true'
77
+ })
78
+
79
+ return clusters
80
+
81
+
82
+ class Config(plugins.DrovePlugin):
83
+ """Plugin for config/context management commands."""
84
+
85
+ def __init__(self) -> None:
86
+ pass
87
+
88
+ def populate_options(self, drove_client, subparser: argparse.ArgumentParser):
89
+ parser = subparser.add_parser("config", help="Manage drove cluster configurations")
90
+ commands = parser.add_subparsers(help="Available config commands")
91
+
92
+ # get-clusters: List all available clusters
93
+ sub_parser = commands.add_parser("get-clusters", help="List all configured clusters")
94
+ sub_parser.set_defaults(func=self.get_clusters)
95
+
96
+ # current-cluster: Show current default
97
+ sub_parser = commands.add_parser("current-cluster", help="Show current default cluster")
98
+ sub_parser.set_defaults(func=self.current_cluster)
99
+
100
+ # use-cluster: Set default cluster
101
+ sub_parser = commands.add_parser("use-cluster", help="Set default cluster")
102
+ sub_parser.add_argument("cluster_name", metavar="cluster-name", help="Cluster name to use as default")
103
+ sub_parser.set_defaults(func=self.use_cluster)
104
+
105
+ # view: Show full config
106
+ sub_parser = commands.add_parser("view", help="Display the full configuration file")
107
+ sub_parser.add_argument("--raw", "-r", help="Show raw config file content", action="store_true")
108
+ sub_parser.set_defaults(func=self.view_config)
109
+
110
+ # init: Initialize config file
111
+ sub_parser = commands.add_parser("init", help="Initialize a new ~/.drove config file")
112
+ sub_parser.add_argument("--endpoint", "-e", help="Drove endpoint URL", required=True)
113
+ sub_parser.add_argument("--name", "-n", help="Cluster name", default="default")
114
+ sub_parser.add_argument("--username", "-u", help="Username for basic auth")
115
+ sub_parser.add_argument("--password", "-p", help="Password for basic auth")
116
+ sub_parser.add_argument("--auth-header", "-t", dest="auth_header", help="Authorization header value")
117
+ sub_parser.add_argument("--insecure", "-i", help="Skip SSL verification", action="store_true")
118
+ sub_parser.set_defaults(func=self.init_config)
119
+
120
+ # add-cluster: Add a new cluster to config
121
+ sub_parser = commands.add_parser("add-cluster", help="Add a new cluster to config")
122
+ sub_parser.add_argument("cluster_name", metavar="cluster-name", help="Name for this cluster")
123
+ sub_parser.add_argument("--endpoint", "-e", help="Drove endpoint URL", required=True)
124
+ sub_parser.add_argument("--username", "-u", help="Username for basic auth")
125
+ sub_parser.add_argument("--password", "-p", help="Password for basic auth")
126
+ sub_parser.add_argument("--auth-header", "-t", dest="auth_header", help="Authorization header value")
127
+ sub_parser.add_argument("--insecure", "-i", help="Skip SSL verification", action="store_true")
128
+ sub_parser.set_defaults(func=self.add_cluster)
129
+
130
+ # delete-cluster: Remove a cluster from config
131
+ sub_parser = commands.add_parser("delete-cluster", help="Remove a cluster from config")
132
+ sub_parser.add_argument("cluster_name", metavar="cluster-name", help="Cluster name to remove")
133
+ sub_parser.set_defaults(func=self.delete_cluster)
134
+
135
+ super().populate_options(drove_client, parser)
136
+
137
+ def get_clusters(self, options: SimpleNamespace):
138
+ config = read_config()
139
+ clusters = get_clusters_from_config(config)
140
+ current = get_current_cluster()
141
+
142
+ if not clusters:
143
+ print("No clusters configured. Run 'drove config init' to set up.")
144
+ return
145
+
146
+ print(f"{'CURRENT':<10} {'NAME':<20} {'ENDPOINT':<50} {'AUTH':<6} {'INSECURE':<8}")
147
+ print("-" * 95)
148
+
149
+ for cluster in clusters:
150
+ marker = "*" if cluster['name'] == current else ""
151
+ auth = "yes" if cluster['has_auth'] else "no"
152
+ insecure = "yes" if cluster['insecure'] else "no"
153
+ print(f"{marker:<10} {cluster['name']:<20} {cluster['endpoint']:<50} {auth:<6} {insecure:<8}")
154
+
155
+ if current:
156
+ print(f"\nCurrent cluster: {current}")
157
+
158
+ def current_cluster(self, options: SimpleNamespace):
159
+ current = get_current_cluster()
160
+ if current:
161
+ print(current)
162
+ else:
163
+ print("No current cluster set. Use 'drove config use-cluster <name>' to set one.")
164
+
165
+ def use_cluster(self, options: SimpleNamespace):
166
+ config = read_config()
167
+ cluster_name = options.cluster_name
168
+
169
+ # Validate cluster exists
170
+ valid_names = [s for s in config.sections()]
171
+ if cluster_name == 'DEFAULT':
172
+ if config.defaults().get('endpoint'):
173
+ valid_names.append('DEFAULT')
174
+
175
+ if cluster_name not in valid_names and cluster_name != 'DEFAULT':
176
+ print(f"Error: cluster '{cluster_name}' not found in config")
177
+ print(f"Available clusters: {', '.join(valid_names) if valid_names else 'none'}")
178
+ return
179
+
180
+ set_current_cluster(cluster_name)
181
+ print(f"Switched to cluster \"{cluster_name}\".")
182
+
183
+ def view_config(self, options: SimpleNamespace):
184
+ config_file = get_config_file_path()
185
+
186
+ if not os.path.isfile(config_file):
187
+ print(f"Config file not found: {config_file}")
188
+ print("Run 'drove config init' to create one.")
189
+ return
190
+
191
+ if options.raw:
192
+ with open(config_file, 'r') as f:
193
+ print(f.read())
194
+ else:
195
+ config = read_config()
196
+ current = get_current_cluster()
197
+
198
+ print(f"Config file: {config_file}")
199
+ print(f"Current cluster: {current or '(not set)'}")
200
+ print()
201
+
202
+ for section in ['DEFAULT'] + config.sections():
203
+ if section == 'DEFAULT':
204
+ items = dict(config.defaults())
205
+ else:
206
+ items = dict(config[section])
207
+
208
+ if not items.get('endpoint'):
209
+ continue
210
+
211
+ marker = " (current)" if section == current else ""
212
+ print(f"[{section}]{marker}")
213
+ for key, value in items.items():
214
+ # Mask sensitive values
215
+ if key in ('password', 'auth_header') and value:
216
+ display_value = value[:4] + "****" + value[-4:] if len(value) > 8 else "****"
217
+ else:
218
+ display_value = value
219
+ print(f" {key} = {display_value}")
220
+ print()
221
+
222
+ def init_config(self, options: SimpleNamespace):
223
+ config_file = get_config_file_path()
224
+
225
+ if os.path.isfile(config_file):
226
+ print(f"Config file already exists: {config_file}")
227
+ print("Use 'drove config add-context' to add more clusters.")
228
+ return
229
+
230
+ config = configparser.ConfigParser()
231
+ section = options.name if options.name != 'default' else 'DEFAULT'
232
+
233
+ if section != 'DEFAULT':
234
+ config.add_section(section)
235
+ config[section]
236
+ else:
237
+ config.defaults()
238
+
239
+ if section == 'DEFAULT':
240
+ config.set('DEFAULT', 'endpoint', options.endpoint)
241
+ if options.username:
242
+ config.set('DEFAULT', 'username', options.username)
243
+ if options.password:
244
+ config.set('DEFAULT', 'password', options.password)
245
+ if options.auth_header:
246
+ config.set('DEFAULT', 'auth_header', options.auth_header)
247
+ if options.insecure:
248
+ config.set('DEFAULT', 'insecure', 'true')
249
+ else:
250
+ config[section]['endpoint'] = options.endpoint
251
+ if options.username:
252
+ config[section]['username'] = options.username
253
+ if options.password:
254
+ config[section]['password'] = options.password
255
+ if options.auth_header:
256
+ config[section]['auth_header'] = options.auth_header
257
+ if options.insecure:
258
+ config[section]['insecure'] = 'true'
259
+
260
+ with open(config_file, 'w') as f:
261
+ config.write(f)
262
+
263
+ set_current_cluster(section)
264
+
265
+ print(f"Config initialized at: {config_file}")
266
+ print(f"Current cluster set to: {section}")
267
+
268
+ def add_cluster(self, options: SimpleNamespace):
269
+ """Add a new cluster."""
270
+ config = read_config()
271
+ cluster_name = options.cluster_name
272
+
273
+ if cluster_name in config.sections():
274
+ print(f"Error: cluster '{cluster_name}' already exists")
275
+ return
276
+
277
+ config.add_section(cluster_name)
278
+ config[cluster_name]['endpoint'] = options.endpoint
279
+ if options.username:
280
+ config[cluster_name]['username'] = options.username
281
+ if options.password:
282
+ config[cluster_name]['password'] = options.password
283
+ if options.auth_header:
284
+ config[cluster_name]['auth_header'] = options.auth_header
285
+ if options.insecure:
286
+ config[cluster_name]['insecure'] = 'true'
287
+
288
+ config_file = get_config_file_path()
289
+ with open(config_file, 'w') as f:
290
+ config.write(f)
291
+
292
+ print(f"Cluster '{cluster_name}' added to {config_file}")
293
+
294
+ def delete_cluster(self, options: SimpleNamespace):
295
+ config = read_config()
296
+ cluster_name = options.cluster_name
297
+
298
+ if cluster_name not in config.sections():
299
+ print(f"Error: cluster '{cluster_name}' not found")
300
+ return
301
+
302
+ config.remove_section(cluster_name)
303
+
304
+ config_file = get_config_file_path()
305
+ with open(config_file, 'w') as f:
306
+ config.write(f)
307
+
308
+ current = get_current_cluster()
309
+ if current == cluster_name:
310
+ config.remove_option('DEFAULT', 'current_cluster')
311
+ write_config(config)
312
+ print(f"Cluster '{cluster_name}' deleted and was current cluster (now unset)")
313
+ else:
314
+ print(f"Cluster '{cluster_name}' deleted from {config_file}")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "drove-cli"
3
- version = "0.0.3"
3
+ version = "0.0.4"
4
4
  description = "Drove Command Line Interface"
5
5
  authors = ["Santanu Sinha <santanu.sinha@gmail.com>"]
6
6
  maintainers = [
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes