snapctl 0.39.2__py3-none-any.whl → 0.41.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
@@ -5,11 +5,13 @@ import base64
5
5
  from binascii import Error as BinasciiError
6
6
  import os
7
7
  import subprocess
8
+ import time
8
9
  import platform as sys_platform
9
10
  from sys import platform
10
11
  from typing import Union, List
11
12
 
12
13
  from rich.progress import Progress, SpinnerColumn, TextColumn
14
+ from snapctl.commands.snapend import Snapend
13
15
  from snapctl.config.constants import SNAPCTL_BYOGS_DEPENDENCY_MISSING, \
14
16
  SNAPCTL_BYOGS_ECR_LOGIN_ERROR, SNAPCTL_BYOGS_BUILD_ERROR, \
15
17
  SNAPCTL_BYOGS_TAG_ERROR, SNAPCTL_BYOGS_PUBLISH_ERROR, \
@@ -24,7 +26,7 @@ class ByoGs:
24
26
  BYOGS CLI commands
25
27
  """
26
28
  SID = 'byogs'
27
- SUBCOMMANDS = ['publish']
29
+ SUBCOMMANDS = ['publish', 'sync']
28
30
  PLATFORMS = ['linux/amd64']
29
31
  LANGUAGES = ['go', 'python', 'ruby', 'c#', 'c++', 'rust', 'java', 'node']
30
32
  DEFAULT_BUILD_PLATFORM = 'linux/amd64'
@@ -32,14 +34,15 @@ class ByoGs:
32
34
  TAG_CHARACTER_LIMIT = 80
33
35
 
34
36
  def __init__(
35
- self, subcommand: str, base_url: str, api_key: Union[str, None],
36
- input_tag: Union[str, None], path: Union[str, None],
37
- resources_path: Union[str, None], dockerfile: str,
38
- skip_build: bool = False
37
+ self, *, subcommand: str, base_url: str, api_key: Union[str, None],
38
+ tag: Union[str, None] = None, path: Union[str, None] = None,
39
+ resources_path: Union[str, None] = None, dockerfile: Union[str, None] = None,
40
+ skip_build: bool = False, snapend_id: Union[str, None] = None,
41
+ fleet_name: Union[str, None] = None, blocking: bool = False
39
42
  ) -> None:
40
43
  self.subcommand: str = subcommand
41
44
  self.base_url: str = base_url
42
- self.api_key: str = api_key
45
+ self.api_key: Union[str, None] = api_key
43
46
  # self.sid: str = sid
44
47
  # if subcommand == 'publish':
45
48
  # self.sid = ByoGs.SID
@@ -49,11 +52,14 @@ class ByoGs:
49
52
  )
50
53
  self.token_parts: Union[List, None] = ByoGs._get_token_values(
51
54
  self.token) if self.token is not None else None
52
- self.input_tag: Union[str, None] = input_tag
55
+ self.tag: Union[str, None] = tag
53
56
  self.path: Union[str, None] = path
54
57
  self.resources_path: Union[str, None] = resources_path
55
58
  self.dockerfile: str = dockerfile
56
59
  self.skip_build: bool = skip_build
60
+ self.snapend_id: Union[str, None] = snapend_id
61
+ self.fleet_name: Union[str, None] = fleet_name
62
+ self.blocking: bool = blocking
57
63
  # Validate input
58
64
  self.validate_input()
59
65
 
@@ -97,10 +103,14 @@ class ByoGs:
97
103
  "docker", "info"
98
104
  ], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
99
105
  if not result.returncode:
100
- return snapctl_success('BYOGS dependencies verified', progress, no_exit=True)
106
+ return snapctl_success(
107
+ message='BYOGS dependencies verified',
108
+ progress=progress, no_exit=True)
101
109
  except subprocess.CalledProcessError:
102
110
  snapctl_error('Snapctl Exception',
103
111
  SNAPCTL_BYOGS_DEPENDENCY_MISSING, progress)
112
+ finally:
113
+ progress.stop()
104
114
  snapctl_error('Docker not running. Please start docker.',
105
115
  SNAPCTL_BYOGS_DEPENDENCY_MISSING, progress)
106
116
 
@@ -130,12 +140,17 @@ class ByoGs:
130
140
  f'--username {ecr_repo_username} --password-stdin {ecr_repo_url}'
131
141
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
132
142
  if not response.returncode:
133
- return snapctl_success('BYOGS ECR login successful', progress, no_exit=True)
143
+ return snapctl_success(
144
+ message='BYOGS ECR login successful', progress=progress, no_exit=True)
134
145
  except subprocess.CalledProcessError:
135
- snapctl_error('Snapctl Exception',
136
- SNAPCTL_BYOGS_ECR_LOGIN_ERROR, progress)
137
- snapctl_error('BYOGS ECR login failure',
138
- SNAPCTL_BYOGS_ECR_LOGIN_ERROR, progress)
146
+ snapctl_error(
147
+ message='Snapctl Exception',
148
+ code=SNAPCTL_BYOGS_ECR_LOGIN_ERROR, progress=progress)
149
+ finally:
150
+ progress.stop()
151
+ snapctl_error(
152
+ message='BYOGS ECR login failure',
153
+ code=SNAPCTL_BYOGS_ECR_LOGIN_ERROR, progress=progress)
139
154
 
140
155
  def _docker_build(self) -> None:
141
156
  # Get the data
@@ -148,7 +163,7 @@ class ByoGs:
148
163
  progress.add_task(
149
164
  description='Building your snap...', total=None)
150
165
  try:
151
- # image_tag = f'{ByoGs.SID}.{self.input_tag}'
166
+ # image_tag = f'{ByoGs.SID}.{self.tag}'
152
167
  build_platform = ByoGs.DEFAULT_BUILD_PLATFORM
153
168
  if len(self.token_parts) == 4:
154
169
  build_platform = self.token_parts[3]
@@ -169,7 +184,7 @@ class ByoGs:
169
184
  if platform == "win32":
170
185
  response = subprocess.run([
171
186
  # f"docker build --no-cache -t {tag} {path}"
172
- 'docker', 'build', '--platform', build_platform, '-t', self.input_tag,
187
+ 'docker', 'build', '--platform', build_platform, '-t', self.tag,
173
188
  '-f', docker_file_path, self.path
174
189
  ], shell=True, check=False)
175
190
  # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
@@ -177,17 +192,23 @@ class ByoGs:
177
192
  response = subprocess.run([
178
193
  # f"docker build --no-cache -t {tag} {path}"
179
194
  "docker build --platform " +
180
- f"{build_platform} -t {self.input_tag} " +
195
+ f"{build_platform} -t {self.tag} " +
181
196
  f"-f {docker_file_path} {self.path}"
182
197
  ], shell=True, check=False)
183
198
  # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
184
199
  if not response.returncode:
185
- return snapctl_success('BYOGS build successful', progress, no_exit=True)
200
+ return snapctl_success(
201
+ message='BYOGS build successful',
202
+ progress=progress, no_exit=True)
186
203
  except subprocess.CalledProcessError:
187
- snapctl_error('Snapctl Exception',
188
- SNAPCTL_BYOGS_BUILD_ERROR, progress)
189
- snapctl_error('BYOGS build failure',
190
- SNAPCTL_BYOGS_BUILD_ERROR, progress)
204
+ snapctl_error(
205
+ message='Snapctl Exception',
206
+ code=SNAPCTL_BYOGS_BUILD_ERROR, progress=progress)
207
+ finally:
208
+ progress.stop()
209
+ snapctl_error(
210
+ message='BYOGS build failure',
211
+ code=SNAPCTL_BYOGS_BUILD_ERROR, progress=progress)
191
212
 
192
213
  def _docker_tag(self) -> None:
193
214
  # Get the data
@@ -201,23 +222,28 @@ class ByoGs:
201
222
  description='Tagging your snap...', total=None)
202
223
  try:
203
224
  ecr_repo_url = self.token_parts[0]
204
- image_tag = f'{ByoGs.SID}.{self.input_tag}'
225
+ image_tag = f'{ByoGs.SID}.{self.tag}'
205
226
  full_ecr_repo_url = f'{ecr_repo_url}:{image_tag}'
206
227
  # Tag the repo
207
228
  if platform == "win32":
208
229
  response = subprocess.run([
209
- 'docker', 'tag', self.input_tag, full_ecr_repo_url
230
+ 'docker', 'tag', self.tag, full_ecr_repo_url
210
231
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
211
232
  else:
212
233
  response = subprocess.run([
213
- f"docker tag {self.input_tag} {full_ecr_repo_url}"
234
+ f"docker tag {self.tag} {full_ecr_repo_url}"
214
235
  ], shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False)
215
236
  if not response.returncode:
216
- return snapctl_success('BYOGS tag successful', progress, no_exit=True)
237
+ return snapctl_success(
238
+ message='BYOGS tag successful', progress=progress, no_exit=True)
217
239
  except subprocess.CalledProcessError:
218
- snapctl_error('Snapctl Exception',
219
- SNAPCTL_BYOGS_TAG_ERROR, progress)
220
- snapctl_error('BYOGS tag failure', SNAPCTL_BYOGS_TAG_ERROR, progress)
240
+ snapctl_error(
241
+ message='Snapctl Exception',
242
+ code=SNAPCTL_BYOGS_TAG_ERROR, progress=progress)
243
+ finally:
244
+ progress.stop()
245
+ snapctl_error(
246
+ message='BYOGS tag failure', code=SNAPCTL_BYOGS_TAG_ERROR, progress=progress)
221
247
 
222
248
  def _docker_push(self) -> None:
223
249
  progress = Progress(
@@ -230,7 +256,7 @@ class ByoGs:
230
256
  description='Pushing your snap...', total=None)
231
257
  try:
232
258
  ecr_repo_url = self.token_parts[0]
233
- image_tag = f'{ByoGs.SID}.{self.input_tag}'
259
+ image_tag = f'{ByoGs.SID}.{self.tag}'
234
260
  full_ecr_repo_url = f'{ecr_repo_url}:{image_tag}'
235
261
  # Push the image
236
262
  if platform == "win32":
@@ -244,12 +270,49 @@ class ByoGs:
244
270
  ], shell=True, check=False)
245
271
  # stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
246
272
  if not response.returncode:
247
- return snapctl_success('BYOGS upload successful', progress, no_exit=True)
273
+ return snapctl_success(
274
+ message='BYOGS upload successful',
275
+ progress=progress, no_exit=True)
248
276
  except subprocess.CalledProcessError:
249
- snapctl_error('Snapctl Exception',
250
- SNAPCTL_BYOGS_PUBLISH_ERROR, progress)
251
- snapctl_error('BYOGS upload failure. Duplicate image error.',
252
- SNAPCTL_BYOGS_PUBLISH_DUPLICATE_TAG_ERROR, progress)
277
+ snapctl_error(
278
+ message='Snapctl Exception',
279
+ code=SNAPCTL_BYOGS_PUBLISH_ERROR, progress=progress)
280
+ finally:
281
+ progress.stop()
282
+ snapctl_error(
283
+ message='BYOGS upload failure. Duplicate image error.',
284
+ code=SNAPCTL_BYOGS_PUBLISH_DUPLICATE_TAG_ERROR, progress=progress)
285
+
286
+ def _clean_slate(self) -> None:
287
+ progress = Progress(
288
+ SpinnerColumn(),
289
+ TextColumn("[progress.description]{task.description}"),
290
+ transient=True,
291
+ )
292
+ progress.start()
293
+ progress.add_task(
294
+ description='Cleaning cache and initializing...', total=None)
295
+ try:
296
+ # Specific ECR repository URL to check against
297
+ ecr_repo_url = self.token_parts[0]
298
+ if platform == "win32":
299
+ # Perform the Docker logout
300
+ logout_response = subprocess.run(
301
+ ['docker', 'logout', ecr_repo_url],
302
+ shell=True, check=False)
303
+ else:
304
+ # Perform the Docker logout
305
+ logout_response = subprocess.run([
306
+ f"docker logout {ecr_repo_url}"
307
+ ], shell=True, check=False)
308
+ if not logout_response.returncode:
309
+ return snapctl_success(
310
+ message='Cleanup complete',
311
+ progress=progress, no_exit=True)
312
+ except subprocess.CalledProcessError:
313
+ warning('Unable to initialize with a clean slate.')
314
+ finally:
315
+ progress.stop()
253
316
 
254
317
  # Public methods
255
318
 
@@ -260,31 +323,51 @@ class ByoGs:
260
323
  """
261
324
  # Check API Key and Base URL
262
325
  if not self.api_key or self.base_url == '':
263
- snapctl_error("Missing API Key.", SNAPCTL_INPUT_ERROR)
326
+ snapctl_error(
327
+ message="Missing API Key.", code=SNAPCTL_INPUT_ERROR)
264
328
  # Check subcommand
265
329
  if not self.subcommand in ByoGs.SUBCOMMANDS:
266
330
  snapctl_error(
267
- "Invalid command. Valid commands are " +
331
+ message="Invalid command. Valid commands are " +
268
332
  f"{', '.join(ByoGs.SUBCOMMANDS)}.",
269
- SNAPCTL_INPUT_ERROR)
333
+ code=SNAPCTL_INPUT_ERROR)
270
334
  # Validation for subcommands
271
335
  if self.token_parts is None:
272
- snapctl_error('Invalid token. Please reach out to your support team',
273
- SNAPCTL_INPUT_ERROR)
336
+ snapctl_error(
337
+ message='Invalid token. Please reach out to your support team',
338
+ code=SNAPCTL_INPUT_ERROR)
274
339
  # Check tag
275
- if self.input_tag is None:
276
- snapctl_error("Missing required parameter: tag",
277
- SNAPCTL_INPUT_ERROR)
278
- if len(self.input_tag.split()) > 1 or len(self.input_tag) > ByoGs.TAG_CHARACTER_LIMIT:
340
+ if self.tag is None:
341
+ snapctl_error(
342
+ message="Missing required parameter: tag",
343
+ code=SNAPCTL_INPUT_ERROR)
344
+ if len(self.tag.split()) > 1 or len(self.tag) > ByoGs.TAG_CHARACTER_LIMIT:
279
345
  snapctl_error(
280
- "Tag should be a single word with maximum of " +
346
+ message="Tag should be a single word with maximum of " +
281
347
  f"{ByoGs.TAG_CHARACTER_LIMIT} characters",
282
- SNAPCTL_INPUT_ERROR
348
+ code=SNAPCTL_INPUT_ERROR
283
349
  )
284
350
  if self.subcommand in ['build', 'publish']:
285
351
  if not self.skip_build and not self.path:
286
- snapctl_error("Missing required parameter: path",
287
- SNAPCTL_INPUT_ERROR)
352
+ snapctl_error(
353
+ message="Missing required parameter: path",
354
+ code=SNAPCTL_INPUT_ERROR)
355
+ # Check path
356
+ if self.resources_path:
357
+ docker_file_path = f"{self.resources_path}/{self.dockerfile}"
358
+ else:
359
+ docker_file_path = f"{self.path}/{self.dockerfile}"
360
+
361
+ if not self.skip_build and not os.path.isfile(docker_file_path):
362
+ snapctl_error(
363
+ message="Unable to find " +
364
+ f"{self.dockerfile} at path {docker_file_path}",
365
+ code=SNAPCTL_INPUT_ERROR)
366
+ elif self.subcommand == 'sync':
367
+ if not self.skip_build and not self.path:
368
+ snapctl_error(
369
+ message="Missing required parameter: path",
370
+ code=SNAPCTL_INPUT_ERROR)
288
371
  # Check path
289
372
  if self.resources_path:
290
373
  docker_file_path = f"{self.resources_path}/{self.dockerfile}"
@@ -293,13 +376,17 @@ class ByoGs:
293
376
 
294
377
  if not self.skip_build and not os.path.isfile(docker_file_path):
295
378
  snapctl_error(
296
- "Unable to find " +
379
+ message="Unable to find " +
297
380
  f"{self.dockerfile} at path {docker_file_path}",
298
- SNAPCTL_INPUT_ERROR)
299
- # elif self.subcommand == 'push':
300
- # if not self.input_tag:
301
- # error("Missing required parameter: tag", SNAPCTL_INPUT_ERROR)
302
- # raise typer.Exit(code=SNAPCTL_INPUT_ERROR)
381
+ code=SNAPCTL_INPUT_ERROR)
382
+ if not self.snapend_id:
383
+ snapctl_error(
384
+ message="Missing required parameter: snapend_id",
385
+ code=SNAPCTL_INPUT_ERROR)
386
+ if not self.fleet_name:
387
+ snapctl_error(
388
+ message="Missing required parameter: fleet_name",
389
+ code=SNAPCTL_INPUT_ERROR)
303
390
 
304
391
  # CRUD methods
305
392
  def build(self) -> None:
@@ -322,11 +409,12 @@ class ByoGs:
322
409
  """
323
410
  self._check_dependencies()
324
411
  self._docker_tag()
412
+ self._clean_slate()
325
413
  self._docker_login()
326
414
  self._docker_push()
327
415
 
328
416
  # Upper echelon commands
329
- def publish(self) -> None:
417
+ def publish(self, no_exit: bool = False) -> None:
330
418
  """
331
419
  Publish the image
332
420
  1. Check Dependencies
@@ -342,6 +430,28 @@ class ByoGs:
342
430
  else:
343
431
  info('--skip-build set. Skipping the build step.')
344
432
  self._docker_tag()
433
+ self._clean_slate()
345
434
  self._docker_login()
346
435
  self._docker_push()
347
- snapctl_success('BYOGS publish successful')
436
+ snapctl_success(
437
+ message='BYOGS publish successful', no_exit=no_exit)
438
+
439
+ def sync(self) -> None:
440
+ """
441
+ Sync the image
442
+ 1. Check Dependencies
443
+ 2. Login to Snapser Registry
444
+ 3. Build your snap
445
+ 4. Tag the repo
446
+ 5. Push the image
447
+ 6. Upload swagger.json
448
+ """
449
+ self.tag = f'{self.tag}-{int(time.time())}'
450
+ self.publish(no_exit=True)
451
+ byogs_list: str = f"{self.fleet_name}:{self.tag}"
452
+ snapend = Snapend(
453
+ subcommand='update', base_url=self.base_url, api_key=self.api_key,
454
+ snapend_id=self.snapend_id, byogs=byogs_list, blocking=self.blocking
455
+ )
456
+ snapend.update(no_exit=True)
457
+ return snapctl_success(message='BYOGs sync successful')