snapctl 0.31.1__py3-none-any.whl → 0.32.1__py3-none-any.whl

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.

Potentially problematic release.


This version of snapctl might be problematic. Click here for more details.

@@ -1,7 +1,6 @@
1
1
  """
2
2
  Snapend CLI commands
3
3
  """
4
- from sys import platform
5
4
  from typing import Union
6
5
 
7
6
  import os
@@ -10,12 +9,20 @@ import time
10
9
  import requests
11
10
  from requests.exceptions import RequestException
12
11
 
12
+ import typer
13
13
  from rich.progress import Progress, SpinnerColumn, TextColumn
14
- from snapctl.config.constants import SERVER_CALL_TIMEOUT
14
+ from snapctl.config.constants import SERVER_CALL_TIMEOUT, SNAPCTL_INPUT_ERROR, \
15
+ SNAPCTL_SNAPEND_ENUMERATE_ERROR, SNAPCTL_SNAPEND_CLONE_SERVER_ERROR, \
16
+ SNAPCTL_SNAPEND_CLONE_TIMEOUT_ERROR, SNAPCTL_SUCCESS, SNAPCTL_SNAPEND_CLONE_ERROR, \
17
+ SNAPCTL_SNAPEND_APPLY_SERVER_ERROR, SNAPCTL_SNAPEND_APPLY_TIMEOUT_ERROR, \
18
+ SNAPCTL_SNAPEND_APPLY_ERROR, SNAPCTL_SNAPEND_PROMOTE_SERVER_ERROR, \
19
+ SNAPCTL_SNAPEND_PROMOTE_TIMEOUT_ERROR, SNAPCTL_SNAPEND_PROMOTE_ERROR, \
20
+ SNAPCTL_SNAPEND_DOWNLOAD_ERROR, SNAPCTL_SNAPEND_UPDATE_TIMEOUT_ERROR, \
21
+ SNAPCTL_SNAPEND_UPDATE_ERROR, SNAPCTL_SNAPEND_STATE_ERROR
15
22
  from snapctl.config.hashes import CLIENT_SDK_TYPES, SERVER_SDK_TYPES, PROTOS_TYPES, \
16
23
  SNAPEND_MANIFEST_TYPES
17
- from snapctl.types.definitions import ResponseType
18
24
  from snapctl.utils.echo import error, success, info
25
+ from snapctl.utils.helper import snapctl_error, snapctl_success
19
26
 
20
27
 
21
28
  class Snapend:
@@ -77,6 +84,10 @@ class Snapend:
77
84
  self.byogs_list: str | None = Snapend._make_byogs_list(
78
85
  byogs) if byogs else None
79
86
  self.blocking: bool = blocking
87
+ # Validate input
88
+ self.validate_input()
89
+
90
+ # Helpers
80
91
 
81
92
  @staticmethod
82
93
  def _get_manifest_file_name(manifest_path: str) -> str | None:
@@ -137,7 +148,7 @@ class Snapend:
137
148
  'state' in cluster_object['cluster']:
138
149
  return cluster_object['cluster']['state']
139
150
  except RequestException as e:
140
- error(f"Exception: Unable to get Snapend state {e}")
151
+ info(f"Exception: Unable to get Snapend state {e}")
141
152
  return 'INVALID'
142
153
 
143
154
  def _blocking_get_status(self) -> bool:
@@ -152,7 +163,7 @@ class Snapend:
152
163
  if current_state == 'LIVE':
153
164
  success('Updated your snapend. Your snapend is Live.')
154
165
  return True
155
- error(
166
+ info(
156
167
  f"Update not completed successfully. Your Snapend status is {current_state}.")
157
168
  return False
158
169
  info(f'Current snapend state is {current_state}')
@@ -215,13 +226,10 @@ class Snapend:
215
226
  f"snapser-{self.snapend_id}-{self.category}"
216
227
  f"-{self.platform_type}-{self.auth_type}.zip"
217
228
  )
218
- file_path_symbol = '/'
219
- if platform == 'win32':
220
- file_path_symbol = '\\'
221
229
  if self.out_path is not None:
222
- file_save_path = f"{self.out_path}{file_path_symbol}{fn}"
230
+ file_save_path = os.path.join(self.out_path, fn)
223
231
  else:
224
- file_save_path = f"{os.getcwd()}{file_path_symbol}{fn}"
232
+ file_save_path = os.path.join(os.getcwd(), fn)
225
233
  if res.ok:
226
234
  content: bytes = res.content
227
235
  with open(file_save_path, "wb") as file:
@@ -230,98 +238,105 @@ class Snapend:
230
238
  json.dump(content, file, indent=4)
231
239
  else:
232
240
  file.write(res.content)
233
- success(f"{self.category} saved at {file_save_path}")
234
241
  return True
235
- error(f'Unable to download {self.category}')
236
242
  except RequestException as e:
237
- error(
243
+ info(
238
244
  f"Exception: Unable to download {self.category}. Reason: {e}"
239
245
  )
240
246
  return False
241
247
 
242
- def validate_input(self) -> ResponseType:
248
+ # Validate input
249
+ def validate_input(self) -> None:
243
250
  """
244
251
  Validator
245
252
  """
246
- response: ResponseType = {
247
- 'error': True,
248
- 'msg': '',
249
- 'data': []
250
- }
251
253
  # Check API Key and Base URL
252
254
  if not self.api_key or self.base_url == '':
253
- response['msg'] = "Missing API Key."
254
- return response
255
+ snapctl_error("Missing API Key.", SNAPCTL_INPUT_ERROR)
255
256
  # Check subcommand
256
257
  if not self.subcommand in Snapend.SUBCOMMANDS:
257
- response['msg'] = \
258
- f"Invalid command. Valid commands are {', '.join(Snapend.SUBCOMMANDS)}."
259
- return response
258
+ snapctl_error(
259
+ f"Invalid command. Valid commands are {', '.join(Snapend.SUBCOMMANDS)}.",
260
+ SNAPCTL_INPUT_ERROR
261
+ )
260
262
  if self.subcommand == 'enumerate':
261
263
  if not self.game_id:
262
- response['msg'] = "Missing required parameter: game_id"
263
- return response
264
+ snapctl_error("Missing required parameter: game_id",
265
+ SNAPCTL_INPUT_ERROR)
264
266
  elif self.subcommand == 'clone':
265
267
  if not self.game_id:
266
- response['msg'] = "Missing required parameter: game_id"
267
- return response
268
+ snapctl_error("Missing required parameter: game_id",
269
+ SNAPCTL_INPUT_ERROR)
268
270
  if not self.name:
269
- response['msg'] = "Missing required parameter: name"
270
- return response
271
+ snapctl_error("Missing required parameter: name",
272
+ SNAPCTL_INPUT_ERROR)
271
273
  if self.env.upper() not in Snapend.ENV_TYPES:
272
- response['msg'] = (
274
+ snapctl_error(
273
275
  "Invalid environment. Valid environments are "
274
- f"{', '.join(Snapend.ENV_TYPES)}."
276
+ f"{', '.join(Snapend.ENV_TYPES)}.",
277
+ SNAPCTL_INPUT_ERROR
275
278
  )
276
- return response
277
279
  if not self.manifest_path:
278
- response['msg'] = "Missing required parameter: manifest_path"
279
- return response
280
+ snapctl_error(
281
+ "Missing required parameter: manifest_path", SNAPCTL_INPUT_ERROR)
280
282
  elif self.subcommand == 'apply':
281
283
  if not self.manifest_path:
282
- response['msg'] = "Missing required parameter: manifest_path"
283
- return response
284
+ snapctl_error(
285
+ "Missing required parameter: manifest_path", SNAPCTL_INPUT_ERROR)
286
+ raise typer.Exit(code=SNAPCTL_INPUT_ERROR)
284
287
  if not self.manifest_file_name:
285
- response['msg'] = "Invalid manifest file. Supported formats are .json, .yml, .yaml"
286
- return response
288
+ snapctl_error(
289
+ "Invalid manifest file. Supported formats are .json, .yml, .yaml",
290
+ SNAPCTL_INPUT_ERROR)
287
291
  elif self.subcommand == 'download':
292
+ if not self.snapend_id:
293
+ snapctl_error(
294
+ "Missing required parameter: snapend_id", SNAPCTL_INPUT_ERROR)
295
+ if not self.category:
296
+ snapctl_error(
297
+ "Missing required parameter: category", SNAPCTL_INPUT_ERROR)
288
298
  if self.category not in Snapend.DOWNLOAD_CATEGORY:
289
- response['msg'] = (
299
+ snapctl_error(
290
300
  "Invalid SDK category. Valid categories are "
291
- f"{', '.join(Snapend.DOWNLOAD_CATEGORY)}."
301
+ f"{', '.join(Snapend.DOWNLOAD_CATEGORY)}.",
302
+ SNAPCTL_INPUT_ERROR
292
303
  )
293
- return response
294
304
  if self.category not in Snapend.DOWNLOAD_TYPE_NOT_REQUIRED and \
295
305
  (self.download_types is None or self.platform_type not in self.download_types):
296
- response['msg'] = "Invalid Download type."
297
- return response
298
- # Check file path
299
- if self.out_path and not os.path.isdir(f"{self.out_path}"):
300
- response['msg'] = (
301
- f"Invalid path {self.out_path}. "
302
- "Please enter a valid path to save your output file"
303
- )
304
- return response
306
+ snapctl_error("Invalid Download type.", SNAPCTL_INPUT_ERROR)
305
307
  # Check the Protos category
306
308
  if self.category == 'protos' and self.protos_category not in Snapend.PROTOS_CATEGORY:
307
- response['msg'] = (
309
+ snapctl_error(
308
310
  "Invalid Protos category. Valid categories are "
309
- f"{', '.join(Snapend.PROTOS_CATEGORY)}."
311
+ f"{', '.join(Snapend.PROTOS_CATEGORY)}.",
312
+ SNAPCTL_INPUT_ERROR
310
313
  )
311
- return response
312
314
  # Check the auth type
313
315
  if self.category == 'server-sdk' and self.auth_type not in Snapend.AUTH_TYPES:
314
- response['msg'] = (
316
+ snapctl_error(
315
317
  "Invalid auth type. Valid auth types are "
316
- f"{', '.join(Snapend.AUTH_TYPES)}."
318
+ f"{', '.join(Snapend.AUTH_TYPES)}.",
319
+ SNAPCTL_INPUT_ERROR
320
+ )
321
+ # Check file path
322
+ if not self.out_path:
323
+ snapctl_error("Missing required parameter: out-path",
324
+ SNAPCTL_INPUT_ERROR)
325
+ if self.out_path and not os.path.isdir(f"{self.out_path}"):
326
+ snapctl_error(
327
+ f"Invalid path {self.out_path}. "
328
+ "Please enter a valid path to save your output file",
329
+ SNAPCTL_INPUT_ERROR
317
330
  )
318
- return response
319
331
  elif self.subcommand == 'promote':
320
332
  if not self.snapend_id:
321
- response['msg'] = "Missing required parameter: snapend_id"
322
- return response
333
+ snapctl_error(
334
+ "Missing required parameter: snapend_id", SNAPCTL_INPUT_ERROR)
323
335
  # Check update commands
324
336
  elif self.subcommand == 'update':
337
+ if not self.snapend_id:
338
+ snapctl_error(
339
+ "Missing required parameter: snapend_id", SNAPCTL_INPUT_ERROR)
325
340
  byosnap_present = True
326
341
  if self.byosnap_list is None or len(self.byosnap_list) == 0:
327
342
  byosnap_present = False
@@ -329,283 +344,348 @@ class Snapend:
329
344
  if self.byogs_list is None or len(self.byogs_list) == 0:
330
345
  byogs_present = False
331
346
  if not byosnap_present and not byogs_present:
332
- response['msg'] = "The update command needs one of byosnaps or byogs"
333
- return response
334
- # Send success
335
- response['error'] = False
336
- return response
347
+ snapctl_error(
348
+ "The update command needs one of byosnaps or byogs", SNAPCTL_INPUT_ERROR)
337
349
 
338
350
  ## Subcommands ##
339
- def enumerate(self) -> bool:
351
+ def enumerate(self) -> None:
340
352
  """
341
353
  List Snapends
342
354
  """
343
- with Progress(
355
+ progress = Progress(
344
356
  SpinnerColumn(),
345
357
  TextColumn("[progress.description]{task.description}"),
346
358
  transient=True,
347
- ) as progress:
348
- progress.add_task(
349
- description='Enumerating all your game snapends...', total=None)
350
- try:
351
- url = f"{self.base_url}/v1/snapser-api/snapends?game_id={self.game_id}"
352
- res = requests.get(
353
- url, headers={'api-key': self.api_key},
354
- timeout=SERVER_CALL_TIMEOUT
355
- )
356
- response_json = res.json()
357
- if res.ok:
358
- if 'clusters' in response_json:
359
- success(response_json['clusters'])
360
- return True
361
- error(response_json)
362
- except RequestException as e:
363
- error(f"Exception: Unable to update your snapend {e}")
364
- return False
359
+ )
360
+ progress.start()
361
+ progress.add_task(
362
+ description='Enumerating all your game snapends...', total=None)
363
+ try:
364
+ url = f"{self.base_url}/v1/snapser-api/snapends?game_id={self.game_id}"
365
+ res = requests.get(
366
+ url, headers={'api-key': self.api_key},
367
+ timeout=SERVER_CALL_TIMEOUT
368
+ )
369
+ response_json = res.json()
370
+ if res.ok and 'clusters' in response_json:
371
+ snapctl_success(response_json['clusters'], progress)
372
+ except RequestException:
373
+ snapctl_error("Snapctl Exception. Unable to enumerate snapends.",
374
+ SNAPCTL_SNAPEND_ENUMERATE_ERROR, progress)
375
+ snapctl_error("Unable to enumerate snapends.",
376
+ SNAPCTL_SNAPEND_ENUMERATE_ERROR, progress)
365
377
 
366
- def clone(self) -> bool:
378
+ def clone(self) -> None:
367
379
  """
368
380
  Create a Snapend from a manifest
369
381
  """
370
- with Progress(
382
+ progress = Progress(
371
383
  SpinnerColumn(),
372
384
  TextColumn("[progress.description]{task.description}"),
373
385
  transient=True,
374
- ) as progress:
375
- progress.add_task(
376
- description='Applying your manifest...', total=None)
377
- try:
378
- with open(self.manifest_path, 'rb') as file:
379
- files = {'snapend-manifest': file}
380
- payload = {
381
- 'game_id': self.game_id,
382
- 'name': self.name,
383
- 'env': self.env.upper(),
384
- 'ext': self.manifest_file_name.split('.')[-1]
385
- }
386
- url = f"{self.base_url}/v1/snapser-api/snapends/snapend-manifest"
387
- res = requests.post(
388
- url, headers={'api-key': self.api_key},
389
- files=files, data=payload, timeout=SERVER_CALL_TIMEOUT
390
- )
391
- if res.ok:
392
- # extract the cluster ID
393
- response = res.json()
394
- if 'cluster' not in response or 'id' not in response['cluster']:
395
- error(
396
- 'Something went wrong. Please try again in sometime.'
397
- )
398
- return False
399
- self._assign_snapend_id(response['cluster']['id'])
400
- info(
401
- f"Cluster ID assigned: {response['cluster']['id']}")
402
- if self.blocking:
403
- status = self._blocking_get_status()
404
- # Fetch the new manifest
405
- if status is True:
406
- # TODO: Uncomment this if we want to do an auto download
407
- # self._setup_for_download(
408
- # self.manifest_file_name.split('.')[-1])
409
- # self._execute_download()
410
- info(
411
- 'Do not forget to download the latest manifest.'
412
- )
413
- return True
414
- info(
415
- 'Snapend clone has been initiated but the Snapend is not up yet.'
416
- 'Please try checking the status of the Snapend in some time'
417
- )
418
- return False
419
- info(
420
- "Snapend clone has been initiated. "
421
- "You can check the status using "
422
- f"`snapctl snapend state --snapend-id {response['cluster']['id']}`"
386
+ )
387
+ progress.start()
388
+ progress.add_task(
389
+ description='Cloning your snapend from the manifest...', total=None)
390
+ try:
391
+ with open(self.manifest_path, 'rb') as file:
392
+ files = {'snapend-manifest': file}
393
+ payload = {
394
+ 'game_id': self.game_id,
395
+ 'name': self.name,
396
+ 'env': self.env.upper(),
397
+ 'ext': self.manifest_file_name.split('.')[-1]
398
+ }
399
+ url = f"{self.base_url}/v1/snapser-api/snapends/snapend-manifest"
400
+ res = requests.post(
401
+ url, headers={'api-key': self.api_key},
402
+ files=files, data=payload, timeout=SERVER_CALL_TIMEOUT
403
+ )
404
+ if res.ok:
405
+ # extract the cluster ID
406
+ response = res.json()
407
+ if 'cluster' not in response or 'id' not in response['cluster']:
408
+ snapctl_error(
409
+ 'Server Error. Unable to get a Snapend ID. '
410
+ 'Please try again in sometime.',
411
+ SNAPCTL_SNAPEND_CLONE_SERVER_ERROR,
412
+ progress
413
+ )
414
+ self._assign_snapend_id(response['cluster']['id'])
415
+ info(
416
+ f"Cluster ID assigned: {response['cluster']['id']}")
417
+ if self.blocking:
418
+ status = self._blocking_get_status()
419
+ # Fetch the new manifest
420
+ if status is True:
421
+ # TODO: Uncomment this if we want to do an auto download
422
+ # self._setup_for_download(
423
+ # self.manifest_file_name.split('.')[-1])
424
+ # self._execute_download()
425
+ snapctl_success(
426
+ 'Snapend clone successful. Do not forget to download the latest manifest.',
427
+ progress)
428
+ snapctl_error(
429
+ 'Snapend clone has been initiated but the Snapend is not up yet.'
430
+ 'Please try checking the status of the Snapend in some time',
431
+ SNAPCTL_SNAPEND_CLONE_TIMEOUT_ERROR,
432
+ progress
423
433
  )
424
- return True
425
- error('Unable to apply the manifest. Reason: ' + res.text)
426
- except RequestException as e:
427
- error(f"Exception: Unable to apply the manifest snapend {e}")
428
- return False
434
+ snapctl_success(
435
+ "Snapend clone has been initiated. "
436
+ "You can check the status using "
437
+ f"`snapctl snapend state --snapend-id {response['cluster']['id']}`",
438
+ progress
439
+ )
440
+ except RequestException as e:
441
+ snapctl_error(
442
+ f"Unable to apply the manifest snapend. {e}",
443
+ SNAPCTL_SNAPEND_CLONE_ERROR, progress
444
+ )
445
+ snapctl_error('Unable to apply the manifest.',
446
+ SNAPCTL_SNAPEND_CLONE_ERROR, progress)
429
447
 
430
- def apply(self) -> bool:
448
+ def apply(self) -> None:
431
449
  """
432
450
  Apply a manifest
433
451
  """
434
- with Progress(
452
+ progress = Progress(
435
453
  SpinnerColumn(),
436
454
  TextColumn("[progress.description]{task.description}"),
437
455
  transient=True,
438
- ) as progress:
439
- progress.add_task(
440
- description='Applying your manifest...', total=None)
441
- try:
442
- with open(self.manifest_path, 'rb') as file:
443
- files = {'snapend-manifest': file}
444
- payload = {
445
- 'ext': self.manifest_file_name.split('.')[-1]
446
- }
447
- url = f"{self.base_url}/v1/snapser-api/snapends/snapend-manifest"
448
- res = requests.put(
449
- url, headers={'api-key': self.api_key},
450
- files=files, data=payload, timeout=SERVER_CALL_TIMEOUT
451
- )
452
- if res.ok:
453
- # extract the cluster ID
454
- response = res.json()
455
- if 'cluster' not in response or 'id' not in response['cluster']:
456
- error(
457
- 'Something went wrong. Please try again in sometime.'
458
- )
459
- return False
460
- self._assign_snapend_id(response['cluster']['id'])
461
- if self.blocking:
462
- status = self._blocking_get_status()
463
- # Fetch the new manifest
464
- if status is True:
465
- # TODO: Uncomment this if we want to do an auto download
466
- # self._setup_for_download(
467
- # self.manifest_file_name.split('.')[-1])
468
- # self._execute_download()
469
- info(
470
- 'Do not forget to download the latest manifest.'
471
- )
472
- return True
473
- info(
474
- 'Snapend apply has been initiated but the Snapend is not up yet.'
475
- 'Please try checking the status of the Snapend in some time'
476
- )
477
- return False
478
- info(
479
- "Snapend apply has been initiated. "
480
- "You can check the status using "
481
- f"`snapctl snapend state --snapend-id {response['cluster']['id']}`"
456
+ )
457
+ progress.start()
458
+ progress.add_task(
459
+ description='Applying your manifest...', total=None)
460
+ try:
461
+ with open(self.manifest_path, 'rb') as file:
462
+ files = {'snapend-manifest': file}
463
+ payload = {
464
+ 'ext': self.manifest_file_name.split('.')[-1]
465
+ }
466
+ url = f"{self.base_url}/v1/snapser-api/snapends/snapend-manifest"
467
+ res = requests.put(
468
+ url, headers={'api-key': self.api_key},
469
+ files=files, data=payload, timeout=SERVER_CALL_TIMEOUT
470
+ )
471
+ if res.ok:
472
+ # extract the cluster ID
473
+ response = res.json()
474
+ if 'cluster' not in response or 'id' not in response['cluster']:
475
+ snapctl_error(
476
+ 'Server Error. Unable to get a Snapend ID. '
477
+ 'Please try again in sometime.',
478
+ SNAPCTL_SNAPEND_APPLY_SERVER_ERROR,
479
+ progress
482
480
  )
483
- return True
484
- error('Unable to apply the manifest. Reason: ' + res.text)
485
- except RequestException as e:
486
- error(f"Exception: Unable to apply the manifest snapend {e}")
487
- return False
481
+ self._assign_snapend_id(response['cluster']['id'])
482
+ if self.blocking:
483
+ status = self._blocking_get_status()
484
+ # Fetch the new manifest
485
+ if status is True:
486
+ # TODO: Uncomment this if we want to do an auto download
487
+ # self._setup_for_download(
488
+ # self.manifest_file_name.split('.')[-1])
489
+ # self._execute_download()
490
+ snapctl_success(
491
+ 'Snapend apply successful. Do not forget to download '
492
+ 'the latest manifest.',
493
+ progress)
494
+ snapctl_error(
495
+ 'Snapend apply has been initiated but the Snapend is not up yet.'
496
+ 'Please try checking the status of the Snapend in some time',
497
+ SNAPCTL_SNAPEND_APPLY_TIMEOUT_ERROR, progress
498
+ )
499
+ snapctl_success(
500
+ "Snapend apply has been initiated. "
501
+ "You can check the status using "
502
+ f"`snapctl snapend state --snapend-id {response['cluster']['id']}`",
503
+ progress
504
+ )
505
+ except RequestException as e:
506
+ snapctl_error(
507
+ f"Unable to apply the manifest snapend. {e}",
508
+ SNAPCTL_SNAPEND_APPLY_ERROR, progress
509
+ )
510
+ snapctl_error(
511
+ 'Unable to apply the manifest.', SNAPCTL_SNAPEND_APPLY_ERROR, progress)
488
512
 
489
- def promote(self) -> bool:
513
+ def promote(self) -> None:
490
514
  """
491
515
  Promote a staging manifest to production
492
516
  """
493
- with Progress(
517
+ progress = Progress(
494
518
  SpinnerColumn(),
495
519
  TextColumn("[progress.description]{task.description}"),
496
520
  transient=True,
497
- ) as progress:
498
- progress.add_task(
499
- description='Promoting your staging snapend...', total=None)
500
- try:
501
- with open(self.manifest_path, 'rb') as file:
502
- payload = {
503
- 'snapend_id': self.snapend_id
504
- }
505
- url = f"{self.base_url}/v1/snapser-api/snapends/promote"
506
- res = requests.put(
507
- url, headers={'api-key': self.api_key},
508
- json=payload, timeout=SERVER_CALL_TIMEOUT
509
- )
510
- if res.ok:
511
- # extract the cluster ID
512
- response = res.json()
513
- if 'cluster' not in response or 'id' not in response['cluster']:
514
- error(
515
- 'Something went wrong. Please try again in sometime.'
516
- )
517
- return False
518
- self._assign_snapend_id(response['cluster']['id'])
519
- if self.blocking:
520
- status = self._blocking_get_status()
521
- if status is True:
522
- # TODO: Uncomment this if we want to do an auto download
523
- # self._setup_for_download(
524
- # self.manifest_file_name.split('.')[-1])
525
- # self._execute_download()
526
- # Fetch the new manifest
527
- info(
528
- 'Do not forget to download the latest manifest.'
529
- )
530
- return True
531
- info(
532
- 'Snapend apply has been initiated but the Snapend is not up yet.'
533
- 'Please try checking the status of the Snapend in some time'
521
+ )
522
+ progress.start()
523
+ progress.add_task(
524
+ description='Promoting your staging snapend...', total=None)
525
+ try:
526
+ with open(self.manifest_path, 'rb') as file:
527
+ payload = {
528
+ 'snapend_id': self.snapend_id
529
+ }
530
+ url = f"{self.base_url}/v1/snapser-api/snapends/promote"
531
+ res = requests.put(
532
+ url, headers={'api-key': self.api_key},
533
+ json=payload, timeout=SERVER_CALL_TIMEOUT
534
+ )
535
+ if res.ok:
536
+ # extract the cluster ID
537
+ response = res.json()
538
+ if 'cluster' not in response or 'id' not in response['cluster']:
539
+ snapctl_error(
540
+ 'Server Error. Unable to get a Snapend ID. '
541
+ 'Please try again in sometime.',
542
+ SNAPCTL_SNAPEND_PROMOTE_SERVER_ERROR,
543
+ progress
544
+ )
545
+ self._assign_snapend_id(response['cluster']['id'])
546
+ if self.blocking:
547
+ status = self._blocking_get_status()
548
+ if status is True:
549
+ # TODO: Uncomment this if we want to do an auto download
550
+ # self._setup_for_download(
551
+ # self.manifest_file_name.split('.')[-1])
552
+ # self._execute_download()
553
+ # Fetch the new manifest
554
+ snapctl_success(
555
+ 'Snapend promote successful. Do not forget to '
556
+ 'download the latest manifest.',
557
+ progress
534
558
  )
535
- return False
536
- info(
537
- "Snapend apply has been initiated. "
538
- "You can check the status using "
539
- f"`snapctl snapend state --snapend-id {response['cluster']['id']}`"
559
+ snapctl_error(
560
+ 'Snapend apply has been initiated but the Snapend is not up yet.'
561
+ 'Please try checking the status of the Snapend in some time',
562
+ SNAPCTL_SNAPEND_PROMOTE_TIMEOUT_ERROR,
563
+ progress
540
564
  )
541
- return True
542
- error('Unable to promote the manifest. Reason: ' + res.text)
543
- except RequestException as e:
544
- error(f"Exception: Unable to apply the manifest snapend {e}")
545
- return False
565
+ snapctl_success(
566
+ "Snapend apply has been initiated. "
567
+ "You can check the status using "
568
+ f"`snapctl snapend state --snapend-id {response['cluster']['id']}`",
569
+ progress
570
+ )
571
+ snapctl_error(f'Unable to promote the manifest. Reason: {res.text}',
572
+ SNAPCTL_SNAPEND_PROMOTE_ERROR, progress)
573
+ except RequestException as e:
574
+ snapctl_error(
575
+ f"Unable to promote the snapend. {e}",
576
+ SNAPCTL_SNAPEND_PROMOTE_ERROR, progress
577
+ )
578
+ snapctl_error("Unable to promote the snapend.",
579
+ SNAPCTL_SNAPEND_PROMOTE_ERROR, progress)
546
580
 
547
- def download(self) -> bool:
581
+ def download(self) -> None:
548
582
  """
549
583
  Download SDKs, Protos, Admin Settings and Configuration
550
584
  """
551
- with Progress(
585
+ progress = Progress(
552
586
  SpinnerColumn(),
553
587
  TextColumn("[progress.description]{task.description}"),
554
588
  transient=True,
555
- ) as progress:
556
- progress.add_task(
557
- description=f'Downloading your Custom {self.category}...', total=None)
558
- return self._execute_download()
589
+ )
590
+ progress.start()
591
+ progress.add_task(
592
+ description=f'Downloading your Custom {self.category}...', total=None)
593
+ try:
594
+ if self._execute_download():
595
+ snapctl_success(
596
+ f"Snapend download successful. {self.category} saved at {self.out_path}",
597
+ progress
598
+ )
599
+ except RequestException as e:
600
+ snapctl_error(
601
+ f"Unable to download {self.category}. Reason: {e}",
602
+ SNAPCTL_SNAPEND_DOWNLOAD_ERROR, progress
603
+ )
604
+ snapctl_error(f"Unable to download {self.category}",
605
+ SNAPCTL_SNAPEND_DOWNLOAD_ERROR, progress)
559
606
 
560
- def update(self) -> bool:
607
+ def update(self) -> None:
561
608
  """
562
609
  Update a Snapend
563
610
  """
564
- with Progress(
611
+ progress = Progress(
565
612
  SpinnerColumn(),
566
613
  TextColumn("[progress.description]{task.description}"),
567
614
  transient=True,
568
- ) as progress:
569
- progress.add_task(
570
- description='Updating your Snapend...', total=None)
571
- try:
572
- payload = {
573
- 'byosnap_updates': self.byosnap_list,
574
- 'byogs_updates': self.byogs_list
575
- }
576
- url = f"{self.base_url}/v1/snapser-api/snapends/{self.snapend_id}"
577
- res = requests.patch(
578
- url, json=payload, headers={'api-key': self.api_key},
579
- timeout=SERVER_CALL_TIMEOUT
580
- )
581
- if res.ok:
582
- if self.blocking:
583
- return self._blocking_get_status()
584
- success(
615
+ )
616
+ progress.start()
617
+ progress.add_task(
618
+ description='Updating your Snapend...', total=None)
619
+ try:
620
+ payload = {
621
+ 'byosnap_updates': self.byosnap_list,
622
+ 'byogs_updates': self.byogs_list
623
+ }
624
+ url = f"{self.base_url}/v1/snapser-api/snapends/{self.snapend_id}"
625
+ res = requests.patch(
626
+ url, json=payload, headers={'api-key': self.api_key},
627
+ timeout=SERVER_CALL_TIMEOUT
628
+ )
629
+ if res.ok:
630
+ if self.blocking:
631
+ status = self._blocking_get_status()
632
+ # Fetch the new manifest
633
+ if status is True:
634
+ # TODO: Uncomment this if we want to do an auto download
635
+ # self._setup_for_download(
636
+ # self.manifest_file_name.split('.')[-1])
637
+ # self._execute_download()
638
+ snapctl_success(
639
+ 'Snapend update successful. Do not forget to '
640
+ 'download the latest manifest.',
641
+ progress
642
+ )
643
+ snapctl_error(
585
644
  'Snapend update has been initiated. '
586
- 'You can check the status using `snapctl snapend state`'
645
+ 'You can check the status using `snapctl snapend state`',
646
+ SNAPCTL_SNAPEND_UPDATE_TIMEOUT_ERROR,
647
+ progress
587
648
  )
588
- return True
589
- response_json = res.json()
590
- error(response_json['details'][0])
591
- except RequestException as e:
592
- error(f"Exception: Unable to update your snapend {e}")
593
- return False
649
+ snapctl_success(
650
+ "Snapend update has been initiated. "
651
+ "You can check the status using "
652
+ f"`snapctl snapend state --snapend-id {self.snapend_id}`",
653
+ progress
654
+ )
655
+ snapctl_error(f"Unable to update the snapend. Reason: {res.text}",
656
+ SNAPCTL_SNAPEND_UPDATE_ERROR, progress)
657
+ except RequestException as e:
658
+ snapctl_error(
659
+ f"Unable to update the snapend {e}",
660
+ SNAPCTL_SNAPEND_UPDATE_ERROR, progress
661
+ )
662
+ snapctl_error("Unable to update the snapend.",
663
+ SNAPCTL_SNAPEND_UPDATE_ERROR, progress)
594
664
 
595
- def state(self) -> bool:
665
+ def state(self) -> None:
596
666
  """
597
667
  Get the state of a Snapend
598
668
  """
599
- with Progress(
669
+ progress = Progress(
600
670
  SpinnerColumn(),
601
671
  TextColumn("[progress.description]{task.description}"),
602
672
  transient=True,
603
- ) as progress:
604
- progress.add_task(
605
- description='Getting your Snapend state...', total=None)
673
+ )
674
+ progress.start()
675
+ progress.add_task(
676
+ description='Getting your Snapend state...', total=None)
677
+ try:
606
678
  current_state = self._get_snapend_state()
607
679
  if current_state != 'INVALID':
608
- success('Current snapend state is: ' + current_state)
609
- return True
610
- error("Unable to get the snapend state.")
611
- return False
680
+ snapctl_success(
681
+ f'Snapend get state successful. Current snapend state is: {current_state}',
682
+ progress)
683
+ snapctl_error("Unable to get the snapend state.",
684
+ SNAPCTL_SNAPEND_STATE_ERROR, progress)
685
+ except RequestException as e:
686
+ snapctl_error(
687
+ f"Unable to get your snapend state {e}",
688
+ SNAPCTL_SNAPEND_STATE_ERROR, progress
689
+ )
690
+ snapctl_error("Unable to get the snapend state.",
691
+ SNAPCTL_SNAPEND_STATE_ERROR, progress)