snapctl 0.32.0__py3-none-any.whl → 0.32.2__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
@@ -8,10 +8,14 @@ import subprocess
8
8
  from sys import platform
9
9
  from typing import Union
10
10
 
11
+ import typer
11
12
  from rich.progress import Progress, SpinnerColumn, TextColumn
12
- from snapctl.types.definitions import ResponseType
13
+ from snapctl.config.constants import SNAPCTL_BYOGS_DEPENDENCY_MISSING, \
14
+ SNAPCTL_BYOGS_ECR_LOGIN_ERROR, SNAPCTL_BYOGS_BUILD_ERROR, \
15
+ SNAPCTL_BYOGS_TAG_ERROR, SNAPCTL_BYOGS_PUBLISH_ERROR, \
16
+ SNAPCTL_BYOGS_PUBLISH_DUPLICATE_TAG_ERROR, SNAPCTL_INPUT_ERROR
13
17
  from snapctl.utils.echo import error, success
14
- from snapctl.utils.helper import get_composite_token
18
+ from snapctl.utils.helper import get_composite_token, snapctl_error, snapctl_success
15
19
 
16
20
 
17
21
  class ByoGs:
@@ -19,7 +23,7 @@ class ByoGs:
19
23
  BYOGS CLI commands
20
24
  """
21
25
  SID = 'byogs'
22
- SUBCOMMANDS = ['build', 'push', 'publish']
26
+ SUBCOMMANDS = ['publish']
23
27
  PLATFORMS = ['linux/amd64']
24
28
  LANGUAGES = ['go', 'python', 'ruby', 'c#', 'c++', 'rust', 'java', 'node']
25
29
  DEFAULT_BUILD_PLATFORM = 'linux/amd64'
@@ -45,6 +49,8 @@ class ByoGs:
45
49
  self.input_tag: Union[str, None] = input_tag
46
50
  self.path: Union[str, None] = path
47
51
  self.dockerfile: str = dockerfile
52
+ # Validate input
53
+ self.validate_input()
48
54
 
49
55
  # Protected methods
50
56
 
@@ -70,232 +76,218 @@ class ByoGs:
70
76
  pass
71
77
  return None
72
78
 
73
- def _check_dependencies(self) -> bool:
79
+ def _check_dependencies(self) -> None:
80
+ progress = Progress(
81
+ SpinnerColumn(),
82
+ TextColumn("[progress.description]{task.description}"),
83
+ transient=True,
84
+ )
85
+ progress.start()
86
+ progress.add_task(
87
+ description='Checking dependencies...', total=None
88
+ )
74
89
  try:
75
90
  # Check dependencies
76
- with Progress(
77
- SpinnerColumn(),
78
- TextColumn("[progress.description]{task.description}"),
79
- transient=True,
80
- ) as progress:
81
- progress.add_task(
82
- description='Checking dependencies...', total=None)
83
- try:
84
- subprocess.run([
85
- "docker", "--version"
86
- ], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
87
- except subprocess.CalledProcessError:
88
- error('Docker not present')
89
- return False
90
- success('Dependencies Verified')
91
- return True
91
+ result = subprocess.run([
92
+ "docker", "info"
93
+ ], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
94
+ if not result.returncode:
95
+ return snapctl_success('BYOGS dependencies verified', progress, no_exit=True)
92
96
  except subprocess.CalledProcessError:
93
- error('CLI Error')
94
- return False
97
+ snapctl_error('Snapctl Exception',
98
+ SNAPCTL_BYOGS_DEPENDENCY_MISSING, progress)
99
+ snapctl_error('Docker not running. Please start docker.',
100
+ SNAPCTL_BYOGS_DEPENDENCY_MISSING, progress)
95
101
 
96
- def _docker_login(self) -> bool:
102
+ def _docker_login(self) -> None:
97
103
  # Get the data
98
104
  ecr_repo_url = self.token_parts[0]
99
105
  ecr_repo_username = self.token_parts[1]
100
106
  ecr_repo_token = self.token_parts[2]
107
+ progress = Progress(
108
+ SpinnerColumn(),
109
+ TextColumn("[progress.description]{task.description}"),
110
+ transient=True,
111
+ )
112
+ progress.start()
113
+ progress.add_task(
114
+ description='Logging into Snapser Image Registry...', total=None)
101
115
  try:
102
116
  # Login to Snapser Registry
103
- with Progress(
104
- SpinnerColumn(),
105
- TextColumn("[progress.description]{task.description}"),
106
- transient=True,
107
- ) as progress:
108
- progress.add_task(
109
- description='Logging into Snapser Image Registry...', total=None)
110
- if platform == 'win32':
111
- response = subprocess.run([
112
- 'docker', 'login', '--username', ecr_repo_username,
113
- '--password', ecr_repo_token, ecr_repo_url
114
- ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
115
- else:
116
- response = subprocess.run([
117
- f'echo "{ecr_repo_token}" | docker login '
118
- f'--username {ecr_repo_username} --password-stdin {ecr_repo_url}'
119
- ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
120
- if response.returncode:
121
- error(
122
- 'Unable to connect to the Snapser Container Repository. '
123
- 'Please confirm if docker is running or try restarting docker'
124
- )
125
- return False
126
- success('Login Successful')
127
- return True
117
+ if platform == 'win32':
118
+ response = subprocess.run([
119
+ 'docker', 'login', '--username', ecr_repo_username,
120
+ '--password', ecr_repo_token, ecr_repo_url
121
+ ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
122
+ else:
123
+ response = subprocess.run([
124
+ f'echo "{ecr_repo_token}" | docker login '
125
+ f'--username {ecr_repo_username} --password-stdin {ecr_repo_url}'
126
+ ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
127
+ if not response.returncode:
128
+ return snapctl_success('BYOGS ECR login successful', progress, no_exit=True)
128
129
  except subprocess.CalledProcessError:
129
- error('CLI Error')
130
- return False
130
+ snapctl_error('Snapctl Exception',
131
+ SNAPCTL_BYOGS_ECR_LOGIN_ERROR, progress)
132
+ snapctl_error('BYOGS ECR login failure',
133
+ SNAPCTL_BYOGS_ECR_LOGIN_ERROR, progress)
131
134
 
132
- def _docker_build(self) -> bool:
135
+ def _docker_build(self) -> None:
133
136
  # Get the data
134
- image_tag = f'{ByoGs.SID}.{self.input_tag}'
135
- build_platform = ByoGs.DEFAULT_BUILD_PLATFORM
136
- if len(self.token_parts) == 4:
137
- build_platform = self.token_parts[3]
137
+ progress = Progress(
138
+ SpinnerColumn(),
139
+ TextColumn("[progress.description]{task.description}"),
140
+ transient=True,
141
+ )
142
+ progress.start()
143
+ progress.add_task(
144
+ description='Building your snap...', total=None)
138
145
  try:
146
+ image_tag = f'{ByoGs.SID}.{self.input_tag}'
147
+ build_platform = ByoGs.DEFAULT_BUILD_PLATFORM
148
+ if len(self.token_parts) == 4:
149
+ build_platform = self.token_parts[3]
139
150
  # Build your snap
140
- with Progress(
141
- SpinnerColumn(),
142
- TextColumn("[progress.description]{task.description}"),
143
- transient=True,
144
- ) as progress:
145
- progress.add_task(
146
- description='Building your snap...', total=None)
147
- docker_file_path = f"{self.path}/{self.dockerfile}"
148
- if platform == "win32":
149
- response = subprocess.run([
150
- # f"docker build --no-cache -t {tag} {path}"
151
- 'docker', 'build', '--platform', build_platform, '-t', image_tag,
152
- '-f', docker_file_path, self.path
153
- ], shell=True, check=False)
154
- # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
155
- else:
156
- response = subprocess.run([
157
- # f"docker build --no-cache -t {tag} {path}"
158
- f"docker build --platform {build_platform} -t {image_tag} -f {docker_file_path} {self.path}"
159
- ], shell=True, check=False)
160
- # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
161
- if response.returncode:
162
- error('Unable to build docker')
163
- return False
164
- success('Build Successful')
165
- return True
151
+ docker_file_path = os.path.join(self.path, self.dockerfile)
152
+ if platform == "win32":
153
+ response = subprocess.run([
154
+ # f"docker build --no-cache -t {tag} {path}"
155
+ 'docker', 'build', '--platform', build_platform, '-t', image_tag,
156
+ '-f', docker_file_path, self.path
157
+ ], shell=True, check=False)
158
+ # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
159
+ else:
160
+ response = subprocess.run([
161
+ # f"docker build --no-cache -t {tag} {path}"
162
+ f"docker build --platform {build_platform} -t {image_tag} "
163
+ f"-f {docker_file_path} {self.path}"
164
+ ], shell=True, check=False)
165
+ # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
166
+ if not response.returncode:
167
+ return snapctl_success('BYOGS build successful', progress, no_exit=True)
166
168
  except subprocess.CalledProcessError:
167
- error('CLI Error')
168
- return False
169
+ snapctl_error('Snapctl Exception',
170
+ SNAPCTL_BYOGS_BUILD_ERROR, progress)
171
+ snapctl_error('BYOGS build failure',
172
+ SNAPCTL_BYOGS_BUILD_ERROR, progress)
169
173
 
170
- def _docker_tag(self) -> bool:
174
+ def _docker_tag(self) -> None:
171
175
  # Get the data
172
- ecr_repo_url = self.token_parts[0]
173
- image_tag = f'{ByoGs.SID}.{self.input_tag}'
174
- full_ecr_repo_url = f'{ecr_repo_url}:{image_tag}'
176
+ progress = Progress(
177
+ SpinnerColumn(),
178
+ TextColumn("[progress.description]{task.description}"),
179
+ transient=True,
180
+ )
181
+ progress.start()
182
+ progress.add_task(
183
+ description='Tagging your snap...', total=None)
175
184
  try:
185
+ ecr_repo_url = self.token_parts[0]
186
+ image_tag = f'{ByoGs.SID}.{self.input_tag}'
187
+ full_ecr_repo_url = f'{ecr_repo_url}:{image_tag}'
176
188
  # Tag the repo
177
- with Progress(
178
- SpinnerColumn(),
179
- TextColumn("[progress.description]{task.description}"),
180
- transient=True,
181
- ) as progress:
182
- progress.add_task(
183
- description='Tagging your snap...', total=None)
184
- if platform == "win32":
185
- response = subprocess.run([
186
- 'docker', 'tag', image_tag, full_ecr_repo_url
187
- ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
188
- else:
189
- response = subprocess.run([
190
- f"docker tag {image_tag} {full_ecr_repo_url}"
191
- ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
192
- if response.returncode:
193
- error('Unable to tag your snap')
194
- return False
195
- success('Tag Successful')
196
- return True
189
+ if platform == "win32":
190
+ response = subprocess.run([
191
+ 'docker', 'tag', image_tag, full_ecr_repo_url
192
+ ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
193
+ else:
194
+ response = subprocess.run([
195
+ f"docker tag {image_tag} {full_ecr_repo_url}"
196
+ ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
197
+ if not response.returncode:
198
+ return snapctl_success('BYOGS tag successful', progress, no_exit=True)
197
199
  except subprocess.CalledProcessError:
198
- error('CLI Error')
199
- return False
200
+ snapctl_error('Snapctl Exception',
201
+ SNAPCTL_BYOGS_TAG_ERROR, progress)
202
+ snapctl_error('BYOGS tag failure', SNAPCTL_BYOGS_TAG_ERROR, progress)
200
203
 
201
- def _docker_push(self) -> bool:
204
+ def _docker_push(self) -> None:
205
+ progress = Progress(
206
+ SpinnerColumn(),
207
+ TextColumn("[progress.description]{task.description}"),
208
+ transient=True,
209
+ )
210
+ progress.start()
211
+ progress.add_task(
212
+ description='Pushing your snap...', total=None)
202
213
  try:
203
214
  ecr_repo_url = self.token_parts[0]
204
215
  image_tag = f'{ByoGs.SID}.{self.input_tag}'
205
216
  full_ecr_repo_url = f'{ecr_repo_url}:{image_tag}'
206
-
207
217
  # Push the image
208
- with Progress(
209
- SpinnerColumn(),
210
- TextColumn("[progress.description]{task.description}"),
211
- transient=True,
212
- ) as progress:
213
- progress.add_task(
214
- description='Pushing your snap...', total=None)
215
- if platform == "win32":
216
- response = subprocess.run([
217
- 'docker', 'push', full_ecr_repo_url
218
- ], shell=True, check=False)
219
- # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
220
- else:
221
- response = subprocess.run([
222
- f"docker push {full_ecr_repo_url}"
223
- ], shell=True, check=False)
224
- # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
225
- if response.returncode:
226
- error('Unable to push your snap')
227
- return False
228
- success('Snap Upload Successful')
229
- return True
218
+ if platform == "win32":
219
+ response = subprocess.run([
220
+ 'docker', 'push', full_ecr_repo_url
221
+ ], shell=True, check=False)
222
+ # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
223
+ else:
224
+ response = subprocess.run([
225
+ f"docker push {full_ecr_repo_url}"
226
+ ], shell=True, check=False)
227
+ # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
228
+ if not response.returncode:
229
+ return snapctl_success('BYOGS upload successful', progress, no_exit=True)
230
230
  except subprocess.CalledProcessError:
231
- error('CLI Error')
232
- return False
231
+ snapctl_error('Snapctl Exception',
232
+ SNAPCTL_BYOGS_PUBLISH_ERROR, progress)
233
+ snapctl_error('BYOGS upload failure. Duplicate image error.',
234
+ SNAPCTL_BYOGS_PUBLISH_DUPLICATE_TAG_ERROR, progress)
233
235
 
234
236
  # Public methods
235
237
 
236
238
  # Validator
237
- def validate_input(self) -> ResponseType:
239
+ def validate_input(self) -> None:
238
240
  """
239
241
  Validator
240
242
  """
241
- response: ResponseType = {
242
- 'error': True,
243
- 'msg': '',
244
- 'data': []
245
- }
246
243
  # Check API Key and Base URL
247
244
  if not self.api_key or self.base_url == '':
248
- response['msg'] = "Missing API Key."
249
- return response
245
+ snapctl_error("Missing API Key.", SNAPCTL_INPUT_ERROR)
250
246
  # Check subcommand
251
247
  if not self.subcommand in ByoGs.SUBCOMMANDS:
252
- response['msg'] = f"Invalid command. Valid commands are {', '.join(ByoGs.SUBCOMMANDS)}."
253
- return response
248
+ snapctl_error(
249
+ f"Invalid command. Valid commands are {', '.join(ByoGs.SUBCOMMANDS)}.",
250
+ SNAPCTL_INPUT_ERROR)
254
251
  # Validation for subcommands
255
252
  if self.token_parts is None:
256
- response['msg'] = 'Invalid token. Please reach out to your support team'
257
- return response
253
+ snapctl_error('Invalid token. Please reach out to your support team',
254
+ SNAPCTL_INPUT_ERROR)
258
255
  # 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:
261
- response['msg'] = (
256
+ if self.input_tag is None:
257
+ snapctl_error("Missing required parameter: tag",
258
+ SNAPCTL_INPUT_ERROR)
259
+ if len(self.input_tag.split()) > 1 or len(self.input_tag) > ByoGs.TAG_CHARACTER_LIMIT:
260
+ snapctl_error(
262
261
  "Tag should be a single word with maximum of "
263
- f"{ByoGs.TAG_CHARACTER_LIMIT} characters"
262
+ f"{ByoGs.TAG_CHARACTER_LIMIT} characters",
263
+ SNAPCTL_INPUT_ERROR
264
264
  )
265
- return response
266
265
  if self.subcommand in ['build', 'publish']:
267
- if not self.input_tag:
268
- response['msg'] = "Missing required parameter: tag"
269
- return response
270
266
  if not self.path:
271
- response['msg'] = "Missing required parameter: path"
272
- return response
267
+ snapctl_error("Missing required parameter: path",
268
+ SNAPCTL_INPUT_ERROR)
273
269
  # Check path
274
270
  if not os.path.isfile(f"{self.path}/{self.dockerfile}"):
275
- response['msg'] = f"Unable to find {self.dockerfile} at path {self.path}"
276
- return response
277
- elif self.subcommand == 'push':
278
- if not self.input_tag:
279
- response['msg'] = "Missing required parameter: tag"
280
- return response
281
- # Send success
282
- response['error'] = False
283
- return response
271
+ snapctl_error(
272
+ f"Unable to find {self.dockerfile} at path {self.path}", SNAPCTL_INPUT_ERROR)
273
+ # elif self.subcommand == 'push':
274
+ # if not self.input_tag:
275
+ # error("Missing required parameter: tag", SNAPCTL_INPUT_ERROR)
276
+ # raise typer.Exit(code=SNAPCTL_INPUT_ERROR)
284
277
 
285
278
  # CRUD methods
286
- def build(self) -> bool:
279
+ def build(self) -> None:
287
280
  """
288
281
  Build the image
289
282
  1. Check Dependencies
290
283
  2. Login to Snapser Registry
291
284
  3. Build your snap
292
285
  """
293
- if not self._check_dependencies() or not self._docker_login() or \
294
- not self._docker_build():
295
- return False
296
- return True
286
+ self._check_dependencies()
287
+ self._docker_login()
288
+ self._docker_build()
297
289
 
298
- def push(self) -> bool:
290
+ def push(self) -> None:
299
291
  """
300
292
  Tag the image
301
293
  1. Check Dependencies
@@ -303,13 +295,13 @@ class ByoGs:
303
295
  3. Tag the snap
304
296
  4. Push your snap
305
297
  """
306
- if not self._check_dependencies() or not self._docker_login() or \
307
- not self._docker_tag() or not self._docker_push():
308
- return False
309
- return True
298
+ self._check_dependencies()
299
+ self._docker_login()
300
+ self._docker_tag()
301
+ self._docker_push()
310
302
 
311
303
  # Upper echelon commands
312
- def publish(self) -> bool:
304
+ def publish(self) -> None:
313
305
  """
314
306
  Publish the image
315
307
  1. Check Dependencies
@@ -319,7 +311,9 @@ class ByoGs:
319
311
  5. Push the image
320
312
  6. Upload swagger.json
321
313
  """
322
- if not self._check_dependencies() or not self._docker_login() or \
323
- not self._docker_build() or not self._docker_tag() or not self._docker_push():
324
- return False
325
- return True
314
+ self._check_dependencies()
315
+ self._docker_login()
316
+ self._docker_build()
317
+ self._docker_tag()
318
+ self._docker_push()
319
+ snapctl_success('BYOGS publish successful')