edge-containers-cli 5.1.0__tar.gz → 5.2.1__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.
Files changed (109) hide show
  1. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/PKG-INFO +1 -1
  2. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/_version.py +3 -3
  3. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/cli.py +6 -2
  4. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/cmds/argo_commands.py +24 -25
  5. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/utils.py +33 -2
  6. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli.egg-info/PKG-INFO +1 -1
  7. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/argocd.yaml +88 -0
  8. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/test_argocd.py +14 -3
  9. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.copier-answers.yml +0 -0
  10. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.devcontainer/devcontainer.json +0 -0
  11. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.dockerignore +0 -0
  12. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/CONTRIBUTING.md +0 -0
  13. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  14. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/ISSUE_TEMPLATE/issue.md +0 -0
  15. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
  16. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/pages/index.html +0 -0
  17. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/pages/make_switcher.py +0 -0
  18. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/workflows/_container.yml +0 -0
  19. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/workflows/_dist.yml +0 -0
  20. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/workflows/_pypi.yml +0 -0
  21. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/workflows/_release.yml +0 -0
  22. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/workflows/_test.yml +0 -0
  23. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/workflows/_tox.yml +0 -0
  24. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.github/workflows/ci.yml +0 -0
  25. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.gitignore +0 -0
  26. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.gitleaks.toml +0 -0
  27. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.pre-commit-config.yaml +0 -0
  28. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.python-version +0 -0
  29. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.vscode/extensions.json +0 -0
  30. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.vscode/launch.json +0 -0
  31. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.vscode/settings.json +0 -0
  32. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/.vscode/tasks.json +0 -0
  33. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/Dockerfile +0 -0
  34. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/LICENSE +0 -0
  35. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/README.md +0 -0
  36. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/conf.py +0 -0
  37. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/explanations/decisions/0001-record-architecture-decisions.rst +0 -0
  38. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst +0 -0
  39. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/explanations/decisions.rst +0 -0
  40. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/how-to/build-docs.rst +0 -0
  41. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/how-to/contribute.rst +0 -0
  42. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/how-to/lint.rst +0 -0
  43. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/how-to/make-release.rst +0 -0
  44. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/how-to/pin-requirements.rst +0 -0
  45. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/how-to/run-tests.rst +0 -0
  46. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/how-to/static-analysis.rst +0 -0
  47. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/how-to/test-container.rst +0 -0
  48. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/how-to/update-tools.rst +0 -0
  49. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/index.rst +0 -0
  50. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/reference/standards.rst +0 -0
  51. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/developer/tutorials/dev-install.rst +0 -0
  52. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/genindex.rst +0 -0
  53. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/images/dls-favicon.ico +0 -0
  54. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/images/dls-logo.svg +0 -0
  55. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/images/ec-logs.png +0 -0
  56. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/images/ec-web.png +0 -0
  57. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/index.rst +0 -0
  58. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/user/explanations/docs-structure.rst +0 -0
  59. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/user/how-to/run-container.rst +0 -0
  60. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/user/index.rst +0 -0
  61. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/user/reference/api.rst +0 -0
  62. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/docs/user/tutorials/installation.rst +0 -0
  63. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/pyproject.toml +0 -0
  64. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/renovate.json +0 -0
  65. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/setup.cfg +0 -0
  66. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/__init__.py +0 -0
  67. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/__main__.py +0 -0
  68. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/autocomplete.py +0 -0
  69. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/backend.py +0 -0
  70. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/cmds/__init__.py +0 -0
  71. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/cmds/commands.py +0 -0
  72. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/cmds/demo_commands.py +0 -0
  73. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/cmds/helm.py +0 -0
  74. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/cmds/k8s_commands.py +0 -0
  75. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/cmds/monitor.py +0 -0
  76. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/cmds/monitor.tcss +0 -0
  77. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/definitions.py +0 -0
  78. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/git.py +0 -0
  79. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/globals.py +0 -0
  80. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/logging.py +0 -0
  81. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli/shell.py +0 -0
  82. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli.egg-info/SOURCES.txt +0 -0
  83. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli.egg-info/dependency_links.txt +0 -0
  84. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli.egg-info/entry_points.txt +0 -0
  85. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli.egg-info/requires.txt +0 -0
  86. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/src/edge_containers_cli.egg-info/top_level.txt +0 -0
  87. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/__init__.py +0 -0
  88. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/conftest.py +0 -0
  89. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-deployment/apps/values.yaml +0 -0
  90. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/bl01t-ea-test-01/Chart.yaml +0 -0
  91. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/bl01t-ea-test-01/config/ioc.db +0 -0
  92. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/bl01t-ea-test-01/config/ioc.yaml +0 -0
  93. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/bl01t-ea-test-01/templates/configmap.yaml +0 -0
  94. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/bl01t-ea-test-01/values.yaml +0 -0
  95. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/bl01t-ea-test-02/Chart.yaml +0 -0
  96. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/bl01t-ea-test-02/values.yaml +0 -0
  97. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/dls-aravis/Chart.yaml +0 -0
  98. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/dls-aravis/config/ioc.yaml +0 -0
  99. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/dls-aravis/templates/configmap.yaml +0 -0
  100. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/dls-aravis/values.yaml +0 -0
  101. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/bl01t-services/services/values.yaml +0 -0
  102. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/cli.yaml +0 -0
  103. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/k8s.yaml +0 -0
  104. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/data/yaml.yaml +0 -0
  105. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/test_cli.py +0 -0
  106. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/test_demo.py +0 -0
  107. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/test_k8s.py +0 -0
  108. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/tests/test_unit.py +0 -0
  109. {edge_containers_cli-5.1.0 → edge_containers_cli-5.2.1}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: edge-containers-cli
3
- Version: 5.1.0
3
+ Version: 5.2.1
4
4
  Summary: CLI for deploying and managing epics containers IOCs and services
5
5
  Author-email: Giles Knap <giles.knap@gmail.com>
6
6
  License: Apache License
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '5.1.0'
22
- __version_tuple__ = version_tuple = (5, 1, 0)
21
+ __version__ = version = '5.2.1'
22
+ __version_tuple__ = version_tuple = (5, 2, 1)
23
23
 
24
- __commit_id__ = commit_id = 'gc92958a76'
24
+ __commit_id__ = commit_id = 'g51703ca8e'
@@ -304,7 +304,9 @@ async def start(
304
304
  autocompletion=all_svc,
305
305
  show_default=False,
306
306
  ),
307
- commit: bool = typer.Option(True, help="Commits the values to the git repo"),
307
+ commit: bool = typer.Option(
308
+ False, help="Also commit the change to the git repo for an audit trail"
309
+ ),
308
310
  ):
309
311
  """Start a service"""
310
312
  try:
@@ -323,7 +325,9 @@ async def stop(
323
325
  autocompletion=running_svc,
324
326
  show_default=False,
325
327
  ),
326
- commit: bool = typer.Option(True, help="Commits the values to the git repo"),
328
+ commit: bool = typer.Option(
329
+ False, help="Also commit the change to the git repo for an audit trail"
330
+ ),
327
331
  ):
328
332
  """Stop a service"""
329
333
  try:
@@ -75,6 +75,16 @@ async def patch_value(target: str, key: str, value: YamlTypes):
75
75
  # Rely on argocd autosync to get the cluster into the right state
76
76
 
77
77
 
78
+ async def _unset_key_and_children(target: str, key: str):
79
+ cmd_unset = f"argocd app unset {target} -p {key}"
80
+ await shell.run_command(cmd_unset, skip_on_dryrun=True)
81
+ app_patches = await get_patches(target)
82
+ for patch in app_patches:
83
+ if re.match(rf"{key}\..*", patch["name"]):
84
+ cmd_unset_child = f"argocd app unset {target} -p {patch['name']}"
85
+ await shell.run_command(cmd_unset_child, skip_on_dryrun=True)
86
+
87
+
78
88
  @do_retry
79
89
  async def push_value(target: str, key: str, value: YamlTypes):
80
90
  # Get source details
@@ -87,9 +97,8 @@ async def push_value(target: str, key: str, value: YamlTypes):
87
97
 
88
98
  await set_value(repo_url, path / "values.yaml", key, value)
89
99
 
90
- # Free a possible patched value & refresh repo
91
- cmd_unset = f"argocd app unset {target} -p {key}"
92
- await shell.run_command(cmd_unset, skip_on_dryrun=True)
100
+ # Free a possible patched value, its children & refresh repo
101
+ await _unset_key_and_children(target, key)
93
102
  cmd_refresh = f"argocd app get {target} --refresh"
94
103
  await shell.run_command(cmd_refresh, skip_on_dryrun=True)
95
104
  # Rely on argocd autosync to get the cluster into the right state
@@ -108,13 +117,7 @@ async def push_remove_key(target: str, key: str):
108
117
  await del_key(repo_url, path / "values.yaml", key)
109
118
 
110
119
  # Free a possible patched value, its children & refresh repo
111
- cmd_unset = f"argocd app unset {target} -p {key}"
112
- await shell.run_command(cmd_unset, skip_on_dryrun=True)
113
- app_patches = await get_patches(target)
114
- for patch in app_patches:
115
- if re.match(rf"{key}\..*", patch["name"]):
116
- cmd_unset_child = f"argocd app unset {target} -p {patch['name']}"
117
- await shell.run_command(cmd_unset_child, skip_on_dryrun=True)
120
+ await _unset_key_and_children(target, key)
118
121
  cmd_refresh = f"argocd app get {target} --refresh"
119
122
  await shell.run_command(cmd_refresh, skip_on_dryrun=True)
120
123
  # Rely on argocd autosync to get the cluster into the right state
@@ -200,13 +203,12 @@ class ArgoCommands(Commands):
200
203
  mani_resp = await shell.run_command(
201
204
  f"argocd app manifests {namespace}/{service_name} --source live",
202
205
  )
203
- for resource_manifest in mani_resp.split("---")[1:]:
204
- manifest = YAML(typ="safe").load(resource_manifest)
205
- if not manifest:
206
+ for manifest in YAML(typ="safe").load_all(mani_resp):
207
+ if not isinstance(manifest, dict):
206
208
  continue
207
- if manifest["kind"] not in ["StatefulSet", "Deployment"]:
209
+ if manifest.get("kind") not in ["StatefulSet", "Deployment"]:
208
210
  continue
209
- if manifest["metadata"]["name"] != service_name:
211
+ if manifest.get("metadata", {}).get("name") != service_name:
210
212
  continue
211
213
  return manifest
212
214
 
@@ -230,19 +232,17 @@ class ArgoCommands(Commands):
230
232
  async def restart(self, service_name):
231
233
  await self._check_stoppable(service_name)
232
234
  namespace, app = extract_ns_app(self.target)
233
- cmd = (
234
- f"argocd app delete-resource {namespace}/{service_name} --kind StatefulSet"
235
- )
235
+ cmd = f"argocd app delete-resource {namespace}/{service_name} --kind StatefulSet --all"
236
236
  await shell.run_command(cmd, skip_on_dryrun=True)
237
237
 
238
- async def start(self, service_name, commit=True):
238
+ async def start(self, service_name, commit=False):
239
239
  await self._check_stoppable(service_name)
240
240
  if commit:
241
241
  await push_value(self.target, f"services.{service_name}.enabled", True)
242
242
  else:
243
243
  await patch_value(self.target, f"services.{service_name}.enabled", True)
244
244
 
245
- async def stop(self, service_name, commit=True):
245
+ async def stop(self, service_name, commit=False):
246
246
  await self._check_stoppable(service_name)
247
247
  if commit:
248
248
  await push_value(self.target, f"services.{service_name}.enabled", False)
@@ -297,12 +297,11 @@ class ArgoCommands(Commands):
297
297
  mani_resp = await shell.run_command(
298
298
  f"argocd app manifests {namespace}/{name} --source live",
299
299
  )
300
- for resource_manifest in mani_resp.split("---")[1:]:
301
- manifest = YAML(typ="safe").load(resource_manifest)
302
- if not manifest:
300
+ for manifest in YAML(typ="safe").load_all(mani_resp):
301
+ if not isinstance(manifest, dict):
303
302
  continue
304
- kind = manifest["kind"]
305
- resource_name = manifest["metadata"]["name"]
303
+ kind = manifest.get("kind")
304
+ resource_name = manifest.get("metadata", {}).get("name")
306
305
  if kind in ["StatefulSet", "Deployment"] and resource_name == name:
307
306
  try:
308
307
  label = manifest["metadata"]["labels"]["description"]
@@ -5,6 +5,7 @@ utility functions
5
5
  import asyncio
6
6
  import contextlib
7
7
  import functools
8
+ import gc
8
9
  import json
9
10
  import os
10
11
  import shutil
@@ -234,15 +235,45 @@ def _run_async(coroutine: Coroutine):
234
235
  import concurrent.futures
235
236
 
236
237
  with concurrent.futures.ThreadPoolExecutor() as pool:
237
- future = pool.submit(asyncio.run, coroutine)
238
+ future = pool.submit(_run_on_new_loop, coroutine)
238
239
  ret = future.result() # blocks the worker thread, not the event loop thread
239
240
  except RuntimeError:
240
241
  # No running loop — safe to block here
241
- ret = asyncio.run(coroutine)
242
+ ret = _run_on_new_loop(coroutine)
242
243
 
243
244
  return ret
244
245
 
245
246
 
247
+ def _run_on_new_loop(coroutine: Coroutine):
248
+ """Run *coroutine* to completion on a fresh event loop, then tear the loop
249
+ down cleanly.
250
+
251
+ asyncio.Process / subprocess transports hold a reference cycle back to the
252
+ loop, so their __del__ only fires during a GC pass. If that pass happens
253
+ after the loop is closed (which is what asyncio.run() does on exit), the
254
+ finalizer schedules a callback on the closed loop and asyncio prints
255
+ "Event loop is closed" / "Loop ... that handles pid X is closed" spam.
256
+ Forcing gc.collect() while the loop is still open lets those finalizers
257
+ run against a live loop, so nothing fails.
258
+ """
259
+ loop = asyncio.new_event_loop()
260
+ try:
261
+ return loop.run_until_complete(coroutine)
262
+ finally:
263
+ try:
264
+ pending = asyncio.all_tasks(loop)
265
+ for task in pending:
266
+ task.cancel()
267
+ if pending:
268
+ loop.run_until_complete(
269
+ asyncio.gather(*pending, return_exceptions=True)
270
+ )
271
+ loop.run_until_complete(loop.shutdown_asyncgens())
272
+ gc.collect()
273
+ finally:
274
+ loop.close()
275
+
276
+
246
277
  def async_command(f):
247
278
  @functools.wraps(f)
248
279
  def wrapper(*args, **kwargs):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: edge-containers-cli
3
- Version: 5.1.0
3
+ Version: 5.2.1
4
4
  Summary: CLI for deploying and managing epics containers IOCs and services
5
5
  Author-email: Giles Knap <giles.knap@gmail.com>
6
6
  License: Apache License
@@ -113,6 +113,8 @@ deploy:
113
113
  rsp: ""
114
114
  - cmd: argocd app unset namespace/bl01t -p services.bl01t-ea-test-01
115
115
  rsp: ""
116
+ - cmd: argocd app get --show-params namespace/bl01t -o json
117
+ rsp: "{}"
116
118
  - cmd: argocd app get namespace/bl01t --refresh
117
119
  rsp: ""
118
120
 
@@ -163,6 +165,8 @@ start_commit:
163
165
  rsp: ""
164
166
  - cmd: argocd app unset namespace/bl01t -p services.bl01t-ea-test-01.enabled
165
167
  rsp: ""
168
+ - cmd: argocd app get --show-params namespace/bl01t -o json
169
+ rsp: "{}"
166
170
  - cmd: argocd app get namespace/bl01t --refresh
167
171
  rsp: ""
168
172
 
@@ -199,6 +203,8 @@ stop_commit:
199
203
  rsp: ""
200
204
  - cmd: argocd app unset namespace/bl01t -p services.bl01t-ea-test-01.enabled
201
205
  rsp: ""
206
+ - cmd: argocd app get --show-params namespace/bl01t -o json
207
+ rsp: "{}"
202
208
  - cmd: argocd app get namespace/bl01t --refresh
203
209
  rsp: ""
204
210
 
@@ -214,3 +220,85 @@ stop:
214
220
  enabled: true
215
221
  - cmd: argocd app set namespace/bl01t -p services.bl01t-ea-test-01.enabled=False
216
222
  rsp: ""
223
+
224
+ deploy_clears_override:
225
+ # Same flow as `deploy`, but the parent app has a lingering
226
+ # `services.bl01t-ea-test-01.enabled=false` parameter override (e.g. from
227
+ # an earlier `ec stop --no-commit` or Monitor's stop button). The fix
228
+ # makes push_value also unset child overrides, so the redeployed service
229
+ # actually starts.
230
+ - cmd: git clone https://github.com/epics-containers/bl01t-services /tmp/.*
231
+ rsp: Cloning into /tmp/xxxx...
232
+ - cmd: git tag --sort=committerdate
233
+ rsp: |
234
+ 1.0
235
+ 2.0
236
+ - cmd: git ls-tree -r 1.0 --name-only
237
+ rsp: |
238
+ services/bl01t-ea-test-01
239
+ - cmd: git ls-tree -r 1.0
240
+ rsp: |
241
+ 100644 blob b7b39845b55fb4d45d58ba86ef4527917877d556 services/bl01t-ea-test-01/Chart.yaml
242
+ - cmd: git diff 1.0 2.0 --name-only
243
+ rsp: ""
244
+ - cmd: git ls-tree -r 2.0
245
+ rsp: |
246
+ 100644 blob b7b39845b55fb4d45d58ba86ef4527917877d556 services/bl01t-ea-test-01/Chart.yaml
247
+ - cmd: git clone https://github.com/epics-containers/bl01t-services -b 1.0 /tmp/ec_tests
248
+ rsp: ""
249
+ - cmd: argocd app get namespace/bl01t
250
+ rsp: |
251
+ spec:
252
+ source:
253
+ repoURL: https://github.com/test/example-deployment.git
254
+ path: apps
255
+ - cmd: argocd app list --app-namespace namespace -o yaml
256
+ rsp: |
257
+ - metadata:
258
+ creationTimestamp: "2024-07-12T13:42:50Z"
259
+ name: bl01t-ea-test-01
260
+ spec:
261
+ source:
262
+ targetRevision: main
263
+ status:
264
+ resources:
265
+ - kind: StatefulSet
266
+ name: bl01t-ea-test-01
267
+ - cmd: argocd app manifests namespace/bl01t-ea-test-01 --source live
268
+ rsp: |
269
+ ---
270
+ apiVersion: apps/v1
271
+ kind: StatefulSet
272
+ metadata:
273
+ name: bl01t-ea-test-01
274
+ creationTimestamp: "2024-07-12T13:52:35Z"
275
+ labels:
276
+ test: test_label
277
+ status:
278
+ readyReplicas: 1
279
+ - cmd: argocd app get namespace/bl01t -o yaml
280
+ rsp: |
281
+ spec:
282
+ source:
283
+ repoURL: https://github.com/test/example-deployment.git
284
+ path: apps
285
+ - cmd: git clone --depth=1 https://github.com/test/example-deployment.git /tmp/ec_tests
286
+ rsp: ""
287
+ - cmd: git add .
288
+ rsp: ""
289
+ - cmd: 'git commit -m "Set services.bl01t-ea-test-01=*'
290
+ rsp: ""
291
+ - cmd: git push
292
+ rsp: ""
293
+ - cmd: argocd app unset namespace/bl01t -p services.bl01t-ea-test-01
294
+ rsp: ""
295
+ - cmd: argocd app get --show-params namespace/bl01t -o json
296
+ rsp: |
297
+ {"spec": {"source": {"helm": {"parameters": [
298
+ {"name": "services.bl01t-ea-test-01.enabled", "value": "false"},
299
+ {"name": "services.other.enabled", "value": "false"}
300
+ ]}}}}
301
+ - cmd: argocd app unset namespace/bl01t -p services.bl01t-ea-test-01.enabled
302
+ rsp: ""
303
+ - cmd: argocd app get namespace/bl01t --refresh
304
+ rsp: ""
@@ -19,6 +19,17 @@ def test_deploy(mock_run, ARGOCD, data: Path):
19
19
  mock_run.run_cli("deploy bl01t-ea-test-01")
20
20
 
21
21
 
22
+ def test_deploy_clears_enabled_override(mock_run, ARGOCD, data: Path):
23
+ # Regression: a lingering `services.X.enabled=false` parameter override
24
+ # (set by `ec stop --no-commit` or Monitor) must be unset by the next
25
+ # deploy, otherwise the redeployed service stays stopped.
26
+ mock_run.set_seq(ARGOCD.deploy_clears_override)
27
+ TMPDIR.mkdir()
28
+ shutil.copytree(data / "bl01t-services/services", TMPDIR / "services")
29
+ shutil.copytree(data / "bl01t-deployment/apps", TMPDIR / "apps")
30
+ mock_run.run_cli("deploy bl01t-ea-test-01")
31
+
32
+
22
33
  def test_logs(mock_run, ARGOCD):
23
34
  mock_run.set_seq(ARGOCD.checks + ARGOCD.logs)
24
35
  mock_run.run_cli("logs bl01t-ea-test-01")
@@ -43,19 +54,19 @@ def test_start_commit(mock_run, ARGOCD, data: Path):
43
54
 
44
55
  def test_start(mock_run, ARGOCD):
45
56
  mock_run.set_seq(ARGOCD.checks + ARGOCD.start)
46
- mock_run.run_cli("start bl01t-ea-test-01 --no-commit")
57
+ mock_run.run_cli("start bl01t-ea-test-01")
47
58
 
48
59
 
49
60
  def test_stop_commit(mock_run, ARGOCD, data: Path):
50
61
  mock_run.set_seq(ARGOCD.checks + ARGOCD.stop_commit)
51
62
  TMPDIR.mkdir()
52
63
  shutil.copytree(data / "bl01t-deployment/apps", TMPDIR / "apps")
53
- mock_run.run_cli("stop bl01t-ea-test-01")
64
+ mock_run.run_cli("stop bl01t-ea-test-01 --commit")
54
65
 
55
66
 
56
67
  def test_stop(mock_run, ARGOCD):
57
68
  mock_run.set_seq(ARGOCD.checks + ARGOCD.stop)
58
- mock_run.run_cli("stop bl01t-ea-test-01 --no-commit")
69
+ mock_run.run_cli("stop bl01t-ea-test-01")
59
70
 
60
71
 
61
72
  def test_ps(mock_run, ARGOCD):