snapctl 0.32.2__tar.gz → 0.35.0__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.32.2
3
+ Version: 0.35.0
4
4
  Summary: Snapser CLI Tool
5
5
  Author: Ajinkya Apte
6
6
  Author-email: aj@snapser.com
@@ -272,9 +272,11 @@ snapctl byosnap publish-image --help
272
272
  # $byosnap_sid = Snap ID for your snap
273
273
  # $image_tag = An image tag for your snap
274
274
  # $code_root_path = Local code path where your Dockerfile is present
275
+ # $skip-build = true/false. Default is false. Pass this flag as true to skip the build and head straight to tag and push. Build step needs to run and tagged using the --tag you pass to the publish-image command for this to work.
275
276
  # Example:
276
277
  # snapctl byosnap publish-image byosnap-jinks-flask --tag my-first-image --path /Users/DevName/Development/SnapserEngine/jinks_flask
277
278
  snapctl byosnap publish-image $byosnap_sid --tag $image_tag --path $code_root_path
279
+ snapctl byosnap publish-image $byosnap_sid --tag $image_tag --skip-build
278
280
  ```
279
281
 
280
282
  #### 7. byosnap publish-version
@@ -292,7 +294,7 @@ snapctl byosnap publish-version --help
292
294
  # $prefix = Prefix for your snap Eg: /v1
293
295
  # $version = Semantic version for your snap Eg: v0.0.1
294
296
  # $ingress_port = Ingress port for your snap Eg: 5003
295
- # $byosnap_profile = BYOSnap profile to configure dev, stage and prod settings for this snap. You can generate a base version of this file using the `snapctl generate byosnap` command
297
+ # $byosnap_profile = BYOSnap profile to configure dev, stage and prod settings for this snap. You can generate a base version of this file using the `snapctl generate profile --category byosnap --out-path <output_path>` command
296
298
  # Example:
297
299
  # snapctl byosnap publish-image byosnap-jinks-flask --tag my-first-image --prefix /v1 --version v0.0.1 --http-port 5003 --byosnap-profile /Users/DevName/Development/SnapserEngine/jinks_flask/snapser-byosnap-profile.json
298
300
  snapctl byosnap publish-version $byosnap_sid --tag $image_tag --prefix $prefix --version $version --http-port $ingress_port --byosnap-profile $byosnap_profile
@@ -353,9 +355,11 @@ snapctl byogs publish --help
353
355
  # Publish a new image
354
356
  # $image_tag = An image tag for your snap
355
357
  # $code_root_path = Local code path where your Dockerfile is present
358
+ # $skip-build = Default is false. Pass this flag as true to skip the build and head straight to tag and push. Build step needs to run and tagged using the --tag you pass to the publish-image command for this to work.
356
359
  # Example:
357
360
  # snapctl byogs publish --tag my-first-image --path /Users/DevName/Development/SnapserEngine/game_server
358
361
  snapctl byogs publish --tag $image_tag --path $code_root_path
362
+ snapctl byogs publish --tag $image_tag --skip-build
359
363
  ```
360
364
 
361
365
 
@@ -393,11 +397,19 @@ See all the supported commands
393
397
  snapctl generate --help
394
398
  ```
395
399
 
396
- #### 2. BYOSnap Profile
400
+ #### 2. Generate BYOSnap Profile
397
401
  Generate the base file for BYOSnap profile to be used in the `snapctl byosnap publish-version` command
398
402
 
399
403
  ```
400
- snapctl generate byosnap-profile --out-path $output_path
404
+ snapctl generate profile --category "byosnap" --out-path $output_path
405
+
406
+ ```
407
+
408
+ #### 3. Generate ECR Credentials
409
+ Generate the ECR credentials. Game studios can use these credentials to self publish their images to Snapser.
410
+
411
+ ```
412
+ snapctl generate credentials --category "ecr" --out-path $output_path
401
413
 
402
414
  ```
403
415
 
@@ -596,5 +608,6 @@ snapctl snapend state $snapend_id
596
608
  | Error Code | Description |
597
609
  |------------|----------------------------------------------------------|
598
610
  | 80 | Generic generate error |
599
- | 81 | Generate BYOSNAP profile error |
611
+ | 81 | Generate profile error |
612
+ | 82 | Generate credentials error |
600
613
 
@@ -253,9 +253,11 @@ snapctl byosnap publish-image --help
253
253
  # $byosnap_sid = Snap ID for your snap
254
254
  # $image_tag = An image tag for your snap
255
255
  # $code_root_path = Local code path where your Dockerfile is present
256
+ # $skip-build = true/false. Default is false. Pass this flag as true to skip the build and head straight to tag and push. Build step needs to run and tagged using the --tag you pass to the publish-image command for this to work.
256
257
  # Example:
257
258
  # snapctl byosnap publish-image byosnap-jinks-flask --tag my-first-image --path /Users/DevName/Development/SnapserEngine/jinks_flask
258
259
  snapctl byosnap publish-image $byosnap_sid --tag $image_tag --path $code_root_path
260
+ snapctl byosnap publish-image $byosnap_sid --tag $image_tag --skip-build
259
261
  ```
260
262
 
261
263
  #### 7. byosnap publish-version
@@ -273,7 +275,7 @@ snapctl byosnap publish-version --help
273
275
  # $prefix = Prefix for your snap Eg: /v1
274
276
  # $version = Semantic version for your snap Eg: v0.0.1
275
277
  # $ingress_port = Ingress port for your snap Eg: 5003
276
- # $byosnap_profile = BYOSnap profile to configure dev, stage and prod settings for this snap. You can generate a base version of this file using the `snapctl generate byosnap` command
278
+ # $byosnap_profile = BYOSnap profile to configure dev, stage and prod settings for this snap. You can generate a base version of this file using the `snapctl generate profile --category byosnap --out-path <output_path>` command
277
279
  # Example:
278
280
  # snapctl byosnap publish-image byosnap-jinks-flask --tag my-first-image --prefix /v1 --version v0.0.1 --http-port 5003 --byosnap-profile /Users/DevName/Development/SnapserEngine/jinks_flask/snapser-byosnap-profile.json
279
281
  snapctl byosnap publish-version $byosnap_sid --tag $image_tag --prefix $prefix --version $version --http-port $ingress_port --byosnap-profile $byosnap_profile
@@ -334,9 +336,11 @@ snapctl byogs publish --help
334
336
  # Publish a new image
335
337
  # $image_tag = An image tag for your snap
336
338
  # $code_root_path = Local code path where your Dockerfile is present
339
+ # $skip-build = Default is false. Pass this flag as true to skip the build and head straight to tag and push. Build step needs to run and tagged using the --tag you pass to the publish-image command for this to work.
337
340
  # Example:
338
341
  # snapctl byogs publish --tag my-first-image --path /Users/DevName/Development/SnapserEngine/game_server
339
342
  snapctl byogs publish --tag $image_tag --path $code_root_path
343
+ snapctl byogs publish --tag $image_tag --skip-build
340
344
  ```
341
345
 
342
346
 
@@ -374,11 +378,19 @@ See all the supported commands
374
378
  snapctl generate --help
375
379
  ```
376
380
 
377
- #### 2. BYOSnap Profile
381
+ #### 2. Generate BYOSnap Profile
378
382
  Generate the base file for BYOSnap profile to be used in the `snapctl byosnap publish-version` command
379
383
 
380
384
  ```
381
- snapctl generate byosnap-profile --out-path $output_path
385
+ snapctl generate profile --category "byosnap" --out-path $output_path
386
+
387
+ ```
388
+
389
+ #### 3. Generate ECR Credentials
390
+ Generate the ECR credentials. Game studios can use these credentials to self publish their images to Snapser.
391
+
392
+ ```
393
+ snapctl generate credentials --category "ecr" --out-path $output_path
382
394
 
383
395
  ```
384
396
 
@@ -577,4 +589,5 @@ snapctl snapend state $snapend_id
577
589
  | Error Code | Description |
578
590
  |------------|----------------------------------------------------------|
579
591
  | 80 | Generic generate error |
580
- | 81 | Generate BYOSNAP profile error |
592
+ | 81 | Generate profile error |
593
+ | 82 | Generate credentials error |
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "snapctl"
3
- version = "0.32.2"
3
+ version = "0.35.0"
4
4
  description = "Snapser CLI Tool"
5
5
  authors = ["Ajinkya Apte <aj@snapser.com>"]
6
6
  readme = "README.md"
@@ -8,14 +8,13 @@ import subprocess
8
8
  from sys import platform
9
9
  from typing import Union
10
10
 
11
- import typer
12
11
  from rich.progress import Progress, SpinnerColumn, TextColumn
13
12
  from snapctl.config.constants import SNAPCTL_BYOGS_DEPENDENCY_MISSING, \
14
13
  SNAPCTL_BYOGS_ECR_LOGIN_ERROR, SNAPCTL_BYOGS_BUILD_ERROR, \
15
14
  SNAPCTL_BYOGS_TAG_ERROR, SNAPCTL_BYOGS_PUBLISH_ERROR, \
16
15
  SNAPCTL_BYOGS_PUBLISH_DUPLICATE_TAG_ERROR, SNAPCTL_INPUT_ERROR
17
- from snapctl.utils.echo import error, success
18
16
  from snapctl.utils.helper import get_composite_token, snapctl_error, snapctl_success
17
+ from snapctl.utils.echo import info
19
18
 
20
19
 
21
20
  class ByoGs:
@@ -33,6 +32,7 @@ class ByoGs:
33
32
  def __init__(
34
33
  self, subcommand: str, base_url: str, api_key: str | None,
35
34
  input_tag: Union[str, None], path: Union[str, None], dockerfile: str,
35
+ skip_build: bool = False
36
36
  ) -> None:
37
37
  self.subcommand: str = subcommand
38
38
  self.base_url: str = base_url
@@ -49,6 +49,7 @@ class ByoGs:
49
49
  self.input_tag: Union[str, None] = input_tag
50
50
  self.path: Union[str, None] = path
51
51
  self.dockerfile: str = dockerfile
52
+ self.skip_build: bool = skip_build
52
53
  # Validate input
53
54
  self.validate_input()
54
55
 
@@ -143,7 +144,7 @@ class ByoGs:
143
144
  progress.add_task(
144
145
  description='Building your snap...', total=None)
145
146
  try:
146
- image_tag = f'{ByoGs.SID}.{self.input_tag}'
147
+ # image_tag = f'{ByoGs.SID}.{self.input_tag}'
147
148
  build_platform = ByoGs.DEFAULT_BUILD_PLATFORM
148
149
  if len(self.token_parts) == 4:
149
150
  build_platform = self.token_parts[3]
@@ -152,14 +153,14 @@ class ByoGs:
152
153
  if platform == "win32":
153
154
  response = subprocess.run([
154
155
  # f"docker build --no-cache -t {tag} {path}"
155
- 'docker', 'build', '--platform', build_platform, '-t', image_tag,
156
+ 'docker', 'build', '--platform', build_platform, '-t', self.input_tag,
156
157
  '-f', docker_file_path, self.path
157
158
  ], shell=True, check=False)
158
159
  # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
159
160
  else:
160
161
  response = subprocess.run([
161
162
  # f"docker build --no-cache -t {tag} {path}"
162
- f"docker build --platform {build_platform} -t {image_tag} "
163
+ f"docker build --platform {build_platform} -t {self.input_tag} "
163
164
  f"-f {docker_file_path} {self.path}"
164
165
  ], shell=True, check=False)
165
166
  # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
@@ -188,11 +189,11 @@ class ByoGs:
188
189
  # Tag the repo
189
190
  if platform == "win32":
190
191
  response = subprocess.run([
191
- 'docker', 'tag', image_tag, full_ecr_repo_url
192
+ 'docker', 'tag', self.input_tag, full_ecr_repo_url
192
193
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
193
194
  else:
194
195
  response = subprocess.run([
195
- f"docker tag {image_tag} {full_ecr_repo_url}"
196
+ f"docker tag {self.input_tag} {full_ecr_repo_url}"
196
197
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
197
198
  if not response.returncode:
198
199
  return snapctl_success('BYOGS tag successful', progress, no_exit=True)
@@ -263,11 +264,11 @@ class ByoGs:
263
264
  SNAPCTL_INPUT_ERROR
264
265
  )
265
266
  if self.subcommand in ['build', 'publish']:
266
- if not self.path:
267
+ if not self.skip_build and not self.path:
267
268
  snapctl_error("Missing required parameter: path",
268
269
  SNAPCTL_INPUT_ERROR)
269
270
  # Check path
270
- if not os.path.isfile(f"{self.path}/{self.dockerfile}"):
271
+ if not self.skip_build and not os.path.isfile(f"{self.path}/{self.dockerfile}"):
271
272
  snapctl_error(
272
273
  f"Unable to find {self.dockerfile} at path {self.path}", SNAPCTL_INPUT_ERROR)
273
274
  # elif self.subcommand == 'push':
@@ -313,7 +314,10 @@ class ByoGs:
313
314
  """
314
315
  self._check_dependencies()
315
316
  self._docker_login()
316
- self._docker_build()
317
+ if not self.skip_build:
318
+ self._docker_build()
319
+ else:
320
+ info('--skip-build set. Skipping the build step.')
317
321
  self._docker_tag()
318
322
  self._docker_push()
319
323
  snapctl_success('BYOGS publish successful')
@@ -46,7 +46,8 @@ class ByoSnap:
46
46
  self, subcommand: str, base_url: str, api_key: str | None, sid: str, name: str,
47
47
  desc: str, platform_type: str, language: str, input_tag: Union[str, None],
48
48
  path: Union[str, None], dockerfile: str, prefix: str, version: Union[str, None],
49
- http_port: Union[int, None], byosnap_profile: Union[str, None]
49
+ http_port: Union[int, None], byosnap_profile: Union[str, None],
50
+ skip_build: bool = False
50
51
  ) -> None:
51
52
  self.subcommand: str = subcommand
52
53
  self.base_url: str = base_url
@@ -72,6 +73,7 @@ class ByoSnap:
72
73
  self.version: Union[str, None] = version
73
74
  self.http_port: Union[int, None] = http_port
74
75
  self.byosnap_profile: Union[str, None] = byosnap_profile
76
+ self.skip_build: bool = skip_build
75
77
  # Validate the input
76
78
  self.validate_input()
77
79
 
@@ -162,7 +164,7 @@ class ByoSnap:
162
164
 
163
165
  def _docker_build(self) -> None:
164
166
  # Get the data
165
- image_tag = f'{self.sid}.{self.input_tag}'
167
+ # image_tag = f'{self.sid}.{self.input_tag}'
166
168
  build_platform = ByoSnap.DEFAULT_BUILD_PLATFORM
167
169
  if len(self.token_parts) == 4:
168
170
  build_platform = self.token_parts[3]
@@ -180,14 +182,14 @@ class ByoSnap:
180
182
  if platform == "win32":
181
183
  response = subprocess.run([
182
184
  # f"docker build --no-cache -t {tag} {path}"
183
- 'docker', 'build', '--platform', build_platform, '-t', image_tag,
185
+ 'docker', 'build', '--platform', build_platform, '-t', self.input_tag,
184
186
  '-f', docker_file_path, self.path
185
187
  ], shell=True, check=False)
186
188
  # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
187
189
  else:
188
190
  response = subprocess.run([
189
191
  # f"docker build --no-cache -t {tag} {path}"
190
- f"docker build --platform {build_platform} -t {image_tag} "
192
+ f"docker build --platform {build_platform} -t {self.input_tag} "
191
193
  f"-f {docker_file_path} {self.path}"
192
194
  ], shell=True, check=False)
193
195
  # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
@@ -217,11 +219,11 @@ class ByoSnap:
217
219
  # Tag the repo
218
220
  if platform == "win32":
219
221
  response = subprocess.run([
220
- 'docker', 'tag', image_tag, full_ecr_repo_url
222
+ 'docker', 'tag', self.input_tag, full_ecr_repo_url
221
223
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
222
224
  else:
223
225
  response = subprocess.run([
224
- f"docker tag {image_tag} {full_ecr_repo_url}"
226
+ f"docker tag {self.input_tag} {full_ecr_repo_url}"
225
227
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
226
228
  if not response.returncode:
227
229
  return snapctl_success('BYOSnap tag successful',
@@ -372,7 +374,7 @@ class ByoSnap:
372
374
  if self.token_parts is None:
373
375
  snapctl_error('Invalid token. Please reach out to your support team.',
374
376
  SNAPCTL_INPUT_ERROR)
375
- if self.subcommand in ['build', 'publish-image']:
377
+ if self.subcommand in ['publish-image']:
376
378
  if not self.input_tag:
377
379
  snapctl_error(
378
380
  "Missing required parameter: tag", SNAPCTL_INPUT_ERROR)
@@ -383,11 +385,11 @@ class ByoSnap:
383
385
  f"{ByoSnap.TAG_CHARACTER_LIMIT} characters",
384
386
  SNAPCTL_INPUT_ERROR
385
387
  )
386
- if not self.path:
388
+ if not self.skip_build and not self.path:
387
389
  snapctl_error("Missing required parameter: path",
388
390
  SNAPCTL_INPUT_ERROR)
389
391
  # Check path
390
- if not os.path.isfile(f"{self.path}/{self.dockerfile}"):
392
+ if not self.skip_build and not os.path.isfile(f"{self.path}/{self.dockerfile}"):
391
393
  snapctl_error(
392
394
  f"Unable to find {self.dockerfile} at path {self.path}",
393
395
  SNAPCTL_INPUT_ERROR)
@@ -592,10 +594,14 @@ class ByoSnap:
592
594
  """
593
595
  self._check_dependencies()
594
596
  self._docker_login()
595
- self._docker_build()
597
+ if not self.skip_build:
598
+ self._docker_build()
599
+ else:
600
+ info('--skip-build set. Skipping the build step.')
596
601
  self._docker_tag()
597
602
  self._docker_push()
598
- self.upload_docs()
603
+ if self.path is not None:
604
+ self.upload_docs()
599
605
  snapctl_success('BYOSNAP publish successful')
600
606
 
601
607
  def publish_version(self) -> None:
@@ -0,0 +1,215 @@
1
+ """
2
+ Generate CLI commands
3
+ """
4
+ import base64
5
+ from binascii import Error as BinasciiError
6
+ import json
7
+ import os
8
+ from typing import Union
9
+ from rich.progress import Progress, SpinnerColumn, TextColumn
10
+ from snapctl.config.constants import SNAPCTL_INPUT_ERROR, \
11
+ SNAPCTL_GENERATE_GENERIC_ERROR, SNAPCTL_GENERATE_PROFILE_ERROR, \
12
+ SNAPCTL_GENERATE_CREDENTIALS_ERROR
13
+ from snapctl.config.hashes import BYOSNAP_TEMPLATE
14
+ from snapctl.utils.helper import get_composite_token, snapctl_error, snapctl_success
15
+
16
+
17
+ class Generate:
18
+ """
19
+ Generate CLI commands
20
+ """
21
+ SUBCOMMANDS = ['byosnap-profile', 'profile', 'credentials']
22
+ DEPRECATED_SOON_SUBCOMMANDS = ['byosnap-profile']
23
+ BYOSNAP_PROFILE_FN = 'snapser-byosnap-profile.json'
24
+ ECR_TOKEN_FN = 'snapser-ecr-credentials.json'
25
+ CATEGORIES = {
26
+ 'profile': ['byosnap'],
27
+ 'credentials': ['ecr']
28
+ }
29
+
30
+ def __init__(
31
+ self, subcommand: str, base_url: str, api_key: str | None,
32
+ category: str | None,
33
+ out_path: Union[str, None]
34
+ ) -> None:
35
+ self.subcommand: str = subcommand
36
+ self.base_url: str = base_url
37
+ self.api_key: str = api_key
38
+ self.category: str | None = category
39
+ self.out_path: Union[str, None] = out_path
40
+ # Validate input
41
+ self.validate_input()
42
+
43
+ # Private methods
44
+ @staticmethod
45
+ def _get_token_values(token: str) -> None | list:
46
+ """
47
+ Get the token values
48
+ """
49
+ try:
50
+ input_token = base64.b64decode(token).decode('ascii')
51
+ token_parts = input_token.split('|')
52
+ # url|web_app_token|service_id|ecr_repo_url|ecr_repo_username|ecr_repo_token
53
+ if len(token_parts) >= 3:
54
+ return token_parts
55
+ except BinasciiError:
56
+ pass
57
+ return None
58
+ # Validator
59
+
60
+ def validate_input(self) -> None:
61
+ """
62
+ Validator
63
+ """
64
+ if self.subcommand not in Generate.SUBCOMMANDS:
65
+ snapctl_error(
66
+ f"Invalid command {self.subcommand}. Valid command are "
67
+ f"{Generate.SUBCOMMANDS}",
68
+ SNAPCTL_INPUT_ERROR
69
+ )
70
+ # Check path
71
+ if self.subcommand == 'profile':
72
+ if self.category not in Generate.CATEGORIES['profile']:
73
+ snapctl_error(
74
+ f"Invalid category {self.category}. Valid category are "
75
+ f"{Generate.CATEGORIES['profile']}",
76
+ SNAPCTL_INPUT_ERROR
77
+ )
78
+ if not self.out_path:
79
+ snapctl_error(
80
+ "Path is required for profile generation",
81
+ SNAPCTL_INPUT_ERROR
82
+ )
83
+ elif self.subcommand == 'credentials':
84
+ if self.category not in Generate.CATEGORIES['credentials']:
85
+ snapctl_error(
86
+ f"Invalid category {self.category}. Valid category are "
87
+ f"{Generate.CATEGORIES['credentials']}",
88
+ SNAPCTL_INPUT_ERROR
89
+ )
90
+ if not self.out_path:
91
+ snapctl_error(
92
+ "Path is required for token generation",
93
+ SNAPCTL_INPUT_ERROR
94
+ )
95
+ # Now confirm that out-path is valid
96
+ if self.out_path and not os.path.isdir(self.out_path):
97
+ snapctl_error(
98
+ f"Invalid path {self.out_path}. Wont be able to "
99
+ "store the output file",
100
+ SNAPCTL_INPUT_ERROR
101
+ )
102
+
103
+ def byosnap_profile(self) -> None:
104
+ """
105
+ Generate snapser-byosnap-profile.json
106
+ """
107
+ progress = Progress(
108
+ SpinnerColumn(),
109
+ TextColumn("[progress.description]{task.description}"),
110
+ transient=True,
111
+ )
112
+ progress.start()
113
+ progress.add_task(
114
+ description='Generating BYOSnap profile...', total=None)
115
+ try:
116
+ if self.out_path is not None:
117
+ file_save_path = os.path.join(
118
+ self.out_path, Generate.BYOSNAP_PROFILE_FN)
119
+ else:
120
+ file_save_path = os.path.join(
121
+ os.getcwd(), Generate.BYOSNAP_PROFILE_FN)
122
+ file_written = False
123
+ with open(file_save_path, "w") as file:
124
+ json.dump(BYOSNAP_TEMPLATE, file, indent=4)
125
+ file_written = True
126
+ if file_written:
127
+ snapctl_success(
128
+ "BYOSNAP Profile generation successful. "
129
+ f"{Generate.BYOSNAP_PROFILE_FN} saved at {file_save_path}",
130
+ progress
131
+ )
132
+ except (IOError, OSError) as file_error:
133
+ snapctl_error(f"File error: {file_error}",
134
+ SNAPCTL_GENERATE_PROFILE_ERROR, progress)
135
+ except json.JSONDecodeError as json_error:
136
+ snapctl_error(f"JSON error: {json_error}",
137
+ SNAPCTL_GENERATE_PROFILE_ERROR, progress)
138
+ snapctl_error(
139
+ "Failed to generate BYOSNAP Profile",
140
+ SNAPCTL_GENERATE_PROFILE_ERROR,
141
+ progress
142
+ )
143
+
144
+ def profile(self) -> None:
145
+ """
146
+ Generate profile
147
+ """
148
+ if self.category == 'byosnap':
149
+ self.byosnap_profile()
150
+
151
+ def ecr_credentials(self) -> None:
152
+ """
153
+ Generate credentials
154
+ """
155
+
156
+ progress = Progress(
157
+ SpinnerColumn(),
158
+ TextColumn("[progress.description]{task.description}"),
159
+ transient=True,
160
+ )
161
+ progress.start()
162
+ progress.add_task(
163
+ description='Generating ECR credentials...', total=None)
164
+ try:
165
+ composite_token: Union[str, None] = get_composite_token(
166
+ self.base_url, self.api_key, 'byogs', {'service_id': 'byogs'}
167
+ )
168
+ token_parts = Generate._get_token_values(composite_token)
169
+ # url|web_app_token|service_id|ecr_repo_url|ecr_repo_username|ecr_repo_token
170
+ if token_parts is None or len(token_parts) != 4:
171
+ snapctl_error(
172
+ "Unable to retrieve token.",
173
+ SNAPCTL_GENERATE_GENERIC_ERROR,
174
+ progress
175
+ )
176
+ token_details = {
177
+ 'ecr_repo_url': token_parts[0],
178
+ 'ecr_repo_username': token_parts[1],
179
+ 'ecr_repo_token': token_parts[2],
180
+ 'ecr_repo_platform': token_parts[3]
181
+ }
182
+ if self.out_path is not None:
183
+ file_save_path = os.path.join(
184
+ self.out_path, Generate.ECR_TOKEN_FN)
185
+ else:
186
+ file_save_path = os.path.join(
187
+ os.getcwd(), Generate.ECR_TOKEN_FN)
188
+ file_written = False
189
+ with open(file_save_path, "w") as file:
190
+ json.dump(token_details, file, indent=4)
191
+ file_written = True
192
+ if file_written:
193
+ snapctl_success(
194
+ "ECR Token generation successful. "
195
+ f"{Generate.ECR_TOKEN_FN} saved at {file_save_path}",
196
+ progress
197
+ )
198
+ except (IOError, OSError) as file_error:
199
+ snapctl_error(f"File error: {file_error}",
200
+ SNAPCTL_GENERATE_CREDENTIALS_ERROR, progress)
201
+ except json.JSONDecodeError as json_error:
202
+ snapctl_error(f"JSON error: {json_error}",
203
+ SNAPCTL_GENERATE_CREDENTIALS_ERROR, progress)
204
+ snapctl_error(
205
+ "Failed to generate Token",
206
+ SNAPCTL_GENERATE_CREDENTIALS_ERROR,
207
+ progress
208
+ )
209
+
210
+ def credentials(self):
211
+ """
212
+ Generate credentials
213
+ """
214
+ if self.category == 'ecr':
215
+ self.ecr_credentials()
@@ -2,7 +2,7 @@
2
2
  Constants used by snapctl
3
3
  """
4
4
  COMPANY_NAME = 'Snapser'
5
- VERSION = '0.32.2'
5
+ VERSION = '0.35.0'
6
6
  CONFIG_FILE_MAC = '~/.snapser/config'
7
7
  CONFIG_FILE_WIN = '%homepath%\\.snapser\\config'
8
8
 
@@ -88,4 +88,5 @@ SNAPCTL_SNAPEND_STATE_ERROR = 75
88
88
 
89
89
  # Generate Errors
90
90
  SNAPCTL_GENERATE_GENERIC_ERROR = 80
91
- SNAPCTL_GENERATE_BYOSNAP_PROFILE_ERROR = 81
91
+ SNAPCTL_GENERATE_PROFILE_ERROR = 81
92
+ SNAPCTL_GENERATE_CREDENTIALS_ERROR = 82
@@ -156,16 +156,32 @@ SERVICE_IDS = [
156
156
  'trackables', 'xp'
157
157
  ]
158
158
 
159
- DEFAULT_BYOSNAP_TEMPLATE = {
159
+ DEFAULT_BYOSNAP_DEV_TEMPLATE = {
160
160
  'cpu': 100,
161
161
  'memory': 0.125,
162
162
  'cmd': '',
163
163
  'args': [],
164
- 'env_params': []
164
+ 'env_params': [{'key': "SNAPSER_ENVIRONMENT", 'value': "DEVELOPMENT"}]
165
+ }
166
+
167
+ DEFAULT_BYOSNAP_STAGE_TEMPLATE = {
168
+ 'cpu': 100,
169
+ 'memory': 0.125,
170
+ 'cmd': '',
171
+ 'args': [],
172
+ 'env_params': [{'key': "SNAPSER_ENVIRONMENT", 'value': "STAGING"}]
173
+ }
174
+
175
+ DEFAULT_BYOSNAP_PROD_TEMPLATE = {
176
+ 'cpu': 100,
177
+ 'memory': 0.125,
178
+ 'cmd': '',
179
+ 'args': [],
180
+ 'env_params': [{'key': "SNAPSER_ENVIRONMENT", 'value': "PRODUCTION"}]
165
181
  }
166
182
 
167
183
  BYOSNAP_TEMPLATE = {
168
- 'dev_template': DEFAULT_BYOSNAP_TEMPLATE,
169
- 'stage_template': DEFAULT_BYOSNAP_TEMPLATE,
170
- 'prod_template': DEFAULT_BYOSNAP_TEMPLATE
184
+ 'dev_template': DEFAULT_BYOSNAP_DEV_TEMPLATE,
185
+ 'stage_template': DEFAULT_BYOSNAP_STAGE_TEMPLATE,
186
+ 'prod_template': DEFAULT_BYOSNAP_PROD_TEMPLATE
171
187
  }
@@ -203,7 +203,7 @@ def version_callback(value: bool = True):
203
203
  def common(
204
204
  ctx: typer.Context,
205
205
  version: bool = typer.Option(
206
- None, "--version",
206
+ None, "--version", "-v",
207
207
  help="Get the Snapctl version.",
208
208
  callback=version_callback
209
209
  ),
@@ -257,6 +257,9 @@ def byogs(
257
257
  docker_file: str = typer.Option(
258
258
  "Dockerfile", help="Dockerfile name to use"
259
259
  ),
260
+ skip_build: bool = typer.Option(
261
+ False, "--skip-build", help="(optional: publish) Skip the build step. You have to pass the image tag you used during the build step."
262
+ ),
260
263
  # overrides
261
264
  api_key: Union[str, None] = typer.Option(
262
265
  None, "--api-key", help="API Key override.", callback=api_key_context_callback
@@ -271,7 +274,7 @@ def byogs(
271
274
  validate_command_context(ctx)
272
275
  byogs_obj: ByoGs = ByoGs(
273
276
  subcommand, ctx.obj['base_url'], ctx.obj['api_key'],
274
- tag, path, docker_file,
277
+ tag, path, docker_file, skip_build
275
278
  )
276
279
  getattr(byogs_obj, subcommand.replace('-', '_'))()
277
280
  success(f"BYOGs {subcommand} complete")
@@ -306,12 +309,12 @@ def byosnap(
306
309
  # publish-image and publish-version
307
310
  tag: str = typer.Option(
308
311
  None, "--tag", help=(
309
- "(req: build, push publish-image and publish-version) Tag for your snap"
312
+ "(req: publish-image and publish-version) Tag for your snap"
310
313
  )
311
314
  ),
312
315
  # publish-image
313
316
  path: Union[str, None] = typer.Option(
314
- None, "--path", help="(req: build, publish-image) Path to your snap code"
317
+ None, "--path", help="(req: publish-image) Path to your snap code"
315
318
  ),
316
319
  docker_file: str = typer.Option(
317
320
  "Dockerfile", help="Dockerfile name to use"
@@ -329,9 +332,13 @@ def byosnap(
329
332
  ),
330
333
  byosnap_profile: Union[str, None] = typer.Option(
331
334
  None, "--byosnap-profile", help=(
332
- "(req: publish-version) Path to your byosnap-profile JSON file"
335
+ "(req: publish-version) Path to your byosnap-profile JSON file. You can generate a base version of this file using the `snapctl generate profile --category byosnap --out-path <output_path>` command."
333
336
  )
334
337
  ),
338
+ skip_build: bool = typer.Option(
339
+ False, "--skip-build", help="(optional: publish-image) Skip the build step. You have to pass the image tag you used during the build step."
340
+ ),
341
+
335
342
  # overrides
336
343
  api_key: Union[str, None] = typer.Option(
337
344
  None, "--api-key", help="API Key override.", callback=api_key_context_callback
@@ -347,7 +354,7 @@ def byosnap(
347
354
  byosnap_obj: ByoSnap = ByoSnap(
348
355
  subcommand, ctx.obj['base_url'], ctx.obj['api_key'], sid,
349
356
  name, desc, platform_type, language, tag, path, docker_file,
350
- prefix, version, http_port, byosnap_profile
357
+ prefix, version, http_port, byosnap_profile, skip_build
351
358
  )
352
359
  getattr(byosnap_obj, subcommand.replace('-', '_'))()
353
360
  success(f"BYOSnap {subcommand} complete")
@@ -390,11 +397,28 @@ def generate(
390
397
  ctx: typer.Context,
391
398
  # Required fields
392
399
  subcommand: str = typer.Argument(
393
- ..., help="Generate Subcommands: " + ", ".join(Generate.SUBCOMMANDS) + "."
400
+ ..., help=(
401
+ "Generate Subcommands: " + \
402
+ ", ".join(Generate.SUBCOMMANDS) + "." + " "
403
+ "Deprecation Notice: " + \
404
+ ",".join(Generate.DEPRECATED_SOON_SUBCOMMANDS) + \
405
+ " will be deprecated soon. "
406
+ "Use `snapctl generate profile --category byosnap --out-path <output_path>` command instead."
407
+ )
408
+ ),
409
+ category: Union[str, None] = typer.Option(
410
+ None, "--category",
411
+ help=(
412
+ "(req: profile, token) (profile: " +
413
+ ", ".join(Generate.CATEGORIES['profile']) +
414
+ ") (token: " + ", ".join(Generate.CATEGORIES['credentials']) + ')'
415
+ )
394
416
  ),
395
- # byosnap-profile
417
+ # byosnap-profile, profile
396
418
  out_path: Union[str, None] = typer.Option(
397
- None, "--out-path", help="(req: byosnap-profile) Path to output the byosnap profile"
419
+ None, "--out-path", help=(
420
+ "(req: byosnap-profile, profile, token) Path to output the byosnap profile"
421
+ )
398
422
  ),
399
423
  # overrides
400
424
  api_key: Union[str, None] = typer.Option(
@@ -410,14 +434,14 @@ def generate(
410
434
  validate_command_context(ctx)
411
435
  generate_obj: Generate = Generate(
412
436
  subcommand, ctx.obj['base_url'], ctx.obj['api_key'],
413
- out_path,
437
+ category, out_path,
414
438
  )
415
439
  getattr(generate_obj, subcommand.replace('-', '_'))()
416
440
  success(f"Generate {subcommand} complete")
417
441
  raise typer.Exit(code=SNAPCTL_SUCCESS)
418
442
 
419
443
 
420
- @app.command()
444
+ @ app.command()
421
445
  def snapend(
422
446
  ctx: typer.Context,
423
447
  # Required fields
@@ -1,93 +0,0 @@
1
- """
2
- Generate CLI commands
3
- """
4
- import json
5
- import os
6
- from typing import Union
7
- from rich.progress import Progress, SpinnerColumn, TextColumn
8
- from snapctl.config.constants import SNAPCTL_INPUT_ERROR, \
9
- SNAPCTL_GENERATE_GENERIC_ERROR
10
- from snapctl.config.hashes import BYOSNAP_TEMPLATE
11
- from snapctl.utils.echo import error
12
- from snapctl.utils.helper import snapctl_error, snapctl_success
13
-
14
-
15
- class Generate:
16
- """
17
- Generate CLI commands
18
- """
19
- SUBCOMMANDS = ['byosnap-profile']
20
- BYOSNAP_PROFILE_FN = 'snapser-byosnap-profile.json'
21
-
22
- def __init__(
23
- self, subcommand: str, base_url: str, api_key: str | None,
24
- out_path: Union[str, None]
25
- ) -> None:
26
- self.subcommand: str = subcommand
27
- self.base_url: str = base_url
28
- self.api_key: str = api_key
29
- self.out_path: Union[str, None] = out_path
30
- # Validate input
31
- self.validate_input()
32
-
33
- # Validator
34
-
35
- def validate_input(self) -> None:
36
- """
37
- Validator
38
- """
39
- if self.subcommand not in Generate.SUBCOMMANDS:
40
- snapctl_error(
41
- f"Invalid command {self.subcommand}. Valid command are "
42
- f"{Generate.SUBCOMMANDS}",
43
- SNAPCTL_INPUT_ERROR
44
- )
45
- if self.subcommand in ['byosnap-profile']:
46
- # Check path
47
- if self.out_path and not os.path.isdir(self.out_path):
48
- snapctl_error(
49
- f"Invalid path {self.out_path}. Wont be able to "
50
- "store the byosnap-profile.json file",
51
- SNAPCTL_INPUT_ERROR
52
- )
53
-
54
- def byosnap_profile(self) -> None:
55
- """
56
- Generate snapser-byosnap-profile.json
57
- """
58
- progress = Progress(
59
- SpinnerColumn(),
60
- TextColumn("[progress.description]{task.description}"),
61
- transient=True,
62
- )
63
- progress.start()
64
- progress.add_task(
65
- description='Promoting your staging snapend...', total=None)
66
- try:
67
- if self.out_path is not None:
68
- file_save_path = os.path.join(
69
- self.out_path, Generate.BYOSNAP_PROFILE_FN)
70
- else:
71
- file_save_path = os.path.join(
72
- os.getcwd(), Generate.BYOSNAP_PROFILE_FN)
73
- file_written = False
74
- with open(file_save_path, "w") as file:
75
- json.dump(BYOSNAP_TEMPLATE, file, indent=4)
76
- file_written = True
77
- if file_written:
78
- snapctl_success(
79
- "BYOSNAP Profile generation successful. "
80
- f"{Generate.BYOSNAP_PROFILE_FN} saved at {file_save_path}",
81
- progress
82
- )
83
- except (IOError, OSError) as file_error:
84
- snapctl_error(f"File error: {file_error}",
85
- SNAPCTL_GENERATE_GENERIC_ERROR, progress)
86
- except json.JSONDecodeError as json_error:
87
- snapctl_error(f"JSON error: {json_error}",
88
- SNAPCTL_GENERATE_GENERIC_ERROR, progress)
89
- snapctl_error(
90
- "Failed to generate BYOSNAP Profile",
91
- SNAPCTL_GENERATE_GENERIC_ERROR,
92
- progress
93
- )
File without changes
File without changes
File without changes
File without changes