snapctl 0.32.1__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.1
3
+ Version: 0.35.0
4
4
  Summary: Snapser CLI Tool
5
5
  Author: Ajinkya Apte
6
6
  Author-email: aj@snapser.com
@@ -177,6 +177,7 @@ snapctl --help
177
177
  ```
178
178
 
179
179
  ### BYO Snap - Bring your own Snap
180
+ Snapctl commands for your custom code
180
181
 
181
182
  #### 1. byosnap help
182
183
 
@@ -208,7 +209,7 @@ snapctl byosnap create --help
208
209
  snapctl byosnap create $byosnap_sid --name "$name" --desc "$desc" --platform "$platform" --language "$language"
209
210
  ```
210
211
 
211
- ### 3. byosnap build
212
+ #### 3. byosnap build
212
213
 
213
214
  Build your snap image
214
215
 
@@ -225,7 +226,7 @@ snapctl byosnap build --help
225
226
  snapctl byosnap build $byosnap_sid --tag $image_tag --path $code_root_path
226
227
  ```
227
228
 
228
- ### 4. byosnap push
229
+ #### 4. byosnap push
229
230
 
230
231
  Push your snap image to Snapser
231
232
 
@@ -271,9 +272,11 @@ snapctl byosnap publish-image --help
271
272
  # $byosnap_sid = Snap ID for your snap
272
273
  # $image_tag = An image tag for your snap
273
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.
274
276
  # Example:
275
277
  # snapctl byosnap publish-image byosnap-jinks-flask --tag my-first-image --path /Users/DevName/Development/SnapserEngine/jinks_flask
276
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
277
280
  ```
278
281
 
279
282
  #### 7. byosnap publish-version
@@ -291,12 +294,14 @@ snapctl byosnap publish-version --help
291
294
  # $prefix = Prefix for your snap Eg: /v1
292
295
  # $version = Semantic version for your snap Eg: v0.0.1
293
296
  # $ingress_port = Ingress port for your snap Eg: 5003
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
294
298
  # Example:
295
- # snapctl byosnap publish-image byosnap-jinks-flask --tag my-first-image --prefix /v1 --version v0.0.1 --http-port 5003
296
- snapctl byosnap publish-version $byosnap_sid --tag $image_tag --prefix $prefix --version $version --http-port $ingress_port
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
300
+ snapctl byosnap publish-version $byosnap_sid --tag $image_tag --prefix $prefix --version $version --http-port $ingress_port --byosnap-profile $byosnap_profile
297
301
  ```
298
302
 
299
303
  ### BYO Game Server - Bring your own Game Server
304
+ Snapctl commands for your custom game server
300
305
 
301
306
  #### 1. byogs help
302
307
 
@@ -350,21 +355,24 @@ snapctl byogs publish --help
350
355
  # Publish a new image
351
356
  # $image_tag = An image tag for your snap
352
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.
353
359
  # Example:
354
360
  # snapctl byogs publish --tag my-first-image --path /Users/DevName/Development/SnapserEngine/game_server
355
361
  snapctl byogs publish --tag $image_tag --path $code_root_path
362
+ snapctl byogs publish --tag $image_tag --skip-build
356
363
  ```
357
364
 
358
365
 
359
366
  ### Game
367
+ Snapctl commands for your game
360
368
 
361
- #### 1. snapend help
369
+ #### 1. game help
362
370
 
363
371
  See all the supported commands
364
372
 
365
373
  ```
366
374
  # Help for the byogs command
367
- snapctl snapend --help
375
+ snapctl game --help
368
376
  ```
369
377
 
370
378
  #### 2. Create a game
@@ -379,8 +387,34 @@ List all the games
379
387
  snapctl game enumerate
380
388
  ```
381
389
 
390
+ ### Generate
391
+ Generator tool to help generate base files to be used in other commands
392
+
393
+ #### 1. generate help
394
+ See all the supported commands
395
+ ```
396
+ # Help for the generate command
397
+ snapctl generate --help
398
+ ```
399
+
400
+ #### 2. Generate BYOSnap Profile
401
+ Generate the base file for BYOSnap profile to be used in the `snapctl byosnap publish-version` command
402
+
403
+ ```
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
413
+
414
+ ```
382
415
 
383
416
  ### Snapend
417
+ Snapctl commands for your snapend
384
418
 
385
419
  #### 1. snapend help
386
420
 
@@ -574,5 +608,6 @@ snapctl snapend state $snapend_id
574
608
  | Error Code | Description |
575
609
  |------------|----------------------------------------------------------|
576
610
  | 80 | Generic generate error |
577
- | 81 | Generate BYOSNAP profile error |
611
+ | 81 | Generate profile error |
612
+ | 82 | Generate credentials error |
578
613
 
@@ -158,6 +158,7 @@ snapctl --help
158
158
  ```
159
159
 
160
160
  ### BYO Snap - Bring your own Snap
161
+ Snapctl commands for your custom code
161
162
 
162
163
  #### 1. byosnap help
163
164
 
@@ -189,7 +190,7 @@ snapctl byosnap create --help
189
190
  snapctl byosnap create $byosnap_sid --name "$name" --desc "$desc" --platform "$platform" --language "$language"
190
191
  ```
191
192
 
192
- ### 3. byosnap build
193
+ #### 3. byosnap build
193
194
 
194
195
  Build your snap image
195
196
 
@@ -206,7 +207,7 @@ snapctl byosnap build --help
206
207
  snapctl byosnap build $byosnap_sid --tag $image_tag --path $code_root_path
207
208
  ```
208
209
 
209
- ### 4. byosnap push
210
+ #### 4. byosnap push
210
211
 
211
212
  Push your snap image to Snapser
212
213
 
@@ -252,9 +253,11 @@ snapctl byosnap publish-image --help
252
253
  # $byosnap_sid = Snap ID for your snap
253
254
  # $image_tag = An image tag for your snap
254
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.
255
257
  # Example:
256
258
  # snapctl byosnap publish-image byosnap-jinks-flask --tag my-first-image --path /Users/DevName/Development/SnapserEngine/jinks_flask
257
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
258
261
  ```
259
262
 
260
263
  #### 7. byosnap publish-version
@@ -272,12 +275,14 @@ snapctl byosnap publish-version --help
272
275
  # $prefix = Prefix for your snap Eg: /v1
273
276
  # $version = Semantic version for your snap Eg: v0.0.1
274
277
  # $ingress_port = Ingress port for your snap Eg: 5003
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
275
279
  # Example:
276
- # snapctl byosnap publish-image byosnap-jinks-flask --tag my-first-image --prefix /v1 --version v0.0.1 --http-port 5003
277
- snapctl byosnap publish-version $byosnap_sid --tag $image_tag --prefix $prefix --version $version --http-port $ingress_port
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
281
+ snapctl byosnap publish-version $byosnap_sid --tag $image_tag --prefix $prefix --version $version --http-port $ingress_port --byosnap-profile $byosnap_profile
278
282
  ```
279
283
 
280
284
  ### BYO Game Server - Bring your own Game Server
285
+ Snapctl commands for your custom game server
281
286
 
282
287
  #### 1. byogs help
283
288
 
@@ -331,21 +336,24 @@ snapctl byogs publish --help
331
336
  # Publish a new image
332
337
  # $image_tag = An image tag for your snap
333
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.
334
340
  # Example:
335
341
  # snapctl byogs publish --tag my-first-image --path /Users/DevName/Development/SnapserEngine/game_server
336
342
  snapctl byogs publish --tag $image_tag --path $code_root_path
343
+ snapctl byogs publish --tag $image_tag --skip-build
337
344
  ```
338
345
 
339
346
 
340
347
  ### Game
348
+ Snapctl commands for your game
341
349
 
342
- #### 1. snapend help
350
+ #### 1. game help
343
351
 
344
352
  See all the supported commands
345
353
 
346
354
  ```
347
355
  # Help for the byogs command
348
- snapctl snapend --help
356
+ snapctl game --help
349
357
  ```
350
358
 
351
359
  #### 2. Create a game
@@ -360,8 +368,34 @@ List all the games
360
368
  snapctl game enumerate
361
369
  ```
362
370
 
371
+ ### Generate
372
+ Generator tool to help generate base files to be used in other commands
373
+
374
+ #### 1. generate help
375
+ See all the supported commands
376
+ ```
377
+ # Help for the generate command
378
+ snapctl generate --help
379
+ ```
380
+
381
+ #### 2. Generate BYOSnap Profile
382
+ Generate the base file for BYOSnap profile to be used in the `snapctl byosnap publish-version` command
383
+
384
+ ```
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
394
+
395
+ ```
363
396
 
364
397
  ### Snapend
398
+ Snapctl commands for your snapend
365
399
 
366
400
  #### 1. snapend help
367
401
 
@@ -555,4 +589,5 @@ snapctl snapend state $snapend_id
555
589
  | Error Code | Description |
556
590
  |------------|----------------------------------------------------------|
557
591
  | 80 | Generic generate error |
558
- | 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.1"
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.1'
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