snapctl 0.31.0__tar.gz → 0.32.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.
- snapctl-0.32.0/LICENSE +29 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/PKG-INFO +16 -73
- {snapctl-0.31.0 → snapctl-0.32.0}/README.md +15 -72
- {snapctl-0.31.0 → snapctl-0.32.0}/pyproject.toml +1 -1
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/commands/byogs.py +32 -200
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/commands/byosnap.py +76 -1
- snapctl-0.32.0/snapctl/commands/generate.py +77 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/config/constants.py +2 -1
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/config/hashes.py +14 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/main.py +65 -47
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/__init__.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/__main__.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/commands/__init__.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/commands/game.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/commands/snapend.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/config/__init__.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/config/endpoints.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/types/__init__.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/types/definitions.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/utils/__init__.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/utils/echo.py +0 -0
- {snapctl-0.31.0 → snapctl-0.32.0}/snapctl/utils/helper.py +0 -0
snapctl-0.32.0/LICENSE
ADDED
|
@@ -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.
|
|
3
|
+
Version: 0.32.0
|
|
4
4
|
Summary: Snapser CLI Tool
|
|
5
5
|
Author: Ajinkya Apte
|
|
6
6
|
Author-email: aj@snapser.com
|
|
@@ -101,7 +101,10 @@ be evaluated after verifying if there is any command line argument.
|
|
|
101
101
|
|
|
102
102
|
Create a file named `~/.snapser/config`. Open it using the editor of your choice and replace with your
|
|
103
103
|
personal Snapser Access key. Save the file. Advantage of using this method is you can use the `--profile`
|
|
104
|
-
argument with your snapctl command to use different API keys.
|
|
104
|
+
argument with your snapctl command to use different API keys. NOTE: You may want to pass your own path
|
|
105
|
+
instead on relying on the default one the CLI looks for. You can do so by setting an environment
|
|
106
|
+
variable `SNAPSER_CONFIG_PATH='<your_custom_path>'`. Doing this will make sure that the CLI tool
|
|
107
|
+
will look for the config file at that path.
|
|
105
108
|
|
|
106
109
|
```
|
|
107
110
|
[default]
|
|
@@ -241,16 +244,16 @@ snapctl byosnap push $byosnap_sid --tag $image_tag
|
|
|
241
244
|
Upload swagger.json and README.md for you Snap
|
|
242
245
|
|
|
243
246
|
```
|
|
244
|
-
# Help for the
|
|
247
|
+
# Help for the byosnap command
|
|
245
248
|
snapctl byosnap upload-docs --help
|
|
246
249
|
|
|
247
250
|
# Publish a new image
|
|
248
|
-
# $
|
|
251
|
+
# $byosnap_sid = Snap ID for your snap
|
|
249
252
|
# $image_tag = An image tag for your snap
|
|
250
253
|
# $code_root_path = Local code path where your swagger.json and README.md files are present
|
|
251
254
|
# Example:
|
|
252
255
|
# snapctl byosnap upload-docs byosnap-jinks-flask --tag my-first-image --path /Users/DevName/Development/SnapserEngine/jinks_flask
|
|
253
|
-
snapctl byosnap upload-docs $
|
|
256
|
+
snapctl byosnap upload-docs $byosnap_sid --tag $image_tag --path $code_root_path
|
|
254
257
|
```
|
|
255
258
|
|
|
256
259
|
#### 6. byosnap publish-image
|
|
@@ -302,28 +305,7 @@ See all the supported commands
|
|
|
302
305
|
snapctl byogs --help
|
|
303
306
|
```
|
|
304
307
|
|
|
305
|
-
#### 2.
|
|
306
|
-
|
|
307
|
-
Create a custom game server. Note that you will have to build, push and publish your game server image, for it to be useable
|
|
308
|
-
in a Snapend fleet.
|
|
309
|
-
|
|
310
|
-
```
|
|
311
|
-
# Help for the byosnap command
|
|
312
|
-
snapctl byogs create --help
|
|
313
|
-
|
|
314
|
-
# Create a new snap
|
|
315
|
-
# $byogs_sid = Game server ID for your snap. Should start with `byogs-`
|
|
316
|
-
# $name = User friendly name for your BYOGs
|
|
317
|
-
# $desc = User friendly description
|
|
318
|
-
# $platform = Currently only supported platform is linux/amd64
|
|
319
|
-
# $language = One of go, python, ruby, c#, c++, rust, java, node
|
|
320
|
-
|
|
321
|
-
# Example:
|
|
322
|
-
# snapctl byogs create byosnap-jinks-gs --name "Jinks Flask Microservice" --desc "Custom Microservice" --platform "linux/arm64" --language "go"
|
|
323
|
-
snapctl byogs create $byogs_sid --name "$name" --desc "$desc" --platform "$platform" --language "$language"
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
#### 3. byogs build
|
|
308
|
+
#### 2. byogs build
|
|
327
309
|
|
|
328
310
|
Build your custom game server image.
|
|
329
311
|
|
|
@@ -332,15 +314,14 @@ Build your custom game server image.
|
|
|
332
314
|
snapctl byogs build --help
|
|
333
315
|
|
|
334
316
|
# Publish a new image
|
|
335
|
-
# $byogs_sid = Game server ID for your snap
|
|
336
317
|
# $image_tag = An image tag for your snap
|
|
337
318
|
# $code_root_path = Local code path where your Dockerfile is present
|
|
338
319
|
# Example:
|
|
339
320
|
# snapctl byogs build byosnap-jinks-gs --tag my-first-image --path /Users/DevName/Development/SnapserEngine/game_server
|
|
340
|
-
snapctl byogs build
|
|
321
|
+
snapctl byogs build --tag $image_tag --path $code_root_path
|
|
341
322
|
```
|
|
342
323
|
|
|
343
|
-
####
|
|
324
|
+
#### 3. byogs push
|
|
344
325
|
|
|
345
326
|
Push your custom game server image.
|
|
346
327
|
|
|
@@ -349,51 +330,13 @@ Push your custom game server image.
|
|
|
349
330
|
snapctl byogs push --help
|
|
350
331
|
|
|
351
332
|
# Publish a new image
|
|
352
|
-
# $byogs_sid = Game server ID for your snap
|
|
353
333
|
# $image_tag = An image tag for your snap
|
|
354
334
|
# Example:
|
|
355
335
|
# snapctl byogs push byosnap-jinks-gs --tag my-first-image
|
|
356
|
-
snapctl byogs push
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
#### 5. [Deprecated soon] byogs publish-image
|
|
360
|
-
|
|
361
|
-
Publish your custom game server image. This command executes, `build` and `push` one after the other.
|
|
362
|
-
|
|
363
|
-
```
|
|
364
|
-
# Help for the byogs command
|
|
365
|
-
snapctl byogs publish-image --help
|
|
366
|
-
|
|
367
|
-
# Publish a new image
|
|
368
|
-
# $byogs_sid = Game server ID for your snap
|
|
369
|
-
# $image_tag = An image tag for your snap
|
|
370
|
-
# $code_root_path = Local code path where your Dockerfile is present
|
|
371
|
-
# Example:
|
|
372
|
-
# snapctl byogs publish-image byosnap-jinks-gs --tag my-first-image --path /Users/DevName/Development/SnapserEngine/game_server
|
|
373
|
-
snapctl byogs publish-image $byogs_sid --tag $image_tag --path $code_root_path
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
#### 6. [Deprecated soon] byogs publish-version
|
|
377
|
-
|
|
378
|
-
Publish a new version for your game server. Only after your game server version is published, you will be able
|
|
379
|
-
to use it in your Snapend fleet. This command should be run after you `push` or `publish-image` commands.
|
|
380
|
-
|
|
381
|
-
```
|
|
382
|
-
# Help for the byogs command
|
|
383
|
-
snapctl byogs publish-version --help
|
|
384
|
-
|
|
385
|
-
# Publish a new image
|
|
386
|
-
# $byogs_sid = Snap ID for your snap
|
|
387
|
-
# $image_tag = Any image tag for your snap
|
|
388
|
-
# $prefix = Prefix for your snap Eg: /v1
|
|
389
|
-
# $version = Semantic version for your snap Eg: v0.0.1
|
|
390
|
-
# $ingress_port = Ingress port for your snap Eg: 5003
|
|
391
|
-
# Example:
|
|
392
|
-
# snapctl byogs publish-image byosnap-jinks-gs --tag my-first-image --prefix /v1 --version v0.0.1 --http-port 5003
|
|
393
|
-
snapctl byogs publish-version $byogs_sid --tag $image_tag --prefix $prefix --version $version --http-port $ingress_port
|
|
336
|
+
snapctl byogs push --tag $image_tag
|
|
394
337
|
```
|
|
395
338
|
|
|
396
|
-
####
|
|
339
|
+
#### 4. byogs publish
|
|
397
340
|
|
|
398
341
|
Publish your custom game server image. This commend replaces the old way of creating, publishing image and
|
|
399
342
|
then publishing the byogs. Now all you have to do is publish your image and create a fleet using the web portal.
|
|
@@ -523,9 +466,9 @@ snapctl snapend update --help
|
|
|
523
466
|
# --blocking = (Optional) This makes sure the CLI waits till your Snapend is live.
|
|
524
467
|
# Note at least one of the two needs to be present
|
|
525
468
|
# Example:
|
|
526
|
-
# snapctl snapend update gx5x6bc0 --byosnaps byosnap-service-1:v1.0.0,byosnap-service--2:v1.0.0 --byogs byogs-fleet-one:gs-1:v0.0.1,my-fleet-two:gs-2:v0.0.4
|
|
527
|
-
# snapctl snapend update gx5x6bc0 --byosnaps byosnap-service-1:v1.0.0,byosnap-service--2:v1.0.0 --byogs fleet-one:v0.0.1,fleet-two:v0.0.4 --blocking
|
|
528
|
-
snapctl snapend update $snapend_id --byosnaps $byosnaps --byogs $byogs --blocking
|
|
469
|
+
# snapctl snapend update --snapend-id gx5x6bc0 --byosnaps byosnap-service-1:v1.0.0,byosnap-service--2:v1.0.0 --byogs byogs-fleet-one:gs-1:v0.0.1,my-fleet-two:gs-2:v0.0.4
|
|
470
|
+
# snapctl snapend update --snapend-id gx5x6bc0 --byosnaps byosnap-service-1:v1.0.0,byosnap-service--2:v1.0.0 --byogs fleet-one:v0.0.1,fleet-two:v0.0.4 --blocking
|
|
471
|
+
snapctl snapend update --snapend-id $snapend_id --byosnaps $byosnaps --byogs $byogs --blocking
|
|
529
472
|
```
|
|
530
473
|
|
|
531
474
|
#### 6. Get the Snapend state
|
|
@@ -84,7 +84,10 @@ be evaluated after verifying if there is any command line argument.
|
|
|
84
84
|
|
|
85
85
|
Create a file named `~/.snapser/config`. Open it using the editor of your choice and replace with your
|
|
86
86
|
personal Snapser Access key. Save the file. Advantage of using this method is you can use the `--profile`
|
|
87
|
-
argument with your snapctl command to use different API keys.
|
|
87
|
+
argument with your snapctl command to use different API keys. NOTE: You may want to pass your own path
|
|
88
|
+
instead on relying on the default one the CLI looks for. You can do so by setting an environment
|
|
89
|
+
variable `SNAPSER_CONFIG_PATH='<your_custom_path>'`. Doing this will make sure that the CLI tool
|
|
90
|
+
will look for the config file at that path.
|
|
88
91
|
|
|
89
92
|
```
|
|
90
93
|
[default]
|
|
@@ -224,16 +227,16 @@ snapctl byosnap push $byosnap_sid --tag $image_tag
|
|
|
224
227
|
Upload swagger.json and README.md for you Snap
|
|
225
228
|
|
|
226
229
|
```
|
|
227
|
-
# Help for the
|
|
230
|
+
# Help for the byosnap command
|
|
228
231
|
snapctl byosnap upload-docs --help
|
|
229
232
|
|
|
230
233
|
# Publish a new image
|
|
231
|
-
# $
|
|
234
|
+
# $byosnap_sid = Snap ID for your snap
|
|
232
235
|
# $image_tag = An image tag for your snap
|
|
233
236
|
# $code_root_path = Local code path where your swagger.json and README.md files are present
|
|
234
237
|
# Example:
|
|
235
238
|
# snapctl byosnap upload-docs byosnap-jinks-flask --tag my-first-image --path /Users/DevName/Development/SnapserEngine/jinks_flask
|
|
236
|
-
snapctl byosnap upload-docs $
|
|
239
|
+
snapctl byosnap upload-docs $byosnap_sid --tag $image_tag --path $code_root_path
|
|
237
240
|
```
|
|
238
241
|
|
|
239
242
|
#### 6. byosnap publish-image
|
|
@@ -285,28 +288,7 @@ See all the supported commands
|
|
|
285
288
|
snapctl byogs --help
|
|
286
289
|
```
|
|
287
290
|
|
|
288
|
-
#### 2.
|
|
289
|
-
|
|
290
|
-
Create a custom game server. Note that you will have to build, push and publish your game server image, for it to be useable
|
|
291
|
-
in a Snapend fleet.
|
|
292
|
-
|
|
293
|
-
```
|
|
294
|
-
# Help for the byosnap command
|
|
295
|
-
snapctl byogs create --help
|
|
296
|
-
|
|
297
|
-
# Create a new snap
|
|
298
|
-
# $byogs_sid = Game server ID for your snap. Should start with `byogs-`
|
|
299
|
-
# $name = User friendly name for your BYOGs
|
|
300
|
-
# $desc = User friendly description
|
|
301
|
-
# $platform = Currently only supported platform is linux/amd64
|
|
302
|
-
# $language = One of go, python, ruby, c#, c++, rust, java, node
|
|
303
|
-
|
|
304
|
-
# Example:
|
|
305
|
-
# snapctl byogs create byosnap-jinks-gs --name "Jinks Flask Microservice" --desc "Custom Microservice" --platform "linux/arm64" --language "go"
|
|
306
|
-
snapctl byogs create $byogs_sid --name "$name" --desc "$desc" --platform "$platform" --language "$language"
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
#### 3. byogs build
|
|
291
|
+
#### 2. byogs build
|
|
310
292
|
|
|
311
293
|
Build your custom game server image.
|
|
312
294
|
|
|
@@ -315,15 +297,14 @@ Build your custom game server image.
|
|
|
315
297
|
snapctl byogs build --help
|
|
316
298
|
|
|
317
299
|
# Publish a new image
|
|
318
|
-
# $byogs_sid = Game server ID for your snap
|
|
319
300
|
# $image_tag = An image tag for your snap
|
|
320
301
|
# $code_root_path = Local code path where your Dockerfile is present
|
|
321
302
|
# Example:
|
|
322
303
|
# snapctl byogs build byosnap-jinks-gs --tag my-first-image --path /Users/DevName/Development/SnapserEngine/game_server
|
|
323
|
-
snapctl byogs build
|
|
304
|
+
snapctl byogs build --tag $image_tag --path $code_root_path
|
|
324
305
|
```
|
|
325
306
|
|
|
326
|
-
####
|
|
307
|
+
#### 3. byogs push
|
|
327
308
|
|
|
328
309
|
Push your custom game server image.
|
|
329
310
|
|
|
@@ -332,51 +313,13 @@ Push your custom game server image.
|
|
|
332
313
|
snapctl byogs push --help
|
|
333
314
|
|
|
334
315
|
# Publish a new image
|
|
335
|
-
# $byogs_sid = Game server ID for your snap
|
|
336
316
|
# $image_tag = An image tag for your snap
|
|
337
317
|
# Example:
|
|
338
318
|
# snapctl byogs push byosnap-jinks-gs --tag my-first-image
|
|
339
|
-
snapctl byogs push
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
#### 5. [Deprecated soon] byogs publish-image
|
|
343
|
-
|
|
344
|
-
Publish your custom game server image. This command executes, `build` and `push` one after the other.
|
|
345
|
-
|
|
346
|
-
```
|
|
347
|
-
# Help for the byogs command
|
|
348
|
-
snapctl byogs publish-image --help
|
|
349
|
-
|
|
350
|
-
# Publish a new image
|
|
351
|
-
# $byogs_sid = Game server ID for your snap
|
|
352
|
-
# $image_tag = An image tag for your snap
|
|
353
|
-
# $code_root_path = Local code path where your Dockerfile is present
|
|
354
|
-
# Example:
|
|
355
|
-
# snapctl byogs publish-image byosnap-jinks-gs --tag my-first-image --path /Users/DevName/Development/SnapserEngine/game_server
|
|
356
|
-
snapctl byogs publish-image $byogs_sid --tag $image_tag --path $code_root_path
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
#### 6. [Deprecated soon] byogs publish-version
|
|
360
|
-
|
|
361
|
-
Publish a new version for your game server. Only after your game server version is published, you will be able
|
|
362
|
-
to use it in your Snapend fleet. This command should be run after you `push` or `publish-image` commands.
|
|
363
|
-
|
|
364
|
-
```
|
|
365
|
-
# Help for the byogs command
|
|
366
|
-
snapctl byogs publish-version --help
|
|
367
|
-
|
|
368
|
-
# Publish a new image
|
|
369
|
-
# $byogs_sid = Snap ID for your snap
|
|
370
|
-
# $image_tag = Any image tag for your snap
|
|
371
|
-
# $prefix = Prefix for your snap Eg: /v1
|
|
372
|
-
# $version = Semantic version for your snap Eg: v0.0.1
|
|
373
|
-
# $ingress_port = Ingress port for your snap Eg: 5003
|
|
374
|
-
# Example:
|
|
375
|
-
# snapctl byogs publish-image byosnap-jinks-gs --tag my-first-image --prefix /v1 --version v0.0.1 --http-port 5003
|
|
376
|
-
snapctl byogs publish-version $byogs_sid --tag $image_tag --prefix $prefix --version $version --http-port $ingress_port
|
|
319
|
+
snapctl byogs push --tag $image_tag
|
|
377
320
|
```
|
|
378
321
|
|
|
379
|
-
####
|
|
322
|
+
#### 4. byogs publish
|
|
380
323
|
|
|
381
324
|
Publish your custom game server image. This commend replaces the old way of creating, publishing image and
|
|
382
325
|
then publishing the byogs. Now all you have to do is publish your image and create a fleet using the web portal.
|
|
@@ -506,9 +449,9 @@ snapctl snapend update --help
|
|
|
506
449
|
# --blocking = (Optional) This makes sure the CLI waits till your Snapend is live.
|
|
507
450
|
# Note at least one of the two needs to be present
|
|
508
451
|
# Example:
|
|
509
|
-
# snapctl snapend update gx5x6bc0 --byosnaps byosnap-service-1:v1.0.0,byosnap-service--2:v1.0.0 --byogs byogs-fleet-one:gs-1:v0.0.1,my-fleet-two:gs-2:v0.0.4
|
|
510
|
-
# snapctl snapend update gx5x6bc0 --byosnaps byosnap-service-1:v1.0.0,byosnap-service--2:v1.0.0 --byogs fleet-one:v0.0.1,fleet-two:v0.0.4 --blocking
|
|
511
|
-
snapctl snapend update $snapend_id --byosnaps $byosnaps --byogs $byogs --blocking
|
|
452
|
+
# snapctl snapend update --snapend-id gx5x6bc0 --byosnaps byosnap-service-1:v1.0.0,byosnap-service--2:v1.0.0 --byogs byogs-fleet-one:gs-1:v0.0.1,my-fleet-two:gs-2:v0.0.4
|
|
453
|
+
# snapctl snapend update --snapend-id gx5x6bc0 --byosnaps byosnap-service-1:v1.0.0,byosnap-service--2:v1.0.0 --byogs fleet-one:v0.0.1,fleet-two:v0.0.4 --blocking
|
|
454
|
+
snapctl snapend update --snapend-id $snapend_id --byosnaps $byosnaps --byogs $byogs --blocking
|
|
512
455
|
```
|
|
513
456
|
|
|
514
457
|
#### 6. Get the Snapend state
|
|
@@ -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,
|
|
41
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
self.
|
|
53
|
-
|
|
54
|
-
|
|
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'{
|
|
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'{
|
|
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'{
|
|
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
|
-
#
|
|
275
|
-
if
|
|
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
|
-
|
|
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
|
-
"
|
|
284
|
-
f"
|
|
262
|
+
"Tag should be a single word with maximum of "
|
|
263
|
+
f"{ByoGs.TAG_CHARACTER_LIMIT} characters"
|
|
285
264
|
)
|
|
286
265
|
return response
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
|
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
|
-
|
|
305
|
-
if self.
|
|
306
|
-
response['msg'] =
|
|
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
|
-
|
|
309
|
-
if
|
|
310
|
-
|
|
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,13 +2,14 @@
|
|
|
2
2
|
Constants used by snapctl
|
|
3
3
|
"""
|
|
4
4
|
COMPANY_NAME = 'Snapser'
|
|
5
|
-
VERSION = '0.
|
|
5
|
+
VERSION = '0.32.0'
|
|
6
6
|
CONFIG_FILE_MAC = '~/.snapser/config'
|
|
7
7
|
CONFIG_FILE_WIN = '%homepath%\\.snapser\\config'
|
|
8
8
|
|
|
9
9
|
DEFAULT_PROFILE = 'default'
|
|
10
10
|
API_KEY = 'SNAPSER_API_KEY'
|
|
11
11
|
URL_KEY = 'SNAPSER_URL_KEY'
|
|
12
|
+
CONFIG_PATH_KEY = 'SNAPSER_CONFIG_PATH'
|
|
12
13
|
SERVER_CALL_TIMEOUT = 30
|
|
13
14
|
|
|
14
15
|
SNAPCTL_SUCCESS = 0
|
|
@@ -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
|
+
}
|
|
@@ -11,9 +11,10 @@ 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
|
-
CONFIG_FILE_WIN, DEFAULT_PROFILE, VERSION, SNAPCTL_SUCCESS, SNAPCTL_ERROR
|
|
17
|
+
CONFIG_FILE_WIN, DEFAULT_PROFILE, VERSION, SNAPCTL_SUCCESS, SNAPCTL_ERROR, CONFIG_PATH_KEY
|
|
17
18
|
from snapctl.config.endpoints import END_POINTS
|
|
18
19
|
from snapctl.config.hashes import CLIENT_SDK_TYPES, SERVER_SDK_TYPES, PROTOS_TYPES, SERVICE_IDS, \
|
|
19
20
|
SNAPEND_MANIFEST_TYPES
|
|
@@ -50,22 +51,23 @@ def extract_config(extract_key: str, profile: str | None = None) -> object:
|
|
|
50
51
|
'location': '',
|
|
51
52
|
'value': None
|
|
52
53
|
}
|
|
53
|
-
# Option 1
|
|
54
|
+
# Option 1 - Get the API Key from the environment variable
|
|
54
55
|
env_api_key = os.getenv(extract_key)
|
|
55
56
|
if env_api_key is not None:
|
|
56
57
|
result['location'] = 'environment-variable'
|
|
57
58
|
result['value'] = env_api_key
|
|
58
59
|
return result
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
encoding: str | None = "utf-8-sig" if platform == 'win32' else None
|
|
61
|
+
# Option 2 - Get the API Key from CONFIG PATH environment variable
|
|
62
|
+
config_file_path: str | None = os.getenv(CONFIG_PATH_KEY)
|
|
63
|
+
# Option 3 - Get the API Key from the hardcoded config file we look for
|
|
64
|
+
if config_file_path is None:
|
|
65
|
+
if platform == 'win32':
|
|
66
|
+
config_file_path = os.path.expandvars(CONFIG_FILE_WIN)
|
|
67
|
+
else:
|
|
68
|
+
config_file_path = os.path.expanduser(CONFIG_FILE_MAC)
|
|
69
|
+
result['location'] = f'config-file:{config_file_path}'
|
|
67
70
|
if os.path.isfile(config_file_path):
|
|
68
|
-
result['location'] = 'config-file'
|
|
69
71
|
config = configparser.ConfigParser()
|
|
70
72
|
config.read(config_file_path, encoding=encoding)
|
|
71
73
|
config_profile: str = DEFAULT_PROFILE
|
|
@@ -282,6 +284,11 @@ def byosnap(
|
|
|
282
284
|
http_port: Union[str, None] = typer.Option(
|
|
283
285
|
None, "--http-port", help="(req: publish-version) Ingress HTTP port version"
|
|
284
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
|
+
),
|
|
285
292
|
# overrides
|
|
286
293
|
api_key: Union[str, None] = typer.Option(
|
|
287
294
|
None, "--api-key", help="API Key override.", callback=api_key_context_callback
|
|
@@ -297,7 +304,7 @@ def byosnap(
|
|
|
297
304
|
byosnap_obj: ByoSnap = ByoSnap(
|
|
298
305
|
subcommand, ctx.obj['base_url'], ctx.obj['api_key'], sid,
|
|
299
306
|
name, desc, platform_type, language, tag, path, docker_file,
|
|
300
|
-
prefix, version, http_port
|
|
307
|
+
prefix, version, http_port, byosnap_profile
|
|
301
308
|
)
|
|
302
309
|
validate_input_response: ResponseType = byosnap_obj.validate_input()
|
|
303
310
|
if validate_input_response['error']:
|
|
@@ -318,48 +325,21 @@ def byogs(
|
|
|
318
325
|
subcommand: str = typer.Argument(
|
|
319
326
|
..., help="BYOGs Subcommands: " + ", ".join(ByoGs.SUBCOMMANDS) + "."
|
|
320
327
|
),
|
|
321
|
-
sid: str = typer.Argument(
|
|
322
|
-
|
|
323
|
-
),
|
|
324
|
-
# create
|
|
325
|
-
name: str = typer.Option(
|
|
326
|
-
None, "--name", help="(req: create) Name for your snap"
|
|
327
|
-
),
|
|
328
|
-
desc: str = typer.Option(
|
|
329
|
-
None, "--desc", help="(req: create) Description for your snap"
|
|
330
|
-
),
|
|
331
|
-
platform_type: str = typer.Option(
|
|
332
|
-
None, "--platform",
|
|
333
|
-
help="(req: create) Platform for your snap - " + \
|
|
334
|
-
", ".join(ByoGs.PLATFORMS) + "."
|
|
335
|
-
),
|
|
336
|
-
language: str = typer.Option(
|
|
337
|
-
None, "--language",
|
|
338
|
-
help="(req: create) Language of your snap - " + \
|
|
339
|
-
", ".join(ByoGs.LANGUAGES) + "."
|
|
340
|
-
),
|
|
328
|
+
# sid: str = typer.Argument(
|
|
329
|
+
# ByoGs.SID, help="Game Server Id. Should start with byogs"
|
|
330
|
+
# ),
|
|
341
331
|
# publish, publish-image and publish-version
|
|
342
332
|
tag: str = typer.Option(
|
|
343
333
|
None, "--tag",
|
|
344
|
-
help="(req: build, push, publish
|
|
334
|
+
help="(req: build, push, publish) Tag for your snap"
|
|
345
335
|
),
|
|
346
336
|
# publish and publish-image
|
|
347
337
|
path: Union[str, None] = typer.Option(
|
|
348
|
-
None, "--path", help="(req: build, publish
|
|
338
|
+
None, "--path", help="(req: build, publish) Path to your snap code"
|
|
349
339
|
),
|
|
350
340
|
docker_file: str = typer.Option(
|
|
351
341
|
"Dockerfile", help="Dockerfile name to use"
|
|
352
342
|
),
|
|
353
|
-
# publish-version
|
|
354
|
-
version: Union[str, None] = typer.Option(
|
|
355
|
-
None, "--version", help="(req: publish-version) Snap version"
|
|
356
|
-
),
|
|
357
|
-
http_port: Union[str, None] = typer.Option(
|
|
358
|
-
None, "--http-port", help="(req: publish-version) Ingress HTTP port version"
|
|
359
|
-
),
|
|
360
|
-
debug_port: Union[str, None] = typer.Option(
|
|
361
|
-
None, "--debug-port", help="(optional: publish-version) Debug HTTP port version"
|
|
362
|
-
),
|
|
363
343
|
# overrides
|
|
364
344
|
api_key: Union[str, None] = typer.Option(
|
|
365
345
|
None, "--api-key", help="API Key override.", callback=api_key_context_callback
|
|
@@ -373,9 +353,8 @@ def byogs(
|
|
|
373
353
|
"""
|
|
374
354
|
validate_command_context(ctx)
|
|
375
355
|
byogs_obj: ByoGs = ByoGs(
|
|
376
|
-
subcommand, ctx.obj['base_url'], ctx.obj['api_key'],
|
|
377
|
-
|
|
378
|
-
version, http_port, debug_port
|
|
356
|
+
subcommand, ctx.obj['base_url'], ctx.obj['api_key'],
|
|
357
|
+
tag, path, docker_file,
|
|
379
358
|
)
|
|
380
359
|
validate_input_response: ResponseType = byogs_obj.validate_input()
|
|
381
360
|
if validate_input_response['error']:
|
|
@@ -561,3 +540,42 @@ def snapend(
|
|
|
561
540
|
error(f"Snapend {subcommand} failed")
|
|
562
541
|
raise typer.Exit(SNAPCTL_ERROR)
|
|
563
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")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|