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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

snapctl/commands/byogs.py CHANGED
@@ -3,18 +3,12 @@
3
3
  """
4
4
  import base64
5
5
  from binascii import Error as BinasciiError
6
- import json
7
6
  import os
8
- import re
9
7
  import subprocess
10
8
  from sys import platform
11
9
  from typing import Union
12
- import requests
13
- from requests.exceptions import RequestException
14
10
 
15
11
  from rich.progress import Progress, SpinnerColumn, TextColumn
16
- from snapctl.config.constants import SERVER_CALL_TIMEOUT
17
- from snapctl.config.constants import ERROR_SERVICE_VERSION_EXISTS, ERROR_TAG_NOT_AVAILABLE
18
12
  from snapctl.types.definitions import ResponseType
19
13
  from snapctl.utils.echo import error, success
20
14
  from snapctl.utils.helper import get_composite_token
@@ -25,11 +19,7 @@ class ByoGs:
25
19
  BYOGS CLI commands
26
20
  """
27
21
  SID = 'byogs'
28
- SUBCOMMANDS = [
29
- 'build', 'push',
30
- 'create', 'publish-image', 'publish-version',
31
- 'publish'
32
- ]
22
+ SUBCOMMANDS = ['build', 'push', 'publish']
33
23
  PLATFORMS = ['linux/amd64']
34
24
  LANGUAGES = ['go', 'python', 'ruby', 'c#', 'c++', 'rust', 'java', 'node']
35
25
  DEFAULT_BUILD_PLATFORM = 'linux/amd64'
@@ -37,34 +27,24 @@ class ByoGs:
37
27
  TAG_CHARACTER_LIMIT = 80
38
28
 
39
29
  def __init__(
40
- self, subcommand: str, base_url: str, api_key: str | None, sid: str, name: str, desc: str,
41
- platform_type: str, language: str, input_tag: Union[str, None], path: Union[str, None],
42
- dockerfile: str, version: Union[str, None], http_port: Union[int, None],
43
- debug_port: Union[int, None]
30
+ self, subcommand: str, base_url: str, api_key: str | None,
31
+ input_tag: Union[str, None], path: Union[str, None], dockerfile: str,
44
32
  ) -> None:
45
33
  self.subcommand: str = subcommand
46
34
  self.base_url: str = base_url
47
35
  self.api_key: str = api_key
48
- self.sid: str = sid
49
- if subcommand == 'publish':
50
- self.sid = ByoGs.SID
51
- self.name: str = name
52
- self.desc: str = desc
53
- self.platform_type: str = platform_type
54
- self.language: str = language
55
- self.token: Union[str, None] = None
56
- if subcommand != 'create':
57
- self.token: Union[str, None] = get_composite_token(
58
- base_url, api_key, 'byogs', {'service_id': self.sid}
59
- )
36
+ # self.sid: str = sid
37
+ # if subcommand == 'publish':
38
+ # self.sid = ByoGs.SID
39
+
40
+ self.token: Union[str, None] = get_composite_token(
41
+ base_url, api_key, 'byogs', {'service_id': ByoGs.SID}
42
+ )
60
43
  self.token_parts: Union[list, None] = ByoGs._get_token_values(
61
44
  self.token) if self.token is not None else None
62
45
  self.input_tag: Union[str, None] = input_tag
63
46
  self.path: Union[str, None] = path
64
47
  self.dockerfile: str = dockerfile
65
- self.version: Union[str, None] = version
66
- self.http_port: Union[int, None] = http_port
67
- self.debug_port: Union[int, None] = debug_port
68
48
 
69
49
  # Protected methods
70
50
 
@@ -151,7 +131,7 @@ class ByoGs:
151
131
 
152
132
  def _docker_build(self) -> bool:
153
133
  # Get the data
154
- image_tag = f'{self.sid}.{self.input_tag}'
134
+ image_tag = f'{ByoGs.SID}.{self.input_tag}'
155
135
  build_platform = ByoGs.DEFAULT_BUILD_PLATFORM
156
136
  if len(self.token_parts) == 4:
157
137
  build_platform = self.token_parts[3]
@@ -190,7 +170,7 @@ class ByoGs:
190
170
  def _docker_tag(self) -> bool:
191
171
  # Get the data
192
172
  ecr_repo_url = self.token_parts[0]
193
- image_tag = f'{self.sid}.{self.input_tag}'
173
+ image_tag = f'{ByoGs.SID}.{self.input_tag}'
194
174
  full_ecr_repo_url = f'{ecr_repo_url}:{image_tag}'
195
175
  try:
196
176
  # Tag the repo
@@ -221,7 +201,7 @@ class ByoGs:
221
201
  def _docker_push(self) -> bool:
222
202
  try:
223
203
  ecr_repo_url = self.token_parts[0]
224
- image_tag = f'{self.sid}.{self.input_tag}'
204
+ image_tag = f'{ByoGs.SID}.{self.input_tag}'
225
205
  full_ecr_repo_url = f'{ecr_repo_url}:{image_tag}'
226
206
 
227
207
  # Push the image
@@ -271,80 +251,33 @@ class ByoGs:
271
251
  if not self.subcommand in ByoGs.SUBCOMMANDS:
272
252
  response['msg'] = f"Invalid command. Valid commands are {', '.join(ByoGs.SUBCOMMANDS)}."
273
253
  return response
274
- # Validate the SID
275
- if not self.sid.startswith(ByoGs.SID):
276
- response['msg'] = (
277
- "Invalid Game Server ID. Valid Game Server IDs start "
278
- f"with {ByoGs.SID}."
279
- )
254
+ # Validation for subcommands
255
+ if self.token_parts is None:
256
+ response['msg'] = 'Invalid token. Please reach out to your support team'
280
257
  return response
281
- if len(self.sid) > ByoGs.SID_CHARACTER_LIMIT:
258
+ # Check tag
259
+ if self.input_tag is None or len(self.input_tag.split()) > 1 or \
260
+ len(self.input_tag) > ByoGs.TAG_CHARACTER_LIMIT:
282
261
  response['msg'] = (
283
- "Invalid Game Server ID. "
284
- f"Game Server ID should be less than {ByoGs.SID_CHARACTER_LIMIT} characters"
262
+ "Tag should be a single word with maximum of "
263
+ f"{ByoGs.TAG_CHARACTER_LIMIT} characters"
285
264
  )
286
265
  return response
287
- # Validation for subcommands
288
- if self.subcommand == 'create':
289
- if self.name == '':
290
- response['msg'] = "Missing name"
291
- return response
292
- if self.language not in ByoGs.LANGUAGES:
293
- response['msg'] = (
294
- "Invalid language. Valid languages "
295
- f"are {', '.join(ByoGs.LANGUAGES)}."
296
- )
266
+ if self.subcommand in ['build', 'publish']:
267
+ if not self.input_tag:
268
+ response['msg'] = "Missing required parameter: tag"
297
269
  return response
298
- if self.platform_type not in ByoGs.PLATFORMS:
299
- response['msg'] = (
300
- "Invalid platform. Valid platforms "
301
- f"are {', '.join(ByoGs.PLATFORMS)}."
302
- )
270
+ if not self.path:
271
+ response['msg'] = "Missing required parameter: path"
303
272
  return response
304
- else:
305
- if self.token_parts is None:
306
- response['msg'] = 'Invalid token. Please reach out to your support team'
273
+ # Check path
274
+ if not os.path.isfile(f"{self.path}/{self.dockerfile}"):
275
+ response['msg'] = f"Unable to find {self.dockerfile} at path {self.path}"
307
276
  return response
308
- # Check tag
309
- if self.input_tag is None or len(self.input_tag.split()) > 1 or \
310
- len(self.input_tag) > ByoGs.TAG_CHARACTER_LIMIT:
311
- response['msg'] = (
312
- "Tag should be a single word with maximum of "
313
- f"{ByoGs.TAG_CHARACTER_LIMIT} characters"
314
- )
277
+ elif self.subcommand == 'push':
278
+ if not self.input_tag:
279
+ response['msg'] = "Missing required parameter: tag"
315
280
  return response
316
- if self.subcommand in ['build', 'publish-image', 'publish']:
317
- if not self.input_tag:
318
- response['msg'] = "Missing required parameter: tag"
319
- return response
320
- if not self.path:
321
- response['msg'] = "Missing required parameter: path"
322
- return response
323
- # Check path
324
- if not os.path.isfile(f"{self.path}/{self.dockerfile}"):
325
- response['msg'] = f"Unable to find {self.dockerfile} at path {self.path}"
326
- return response
327
- elif self.subcommand == 'push':
328
- if not self.input_tag:
329
- response['msg'] = "Missing required parameter: tag"
330
- return response
331
- elif self.subcommand == 'publish-version':
332
- if not self.version:
333
- response['msg'] = "Missing required parameter: version"
334
- return response
335
- if not self.http_port:
336
- response['msg'] = "Missing required parameter: Ingress HTTP Port"
337
- return response
338
- pattern = r'^v\d+\.\d+\.\d+$'
339
- if not re.match(pattern, self.version):
340
- response['msg'] = "Version should be in the format vX.X.X"
341
- return response
342
- if not self.http_port.isdigit():
343
- response['msg'] = "Ingress HTTP Port should be a number"
344
- return response
345
- if self.debug_port and not self.debug_port.isdigit():
346
- response['msg'] = "Debug Port should be a number"
347
- return response
348
281
  # Send success
349
282
  response['error'] = False
350
283
  return response
@@ -376,63 +309,6 @@ class ByoGs:
376
309
  return True
377
310
 
378
311
  # Upper echelon commands
379
- def create(self) -> bool:
380
- """
381
- Create a new game server
382
- """
383
- with Progress(
384
- SpinnerColumn(),
385
- TextColumn("[progress.description]{task.description}"),
386
- transient=True,
387
- ) as progress:
388
- progress.add_task(
389
- description='Creating your game server...', total=None)
390
- try:
391
- payload = {
392
- "service_id": self.sid,
393
- "name": self.name,
394
- "description": self.desc,
395
- "platform": self.platform_type,
396
- "language": self.language,
397
- }
398
- res = requests.post(
399
- f"{self.base_url}/v1/snapser-api/byogs",
400
- json=payload, headers={'api-key': self.api_key},
401
- timeout=SERVER_CALL_TIMEOUT
402
- )
403
- if res.ok:
404
- return True
405
- response_json = res.json()
406
- if "api_error_code" in response_json:
407
- if response_json['api_error_code'] == ERROR_SERVICE_VERSION_EXISTS:
408
- error(
409
- 'Version already exists. Please update your version and try again'
410
- )
411
- if response_json['api_error_code'] == ERROR_TAG_NOT_AVAILABLE:
412
- error('Invalid tag. Please use the correct tag')
413
- else:
414
- error(
415
- f'Server error: {json.dumps(response_json, indent=2)}'
416
- )
417
- except RequestException as e:
418
- error(f"Exception: Unable to create your game server {e}")
419
- return False
420
-
421
- def publish_image(self) -> bool:
422
- """
423
- Publish the image
424
- 1. Check Dependencies
425
- 2. Login to Snapser Registry
426
- 3. Build your snap
427
- 4. Tag the repo
428
- 5. Push the image
429
- 6. Upload swagger.json
430
- """
431
- if not self._check_dependencies() or not self._docker_login() or \
432
- not self._docker_build() or not self._docker_tag() or not self._docker_push():
433
- return False
434
- return True
435
-
436
312
  def publish(self) -> bool:
437
313
  """
438
314
  Publish the image
@@ -447,47 +323,3 @@ class ByoGs:
447
323
  not self._docker_build() or not self._docker_tag() or not self._docker_push():
448
324
  return False
449
325
  return True
450
-
451
- def publish_version(self) -> bool:
452
- """
453
- Publish your game server version
454
- """
455
- with Progress(
456
- SpinnerColumn(),
457
- TextColumn("[progress.description]{task.description}"),
458
- transient=True,
459
- ) as progress:
460
- progress.add_task(
461
- description='Publishing your snap...', total=None)
462
- try:
463
- payload = {
464
- "version": self.version,
465
- "image_tag": self.input_tag,
466
- "http_port": self.http_port,
467
- }
468
- if self.debug_port:
469
- payload['debug_port'] = self.debug_port
470
- res = requests.post(
471
- f"{self.base_url}/v1/snapser-api/byogs/{self.sid}/versions",
472
- json=payload, headers={'api-key': self.api_key},
473
- timeout=SERVER_CALL_TIMEOUT
474
- )
475
- if res.ok:
476
- return True
477
- response_json = res.json()
478
- if "api_error_code" in response_json:
479
- if response_json['api_error_code'] == ERROR_SERVICE_VERSION_EXISTS:
480
- error(
481
- 'Version already exists. Please update your version and try again'
482
- )
483
- if response_json['api_error_code'] == ERROR_TAG_NOT_AVAILABLE:
484
- error('Invalid tag. Please use the correct tag')
485
- else:
486
- error(
487
- f'Server error: {json.dumps(response_json, indent=2)}'
488
- )
489
- except RequestException as e:
490
- error(
491
- f"Exception: Unable to publish a version for your snap {e}"
492
- )
493
- return False
@@ -35,12 +35,14 @@ class ByoSnap:
35
35
  DEFAULT_BUILD_PLATFORM = 'linux/arm64'
36
36
  SID_CHARACTER_LIMIT = 47
37
37
  TAG_CHARACTER_LIMIT = 80
38
+ VALID_CPU_MARKS = [100, 250, 500, 750, 1000, 1500, 2000, 3000]
39
+ VALID_MEMORY_MARKS = [0.125, 0.25, 0.5, 1, 2, 3, 4]
38
40
 
39
41
  def __init__(
40
42
  self, subcommand: str, base_url: str, api_key: str | None, sid: str, name: str,
41
43
  desc: str, platform_type: str, language: str, input_tag: Union[str, None],
42
44
  path: Union[str, None], dockerfile: str, prefix: str, version: Union[str, None],
43
- http_port: Union[int, None]
45
+ http_port: Union[int, None], byosnap_profile: Union[str, None]
44
46
  ) -> None:
45
47
  self.subcommand: str = subcommand
46
48
  self.base_url: str = base_url
@@ -65,6 +67,7 @@ class ByoSnap:
65
67
  self.prefix: str = prefix
66
68
  self.version: Union[str, None] = version
67
69
  self.http_port: Union[int, None] = http_port
70
+ self.byosnap_profile: Union[str, None] = byosnap_profile
68
71
 
69
72
  # Protected methods
70
73
  @staticmethod
@@ -254,6 +257,63 @@ class ByoSnap:
254
257
  success('Snap Upload Successful')
255
258
  return True
256
259
 
260
+ def _validate_byosnap_profile(self) -> bool:
261
+ """
262
+ Validate the BYOSnap profile
263
+ """
264
+ response = {
265
+ 'error': True,
266
+ 'message': ''
267
+ }
268
+ if not self.byosnap_profile:
269
+ response['message'] = "Missing BYOSnap profile path"
270
+ return response
271
+ if not os.path.isfile(self.byosnap_profile):
272
+ response['msg'] = (
273
+ "Unable to find BYOSnap profile "
274
+ F"JSON at path {self.byosnap_profile}"
275
+ )
276
+ return response
277
+ with open(self.byosnap_profile, 'rb') as file:
278
+ try:
279
+ profile_data = json.load(file)
280
+ except json.JSONDecodeError:
281
+ response['message'] = (
282
+ 'Invalid BYOSnap profile JSON. Please check the JSON structure'
283
+ )
284
+ return response
285
+ if 'dev_template' not in profile_data or \
286
+ 'stage_template' not in profile_data or \
287
+ 'prod_template' not in profile_data:
288
+ response['message'] = (
289
+ 'Invalid BYOSnap profile JSON. Please check the JSON structure'
290
+ )
291
+ return response
292
+ for profile in ['dev_template', 'stage_template', 'prod_template']:
293
+ if 'cpu' not in profile_data[profile] or \
294
+ 'memory' not in profile_data[profile] or \
295
+ 'cmd' not in profile_data[profile] or \
296
+ 'args' not in profile_data[profile] or \
297
+ 'env_params' not in profile_data[profile]:
298
+ response['message'] = (
299
+ 'Invalid BYOSnap profile JSON. Please check the JSON structure'
300
+ )
301
+ return response
302
+ if profile_data[profile]['cpu'] not in ByoSnap.VALID_CPU_MARKS:
303
+ response['message'] = (
304
+ 'Invalid CPU value in BYOSnap profile. '
305
+ f'Valid values are {", ".join(ByoSnap.VALID_CPU_MARKS)}'
306
+ )
307
+ return response
308
+ if profile_data[profile]['memory'] not in ByoSnap.VALID_MEMORY_MARKS:
309
+ response['message'] = (
310
+ 'Invalid Memory value in BYOSnap profile. '
311
+ f'Valid values are {", ".join(ByoSnap.VALID_MEMORY_MARKS)}'
312
+ )
313
+ return response
314
+ response['error'] = False
315
+ return response
316
+
257
317
  # Public methods
258
318
 
259
319
  # Validator
@@ -359,6 +419,12 @@ class ByoSnap:
359
419
  if not self.http_port.isdigit():
360
420
  response['msg'] = "Ingress HTTP Port should be a number"
361
421
  return response
422
+ # Check byosnap_profile path
423
+ validation_response = self._validate_byosnap_profile()
424
+ if validation_response['error']:
425
+ response['msg'] = validation_response['message']
426
+ return response
427
+
362
428
  # Send success
363
429
  response['error'] = False
364
430
  return response
@@ -539,11 +605,20 @@ class ByoSnap:
539
605
  progress.add_task(
540
606
  description='Publishing your snap...', total=None)
541
607
  try:
608
+ profile_data = {}
609
+ profile_data['dev_template'] = None
610
+ profile_data['stage_template'] = None
611
+ profile_data['prod_template'] = None
612
+ with open(self.byosnap_profile, 'rb') as file:
613
+ profile_data = json.load(file)
542
614
  payload = {
543
615
  "version": self.version,
544
616
  "image_tag": self.input_tag,
545
617
  "base_url": f"{self.prefix}/{self.sid}",
546
618
  "http_port": self.http_port,
619
+ "dev_template": profile_data['dev_template'],
620
+ "stage_template": profile_data['stage_template'],
621
+ "prod_template": profile_data['prod_template']
547
622
  }
548
623
  res = requests.post(
549
624
  f"{self.base_url}/v1/snapser-api/byosnaps/{self.sid}/versions",
@@ -0,0 +1,77 @@
1
+ """
2
+ Generate CLI commands
3
+ """
4
+ import json
5
+ from sys import platform
6
+ import os
7
+ from typing import Union
8
+
9
+ from snapctl.config.hashes import BYOSNAP_TEMPLATE
10
+ from snapctl.types.definitions import ResponseType
11
+ from snapctl.utils.echo import error, success
12
+
13
+
14
+ class Generate:
15
+ """
16
+ Generate CLI commands
17
+ """
18
+ SUBCOMMANDS = ['byosnap-profile']
19
+ BYOSNAP_PROFILE_FN = 'snapser-byosnap-profile.json'
20
+
21
+ def __init__(
22
+ self, subcommand: str, base_url: str, api_key: str | None,
23
+ out_path: Union[str, None]
24
+ ) -> None:
25
+ self.subcommand: str = subcommand
26
+ self.base_url: str = base_url
27
+ self.api_key: str = api_key
28
+ self.out_path: Union[str, None] = out_path
29
+
30
+ # Validator
31
+
32
+ def validate_input(self) -> ResponseType:
33
+ """
34
+ Validator
35
+ """
36
+ response: ResponseType = {
37
+ 'error': True,
38
+ 'msg': '',
39
+ 'data': []
40
+ }
41
+ if self.subcommand in ['byosnap-profile']:
42
+ # Check path
43
+ if self.out_path and not os.path.isdir(self.out_path):
44
+ response['msg'] = (
45
+ f"Invalid path {self.out_path}. Wont be able to "
46
+ "store the byosnap-profile.json file"
47
+ )
48
+ return response
49
+ # Send success
50
+ response['error'] = False
51
+ return response
52
+
53
+ def byosnap_profile(self) -> bool:
54
+ """
55
+ Generate snapser-byosnap-profile.json
56
+ """
57
+ file_path_symbol = '/'
58
+ if platform == 'win32':
59
+ file_path_symbol = '\\'
60
+ if self.out_path is not None:
61
+ file_save_path = f"{self.out_path}{file_path_symbol}{Generate.BYOSNAP_PROFILE_FN}"
62
+ else:
63
+ file_save_path = f"{os.getcwd()}{file_path_symbol}{Generate.BYOSNAP_PROFILE_FN}"
64
+ try:
65
+ with open(file_save_path, "w") as file:
66
+ json.dump(BYOSNAP_TEMPLATE, file, indent=4)
67
+ success(
68
+ f"{Generate.BYOSNAP_PROFILE_FN} saved at {file_save_path}"
69
+ )
70
+ return True
71
+ except (IOError, OSError) as file_error:
72
+ error(f"File error: {file_error}")
73
+ except json.JSONDecodeError as json_error:
74
+ error(f"JSON error: {json_error}")
75
+ except Exception as exception_error:
76
+ error(f"An unexpected error occurred: {exception_error}")
77
+ return False
@@ -2,7 +2,7 @@
2
2
  Constants used by snapctl
3
3
  """
4
4
  COMPANY_NAME = 'Snapser'
5
- VERSION = '0.31.1'
5
+ VERSION = '0.32.0'
6
6
  CONFIG_FILE_MAC = '~/.snapser/config'
7
7
  CONFIG_FILE_WIN = '%homepath%\\.snapser\\config'
8
8
 
snapctl/config/hashes.py CHANGED
@@ -155,3 +155,17 @@ SERVICE_IDS = [
155
155
  'relay', 'remote-config', 'scheduler', 'sequencer', 'social-graph', 'statistics', 'storage',
156
156
  'trackables', 'xp'
157
157
  ]
158
+
159
+ DEFAULT_BYOSNAP_TEMPLATE = {
160
+ 'cpu': 100,
161
+ 'memory': 0.125,
162
+ 'cmd': '',
163
+ 'args': [],
164
+ 'env_params': []
165
+ }
166
+
167
+ BYOSNAP_TEMPLATE = {
168
+ 'dev_template': DEFAULT_BYOSNAP_TEMPLATE,
169
+ 'stage_template': DEFAULT_BYOSNAP_TEMPLATE,
170
+ 'prod_template': DEFAULT_BYOSNAP_TEMPLATE
171
+ }
snapctl/main.py CHANGED
@@ -11,6 +11,7 @@ import pyfiglet
11
11
  from snapctl.commands.byosnap import ByoSnap
12
12
  from snapctl.commands.byogs import ByoGs
13
13
  from snapctl.commands.game import Game
14
+ from snapctl.commands.generate import Generate
14
15
  from snapctl.commands.snapend import Snapend
15
16
  from snapctl.config.constants import COMPANY_NAME, API_KEY, URL_KEY, CONFIG_FILE_MAC, \
16
17
  CONFIG_FILE_WIN, DEFAULT_PROFILE, VERSION, SNAPCTL_SUCCESS, SNAPCTL_ERROR, CONFIG_PATH_KEY
@@ -283,6 +284,11 @@ def byosnap(
283
284
  http_port: Union[str, None] = typer.Option(
284
285
  None, "--http-port", help="(req: publish-version) Ingress HTTP port version"
285
286
  ),
287
+ byosnap_profile: Union[str, None] = typer.Option(
288
+ None, "--byosnap-profile", help=(
289
+ "(req: publish-version) Path to your byosnap-profile JSON file"
290
+ )
291
+ ),
286
292
  # overrides
287
293
  api_key: Union[str, None] = typer.Option(
288
294
  None, "--api-key", help="API Key override.", callback=api_key_context_callback
@@ -298,7 +304,7 @@ def byosnap(
298
304
  byosnap_obj: ByoSnap = ByoSnap(
299
305
  subcommand, ctx.obj['base_url'], ctx.obj['api_key'], sid,
300
306
  name, desc, platform_type, language, tag, path, docker_file,
301
- prefix, version, http_port
307
+ prefix, version, http_port, byosnap_profile
302
308
  )
303
309
  validate_input_response: ResponseType = byosnap_obj.validate_input()
304
310
  if validate_input_response['error']:
@@ -319,48 +325,21 @@ def byogs(
319
325
  subcommand: str = typer.Argument(
320
326
  ..., help="BYOGs Subcommands: " + ", ".join(ByoGs.SUBCOMMANDS) + "."
321
327
  ),
322
- sid: str = typer.Argument(
323
- ByoGs.SID, help="Game Server Id. Should start with byogs"
324
- ),
325
- # create
326
- name: str = typer.Option(
327
- None, "--name", help="(req: create) Name for your snap"
328
- ),
329
- desc: str = typer.Option(
330
- None, "--desc", help="(req: create) Description for your snap"
331
- ),
332
- platform_type: str = typer.Option(
333
- None, "--platform",
334
- help="(req: create) Platform for your snap - " + \
335
- ", ".join(ByoGs.PLATFORMS) + "."
336
- ),
337
- language: str = typer.Option(
338
- None, "--language",
339
- help="(req: create) Language of your snap - " + \
340
- ", ".join(ByoGs.LANGUAGES) + "."
341
- ),
328
+ # sid: str = typer.Argument(
329
+ # ByoGs.SID, help="Game Server Id. Should start with byogs"
330
+ # ),
342
331
  # publish, publish-image and publish-version
343
332
  tag: str = typer.Option(
344
333
  None, "--tag",
345
- help="(req: build, push, publish, publish-image and publish-version) Tag for your snap"
334
+ help="(req: build, push, publish) Tag for your snap"
346
335
  ),
347
336
  # publish and publish-image
348
337
  path: Union[str, None] = typer.Option(
349
- None, "--path", help="(req: build, publish, publish-image, upload-docs) Path to your snap code"
338
+ None, "--path", help="(req: build, publish) Path to your snap code"
350
339
  ),
351
340
  docker_file: str = typer.Option(
352
341
  "Dockerfile", help="Dockerfile name to use"
353
342
  ),
354
- # publish-version
355
- version: Union[str, None] = typer.Option(
356
- None, "--version", help="(req: publish-version) Snap version"
357
- ),
358
- http_port: Union[str, None] = typer.Option(
359
- None, "--http-port", help="(req: publish-version) Ingress HTTP port version"
360
- ),
361
- debug_port: Union[str, None] = typer.Option(
362
- None, "--debug-port", help="(optional: publish-version) Debug HTTP port version"
363
- ),
364
343
  # overrides
365
344
  api_key: Union[str, None] = typer.Option(
366
345
  None, "--api-key", help="API Key override.", callback=api_key_context_callback
@@ -374,9 +353,8 @@ def byogs(
374
353
  """
375
354
  validate_command_context(ctx)
376
355
  byogs_obj: ByoGs = ByoGs(
377
- subcommand, ctx.obj['base_url'], ctx.obj['api_key'], sid,
378
- name, desc, platform_type, language, tag, path, docker_file,
379
- version, http_port, debug_port
356
+ subcommand, ctx.obj['base_url'], ctx.obj['api_key'],
357
+ tag, path, docker_file,
380
358
  )
381
359
  validate_input_response: ResponseType = byogs_obj.validate_input()
382
360
  if validate_input_response['error']:
@@ -562,3 +540,42 @@ def snapend(
562
540
  error(f"Snapend {subcommand} failed")
563
541
  raise typer.Exit(SNAPCTL_ERROR)
564
542
  success(f"Snapend {subcommand} complete")
543
+
544
+
545
+ @app.command()
546
+ def generate(
547
+ ctx: typer.Context,
548
+ # Required fields
549
+ subcommand: str = typer.Argument(
550
+ ..., help="Generate Subcommands: " + ", ".join(Generate.SUBCOMMANDS) + "."
551
+ ),
552
+ # byosnap-profile
553
+ out_path: Union[str, None] = typer.Option(
554
+ None, "--out-path", help="(req: byosnap-profile) Path to output the byosnap profile"
555
+ ),
556
+ # overrides
557
+ api_key: Union[str, None] = typer.Option(
558
+ None, "--api-key", help="API Key override.", callback=api_key_context_callback
559
+ ),
560
+ profile: Union[str, None] = typer.Option(
561
+ None, "--profile", help="Profile to use.", callback=profile_context_callback
562
+ ),
563
+ ) -> None:
564
+ """
565
+ Generate files to be used by other commands
566
+ """
567
+ validate_command_context(ctx)
568
+ generate_obj: Generate = Generate(
569
+ subcommand, ctx.obj['base_url'], ctx.obj['api_key'],
570
+ out_path,
571
+ )
572
+ validate_input_response: ResponseType = generate_obj.validate_input()
573
+ if validate_input_response['error']:
574
+ error(validate_input_response['msg'])
575
+ raise typer.Exit(SNAPCTL_ERROR)
576
+ command_method = subcommand.replace('-', '_')
577
+ method: Callable[..., bool] = getattr(generate_obj, command_method)
578
+ if not method():
579
+ error(f"Generate {subcommand} failed")
580
+ raise typer.Exit(SNAPCTL_ERROR)
581
+ success(f"Generate {subcommand} complete")
@@ -0,0 +1,29 @@
1
+ Snapser Inc. Proprietary License
2
+
3
+ This CLI tool, its source code, and any accompanying documentation (collectively referred to as the "Software") are the property of Snapser Inc. ("Snapser"). The Software is provided under the following license terms and conditions:
4
+
5
+ 1. License Grant:
6
+ Snapser grants you a non-exclusive, non-transferable, revocable license to use the Software solely for your internal business purposes. You may not distribute, sublicense, rent, lease, sell, or otherwise transfer the Software or any portion thereof.
7
+
8
+ 2. Restrictions:
9
+ You may not modify, adapt, translate, reverse engineer, decompile, disassemble, or create derivative works based on the Software. You may not remove or alter any copyright, trademark, or other proprietary rights notices contained in the Software.
10
+
11
+ 3. Ownership:
12
+ The Software and all intellectual property rights therein are and shall remain the exclusive property of Snapser Inc. Nothing in this license agreement shall be construed to transfer ownership of the Software to you.
13
+
14
+ 4. Term and Termination:
15
+ This license is effective until terminated by either party. Snapser may terminate this license at any time if you breach any of its terms and conditions. Upon termination, you must immediately cease all use of the Software and destroy all copies thereof.
16
+
17
+ 5. Disclaimer of Warranty:
18
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, SNAPSER DISCLAIMS ALL WARRANTIES, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. SNAPSER DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET YOUR REQUIREMENTS OR THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE.
19
+
20
+ 6. Limitation of Liability:
21
+ IN NO EVENT SHALL SNAPSER BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, LOSS OF INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF SNAPSER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
22
+
23
+ 7. Governing Law:
24
+ This license agreement shall be governed by and construed in accordance with the laws of the United States of America, excluding its conflicts of law principles. Any disputes arising out of or in connection with this agreement shall be subject to the exclusive jurisdiction of the courts located in the United States of America.
25
+
26
+ By using the Software, you agree to be bound by the terms and conditions of this license agreement. If you do not agree to these terms and conditions, do not use the Software.
27
+
28
+ Snapser Inc.
29
+ June 4, 2024
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: snapctl
3
- Version: 0.31.1
3
+ Version: 0.32.0
4
4
  Summary: Snapser CLI Tool
5
5
  Author: Ajinkya Apte
6
6
  Author-email: aj@snapser.com
@@ -244,16 +244,16 @@ snapctl byosnap push $byosnap_sid --tag $image_tag
244
244
  Upload swagger.json and README.md for you Snap
245
245
 
246
246
  ```
247
- # Help for the byogs command
247
+ # Help for the byosnap command
248
248
  snapctl byosnap upload-docs --help
249
249
 
250
250
  # Publish a new image
251
- # $byogs_sid = Game server ID for your snap
251
+ # $byosnap_sid = Snap ID for your snap
252
252
  # $image_tag = An image tag for your snap
253
253
  # $code_root_path = Local code path where your swagger.json and README.md files are present
254
254
  # Example:
255
255
  # snapctl byosnap upload-docs byosnap-jinks-flask --tag my-first-image --path /Users/DevName/Development/SnapserEngine/jinks_flask
256
- snapctl byosnap upload-docs $byogs_sid --tag $image_tag --path $code_root_path
256
+ snapctl byosnap upload-docs $byosnap_sid --tag $image_tag --path $code_root_path
257
257
  ```
258
258
 
259
259
  #### 6. byosnap publish-image
@@ -305,28 +305,7 @@ See all the supported commands
305
305
  snapctl byogs --help
306
306
  ```
307
307
 
308
- #### 2. [Deprecated soon] byogs create
309
-
310
- Create a custom game server. Note that you will have to build, push and publish your game server image, for it to be useable
311
- in a Snapend fleet.
312
-
313
- ```
314
- # Help for the byosnap command
315
- snapctl byogs create --help
316
-
317
- # Create a new snap
318
- # $byogs_sid = Game server ID for your snap. Should start with `byogs-`
319
- # $name = User friendly name for your BYOGs
320
- # $desc = User friendly description
321
- # $platform = Currently only supported platform is linux/amd64
322
- # $language = One of go, python, ruby, c#, c++, rust, java, node
323
-
324
- # Example:
325
- # snapctl byogs create byosnap-jinks-gs --name "Jinks Flask Microservice" --desc "Custom Microservice" --platform "linux/arm64" --language "go"
326
- snapctl byogs create $byogs_sid --name "$name" --desc "$desc" --platform "$platform" --language "$language"
327
- ```
328
-
329
- #### 3. byogs build
308
+ #### 2. byogs build
330
309
 
331
310
  Build your custom game server image.
332
311
 
@@ -335,15 +314,14 @@ Build your custom game server image.
335
314
  snapctl byogs build --help
336
315
 
337
316
  # Publish a new image
338
- # $byogs_sid = Game server ID for your snap
339
317
  # $image_tag = An image tag for your snap
340
318
  # $code_root_path = Local code path where your Dockerfile is present
341
319
  # Example:
342
320
  # snapctl byogs build byosnap-jinks-gs --tag my-first-image --path /Users/DevName/Development/SnapserEngine/game_server
343
- snapctl byogs build $byogs_sid --tag $image_tag --path $code_root_path
321
+ snapctl byogs build --tag $image_tag --path $code_root_path
344
322
  ```
345
323
 
346
- #### 4. byogs push
324
+ #### 3. byogs push
347
325
 
348
326
  Push your custom game server image.
349
327
 
@@ -352,51 +330,13 @@ Push your custom game server image.
352
330
  snapctl byogs push --help
353
331
 
354
332
  # Publish a new image
355
- # $byogs_sid = Game server ID for your snap
356
333
  # $image_tag = An image tag for your snap
357
334
  # Example:
358
335
  # snapctl byogs push byosnap-jinks-gs --tag my-first-image
359
- snapctl byogs push $byogs_sid --tag $image_tag
360
- ```
361
-
362
- #### 5. [Deprecated soon] byogs publish-image
363
-
364
- Publish your custom game server image. This command executes, `build` and `push` one after the other.
365
-
366
- ```
367
- # Help for the byogs command
368
- snapctl byogs publish-image --help
369
-
370
- # Publish a new image
371
- # $byogs_sid = Game server ID for your snap
372
- # $image_tag = An image tag for your snap
373
- # $code_root_path = Local code path where your Dockerfile is present
374
- # Example:
375
- # snapctl byogs publish-image byosnap-jinks-gs --tag my-first-image --path /Users/DevName/Development/SnapserEngine/game_server
376
- snapctl byogs publish-image $byogs_sid --tag $image_tag --path $code_root_path
377
- ```
378
-
379
- #### 6. [Deprecated soon] byogs publish-version
380
-
381
- Publish a new version for your game server. Only after your game server version is published, you will be able
382
- to use it in your Snapend fleet. This command should be run after you `push` or `publish-image` commands.
383
-
384
- ```
385
- # Help for the byogs command
386
- snapctl byogs publish-version --help
387
-
388
- # Publish a new image
389
- # $byogs_sid = Snap ID for your snap
390
- # $image_tag = Any image tag for your snap
391
- # $prefix = Prefix for your snap Eg: /v1
392
- # $version = Semantic version for your snap Eg: v0.0.1
393
- # $ingress_port = Ingress port for your snap Eg: 5003
394
- # Example:
395
- # snapctl byogs publish-image byosnap-jinks-gs --tag my-first-image --prefix /v1 --version v0.0.1 --http-port 5003
396
- snapctl byogs publish-version $byogs_sid --tag $image_tag --prefix $prefix --version $version --http-port $ingress_port
336
+ snapctl byogs push --tag $image_tag
397
337
  ```
398
338
 
399
- #### 7. [New] byogs publish
339
+ #### 4. byogs publish
400
340
 
401
341
  Publish your custom game server image. This commend replaces the old way of creating, publishing image and
402
342
  then publishing the byogs. Now all you have to do is publish your image and create a fleet using the web portal.
@@ -1,21 +1,23 @@
1
1
  snapctl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  snapctl/__main__.py,sha256=43jKoTk8b85hk_MT6499N3ruHdEfM8WBImd_-3VzjI8,116
3
3
  snapctl/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- snapctl/commands/byogs.py,sha256=2Jocaemxn01IrKno3u9QrVeiAsqIpCJBVsWi2ivHuCY,19762
5
- snapctl/commands/byosnap.py,sha256=RQv3r30dkz8n1BgEnE-tAnAzPLoz-CLEQoiy1WKZQeg,23172
4
+ snapctl/commands/byogs.py,sha256=LxGKlvKsnt6YIVjgj8I-5ziwNuEysLx3lgH8voYgpS8,12610
5
+ snapctl/commands/byosnap.py,sha256=mhCDzzHSVyYhA3h4BSdGbS3ph1KeK47S3LutnN3mIiE,26727
6
6
  snapctl/commands/game.py,sha256=rnsTqrXavE5D-KULXkDBQ-PBI8sSKK4it3S_YMJfiUY,3633
7
+ snapctl/commands/generate.py,sha256=E-EIm9X4DqCLOfUxA-412moG9aliNcL4UuI8X_nf2yk,2438
7
8
  snapctl/commands/snapend.py,sha256=exMH-8lp9qUociAWHJS15xRr-MtCe1fjbQAQmgODNIw,26187
8
9
  snapctl/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- snapctl/config/constants.py,sha256=iX5zkftpOqdGJWoCK8-zwP_Mz9GD3BU62DVKrzTygpw,565
10
+ snapctl/config/constants.py,sha256=_KnxkpD_VSBYj8Mtngc3p58gdq4f24H5kZJaBZd6lXI,565
10
11
  snapctl/config/endpoints.py,sha256=VAeOmx3k3ukB-9XuGI65KtCJwFK-KFgzor-UWE8JU0g,297
11
- snapctl/config/hashes.py,sha256=tb0ilslgYvI8L4IKeiMfz2qYRDcezat8tg8dPGqlbAU,3093
12
- snapctl/main.py,sha256=QES1PqGgMWjKVcOdUA8b14KHweiE2iJigxKtaoJfBDw,19147
12
+ snapctl/config/hashes.py,sha256=4yydu7uPRwNo72WcU_HWjoCLDluG7mLPGCWVUFFF-xU,3378
13
+ snapctl/main.py,sha256=HR6EKtxAh1ekpBuS9ug_9h44J-RNOBLdOTDd0VFAyiw,19649
13
14
  snapctl/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
15
  snapctl/types/definitions.py,sha256=rkRyTBHzeQtCt_uYObgYvL5txnVq8r_n5g4IUAq2FWc,233
15
16
  snapctl/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
17
  snapctl/utils/echo.py,sha256=0nhWYDBQTfZGtl8EK21hJhj0now2rQmCT-yYMCKupy4,584
17
18
  snapctl/utils/helper.py,sha256=xasSsg-0DgHT-TWejh2IXW-s9AYntO1D2O6Uy6BQLcE,1381
18
- snapctl-0.31.1.dist-info/METADATA,sha256=cIywFLCBwuCumEUspq8sf4qgNcsAcixFSIph1Wz0fvI,16509
19
- snapctl-0.31.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
20
- snapctl-0.31.1.dist-info/entry_points.txt,sha256=tkKW9MzmFdRs6Bgkv29G78i9WEBK4WIOWunPfe3t2Wg,44
21
- snapctl-0.31.1.dist-info/RECORD,,
19
+ snapctl-0.32.0.dist-info/LICENSE,sha256=6AcXm54KFSpmUI1ji9NIBd4Xl-DtjTqiyjBzfVb_CEk,2804
20
+ snapctl-0.32.0.dist-info/METADATA,sha256=_P_CjVusW-2d6b4ttg_nI7A9M1jMNpbikk46hPIjSCk,14113
21
+ snapctl-0.32.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
22
+ snapctl-0.32.0.dist-info/entry_points.txt,sha256=tkKW9MzmFdRs6Bgkv29G78i9WEBK4WIOWunPfe3t2Wg,44
23
+ snapctl-0.32.0.dist-info/RECORD,,