snapctl 0.1.1__tar.gz → 0.2.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.1.1 → snapctl-0.2.0}/PKG-INFO +7 -1
- snapctl-0.2.0/README.md +8 -0
- {snapctl-0.1.1 → snapctl-0.2.0}/pyproject.toml +2 -1
- snapctl-0.2.0/snapctl/commands/__init__.py +0 -0
- snapctl-0.2.0/snapctl/commands/byosnap.py +216 -0
- snapctl-0.2.0/snapctl/main.py +43 -0
- snapctl-0.2.0/snapctl/types/__init__.py +0 -0
- snapctl-0.2.0/snapctl/types/definitions.py +4 -0
- snapctl-0.2.0/snapctl/utils/__init__.py +0 -0
- snapctl-0.1.1/README.md +0 -2
- snapctl-0.1.1/snapctl/main.py +0 -138
- snapctl-0.1.1/snapctl/utils.py +0 -38
- {snapctl-0.1.1 → snapctl-0.2.0}/snapctl/__init__.py +0 -0
- {snapctl-0.1.1 → snapctl-0.2.0}/snapctl/__main__.py +0 -0
- {snapctl-0.1.1/snapctl → snapctl-0.2.0/snapctl/utils}/echo.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: snapctl
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Snapser CLI Tool
|
|
5
5
|
Author: Ajinkya Apte
|
|
6
6
|
Author-email: aj@snapser.com
|
|
@@ -8,9 +8,15 @@ Requires-Python: >=3.10,<4.0
|
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.10
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Requires-Dist: requests (>=2.28.2,<3.0.0)
|
|
11
12
|
Requires-Dist: typer[all] (>=0.7.0,<0.8.0)
|
|
12
13
|
Description-Content-Type: text/markdown
|
|
13
14
|
|
|
14
15
|
# Snapser CLI Tool
|
|
15
16
|
Snapser CLI Tool
|
|
16
17
|
|
|
18
|
+
## Commands
|
|
19
|
+
Run the following to see the list of commands Snapser supports
|
|
20
|
+
```bash
|
|
21
|
+
snapctl --help
|
|
22
|
+
```
|
snapctl-0.2.0/README.md
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "snapctl"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
description = "Snapser CLI Tool"
|
|
5
5
|
authors = ["Ajinkya Apte <aj@snapser.com>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -12,6 +12,7 @@ snapctl = "snapctl.main:app"
|
|
|
12
12
|
[tool.poetry.dependencies]
|
|
13
13
|
python = "^3.10"
|
|
14
14
|
typer = {extras = ["all"], version = "^0.7.0"}
|
|
15
|
+
requests = "^2.28.2"
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
[build-system]
|
|
File without changes
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import os
|
|
3
|
+
import requests
|
|
4
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
5
|
+
import subprocess
|
|
6
|
+
|
|
7
|
+
from snapctl.types.definitions import ResponseType
|
|
8
|
+
from snapctl.utils.echo import error, success, info
|
|
9
|
+
|
|
10
|
+
class ByoSnap:
|
|
11
|
+
COMMANDS = ['build', 'push', 'upload-docs', 'publish']
|
|
12
|
+
|
|
13
|
+
def __init__(self, command: str, path: str, tag: str, token: str, dockerfile: str = 'Dockerfile') -> None:
|
|
14
|
+
self.command: str = command
|
|
15
|
+
self.path: str = path
|
|
16
|
+
self.tag: str = tag
|
|
17
|
+
self.token: str = token
|
|
18
|
+
self.token_parts: list = ByoSnap.get_token_values(token)
|
|
19
|
+
self.dockerfile = dockerfile
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def get_token_values(token: str) -> None | list:
|
|
23
|
+
try:
|
|
24
|
+
input_token = base64.b64decode(token).decode('ascii')
|
|
25
|
+
token_parts = input_token.split('|')
|
|
26
|
+
# url|web_app_token|service_id|ecr_repo_url|ecr_repo_username|ecr_repo_token
|
|
27
|
+
# url = self.token_parts[0]
|
|
28
|
+
# web_app_token = self.token_parts[1]
|
|
29
|
+
# service_id = self.token_parts[2]
|
|
30
|
+
# ecr_repo_url = self.token_parts[3]
|
|
31
|
+
# ecr_repo_username = self.token_parts[4]
|
|
32
|
+
# ecr_repo_token = self.token_parts[5]
|
|
33
|
+
if len(token_parts) == 6:
|
|
34
|
+
return token_parts
|
|
35
|
+
except Exception:
|
|
36
|
+
pass
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
def validate_input(self) -> ResponseType:
|
|
40
|
+
response: ResponseType = {
|
|
41
|
+
'error': True,
|
|
42
|
+
'msg': '',
|
|
43
|
+
'data': []
|
|
44
|
+
}
|
|
45
|
+
# Check command
|
|
46
|
+
if not self.command in ByoSnap.COMMANDS:
|
|
47
|
+
response['msg'] = f"Invalid command. Valid commands are {', '.join(ByoSnap.COMMANDS['byosnap'])}."
|
|
48
|
+
return response
|
|
49
|
+
# Check path
|
|
50
|
+
if not os.path.isfile(f"{self.path}/{self.dockerfile}"):
|
|
51
|
+
response['msg'] = f"Unable to find {self.dockerfile} at path {self.path}"
|
|
52
|
+
return response
|
|
53
|
+
# Check tag
|
|
54
|
+
if len(self.tag.split()) > 1 or len(self.tag) > 25:
|
|
55
|
+
response['msg'] = f"Tag should be a single word with maximum of 25 characters"
|
|
56
|
+
return response
|
|
57
|
+
# Check the token
|
|
58
|
+
if self.token_parts is None:
|
|
59
|
+
response['msg'] = 'Invalid token. Please reach out to your support team.'
|
|
60
|
+
return response
|
|
61
|
+
# Send success
|
|
62
|
+
response['error'] = False
|
|
63
|
+
return response
|
|
64
|
+
|
|
65
|
+
def build(self) -> bool:
|
|
66
|
+
# Get the data
|
|
67
|
+
# url = self.token_parts[0]
|
|
68
|
+
# web_app_token = self.token_parts[1]
|
|
69
|
+
service_id = self.token_parts[2]
|
|
70
|
+
ecr_repo_url = self.token_parts[3]
|
|
71
|
+
ecr_repo_username = self.token_parts[4]
|
|
72
|
+
ecr_repo_token = self.token_parts[5]
|
|
73
|
+
try:
|
|
74
|
+
# Check dependencies
|
|
75
|
+
with Progress(
|
|
76
|
+
SpinnerColumn(),
|
|
77
|
+
TextColumn("[progress.description]{task.description}"),
|
|
78
|
+
transient=True,
|
|
79
|
+
) as progress:
|
|
80
|
+
progress.add_task(description=f'Checking dependencies...', total=None)
|
|
81
|
+
try:
|
|
82
|
+
subprocess.run([
|
|
83
|
+
"docker", "--version"
|
|
84
|
+
], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
85
|
+
except:
|
|
86
|
+
error('Docker not present')
|
|
87
|
+
return False
|
|
88
|
+
success('Dependencies Verified')
|
|
89
|
+
|
|
90
|
+
# Login to Snapser Registry
|
|
91
|
+
with Progress(
|
|
92
|
+
SpinnerColumn(),
|
|
93
|
+
TextColumn("[progress.description]{task.description}"),
|
|
94
|
+
transient=True,
|
|
95
|
+
) as progress:
|
|
96
|
+
progress.add_task(description=f'Logging into Snapser Image Registry...', total=None)
|
|
97
|
+
response = subprocess.run([
|
|
98
|
+
f'echo "{ecr_repo_token}" | docker login --username {ecr_repo_username} --password-stdin {ecr_repo_url}'
|
|
99
|
+
], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
100
|
+
if response.returncode:
|
|
101
|
+
error('Unable to connect to the Snapser Container Repository. Please get the latest token from the Web app.')
|
|
102
|
+
return False
|
|
103
|
+
success('Login Successful')
|
|
104
|
+
|
|
105
|
+
# Build your snap
|
|
106
|
+
with Progress(
|
|
107
|
+
SpinnerColumn(),
|
|
108
|
+
TextColumn("[progress.description]{task.description}"),
|
|
109
|
+
transient=True,
|
|
110
|
+
) as progress:
|
|
111
|
+
progress.add_task(description=f'Building your snap...', total=None)
|
|
112
|
+
response = subprocess.run([
|
|
113
|
+
#f"docker build --no-cache -t {tag} {path}"
|
|
114
|
+
f"docker build --platform linux/arm64 -t {service_id}.{self.tag} {self.path}"
|
|
115
|
+
], shell=True, )#stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
116
|
+
if response.returncode:
|
|
117
|
+
error('Unable to build docker.')
|
|
118
|
+
return False
|
|
119
|
+
success('Build Successfull')
|
|
120
|
+
|
|
121
|
+
# Tag the repo
|
|
122
|
+
with Progress(
|
|
123
|
+
SpinnerColumn(),
|
|
124
|
+
TextColumn("[progress.description]{task.description}"),
|
|
125
|
+
transient=True,
|
|
126
|
+
) as progress:
|
|
127
|
+
progress.add_task(description=f'Tagging your snap...', total=None)
|
|
128
|
+
response = subprocess.run([
|
|
129
|
+
f"docker tag {service_id}.{self.tag} {ecr_repo_url}:{service_id}.{self.tag}"
|
|
130
|
+
], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
131
|
+
if response.returncode:
|
|
132
|
+
error('Unable to tag your snap.')
|
|
133
|
+
return False
|
|
134
|
+
success('Tag Successfull')
|
|
135
|
+
|
|
136
|
+
return True
|
|
137
|
+
except:
|
|
138
|
+
error('CLI Error')
|
|
139
|
+
return False
|
|
140
|
+
|
|
141
|
+
def push(self) -> bool:
|
|
142
|
+
# url = self.token_parts[0]
|
|
143
|
+
# web_app_token = self.token_parts[1]
|
|
144
|
+
service_id = self.token_parts[2]
|
|
145
|
+
ecr_repo_url = self.token_parts[3]
|
|
146
|
+
# ecr_repo_username = self.token_parts[4]
|
|
147
|
+
# ecr_repo_token = self.token_parts[5]
|
|
148
|
+
|
|
149
|
+
# Push the image
|
|
150
|
+
with Progress(
|
|
151
|
+
SpinnerColumn(),
|
|
152
|
+
TextColumn("[progress.description]{task.description}"),
|
|
153
|
+
transient=True,
|
|
154
|
+
) as progress:
|
|
155
|
+
progress.add_task(description=f'Pushing your snap...', total=None)
|
|
156
|
+
response = subprocess.run([
|
|
157
|
+
f"docker push {ecr_repo_url}:{service_id}.{self.tag}"
|
|
158
|
+
], shell=True, )#stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
159
|
+
if response.returncode:
|
|
160
|
+
error('Unable to push your snap.')
|
|
161
|
+
return False
|
|
162
|
+
success('Snap Upload Successfull')
|
|
163
|
+
return True
|
|
164
|
+
|
|
165
|
+
def upload_docs(self) -> bool:
|
|
166
|
+
'''
|
|
167
|
+
Note this step is optional hence we always respond with a True
|
|
168
|
+
'''
|
|
169
|
+
url = self.token_parts[0]
|
|
170
|
+
web_app_token = self.token_parts[1]
|
|
171
|
+
service_id = self.token_parts[2]
|
|
172
|
+
ecr_repo_url = self.token_parts[3]
|
|
173
|
+
ecr_repo_username = self.token_parts[4]
|
|
174
|
+
ecr_repo_token = self.token_parts[5]
|
|
175
|
+
|
|
176
|
+
# Push the swagger.json
|
|
177
|
+
with Progress(
|
|
178
|
+
SpinnerColumn(),
|
|
179
|
+
TextColumn("[progress.description]{task.description}"),
|
|
180
|
+
transient=True,
|
|
181
|
+
) as progress:
|
|
182
|
+
progress.add_task(description=f'Uploading your API Json...', total=None)
|
|
183
|
+
try:
|
|
184
|
+
dfile = open(f"{self.path}/swagger.json", "rb")
|
|
185
|
+
test_res = requests.post(f"{url}/{self.tag}/openapispec", files = {"attachment": dfile}, headers={'Token': web_app_token})
|
|
186
|
+
if test_res.ok:
|
|
187
|
+
success('Uploaded Swagger.json')
|
|
188
|
+
else:
|
|
189
|
+
error(test_res.status_code)
|
|
190
|
+
response_json = test_res.json()
|
|
191
|
+
error(response_json['details'][0])
|
|
192
|
+
except Exception as e:
|
|
193
|
+
info('Unable to find swagger.json at ' + self.path + str(e))
|
|
194
|
+
|
|
195
|
+
# Push the README.md
|
|
196
|
+
with Progress(
|
|
197
|
+
SpinnerColumn(),
|
|
198
|
+
TextColumn("[progress.description]{task.description}"),
|
|
199
|
+
transient=True,
|
|
200
|
+
) as progress:
|
|
201
|
+
progress.add_task(description=f'Uploading your README...', total=None)
|
|
202
|
+
try:
|
|
203
|
+
dfile = open(f"{self.path}/README.md", "rb")
|
|
204
|
+
test_res = requests.post(f"{url}/{self.tag}/markdown", files = {"attachment": dfile}, headers={'Token': web_app_token})
|
|
205
|
+
if test_res.ok:
|
|
206
|
+
success('Uploaded README.md')
|
|
207
|
+
else:
|
|
208
|
+
error('Unable to upload your README.md')
|
|
209
|
+
except:
|
|
210
|
+
info('Unable to find README.md at ' + self.path)
|
|
211
|
+
return True
|
|
212
|
+
|
|
213
|
+
def publish(self) -> None:
|
|
214
|
+
if not self.build() or not self.push() or not self.upload_docs():
|
|
215
|
+
return False
|
|
216
|
+
return True
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from snapctl.commands.byosnap import ByoSnap
|
|
4
|
+
from snapctl.types.definitions import ResponseType
|
|
5
|
+
from snapctl.utils.echo import error, success, info
|
|
6
|
+
|
|
7
|
+
app = typer.Typer()
|
|
8
|
+
|
|
9
|
+
# Commands
|
|
10
|
+
@app.callback()
|
|
11
|
+
def callback():
|
|
12
|
+
"""
|
|
13
|
+
Snapser CLI Tool
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
# command: Optional[str] = typer.Argument(None)
|
|
17
|
+
@app.command()
|
|
18
|
+
def byosnap(
|
|
19
|
+
command: str = typer.Argument(..., help="BYOSnap Commands: " + ", ".join(ByoSnap.COMMANDS) + "."),
|
|
20
|
+
path: str = typer.Argument(..., help="Path to your snap code"),
|
|
21
|
+
tag: str = typer.Argument(..., help="Tag for your snap"),
|
|
22
|
+
token: str = typer.Argument(..., help="Copy the token from the Web App"),
|
|
23
|
+
docker_file: str = typer.Option("Dockerfile", help="Dockerfile name to use")
|
|
24
|
+
) -> None:
|
|
25
|
+
"""
|
|
26
|
+
Bring your own Snap
|
|
27
|
+
"""
|
|
28
|
+
byosnap: ByoSnap = ByoSnap(command, path, tag, token, docker_file)
|
|
29
|
+
validate_input_response: ResponseType = byosnap.validate_input()
|
|
30
|
+
if validate_input_response['error']:
|
|
31
|
+
return error(validate_input_response['msg'])
|
|
32
|
+
command_method = command.replace('-', '_')
|
|
33
|
+
method: function = getattr(byosnap, command_method)
|
|
34
|
+
if not method():
|
|
35
|
+
return
|
|
36
|
+
success(f"BYOSnap {command} complete :oncoming_fist:")
|
|
37
|
+
|
|
38
|
+
# @app.command()
|
|
39
|
+
# def byow():
|
|
40
|
+
# """
|
|
41
|
+
# Bring your own workstation
|
|
42
|
+
# """
|
|
43
|
+
# typer.echo("Connecting to your cluster")
|
|
File without changes
|
|
File without changes
|
snapctl-0.1.1/README.md
DELETED
snapctl-0.1.1/snapctl/main.py
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import subprocess
|
|
3
|
-
import typer
|
|
4
|
-
from typing import Optional
|
|
5
|
-
|
|
6
|
-
from snapctl.echo import error, success, info
|
|
7
|
-
from snapctl.utils import get_token_values, check_docker
|
|
8
|
-
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
9
|
-
|
|
10
|
-
app = typer.Typer()
|
|
11
|
-
|
|
12
|
-
# Constants
|
|
13
|
-
VALID_COMMANDS = {
|
|
14
|
-
'byosnap': ['upload']
|
|
15
|
-
}
|
|
16
|
-
# TOKEN="eyJwYXlsb2FkIjoiZTQ0dEo2dDNnSGhaOVRlYThRcmFyWFhQdVZVMWhxTmpnS0tJcGdDNUMvR3JzNEZadkhhTC8vSmlDR2hSNlFrNzZ5d1JkVFhDRVAzTTJhK3dGYmp1VUJCNnJzWU91SVUrelhVOXdvdFF0dWlCZENnOXBLVHcySGt4ODlNUmlEUFhvaU9wN0lHaTlXcUtGUVl3YmovYTN4OXcvNUxJaDFUZzlTYnRtQ3BXeGlINDYyZUJHZzFTOHVranVSNlV4YTNtWWsrb3FBcTk0TmVHNUlxM1g3bTFBc2ovU1R4Wk5DTFI3OGpNRnhBZUFsTE5FYk45aTRIYnpSNk5Gdk56SDVrKytoVE1VNVNrbERvWlhFcVV2VzNhVTJ3L2JIRkd4d1Y0RG9PN2MrYUtWai9mNWlER2xLMkJkMG83VUxsVnBZcDYvQ3JON213RFN3b2phSFV4YTBZOEpJdHpHY3lCK1ZnRW9TTUdMaWc0bDIrMjVUVXpSK1pxVXBmeUhhTmV5L05ic1l3MUhya0h3Tko2ZzlIa1FNd1NXeDVYRmNnY3E1UmpKUjROQkJCWGFqRXdPMXQrMkphZjVxa0FieFdKckJ0TUxwcytGYll6Y3p2VS9iSDRQaTZIOGFzSGwrM0lGQzJ3R1ZpRDBwSkU4amhzRTRuakpmZjJVbnplUDAvRnVET2plMzNXOVpsK1kxRjdUWEJNZVRDRXVWendkVk9Vd3JNRDZ1L1ZqQVcyOWFZdXJSR3dHTHJnTzhTYzhteDY4WCs5b05leXljOW9JL2hNUnk4VG5DTHNZTk5xZG5CZnNRZW5MWEwyL20zS1BxMmZNaWJ4akF0bE9xTUpMK2Nxd2JrSHZhRUZtMnlNQTFOYnVtOTNUTHEwdFRRZkZBSGl1UXFvd0R5NittcHAvZmZLZXUzclEwRFE5UHZib3JUbDBlV2M2YmdxUXdRUU1HOFQvcnJMZXRUZW4zSnNucVpZWk1zQ1lqM3NSZ1F3ZG1LcjU5dUpyNmREOENKN0M2bUllTWRXajhHalhvVlFXcmViOU5jU0xwbVFsZyt3RUZQRXo2Zjlsd2h5WlNNRUFYUkVMbHRnNS9FTkkyajluYTJFQlJMUUhkcUp3K2QyM1NWRDNLWXJjWE41MzJjRjcrYUZhWndMNWhyV3JkRFdIbjZuOFlTSTNGYVNGb2haRmRzMXdTcW1DR1NIbTAvcEFld2toaGt4M2krTXA5aDk1UGtqaUZpUmtRQ21LSzBxQzh6NHZ6d0tvTnBEN1p1OXRvY296bExNL0E0ZDRYUzc1cmk4MThxeVRaS2d1ZHcyNnpMSTkwcUlPSFRRaGdOalNDeTI4elI0SUtqeGEzUE5LMFZrelAwYW5kcmRoVHV6M2VIbDlUNUE5VzExdEhnNlBzdzNPS0RlR2J6NmZnK0N5YStUNHlFOEFkYWphTTJRcDcrL2o5NUR4RXBxNVI0cmFyQ01RbzRBZjBBOG9xRnNwNko1ekRJU3ducXNXcy9TVGtQYkJ2ODBVUUMyTW51NVlJazRPYUZ5enZ1ZGdmaHNJWWNVMk04RWdoZkFEdjR3MTU4UWhiRjcvUHlEV3kwc3k4Q3luRm9mbldlWThnNEVaNkV4cEg0RUJYKzB4T2RyZG9YOHh3RVpXbG13dVcwa0pxdXpHdy9pZDlLd21UeFEyK3RFUHJ3dlVNQ1N4QjN1OWVFNVlzSWhXRCtSd25JTEE0Qkk5R3BySnpkcUhRcHNVaW1SRjluUWRTdTV1N0Zad2FUQmlUd0JHaXJDWXM0Szl3aklTeURxY090cDBWWHIzaFpkYlg5K0xsV3F3VXZseGNXWjFqWnFLRFlmemh2WEVOYmpkaXVYclJrRWo5bWNWMkhJRmtkSEJweS8wNzQ9IiwiZGF0YWtleSI6IkFRRUJBSGo2bGM0WElKdy83bG4wSGMwMERNZWs2R0V4SENiWTRSSXBUTUNJNThJblV3QUFBSDR3ZkFZSktvWklodmNOQVFjR29HOHdiUUlCQURCb0Jna3Foa2lHOXcwQkJ3RXdIZ1lKWUlaSUFXVURCQUV1TUJFRURJZjN6bERvelJEeVpScTYvUUlCRUlBN1ZsUURQbzBMaFUyU0dwREpSREFrdXg1L1pDWVE0RVVCMWVuV2M5cGtZdHF2R2J0cC9aTzFRY2kwNzBPSGpneWhDY0JCdzIwSGZZaW54Uk09IiwidmVyc2lvbiI6IjIiLCJ0eXBlIjoiREFUQV9LRVkiLCJleHBpcmF0aW9uIjoxNjc4NTAzMjc0fQ=="
|
|
17
|
-
# BASE_REPO= '131164543756.dkr.ecr.us-west-2.amazonaws.com'
|
|
18
|
-
# REPO_NAME="sandbox-multi-tools"
|
|
19
|
-
# ECR_PATH=f"{BASE_REPO}/{REPO_NAME}"
|
|
20
|
-
|
|
21
|
-
# Commands
|
|
22
|
-
@app.callback()
|
|
23
|
-
def callback():
|
|
24
|
-
"""
|
|
25
|
-
Snapser CLI Tool
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
# command: Optional[str] = typer.Argument(None)
|
|
29
|
-
@app.command()
|
|
30
|
-
def byosnap(
|
|
31
|
-
command: str = typer.Argument(..., help="Bring your own Commands: " + ", ".join(VALID_COMMANDS['byosnap']) + "."),
|
|
32
|
-
path: str = typer.Argument(..., help="Path to your snap code"),
|
|
33
|
-
tag: str = typer.Argument(..., help="Tag for your snap"),
|
|
34
|
-
token: str = typer.Argument(..., help="Copy the token from the Web App"),
|
|
35
|
-
docker_file: str = typer.Option("Dockerfile", help="Dockerfile name to use")
|
|
36
|
-
):
|
|
37
|
-
"""
|
|
38
|
-
Bring your own code
|
|
39
|
-
"""
|
|
40
|
-
token_list = []
|
|
41
|
-
# Error checking
|
|
42
|
-
with Progress(
|
|
43
|
-
SpinnerColumn(),
|
|
44
|
-
TextColumn("[progress.description]{task.description}"),
|
|
45
|
-
transient=True,
|
|
46
|
-
) as progress:
|
|
47
|
-
progress.add_task(description=f'Checking dependencies...', total=None)
|
|
48
|
-
if not check_docker():
|
|
49
|
-
return error('Docker not present')
|
|
50
|
-
if not command in VALID_COMMANDS['byosnap']:
|
|
51
|
-
error_message: str = 'Invalid command. Valid commands are ' + ', '.join(VALID_COMMANDS['byosnap']) + '.'
|
|
52
|
-
return error(error_message)
|
|
53
|
-
token_list = get_token_values(token)
|
|
54
|
-
if token_list is None:
|
|
55
|
-
error_message: str = 'Invalid token. Please reach out to your support team.'
|
|
56
|
-
return error(error_message)
|
|
57
|
-
|
|
58
|
-
success('Dependencies Verified')
|
|
59
|
-
|
|
60
|
-
# Extract details from the token
|
|
61
|
-
web_app_token = token_list[0]
|
|
62
|
-
service_id = token_list[1]
|
|
63
|
-
ecr_repo_url = token_list[2]
|
|
64
|
-
ecr_repo_username = token_list[3]
|
|
65
|
-
ecr_repo_token = token_list[4]
|
|
66
|
-
|
|
67
|
-
try:
|
|
68
|
-
|
|
69
|
-
# Login to Snapser Registry
|
|
70
|
-
with Progress(
|
|
71
|
-
SpinnerColumn(),
|
|
72
|
-
TextColumn("[progress.description]{task.description}"),
|
|
73
|
-
transient=True,
|
|
74
|
-
) as progress:
|
|
75
|
-
progress.add_task(description=f'Logging into Snapser Image Registry...', total=None)
|
|
76
|
-
response = subprocess.run([
|
|
77
|
-
f'echo "{ecr_repo_token}" | docker login --username {ecr_repo_username} --password-stdin {ecr_repo_url}'
|
|
78
|
-
], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
79
|
-
if response.returncode:
|
|
80
|
-
return error('Unable to connect to the Snapser Container Repository. Please get the latest token from the Web app.')
|
|
81
|
-
success('Login Successful')
|
|
82
|
-
|
|
83
|
-
# Build your snap
|
|
84
|
-
with Progress(
|
|
85
|
-
SpinnerColumn(),
|
|
86
|
-
TextColumn("[progress.description]{task.description}"),
|
|
87
|
-
transient=True,
|
|
88
|
-
) as progress:
|
|
89
|
-
progress.add_task(description=f'Building your snap...', total=None)
|
|
90
|
-
response = subprocess.run([
|
|
91
|
-
#f"docker build --no-cache -t {tag} {path}"
|
|
92
|
-
f"docker build -t {service_id}.{tag} {path}"
|
|
93
|
-
], shell=True, )#stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
94
|
-
if response.returncode:
|
|
95
|
-
return error('Unable to build docker.')
|
|
96
|
-
success('Build Successfull')
|
|
97
|
-
|
|
98
|
-
# Tag the repo
|
|
99
|
-
with Progress(
|
|
100
|
-
SpinnerColumn(),
|
|
101
|
-
TextColumn("[progress.description]{task.description}"),
|
|
102
|
-
transient=True,
|
|
103
|
-
) as progress:
|
|
104
|
-
progress.add_task(description=f'Tagging your snap...', total=None)
|
|
105
|
-
response = subprocess.run([
|
|
106
|
-
f"docker tag {service_id}.{tag} {ecr_repo_url}:{service_id}.{tag}"
|
|
107
|
-
], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
108
|
-
if response.returncode:
|
|
109
|
-
return error('Unable to tag your snap.')
|
|
110
|
-
success('Tag Successfull')
|
|
111
|
-
|
|
112
|
-
# Push the image
|
|
113
|
-
with Progress(
|
|
114
|
-
SpinnerColumn(),
|
|
115
|
-
TextColumn("[progress.description]{task.description}"),
|
|
116
|
-
transient=True,
|
|
117
|
-
) as progress:
|
|
118
|
-
progress.add_task(description=f'Pushing your snap...', total=None)
|
|
119
|
-
response = subprocess.run([
|
|
120
|
-
f"docker push {ecr_repo_url}:{service_id}.{tag}"
|
|
121
|
-
], shell=True, )#stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
122
|
-
if response.returncode:
|
|
123
|
-
return error('Unable to push your snap.')
|
|
124
|
-
success('Snap Upload Successfull')
|
|
125
|
-
|
|
126
|
-
# white_check_mark thumbsup love-you_gesture
|
|
127
|
-
|
|
128
|
-
except Exception as e:
|
|
129
|
-
return error('CLI Error')
|
|
130
|
-
success(f"BYOSnap " + command + ' complete :oncoming_fist:')
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
@app.command()
|
|
134
|
-
def byow():
|
|
135
|
-
"""
|
|
136
|
-
Bring your own workstation
|
|
137
|
-
"""
|
|
138
|
-
typer.echo("Connecting to your cluster")
|
snapctl-0.1.1/snapctl/utils.py
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import base64
|
|
2
|
-
import subprocess
|
|
3
|
-
|
|
4
|
-
def check_docker() -> bool:
|
|
5
|
-
try:
|
|
6
|
-
subprocess.run([
|
|
7
|
-
"docker", "--version"
|
|
8
|
-
], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
9
|
-
return True
|
|
10
|
-
except:
|
|
11
|
-
return False
|
|
12
|
-
|
|
13
|
-
def get_token_values(token: str) -> None | list:
|
|
14
|
-
try:
|
|
15
|
-
input_token = base64.b64decode(token).decode('ascii')
|
|
16
|
-
token_parts = input_token.split('|')
|
|
17
|
-
# web_app_token|service_id|ecr_repo_url|ecr_repo_username|ecr_repo_token
|
|
18
|
-
if len(token_parts) == 5:
|
|
19
|
-
#token_parts[2] = 'http://131164543756.dkr.ecr.us-west-2.amazonaws.com/adhoc-c1a8eb1f-ee36-4313-bda5-046039ea06b3'
|
|
20
|
-
return token_parts
|
|
21
|
-
if len(token_parts) == 4:
|
|
22
|
-
#token_parts[1] = 'http://131164543756.dkr.ecr.us-west-2.amazonaws.com/adhoc-c1a8eb1f-ee36-4313-bda5-046039ea06b3'
|
|
23
|
-
token_parts.insert(0, '')
|
|
24
|
-
return token_parts
|
|
25
|
-
except Exception:
|
|
26
|
-
pass
|
|
27
|
-
return None
|
|
28
|
-
|
|
29
|
-
# TOKEN_ENV_VAR_NAME = 'SNP_TOKEN'
|
|
30
|
-
# def check_token_env_var() -> bool:
|
|
31
|
-
# if TOKEN_ENV_VAR_NAME in os.environ and os.environ[TOKEN_ENV_VAR_NAME] != '':
|
|
32
|
-
# return True
|
|
33
|
-
# return False
|
|
34
|
-
|
|
35
|
-
# def get_token() -> str:
|
|
36
|
-
# if TOKEN_ENV_VAR_NAME in os.environ and os.environ[TOKEN_ENV_VAR_NAME] != '':
|
|
37
|
-
# return os.environ[TOKEN_ENV_VAR_NAME]
|
|
38
|
-
# return ''
|
|
File without changes
|
|
File without changes
|
|
File without changes
|