snapctl 0.38.0__tar.gz → 0.38.2__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.

Potentially problematic release.


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

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: snapctl
3
- Version: 0.38.0
3
+ Version: 0.38.2
4
4
  Summary: Snapser CLI Tool
5
5
  Author: Ajinkya Apte
6
6
  Author-email: aj@snapser.com
@@ -17,7 +17,10 @@ Requires-Dist: requests (>=2.28.2,<3.0.0)
17
17
  Requires-Dist: typer[all] (>=0.12.3,<0.13.0)
18
18
  Description-Content-Type: text/markdown
19
19
 
20
- # Snapser CLI Tool
20
+ # Snapser CLI
21
+
22
+ Snapser has developed a CLI tool called **snapctl** that can be used on MaxOSX, Linux and Windows machines.
23
+ Snapctl will be the best way for game studios to integrate Snapser into their build pipelines.
21
24
 
22
25
  ## Dependencies
23
26
 
@@ -53,12 +56,10 @@ If you also have Python 2.X on your machine, you may have to run the following c
53
56
  pip3 install --user snapctl
54
57
  ```
55
58
 
56
- <Note>
57
- After you install snapctl you may have to add the python bin folder to your
58
- path. For example, on MacOSX this is usually **~/Library/Python/3.9/bin**. On
59
- Windows this is usually
60
- **C:\Users\username\AppData\Roaming\Python\Python39\Scripts**.
61
- </Note>
59
+ **IMPORTANT**: After you install snapctl you may have to add the python bin folder to your
60
+ path. For example, on MacOSX this is usually **~/Library/Python/3.9/bin**. On
61
+ Windows this is usually
62
+ **C:\Users\username\AppData\Roaming\Python\Python39\Scripts**.
62
63
 
63
64
  ## Upgrade
64
65
 
@@ -77,10 +78,8 @@ In the left navigation click on **Developer** which will bring up your Personal
77
78
  If you have not generated an API Key yet click on the **Generate** button to generate a new key.
78
79
  You can generate up to 3 API Keys per user account.
79
80
 
80
- <Note>
81
- Please make sure you save your API key in a safe place. You will not be able
82
- to see it again.
83
- </Note>
81
+ **IMPORTANT**: Please make sure you save your API key in a safe place. You will not be able
82
+ to see it again.
84
83
 
85
84
  ### Setup a local config
86
85
 
@@ -288,6 +287,9 @@ snapctl byosnap publish-image $byosnap_sid --tag $image_tag --skip-build
288
287
  Publish a new version for your Snap. Only after your Snap version is published, you will be able
289
288
  to use your snap in your Snapend. This command should be run after `push` or `publish-image` commands.
290
289
 
290
+ IMPORTANT: You need to have $byosnapProfile to run this command. BYOSnap profile is a JSON configuration
291
+ of your BYOSnap for the development, staging and production environments.
292
+
291
293
  ```
292
294
  # Help for the byosnap command
293
295
  snapctl byosnap publish-version --help
@@ -619,3 +621,93 @@ snapctl snapend state $snapend_id
619
621
  | 81 | Generate profile error |
620
622
  | 82 | Generate credentials error |
621
623
 
624
+
625
+
626
+ ## CLI Return Codes
627
+
628
+ | Error Code | Description |
629
+ |------------|----------------------------------------------------------|
630
+ | 0 | Operation completed successfully |
631
+ | 1 | General error |
632
+ | 2 | Input error |
633
+
634
+ ### Configuration Errors
635
+
636
+ | Error Code | Description |
637
+ |------------|----------------------------------------------------------|
638
+ | 10 | Configuration incorrect |
639
+ | 11 | Configuration error |
640
+ | 12 | Dependency missing |
641
+
642
+ ### BYOGS Errors
643
+
644
+ | Error Code | Description |
645
+ |------------|----------------------------------------------------------|
646
+ | 20 | Generic BYOGS error |
647
+ | 21 | BYOGS dependency missing |
648
+ | 22 | BYOGS ECR login error |
649
+ | 23 | BYOGS build error |
650
+ | 24 | BYOGS tag error |
651
+ | 25 | BYOGS publish error |
652
+ | 26 | BYOGS publish permission error |
653
+ | 27 | BYOGS publish duplicate tag error |
654
+
655
+ ### BYOSNAP Errors
656
+
657
+ | Error Code | Description |
658
+ |------------|----------------------------------------------------------|
659
+ | 30 | Generic BYOSNAP error |
660
+ | 31 | BYOSNAP dependency missing |
661
+ | 32 | BYOSNAP ECR login error |
662
+ | 33 | BYOSNAP build error |
663
+ | 34 | BYOSNAP tag error |
664
+ | 35 | BYOSNAP publish image error |
665
+ | 36 | BYOSNAP publish image permission error |
666
+ | 37 | BYOSNAP publish image duplicate tag error |
667
+ | 38 | BYOSNAP create error |
668
+ | 39 | BYOSNAP create permission error |
669
+ | 40 | BYOSNAP create duplicate name error |
670
+ | 41 | BYOSNAP publish version error |
671
+ | 42 | BYOSNAP publish version permission error |
672
+ | 43 | BYOSNAP publish version duplicate version error |
673
+ | 44 | BYOSNAP publish version duplicate tag error |
674
+
675
+ ### Game Errors
676
+
677
+ | Error Code | Description |
678
+ |------------|----------------------------------------------------------|
679
+ | 50 | Generic game error |
680
+ | 51 | Game create error |
681
+ | 52 | Game create permission error |
682
+ | 53 | Game create duplicate name error |
683
+ | 54 | Game enumerate error |
684
+
685
+ ### Snapend Errors
686
+
687
+ | Error Code | Description |
688
+ |------------|----------------------------------------------------------|
689
+ | 60 | Generic snapend error |
690
+ | 61 | Snapend enumerate error |
691
+ | 62 | Snapend clone error |
692
+ | 63 | Snapend clone server error |
693
+ | 64 | Snapend clone timeout error |
694
+ | 65 | Snapend apply error |
695
+ | 66 | Snapend apply server error |
696
+ | 67 | Snapend apply timeout error |
697
+ | 68 | Snapend promote error |
698
+ | 69 | Snapend promote server error |
699
+ | 70 | Snapend promote timeout error |
700
+ | 71 | Snapend download error |
701
+ | 72 | Snapend update error |
702
+ | 73 | Snapend update server error |
703
+ | 74 | Snapend update timeout error |
704
+ | 75 | Snapend state error |
705
+
706
+ ### Generate Errors
707
+
708
+ | Error Code | Description |
709
+ |------------|----------------------------------------------------------|
710
+ | 80 | Generic generate error |
711
+ | 81 | Generate profile error |
712
+ | 82 | Generate credentials error |
713
+
@@ -1,4 +1,7 @@
1
- # Snapser CLI Tool
1
+ # Snapser CLI
2
+
3
+ Snapser has developed a CLI tool called **snapctl** that can be used on MaxOSX, Linux and Windows machines.
4
+ Snapctl will be the best way for game studios to integrate Snapser into their build pipelines.
2
5
 
3
6
  ## Dependencies
4
7
 
@@ -34,12 +37,10 @@ If you also have Python 2.X on your machine, you may have to run the following c
34
37
  pip3 install --user snapctl
35
38
  ```
36
39
 
37
- <Note>
38
- After you install snapctl you may have to add the python bin folder to your
39
- path. For example, on MacOSX this is usually **~/Library/Python/3.9/bin**. On
40
- Windows this is usually
41
- **C:\Users\username\AppData\Roaming\Python\Python39\Scripts**.
42
- </Note>
40
+ **IMPORTANT**: After you install snapctl you may have to add the python bin folder to your
41
+ path. For example, on MacOSX this is usually **~/Library/Python/3.9/bin**. On
42
+ Windows this is usually
43
+ **C:\Users\username\AppData\Roaming\Python\Python39\Scripts**.
43
44
 
44
45
  ## Upgrade
45
46
 
@@ -58,10 +59,8 @@ In the left navigation click on **Developer** which will bring up your Personal
58
59
  If you have not generated an API Key yet click on the **Generate** button to generate a new key.
59
60
  You can generate up to 3 API Keys per user account.
60
61
 
61
- <Note>
62
- Please make sure you save your API key in a safe place. You will not be able
63
- to see it again.
64
- </Note>
62
+ **IMPORTANT**: Please make sure you save your API key in a safe place. You will not be able
63
+ to see it again.
65
64
 
66
65
  ### Setup a local config
67
66
 
@@ -269,6 +268,9 @@ snapctl byosnap publish-image $byosnap_sid --tag $image_tag --skip-build
269
268
  Publish a new version for your Snap. Only after your Snap version is published, you will be able
270
269
  to use your snap in your Snapend. This command should be run after `push` or `publish-image` commands.
271
270
 
271
+ IMPORTANT: You need to have $byosnapProfile to run this command. BYOSnap profile is a JSON configuration
272
+ of your BYOSnap for the development, staging and production environments.
273
+
272
274
  ```
273
275
  # Help for the byosnap command
274
276
  snapctl byosnap publish-version --help
@@ -599,3 +601,93 @@ snapctl snapend state $snapend_id
599
601
  | 80 | Generic generate error |
600
602
  | 81 | Generate profile error |
601
603
  | 82 | Generate credentials error |
604
+
605
+
606
+
607
+ ## CLI Return Codes
608
+
609
+ | Error Code | Description |
610
+ |------------|----------------------------------------------------------|
611
+ | 0 | Operation completed successfully |
612
+ | 1 | General error |
613
+ | 2 | Input error |
614
+
615
+ ### Configuration Errors
616
+
617
+ | Error Code | Description |
618
+ |------------|----------------------------------------------------------|
619
+ | 10 | Configuration incorrect |
620
+ | 11 | Configuration error |
621
+ | 12 | Dependency missing |
622
+
623
+ ### BYOGS Errors
624
+
625
+ | Error Code | Description |
626
+ |------------|----------------------------------------------------------|
627
+ | 20 | Generic BYOGS error |
628
+ | 21 | BYOGS dependency missing |
629
+ | 22 | BYOGS ECR login error |
630
+ | 23 | BYOGS build error |
631
+ | 24 | BYOGS tag error |
632
+ | 25 | BYOGS publish error |
633
+ | 26 | BYOGS publish permission error |
634
+ | 27 | BYOGS publish duplicate tag error |
635
+
636
+ ### BYOSNAP Errors
637
+
638
+ | Error Code | Description |
639
+ |------------|----------------------------------------------------------|
640
+ | 30 | Generic BYOSNAP error |
641
+ | 31 | BYOSNAP dependency missing |
642
+ | 32 | BYOSNAP ECR login error |
643
+ | 33 | BYOSNAP build error |
644
+ | 34 | BYOSNAP tag error |
645
+ | 35 | BYOSNAP publish image error |
646
+ | 36 | BYOSNAP publish image permission error |
647
+ | 37 | BYOSNAP publish image duplicate tag error |
648
+ | 38 | BYOSNAP create error |
649
+ | 39 | BYOSNAP create permission error |
650
+ | 40 | BYOSNAP create duplicate name error |
651
+ | 41 | BYOSNAP publish version error |
652
+ | 42 | BYOSNAP publish version permission error |
653
+ | 43 | BYOSNAP publish version duplicate version error |
654
+ | 44 | BYOSNAP publish version duplicate tag error |
655
+
656
+ ### Game Errors
657
+
658
+ | Error Code | Description |
659
+ |------------|----------------------------------------------------------|
660
+ | 50 | Generic game error |
661
+ | 51 | Game create error |
662
+ | 52 | Game create permission error |
663
+ | 53 | Game create duplicate name error |
664
+ | 54 | Game enumerate error |
665
+
666
+ ### Snapend Errors
667
+
668
+ | Error Code | Description |
669
+ |------------|----------------------------------------------------------|
670
+ | 60 | Generic snapend error |
671
+ | 61 | Snapend enumerate error |
672
+ | 62 | Snapend clone error |
673
+ | 63 | Snapend clone server error |
674
+ | 64 | Snapend clone timeout error |
675
+ | 65 | Snapend apply error |
676
+ | 66 | Snapend apply server error |
677
+ | 67 | Snapend apply timeout error |
678
+ | 68 | Snapend promote error |
679
+ | 69 | Snapend promote server error |
680
+ | 70 | Snapend promote timeout error |
681
+ | 71 | Snapend download error |
682
+ | 72 | Snapend update error |
683
+ | 73 | Snapend update server error |
684
+ | 74 | Snapend update timeout error |
685
+ | 75 | Snapend state error |
686
+
687
+ ### Generate Errors
688
+
689
+ | Error Code | Description |
690
+ |------------|----------------------------------------------------------|
691
+ | 80 | Generic generate error |
692
+ | 81 | Generate profile error |
693
+ | 82 | Generate credentials error |
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "snapctl"
3
- version = "0.38.0"
3
+ version = "0.38.2"
4
4
  description = "Snapser CLI Tool"
5
5
  authors = ["Ajinkya Apte <aj@snapser.com>"]
6
6
  readme = "README.md"
@@ -7,7 +7,7 @@ import os
7
7
  import subprocess
8
8
  import platform as sys_platform
9
9
  from sys import platform
10
- from typing import Union
10
+ from typing import Union, List
11
11
 
12
12
  from rich.progress import Progress, SpinnerColumn, TextColumn
13
13
  from snapctl.config.constants import SNAPCTL_BYOGS_DEPENDENCY_MISSING, \
@@ -32,7 +32,7 @@ class ByoGs:
32
32
  TAG_CHARACTER_LIMIT = 80
33
33
 
34
34
  def __init__(
35
- self, subcommand: str, base_url: str, api_key: str | None,
35
+ self, subcommand: str, base_url: str, api_key: Union[str, None],
36
36
  input_tag: Union[str, None], path: Union[str, None], dockerfile: str,
37
37
  skip_build: bool = False
38
38
  ) -> None:
@@ -46,7 +46,7 @@ class ByoGs:
46
46
  self.token: Union[str, None] = get_composite_token(
47
47
  base_url, api_key, 'byogs', {'service_id': ByoGs.SID}
48
48
  )
49
- self.token_parts: Union[list, None] = ByoGs._get_token_values(
49
+ self.token_parts: Union[List, None] = ByoGs._get_token_values(
50
50
  self.token) if self.token is not None else None
51
51
  self.input_tag: Union[str, None] = input_tag
52
52
  self.path: Union[str, None] = path
@@ -58,7 +58,7 @@ class ByoGs:
58
58
  # Protected methods
59
59
 
60
60
  @staticmethod
61
- def _get_token_values(token: str) -> None | list:
61
+ def _get_token_values(token: str) -> Union[None, List]:
62
62
  """
63
63
  Get the token values
64
64
  """
@@ -124,7 +124,7 @@ class ByoGs:
124
124
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
125
125
  else:
126
126
  response = subprocess.run([
127
- f'echo "{ecr_repo_token}" | docker login '
127
+ f'echo "{ecr_repo_token}" | docker login ' +
128
128
  f'--username {ecr_repo_username} --password-stdin {ecr_repo_url}'
129
129
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
130
130
  if not response.returncode:
@@ -169,8 +169,8 @@ class ByoGs:
169
169
  else:
170
170
  response = subprocess.run([
171
171
  # f"docker build --no-cache -t {tag} {path}"
172
- f"docker build --platform {
173
- build_platform} -t {self.input_tag} "
172
+ "docker build --platform " +
173
+ f"{build_platform} -t {self.input_tag} " +
174
174
  f"-f {docker_file_path} {self.path}"
175
175
  ], shell=True, check=False)
176
176
  # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
@@ -257,8 +257,8 @@ class ByoGs:
257
257
  # Check subcommand
258
258
  if not self.subcommand in ByoGs.SUBCOMMANDS:
259
259
  snapctl_error(
260
- f"Invalid command. Valid commands are {
261
- ', '.join(ByoGs.SUBCOMMANDS)}.",
260
+ "Invalid command. Valid commands are " +
261
+ f"{', '.join(ByoGs.SUBCOMMANDS)}.",
262
262
  SNAPCTL_INPUT_ERROR)
263
263
  # Validation for subcommands
264
264
  if self.token_parts is None:
@@ -270,7 +270,7 @@ class ByoGs:
270
270
  SNAPCTL_INPUT_ERROR)
271
271
  if len(self.input_tag.split()) > 1 or len(self.input_tag) > ByoGs.TAG_CHARACTER_LIMIT:
272
272
  snapctl_error(
273
- "Tag should be a single word with maximum of "
273
+ "Tag should be a single word with maximum of " +
274
274
  f"{ByoGs.TAG_CHARACTER_LIMIT} characters",
275
275
  SNAPCTL_INPUT_ERROR
276
276
  )
@@ -9,7 +9,7 @@ import re
9
9
  import subprocess
10
10
  import platform as sys_platform
11
11
  from sys import platform
12
- from typing import Union
12
+ from typing import Union, List
13
13
  import requests
14
14
  from requests.exceptions import RequestException
15
15
 
@@ -47,7 +47,7 @@ class ByoSnap:
47
47
  MAX_MIN_REPLICAS = 4
48
48
 
49
49
  def __init__(
50
- self, subcommand: str, base_url: str, api_key: str | None, sid: str, name: str,
50
+ self, subcommand: str, base_url: str, api_key: Union[str, None], sid: str, name: str,
51
51
  desc: str, platform_type: str, language: str, input_tag: Union[str, None],
52
52
  path: Union[str, None], dockerfile: str, prefix: str, version: Union[str, None],
53
53
  http_port: Union[int, None], byosnap_profile: Union[str, None],
@@ -86,7 +86,7 @@ class ByoSnap:
86
86
 
87
87
  # Protected methods
88
88
  @staticmethod
89
- def _get_token_values(token: str) -> None | list:
89
+ def _get_token_values(token: str) -> Union[None, List]:
90
90
  """
91
91
  Method to break open the token
92
92
  """
@@ -157,7 +157,7 @@ class ByoSnap:
157
157
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
158
158
  else:
159
159
  response = subprocess.run([
160
- f'echo "{ecr_repo_token}" | docker login '
160
+ f'echo "{ecr_repo_token}" | docker login ' +
161
161
  f'--username {ecr_repo_username} --password-stdin {ecr_repo_url}'
162
162
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
163
163
  if not response.returncode:
@@ -203,8 +203,8 @@ class ByoSnap:
203
203
  else:
204
204
  response = subprocess.run([
205
205
  # f"docker build --no-cache -t {tag} {path}"
206
- f"docker build --platform {
207
- build_platform} -t {self.input_tag} "
206
+ "docker build --platform " +
207
+ f"{build_platform} -t {self.input_tag} " +
208
208
  f"-f {docker_file_path} {self.path}"
209
209
  ], shell=True, check=False)
210
210
  # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
@@ -292,8 +292,8 @@ class ByoSnap:
292
292
  snapctl_error("Missing BYOSnap profile path", SNAPCTL_INPUT_ERROR)
293
293
  if not os.path.isfile(self.byosnap_profile):
294
294
  snapctl_error(
295
- "Unable to find BYOSnap profile "
296
- F"JSON at path {self.byosnap_profile}",
295
+ "Unable to find BYOSnap profile " +
296
+ f"JSON at path {self.byosnap_profile}",
297
297
  SNAPCTL_INPUT_ERROR
298
298
  )
299
299
  profile_data = None
@@ -327,16 +327,14 @@ class ByoSnap:
327
327
  )
328
328
  if profile_data[profile]['cpu'] not in ByoSnap.VALID_CPU_MARKS:
329
329
  snapctl_error(
330
- 'Invalid CPU value in BYOSnap profile. '
331
- f'Valid values are {
332
- ", ".join(map(str, ByoSnap.VALID_CPU_MARKS))}',
330
+ 'Invalid CPU value in BYOSnap profile. Valid values are' +
331
+ f'{", ".join(map(str, ByoSnap.VALID_CPU_MARKS))}',
333
332
  SNAPCTL_INPUT_ERROR
334
333
  )
335
334
  if profile_data[profile]['memory'] not in ByoSnap.VALID_MEMORY_MARKS:
336
335
  snapctl_error(
337
- 'Invalid Memory value in BYOSnap profile. '
338
- f'Valid values are {
339
- ", ".join(map(str, ByoSnap.VALID_MEMORY_MARKS))}',
336
+ 'Invalid Memory value in BYOSnap profile. Valid values are ' +
337
+ f'{", ".join(map(str, ByoSnap.VALID_MEMORY_MARKS))}',
340
338
  SNAPCTL_INPUT_ERROR
341
339
  )
342
340
  if 'min_replicas' in profile_data[profile] and \
@@ -344,9 +342,9 @@ class ByoSnap:
344
342
  int(profile_data[profile]['min_replicas']) < 0 or
345
343
  int(profile_data[profile]['min_replicas']) > ByoSnap.MAX_MIN_REPLICAS):
346
344
  snapctl_error(
347
- 'Invalid Min Replicas value in BYOSnap profile. '
348
- f'Minimum replicas should be between 0 and {
349
- ByoSnap.MAX_MIN_REPLICAS}',
345
+ 'Invalid Min Replicas value in BYOSnap profile. ' +
346
+ 'Minimum replicas should be between 0 and ' +
347
+ f'{ByoSnap.MAX_MIN_REPLICAS}',
350
348
  SNAPCTL_INPUT_ERROR
351
349
  )
352
350
 
@@ -363,22 +361,21 @@ class ByoSnap:
363
361
  # Check subcommand
364
362
  if not self.subcommand in ByoSnap.SUBCOMMANDS:
365
363
  snapctl_error(
366
- "Invalid command. Valid commands "
367
- f"are {', '.join(ByoSnap.SUBCOMMANDS)}.",
364
+ "Invalid command. Valid commands are " +
365
+ f"{', '.join(ByoSnap.SUBCOMMANDS)}.",
368
366
  SNAPCTL_INPUT_ERROR
369
367
  )
370
368
  # Validate the SID
371
369
  if not self.sid.startswith(ByoSnap.ID_PREFIX):
372
370
  snapctl_error(
373
- f"Invalid Snap ID. Valid Snap IDs start with {
374
- ByoSnap.ID_PREFIX}.",
371
+ "Invalid Snap ID. Valid Snap IDs start with " +
372
+ f"{ByoSnap.ID_PREFIX}.",
375
373
  SNAPCTL_INPUT_ERROR
376
374
  )
377
375
  if len(self.sid) > ByoSnap.SID_CHARACTER_LIMIT:
378
376
  snapctl_error(
379
- "Invalid Snap ID. "
380
- f"Snap ID should be less than {
381
- ByoSnap.SID_CHARACTER_LIMIT} characters",
377
+ "Invalid Snap ID. Snap ID should be less than " +
378
+ f"{ByoSnap.SID_CHARACTER_LIMIT} characters",
382
379
  SNAPCTL_INPUT_ERROR
383
380
  )
384
381
  # Validation for subcommands
@@ -389,13 +386,13 @@ class ByoSnap:
389
386
  snapctl_error("Missing language", SNAPCTL_INPUT_ERROR)
390
387
  if self.language not in ByoSnap.LANGUAGES:
391
388
  snapctl_error(
392
- "Invalid language. Valid languages are "
389
+ "Invalid language. Valid languages are " +
393
390
  f"{', '.join(ByoSnap.LANGUAGES)}.",
394
391
  SNAPCTL_INPUT_ERROR
395
392
  )
396
393
  if self.platform_type not in ByoSnap.PLATFORMS:
397
394
  snapctl_error(
398
- "Invalid platform. Valid platforms are "
395
+ "Invalid platform. Valid platforms are " +
399
396
  f"{', '.join(ByoSnap.PLATFORMS)}.",
400
397
  SNAPCTL_INPUT_ERROR
401
398
  )
@@ -411,7 +408,7 @@ class ByoSnap:
411
408
  if len(self.input_tag.split()) > 1 or \
412
409
  len(self.input_tag) > ByoSnap.TAG_CHARACTER_LIMIT:
413
410
  snapctl_error(
414
- "Tag should be a single word with maximum of "
411
+ "Tag should be a single word with maximum of " +
415
412
  f"{ByoSnap.TAG_CHARACTER_LIMIT} characters",
416
413
  SNAPCTL_INPUT_ERROR
417
414
  )
@@ -421,8 +418,8 @@ class ByoSnap:
421
418
  # Check path
422
419
  if not self.skip_build and not os.path.isfile(f"{self.path}/{self.dockerfile}"):
423
420
  snapctl_error(
424
- f"Unable to find {
425
- self.dockerfile} at path {self.path}",
421
+ f"Unable to find " +
422
+ f"{self.dockerfile} at path {self.path}",
426
423
  SNAPCTL_INPUT_ERROR)
427
424
  # elif self.subcommand == 'push':
428
425
  # if not self.input_tag:
@@ -439,7 +436,7 @@ class ByoSnap:
439
436
  if len(self.input_tag.split()) > 1 or \
440
437
  len(self.input_tag) > ByoSnap.TAG_CHARACTER_LIMIT:
441
438
  snapctl_error(
442
- "Tag should be a single word with maximum of "
439
+ "Tag should be a single word with maximum of " +
443
440
  f"{ByoSnap.TAG_CHARACTER_LIMIT} characters",
444
441
  SNAPCTL_INPUT_ERROR
445
442
  )
@@ -473,8 +470,9 @@ class ByoSnap:
473
470
  if self.readiness_delay is not None:
474
471
  if self.readiness_delay < 0 or \
475
472
  self.readiness_delay > ByoSnap.MAX_READINESS_TIMEOUT:
476
- snapctl_error("Readiness delay should be between 0 "
477
- f"and {ByoSnap.MAX_READINESS_TIMEOUT}", SNAPCTL_INPUT_ERROR)
473
+ snapctl_error(
474
+ "Readiness delay should be between 0 " +
475
+ f"and {ByoSnap.MAX_READINESS_TIMEOUT}", SNAPCTL_INPUT_ERROR)
478
476
  # Check byosnap_profile path
479
477
  self._validate_byosnap_profile()
480
478
 
@@ -539,12 +537,14 @@ class ByoSnap:
539
537
  info('Unable to upload your swagger.json')
540
538
  except RequestException as e:
541
539
  info(
542
- f'Exception: Unable to find swagger.json at {
543
- self.path} {e}'
540
+ 'Exception: Unable to find swagger.json at ' +
541
+ f'{self.path} {e}'
544
542
  )
545
543
  else:
546
- info(f'No swagger.json found at {self.path}'
547
- '. Skipping swagger.json upload')
544
+ info(
545
+ f'No swagger.json found at {self.path}' +
546
+ '. Skipping swagger.json upload'
547
+ )
548
548
 
549
549
  # Push the README.md
550
550
  if os.path.isfile(readme_file):
@@ -566,7 +566,9 @@ class ByoSnap:
566
566
  info('Unable to upload your README.md')
567
567
  except RequestException as e:
568
568
  info(
569
- f'Exception: Unable to find README.md at {self.path} {str(e)}')
569
+ 'Exception: Unable to find README.md at ' +
570
+ f'{self.path} {str(e)}'
571
+ )
570
572
  else:
571
573
  info(
572
574
  f'No README.md found at {self.path}. Skipping README.md upload')
@@ -606,8 +608,8 @@ class ByoSnap:
606
608
  if "api_error_code" in response_json and "message" in response_json:
607
609
  if response_json['api_error_code'] == HTTP_ERROR_SERVICE_VERSION_EXISTS:
608
610
  snapctl_error(
609
- f'BYOSnap {
610
- self.name} already exists. Please use a different name',
611
+ f'BYOSnap {self.name} already exists. ' +
612
+ 'Please use a different name',
611
613
  SNAPCTL_BYOSNAP_CREATE_DUPLICATE_NAME_ERROR,
612
614
  progress
613
615
  )
@@ -1,15 +1,13 @@
1
1
  """
2
2
  Snapend CLI commands
3
3
  """
4
+ from typing import Union, Dict
4
5
  import requests
5
6
  from requests.exceptions import RequestException
6
-
7
- import typer
8
7
  from rich.progress import Progress, SpinnerColumn, TextColumn
9
8
  from snapctl.config.constants import SERVER_CALL_TIMEOUT, SNAPCTL_INPUT_ERROR, \
10
- SNAPCTL_SUCCESS, SNAPCTL_GAME_CREATE_ERROR, SNAPCTL_GAME_ENUMERATE_ERROR, \
9
+ SNAPCTL_GAME_CREATE_ERROR, SNAPCTL_GAME_ENUMERATE_ERROR, \
11
10
  HTTP_ERROR_DUPLICATE_GAME_NAME, SNAPCTL_GAME_CREATE_DUPLICATE_NAME_ERROR
12
- from snapctl.utils.echo import error, success
13
11
  from snapctl.utils.helper import snapctl_error, snapctl_success
14
12
 
15
13
 
@@ -20,12 +18,12 @@ class Game:
20
18
  SUBCOMMANDS = ['create', 'enumerate']
21
19
 
22
20
  def __init__(
23
- self, subcommand: str, base_url: str, api_key: str | None, name: str | None
21
+ self, subcommand: str, base_url: str, api_key: Union[str, None], name: Union[str, None]
24
22
  ) -> None:
25
23
  self.subcommand: str = subcommand
26
24
  self.base_url: str = base_url
27
25
  self.api_key: str = api_key
28
- self.name: str | None = name
26
+ self.name: Union[str, None] = name
29
27
  # Validate input
30
28
  self.validate_input()
31
29
 
@@ -38,9 +36,9 @@ class Game:
38
36
  snapctl_error("Missing API Key.", SNAPCTL_INPUT_ERROR)
39
37
  # Check subcommand
40
38
  if not self.subcommand in Game.SUBCOMMANDS:
41
- snapctl_error(
42
- f"Invalid command. Valid commands are {', '.join(Game.SUBCOMMANDS)}.",
43
- SNAPCTL_INPUT_ERROR)
39
+ snapctl_error("Invalid command. Valid commands are" +
40
+ f"{', '.join(Game.SUBCOMMANDS)}.",
41
+ SNAPCTL_INPUT_ERROR)
44
42
  # Check sdk-download commands
45
43
  if self.subcommand == 'create':
46
44
  if self.name is None or self.name == '':
@@ -5,7 +5,7 @@ import base64
5
5
  from binascii import Error as BinasciiError
6
6
  import json
7
7
  import os
8
- from typing import Union
8
+ from typing import Union, List
9
9
  from rich.progress import Progress, SpinnerColumn, TextColumn
10
10
  from snapctl.config.constants import SNAPCTL_INPUT_ERROR, \
11
11
  SNAPCTL_GENERATE_GENERIC_ERROR, SNAPCTL_GENERATE_PROFILE_ERROR, \
@@ -28,21 +28,21 @@ class Generate:
28
28
  }
29
29
 
30
30
  def __init__(
31
- self, subcommand: str, base_url: str, api_key: str | None,
32
- category: str | None,
31
+ self, subcommand: str, base_url: str, api_key: Union[str, None],
32
+ category: Union[str, None],
33
33
  out_path: Union[str, None]
34
34
  ) -> None:
35
35
  self.subcommand: str = subcommand
36
36
  self.base_url: str = base_url
37
37
  self.api_key: str = api_key
38
- self.category: str | None = category
38
+ self.category: Union[str, None] = category
39
39
  self.out_path: Union[str, None] = out_path
40
40
  # Validate input
41
41
  self.validate_input()
42
42
 
43
43
  # Private methods
44
44
  @staticmethod
45
- def _get_token_values(token: str) -> None | list:
45
+ def _get_token_values(token: str) -> Union[None, List]:
46
46
  """
47
47
  Get the token values
48
48
  """
@@ -63,7 +63,7 @@ class Generate:
63
63
  """
64
64
  if self.subcommand not in Generate.SUBCOMMANDS:
65
65
  snapctl_error(
66
- f"Invalid command {self.subcommand}. Valid command are "
66
+ f"Invalid command {self.subcommand}. Valid command are " +
67
67
  f"{Generate.SUBCOMMANDS}",
68
68
  SNAPCTL_INPUT_ERROR
69
69
  )
@@ -71,7 +71,7 @@ class Generate:
71
71
  if self.subcommand == 'profile':
72
72
  if self.category not in Generate.CATEGORIES['profile']:
73
73
  snapctl_error(
74
- f"Invalid category {self.category}. Valid category are "
74
+ f"Invalid category {self.category}. Valid category are " +
75
75
  f"{Generate.CATEGORIES['profile']}",
76
76
  SNAPCTL_INPUT_ERROR
77
77
  )
@@ -83,7 +83,7 @@ class Generate:
83
83
  elif self.subcommand == 'credentials':
84
84
  if self.category not in Generate.CATEGORIES['credentials']:
85
85
  snapctl_error(
86
- f"Invalid category {self.category}. Valid category are "
86
+ f"Invalid category {self.category}. Valid category are " +
87
87
  f"{Generate.CATEGORIES['credentials']}",
88
88
  SNAPCTL_INPUT_ERROR
89
89
  )
@@ -95,7 +95,7 @@ class Generate:
95
95
  # Now confirm that out-path is valid
96
96
  if self.out_path and not os.path.isdir(self.out_path):
97
97
  snapctl_error(
98
- f"Invalid path {self.out_path}. Wont be able to "
98
+ f"Invalid path {self.out_path}. Wont be able to " +
99
99
  "store the output file",
100
100
  SNAPCTL_INPUT_ERROR
101
101
  )
@@ -125,7 +125,7 @@ class Generate:
125
125
  file_written = True
126
126
  if file_written:
127
127
  snapctl_success(
128
- "BYOSNAP Profile generation successful. "
128
+ "BYOSNAP Profile generation successful. " +
129
129
  f"{Generate.BYOSNAP_PROFILE_FN} saved at {file_save_path}",
130
130
  progress
131
131
  )
@@ -191,7 +191,7 @@ class Generate:
191
191
  file_written = True
192
192
  if file_written:
193
193
  snapctl_success(
194
- "ECR Token generation successful. "
194
+ "ECR Token generation successful. " +
195
195
  f"{Generate.ECR_TOKEN_FN} saved at {file_save_path}",
196
196
  progress
197
197
  )
@@ -7,6 +7,7 @@ import os
7
7
  import json
8
8
  import time
9
9
  import requests
10
+ from typing import Dict
10
11
  from requests.exceptions import RequestException
11
12
 
12
13
  import typer
@@ -44,44 +45,44 @@ class Snapend:
44
45
  MAX_BLOCKING_RETRIES = 120
45
46
 
46
47
  def __init__(
47
- self, subcommand: str, base_url: str, api_key: str | None, snapend_id: str | None,
48
+ self, subcommand: str, base_url: str, api_key: Union[str, None], snapend_id: Union[str, None],
48
49
  # Enumerate, Clone
49
- game_id: str | None,
50
+ game_id: Union[str, None],
50
51
  # Clone
51
- name: str | None,
52
- env: str | None,
52
+ name: Union[str, None],
53
+ env: Union[str, None],
53
54
  # Clone, Apply, Promote
54
- manifest_path: str | None,
55
+ manifest_path: Union[str, None],
55
56
  # Download
56
- category: str, platform_type: str, protos_category: str, auth_type: str, snaps: str | None,
57
+ category: str, platform_type: str, protos_category: str, auth_type: str, snaps: Union[str, None],
57
58
  # Clone, Apply, Promote, Download
58
- out_path: str | None,
59
+ out_path: Union[str, None],
59
60
  # Update
60
- byosnaps: str | None, byogs: str | None, blocking: bool = False
61
+ byosnaps: Union[str, None], byogs: Union[str, None], blocking: bool = False
61
62
  ) -> None:
62
63
  self.subcommand: str = subcommand
63
64
  self.base_url: str = base_url
64
65
  self.api_key: str = api_key
65
66
  self.snapend_id: str = snapend_id
66
- self.game_id: str | None = game_id
67
+ self.game_id: Union[str, None] = game_id
67
68
  self.name: str = name
68
69
  self.env: str = env
69
- self.manifest_path: str | None = manifest_path
70
- self.manifest_file_name: str | None = Snapend._get_manifest_file_name(
70
+ self.manifest_path: Union[str, None] = manifest_path
71
+ self.manifest_file_name: Union[str, None] = Snapend._get_manifest_file_name(
71
72
  manifest_path
72
73
  )
73
74
  self.category: str = category
74
75
  self.download_types: Union[
75
- dict[str, dict[str, str]], None
76
+ Dict[str, Dict[str, str]], None
76
77
  ] = Snapend._make_download_type(category)
77
78
  self.protos_category: str = protos_category
78
79
  self.auth_type: str = auth_type
79
80
  self.platform_type: str = platform_type
80
- self.out_path: str | None = out_path
81
- self.snaps: str | None = snaps
81
+ self.out_path: Union[str, None] = out_path
82
+ self.snaps: Union[str, None] = snaps
82
83
  self.byosnap_list: Union[list, None] = Snapend._make_byosnap_list(
83
84
  byosnaps) if byosnaps else None
84
- self.byogs_list: str | None = Snapend._make_byogs_list(
85
+ self.byogs_list: Union[str, None] = Snapend._make_byogs_list(
85
86
  byogs) if byogs else None
86
87
  self.blocking: bool = blocking
87
88
  # Validate input
@@ -90,7 +91,7 @@ class Snapend:
90
91
  # Helpers
91
92
 
92
93
  @staticmethod
93
- def _get_manifest_file_name(manifest_path: str) -> str | None:
94
+ def _get_manifest_file_name(manifest_path: str) -> Union[str, None]:
94
95
  if manifest_path and manifest_path != '' and os.path.isfile(manifest_path):
95
96
  file_name = os.path.basename(manifest_path)
96
97
  if file_name.endswith('.json') or file_name.endswith('.yml') or \
@@ -181,7 +182,7 @@ class Snapend:
181
182
  self.category = download_category
182
183
  self.platform_type = platform_type
183
184
  self.download_types: Union[
184
- dict[str, dict[str, str]], None
185
+ Dict[str, Dict[str, str]], None
185
186
  ] = Snapend._make_download_type(download_category)
186
187
 
187
188
  def _execute_download(self) -> bool:
@@ -191,13 +192,15 @@ class Snapend:
191
192
  f"download?category={self.category}"
192
193
  )
193
194
  if self.category not in Snapend.DOWNLOAD_TYPE_NOT_REQUIRED:
194
- url += f"&type={self.download_types[self.platform_type]['type']}"
195
+ url += "&type=" + \
196
+ f"{self.download_types[self.platform_type]['type']}"
195
197
  # If Protos, add protos category
196
198
  if self.category == 'protos':
197
199
  url += f"&subtype={self.protos_category}"
198
200
  # If client or server SDK, add sub type and auth type
199
201
  if self.category in ['client-sdk', 'server-sdk']:
200
- url += f"&subtype={self.download_types[self.platform_type]['subtype']}"
202
+ url += "&subtype=" + \
203
+ f"{self.download_types[self.platform_type]['subtype']}"
201
204
  url_auth_type: str = 'user'
202
205
  if self.category == 'server-sdk' and self.auth_type == 'app':
203
206
  url_auth_type = 'app'
@@ -212,20 +215,14 @@ class Snapend:
212
215
  if self.category == 'admin-settings':
213
216
  fn = f"snapser-{self.snapend_id}-admin-settings.json"
214
217
  elif self.category == 'snapend-manifest':
215
- fn = (
216
- f"snapser-{self.snapend_id}-"
217
- f"manifest.{self.download_types[self.platform_type]['type']}"
218
- )
218
+ fn = f"snapser-{self.snapend_id}-manifest." + \
219
+ f"{self.download_types[self.platform_type]['type']}"
219
220
  elif self.category == 'protos':
220
- fn = (
221
- f"snapser-{self.snapend_id}-{self.category}"
221
+ fn = f"snapser-{self.snapend_id}-{self.category}" + \
222
222
  f"-{self.platform_type}-{self.protos_category}.zip"
223
- )
224
223
  else:
225
- fn = (
226
- f"snapser-{self.snapend_id}-{self.category}"
224
+ fn = f"snapser-{self.snapend_id}-{self.category}" + \
227
225
  f"-{self.platform_type}-{self.auth_type}.zip"
228
- )
229
226
  if self.out_path is not None:
230
227
  file_save_path = os.path.join(self.out_path, fn)
231
228
  else:
@@ -256,7 +253,8 @@ class Snapend:
256
253
  # Check subcommand
257
254
  if not self.subcommand in Snapend.SUBCOMMANDS:
258
255
  snapctl_error(
259
- f"Invalid command. Valid commands are {', '.join(Snapend.SUBCOMMANDS)}.",
256
+ "Invalid command. Valid commands are " +
257
+ f"{', '.join(Snapend.SUBCOMMANDS)}.",
260
258
  SNAPCTL_INPUT_ERROR
261
259
  )
262
260
  if self.subcommand == 'enumerate':
@@ -279,11 +277,23 @@ class Snapend:
279
277
  if not self.manifest_path:
280
278
  snapctl_error(
281
279
  "Missing required parameter: manifest_path", SNAPCTL_INPUT_ERROR)
280
+ if not os.path.isfile(self.manifest_path):
281
+ snapctl_error(
282
+ f"Invalid path {
283
+ self.manifest_path}. Please enter a valid path to the manifest file",
284
+ SNAPCTL_INPUT_ERROR
285
+ )
282
286
  elif self.subcommand == 'apply':
283
287
  if not self.manifest_path:
284
288
  snapctl_error(
285
289
  "Missing required parameter: manifest_path", SNAPCTL_INPUT_ERROR)
286
290
  raise typer.Exit(code=SNAPCTL_INPUT_ERROR)
291
+ if not os.path.isfile(self.manifest_path):
292
+ snapctl_error(
293
+ f"Invalid path {
294
+ self.manifest_path}. Please enter a valid path to the manifest file",
295
+ SNAPCTL_INPUT_ERROR
296
+ )
287
297
  if not self.manifest_file_name:
288
298
  snapctl_error(
289
299
  "Invalid manifest file. Supported formats are .json, .yml, .yaml",
@@ -426,15 +436,16 @@ class Snapend:
426
436
  'Snapend clone successful. Do not forget to download the latest manifest.',
427
437
  progress)
428
438
  snapctl_error(
429
- 'Snapend clone has been initiated but the Snapend is not up yet.'
439
+ 'Snapend clone has been initiated but the Snapend is not up yet.' +
430
440
  'Please try checking the status of the Snapend in some time',
431
441
  SNAPCTL_SNAPEND_CLONE_TIMEOUT_ERROR,
432
442
  progress
433
443
  )
434
444
  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']}`",
445
+ "Snapend clone has been initiated. " +
446
+ "You can check the status using " +
447
+ "`snapctl snapend state --snapend-id" +
448
+ f"{response['cluster']['id']}`",
438
449
  progress
439
450
  )
440
451
  except RequestException as e:
@@ -488,18 +499,19 @@ class Snapend:
488
499
  # self.manifest_file_name.split('.')[-1])
489
500
  # self._execute_download()
490
501
  snapctl_success(
491
- 'Snapend apply successful. Do not forget to download '
502
+ 'Snapend apply successful. Do not forget to download ' +
492
503
  'the latest manifest.',
493
504
  progress)
494
505
  snapctl_error(
495
- 'Snapend apply has been initiated but the Snapend is not up yet.'
506
+ 'Snapend apply has been initiated but the Snapend is not up yet.' +
496
507
  'Please try checking the status of the Snapend in some time',
497
508
  SNAPCTL_SNAPEND_APPLY_TIMEOUT_ERROR, progress
498
509
  )
499
510
  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']}`",
511
+ "Snapend apply has been initiated. " +
512
+ "You can check the status using " +
513
+ "`snapctl snapend state --snapend-id" +
514
+ f"{response['cluster']['id']}`",
503
515
  progress
504
516
  )
505
517
  except RequestException as e:
@@ -552,20 +564,21 @@ class Snapend:
552
564
  # self._execute_download()
553
565
  # Fetch the new manifest
554
566
  snapctl_success(
555
- 'Snapend promote successful. Do not forget to '
567
+ 'Snapend promote successful. Do not forget to ' +
556
568
  'download the latest manifest.',
557
569
  progress
558
570
  )
559
571
  snapctl_error(
560
- 'Snapend apply has been initiated but the Snapend is not up yet.'
572
+ 'Snapend apply has been initiated but the Snapend is not up yet.' +
561
573
  'Please try checking the status of the Snapend in some time',
562
574
  SNAPCTL_SNAPEND_PROMOTE_TIMEOUT_ERROR,
563
575
  progress
564
576
  )
565
577
  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']}`",
578
+ "Snapend apply has been initiated. " +
579
+ "You can check the status using " +
580
+ "`snapctl snapend state --snapend-id" +
581
+ f"{response['cluster']['id']}`",
569
582
  progress
570
583
  )
571
584
  snapctl_error(f'Unable to promote the manifest. Reason: {res.text}',
@@ -593,7 +606,8 @@ class Snapend:
593
606
  try:
594
607
  if self._execute_download():
595
608
  snapctl_success(
596
- f"Snapend download successful. {self.category} saved at {self.out_path}",
609
+ "Snapend download successful. " +
610
+ f"{self.category} saved at {self.out_path}",
597
611
  progress
598
612
  )
599
613
  except RequestException as e:
@@ -636,19 +650,19 @@ class Snapend:
636
650
  # self.manifest_file_name.split('.')[-1])
637
651
  # self._execute_download()
638
652
  snapctl_success(
639
- 'Snapend update successful. Do not forget to '
653
+ 'Snapend update successful. Do not forget to ' +
640
654
  'download the latest manifest.',
641
655
  progress
642
656
  )
643
657
  snapctl_error(
644
- 'Snapend update has been initiated. '
658
+ 'Snapend update has been initiated. ' +
645
659
  'You can check the status using `snapctl snapend state`',
646
660
  SNAPCTL_SNAPEND_UPDATE_TIMEOUT_ERROR,
647
661
  progress
648
662
  )
649
663
  snapctl_success(
650
- "Snapend update has been initiated. "
651
- "You can check the status using "
664
+ "Snapend update has been initiated. " +
665
+ "You can check the status using " +
652
666
  f"`snapctl snapend state --snapend-id {self.snapend_id}`",
653
667
  progress
654
668
  )
@@ -678,7 +692,8 @@ class Snapend:
678
692
  current_state = self._get_snapend_state()
679
693
  if current_state != 'INVALID':
680
694
  snapctl_success(
681
- f'Snapend get state successful. Current snapend state is: {current_state}',
695
+ 'Snapend get state successful. Current snapend state is: ' +
696
+ f'{current_state}',
682
697
  progress)
683
698
  snapctl_error("Unable to get the snapend state.",
684
699
  SNAPCTL_SNAPEND_STATE_ERROR, progress)
@@ -2,7 +2,7 @@
2
2
  Constants used by snapctl
3
3
  """
4
4
  COMPANY_NAME = 'Snapser'
5
- VERSION = '0.38.0'
5
+ VERSION = '0.38.2'
6
6
  CONFIG_FILE_MAC = '~/.snapser/config'
7
7
  CONFIG_FILE_WIN = '%homepath%\\.snapser\\config'
8
8
 
@@ -1,7 +1,9 @@
1
+ from typing import Dict, List
2
+
1
3
  """
2
4
  This file contains the hashes / list constants
3
5
  """
4
- CLIENT_SDK_TYPES: dict[str, dict[str, str]] = {
6
+ CLIENT_SDK_TYPES: Dict[str, Dict[str, str]] = {
5
7
  'unity': {
6
8
  'type': 'csharp',
7
9
  'subtype': 'unity',
@@ -52,7 +54,7 @@ CLIENT_SDK_TYPES: dict[str, dict[str, str]] = {
52
54
  },
53
55
  }
54
56
 
55
- SERVER_SDK_TYPES: dict[str, dict[str, str]] = {
57
+ SERVER_SDK_TYPES: Dict[str, Dict[str, str]] = {
56
58
  'csharp': {
57
59
  'type': 'csharp',
58
60
  'subtype': '',
@@ -119,7 +121,7 @@ SERVER_SDK_TYPES: dict[str, dict[str, str]] = {
119
121
  },
120
122
  }
121
123
 
122
- PROTOS_TYPES: dict[str, dict[str, str]] = {
124
+ PROTOS_TYPES: Dict[str, Dict[str, str]] = {
123
125
  'cpp': {
124
126
  'type': 'cpp',
125
127
  'subtype': '',
@@ -138,7 +140,7 @@ PROTOS_TYPES: dict[str, dict[str, str]] = {
138
140
  },
139
141
  }
140
142
 
141
- SNAPEND_MANIFEST_TYPES: dict[str, dict[str, str]] = {
143
+ SNAPEND_MANIFEST_TYPES: Dict[str, Dict[str, str]] = {
142
144
  'json': {
143
145
  'type': 'json',
144
146
  'subtype': '',
@@ -149,14 +151,14 @@ SNAPEND_MANIFEST_TYPES: dict[str, dict[str, str]] = {
149
151
  },
150
152
  }
151
153
 
152
- SERVICE_IDS: list[str] = [
154
+ SERVICE_IDS: List[str] = [
153
155
  'analytics', 'auth', 'client-logs', 'events', 'experiments', 'gdpr', 'guilds', 'hades', 'iap',
154
156
  'inventory', 'leaderboards', 'matchmaking', 'notifications', 'parties', 'profiles', 'quests',
155
157
  'relay', 'remote-config', 'scheduler', 'sequencer', 'social-graph', 'statistics', 'storage',
156
158
  'trackables', 'xp'
157
159
  ]
158
160
 
159
- DEFAULT_BYOSNAP_DEV_TEMPLATE = {
161
+ DEFAULT_BYOSNAP_DEV_TEMPLATE: Dict[str, object] = {
160
162
  'cpu': 100,
161
163
  'memory': 0.125,
162
164
  'min_replicas': 1,
@@ -165,7 +167,7 @@ DEFAULT_BYOSNAP_DEV_TEMPLATE = {
165
167
  'env_params': [{'key': "SNAPSER_ENVIRONMENT", 'value': "DEVELOPMENT"}]
166
168
  }
167
169
 
168
- DEFAULT_BYOSNAP_STAGE_TEMPLATE = {
170
+ DEFAULT_BYOSNAP_STAGE_TEMPLATE: Dict[str, object] = {
169
171
  'cpu': 100,
170
172
  'memory': 0.125,
171
173
  'min_replicas': 1,
@@ -174,7 +176,7 @@ DEFAULT_BYOSNAP_STAGE_TEMPLATE = {
174
176
  'env_params': [{'key': "SNAPSER_ENVIRONMENT", 'value': "STAGING"}]
175
177
  }
176
178
 
177
- DEFAULT_BYOSNAP_PROD_TEMPLATE = {
179
+ DEFAULT_BYOSNAP_PROD_TEMPLATE: Dict[str, object] = {
178
180
  'cpu': 100,
179
181
  'memory': 0.125,
180
182
  'min_replicas': 2,
@@ -183,13 +185,13 @@ DEFAULT_BYOSNAP_PROD_TEMPLATE = {
183
185
  'env_params': [{'key': "SNAPSER_ENVIRONMENT", 'value': "PRODUCTION"}]
184
186
  }
185
187
 
186
- BYOSNAP_TEMPLATE = {
188
+ BYOSNAP_TEMPLATE: Dict[str, Dict[str, object]] = {
187
189
  'dev_template': DEFAULT_BYOSNAP_DEV_TEMPLATE,
188
190
  'stage_template': DEFAULT_BYOSNAP_STAGE_TEMPLATE,
189
191
  'prod_template': DEFAULT_BYOSNAP_PROD_TEMPLATE
190
192
  }
191
193
 
192
- ARCHITECTURE_MAPPING: dict[str, str] = {
194
+ ARCHITECTURE_MAPPING: Dict[str, str] = {
193
195
  'x86_64': 'amd64',
194
196
  'arm64': 'arm64',
195
197
  'aarch64': 'arm64',
@@ -44,7 +44,7 @@ app = typer.Typer(
44
44
  ######### HELPER METHODS #########
45
45
 
46
46
 
47
- def extract_config(extract_key: str, profile: str | None = None) -> object:
47
+ def extract_config(extract_key: str, profile: Union[str, None] = None) -> object:
48
48
  """
49
49
  Extracts the API Key from the environment variable and if not present from the config file
50
50
  """
@@ -58,9 +58,9 @@ def extract_config(extract_key: str, profile: str | None = None) -> object:
58
58
  result['location'] = 'environment-variable'
59
59
  result['value'] = env_api_key
60
60
  return result
61
- encoding: str | None = "utf-8-sig" if platform == 'win32' else None
61
+ encoding: Union[str, None] = "utf-8-sig" if platform == 'win32' else None
62
62
  # Option 2 - Get the API Key from CONFIG PATH environment variable
63
- config_file_path: str | None = os.getenv(CONFIG_PATH_KEY)
63
+ config_file_path: Union[str, None] = os.getenv(CONFIG_PATH_KEY)
64
64
  # Option 3 - Get the API Key from the hardcoded config file we look for
65
65
  if config_file_path is None:
66
66
  if platform == 'win32':
@@ -76,8 +76,8 @@ def extract_config(extract_key: str, profile: str | None = None) -> object:
76
76
  result['location'] = f'"{config_file_path}:profile {profile}"'
77
77
  config_profile = f'profile {profile}'
78
78
  info(
79
- f'Trying to extract API KEY from "{
80
- config_file_path}:profile {profile}"'
79
+ 'Trying to extract API KEY from ' +
80
+ f'{config_file_path}:profile {profile}"'
81
81
  )
82
82
  result['value'] = config.get(
83
83
  config_profile, extract_key, fallback=None, raw=True
@@ -88,7 +88,7 @@ def extract_config(extract_key: str, profile: str | None = None) -> object:
88
88
  return result
89
89
 
90
90
 
91
- def get_base_url(api_key: str | None) -> str:
91
+ def get_base_url(api_key: Union[str, None]) -> str:
92
92
  """
93
93
  Returns the base url based on the api_key
94
94
  """
@@ -141,7 +141,7 @@ def default_context_callback(ctx: typer.Context):
141
141
 
142
142
  def api_key_context_callback(
143
143
  ctx: typer.Context,
144
- api_key: str | None = None
144
+ api_key: Union[str, None] = None
145
145
  ):
146
146
  """
147
147
  Callback to set the context for the api_key
@@ -160,7 +160,7 @@ def api_key_context_callback(
160
160
 
161
161
  def profile_context_callback(
162
162
  ctx: typer.Context,
163
- profile: str | None = None
163
+ profile: Union[str, None] = None
164
164
  ):
165
165
  """
166
166
  Callback to set the context for the profile
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Helper functions for snapctl
3
3
  """
4
+ from typing import Union, Dict
4
5
  import re
5
6
  import requests
6
7
  import typer
@@ -12,7 +13,7 @@ from snapctl.config.hashes import ARCHITECTURE_MAPPING
12
13
  from snapctl.utils.echo import error, success
13
14
 
14
15
 
15
- def validate_api_key(base_url: str, api_key: str | None) -> bool:
16
+ def validate_api_key(base_url: str, api_key: Union[str, None]) -> bool:
16
17
  """
17
18
  This function validates the API Key
18
19
  """
@@ -45,7 +46,7 @@ def validate_api_key(base_url: str, api_key: str | None) -> bool:
45
46
  raise typer.Exit(code=SNAPCTL_CONFIGURATION_ERROR)
46
47
 
47
48
 
48
- def get_composite_token(base_url: str, api_key: str | None, action: str, params: object) -> str:
49
+ def get_composite_token(base_url: str, api_key: Union[str, None], action: str, params: object) -> str:
49
50
  """
50
51
  This function exchanges the api_key for a composite token.
51
52
  """
@@ -76,7 +77,7 @@ def get_composite_token(base_url: str, api_key: str | None, action: str, params:
76
77
  return res.json()['token']
77
78
 
78
79
 
79
- def check_dockerfile_architecture(dockerfile_path: str, system_arch: str) -> dict[str, object]:
80
+ def check_dockerfile_architecture(dockerfile_path: str, system_arch: str) -> Dict[str, object]:
80
81
  """
81
82
  Check the Dockerfile for architecture specific commands
82
83
  """
@@ -113,14 +114,11 @@ def check_dockerfile_architecture(dockerfile_path: str, system_arch: str) -> dic
113
114
  match = re.search(pattern, line)
114
115
  if match and ARCHITECTURE_MAPPING.get(match.group(1)) != system_arch:
115
116
  response['error'] = True
116
- response['message'] = (
117
- f'[Architecture Mismatch] Line {line_number}: "{
118
- line.strip()}" '
119
- f' of Dockerfile {dockerfile_path}'
120
- f' specifies architecture {
121
- match.group(1)}, which does not match the '
122
- f' systems ({system_arch}).'
123
- )
117
+ response['message'] = '[Architecture Mismatch] Line ' + \
118
+ f'{line_number}: "{line.strip()}" ' + \
119
+ f'of Dockerfile {dockerfile_path} ' + \
120
+ f'specifies architecture {match.group(1)}, which does not match the ' + \
121
+ f'systems ({system_arch}).'
124
122
  return response
125
123
  except FileNotFoundError:
126
124
  response['error'] = True
@@ -133,7 +131,7 @@ def check_dockerfile_architecture(dockerfile_path: str, system_arch: str) -> dic
133
131
  return response
134
132
 
135
133
 
136
- def snapctl_success(message: str, progress: Progress | None = None, no_exit: bool = False):
134
+ def snapctl_success(message: str, progress: Union[Progress, None] = None, no_exit: bool = False):
137
135
  """
138
136
  This function exits the snapctl
139
137
  """
@@ -144,7 +142,7 @@ def snapctl_success(message: str, progress: Progress | None = None, no_exit: boo
144
142
  raise typer.Exit(code=SNAPCTL_SUCCESS)
145
143
 
146
144
 
147
- def snapctl_error(message: str, code: int, progress: Progress | None = None):
145
+ def snapctl_error(message: str, code: int, progress: Union[Progress, None] = None):
148
146
  """
149
147
  This function exits the snapctl
150
148
  """
File without changes
File without changes
File without changes
File without changes