edge-containers-cli 3.4.1__tar.gz → 3.5.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.
Files changed (108) hide show
  1. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/workflows/_release.yml +1 -1
  2. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.pre-commit-config.yaml +1 -1
  3. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/PKG-INFO +2 -1
  4. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/pyproject.toml +1 -0
  5. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/_version.py +2 -2
  6. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/autocomplete.py +8 -8
  7. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/cmds/cli.py +59 -58
  8. edge_containers_cli-3.5.0/src/edge_containers_cli/cmds/commands.py +86 -0
  9. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/cmds/helm.py +10 -5
  10. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/cmds/k8s_commands.py +35 -49
  11. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/cmds/local_commands.py +28 -49
  12. edge_containers_cli-3.5.0/src/edge_containers_cli/cmds/monitor.py +285 -0
  13. edge_containers_cli-3.5.0/src/edge_containers_cli/cmds/monitor.tcss +45 -0
  14. edge_containers_cli-3.5.0/src/edge_containers_cli/git.py +116 -0
  15. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli.egg-info/PKG-INFO +2 -1
  16. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli.egg-info/SOURCES.txt +3 -0
  17. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli.egg-info/requires.txt +1 -0
  18. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/autocomplete.yaml +4 -0
  19. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/ioc.yaml +15 -8
  20. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/local.yaml +10 -4
  21. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/test_ioc.py +1 -1
  22. edge-containers-cli-3.4.1/src/edge_containers_cli/git.py +0 -71
  23. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.copier-answers.yml +0 -0
  24. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.devcontainer/devcontainer.json +0 -0
  25. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/CONTRIBUTING.md +0 -0
  26. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/actions/install_requirements/action.yml +0 -0
  27. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/dependabot.yml +0 -0
  28. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/pages/index.html +0 -0
  29. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/pages/make_switcher.py +0 -0
  30. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/workflows/_check.yml +0 -0
  31. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/workflows/_dist.yml +0 -0
  32. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/workflows/_pypi.yml +0 -0
  33. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/workflows/_sys_test.yml +0 -0
  34. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/workflows/_test.yml +0 -0
  35. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/workflows/_tox.yml +0 -0
  36. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.github/workflows/ci.yml +0 -0
  37. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.gitignore +0 -0
  38. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.vscode/extensions.json +0 -0
  39. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.vscode/launch.json +0 -0
  40. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.vscode/settings.json +0 -0
  41. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/.vscode/tasks.json +0 -0
  42. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/Dockerfile +0 -0
  43. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/LICENSE +0 -0
  44. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/README.md +0 -0
  45. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/catalog-info.yaml +0 -0
  46. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/conf.py +0 -0
  47. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/explanations/decisions/0001-record-architecture-decisions.rst +0 -0
  48. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst +0 -0
  49. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/explanations/decisions.rst +0 -0
  50. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/how-to/build-docs.rst +0 -0
  51. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/how-to/contribute.rst +0 -0
  52. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/how-to/lint.rst +0 -0
  53. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/how-to/make-release.rst +0 -0
  54. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/how-to/pin-requirements.rst +0 -0
  55. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/how-to/run-tests.rst +0 -0
  56. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/how-to/static-analysis.rst +0 -0
  57. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/how-to/test-container.rst +0 -0
  58. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/how-to/update-tools.rst +0 -0
  59. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/index.rst +0 -0
  60. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/reference/standards.rst +0 -0
  61. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/developer/tutorials/dev-install.rst +0 -0
  62. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/genindex.rst +0 -0
  63. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/images/dls-favicon.ico +0 -0
  64. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/images/dls-logo.svg +0 -0
  65. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/index.rst +0 -0
  66. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/user/explanations/docs-structure.rst +0 -0
  67. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/user/how-to/run-container.rst +0 -0
  68. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/user/index.rst +0 -0
  69. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/user/reference/api.rst +0 -0
  70. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/docs/user/tutorials/installation.rst +0 -0
  71. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/setup.cfg +0 -0
  72. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/__init__.py +0 -0
  73. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/__main__.py +0 -0
  74. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/cmds/__init__.py +0 -0
  75. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/cmds/kubectl.py +0 -0
  76. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/docker.py +0 -0
  77. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/globals.py +0 -0
  78. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/logging.py +0 -0
  79. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/shell.py +0 -0
  80. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli/utils.py +0 -0
  81. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli.egg-info/dependency_links.txt +0 -0
  82. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli.egg-info/entry_points.txt +0 -0
  83. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/src/edge_containers_cli.egg-info/top_level.txt +0 -0
  84. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/__init__.py +0 -0
  85. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/conftest.py +0 -0
  86. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/.copier-answers.yml +0 -0
  87. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/.github/dependabot.yml +0 -0
  88. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/.github/workflows/ci_verify.sh +0 -0
  89. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/.github/workflows/verify.yml +0 -0
  90. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/.gitignore +0 -0
  91. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/LICENSE +0 -0
  92. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/README.md +0 -0
  93. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/environment.sh +0 -0
  94. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/helm/shared/Chart.yaml +0 -0
  95. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/helm/shared/README.md +0 -0
  96. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/helm/shared/values.yaml +0 -0
  97. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/include/iocs/Chart.yaml +0 -0
  98. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/include/iocs/templates/configmap.yaml +0 -0
  99. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/services/bl01t-ea-test-01/Chart.yaml +0 -0
  100. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/services/bl01t-ea-test-01/config/ioc.db +0 -0
  101. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/services/bl01t-ea-test-01/config/ioc.yaml +0 -0
  102. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/services/bl01t-ea-test-01/pretend_helm.tgz +0 -0
  103. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/services/bl01t-ea-test-01/values.yaml +0 -0
  104. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/data/bl01t/update-helm +0 -0
  105. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/test_autocomplete.py +0 -0
  106. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/test_cli.py +0 -0
  107. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/test_local.py +0 -0
  108. {edge-containers-cli-3.4.1 → edge_containers_cli-3.5.0}/tests/test_system.py +0 -0
@@ -23,7 +23,7 @@ jobs:
23
23
  - name: Create GitHub Release
24
24
  # We pin to the SHA, not the tag, for security reasons.
25
25
  # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
26
- uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v0.1.15
26
+ uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # v0.1.15
27
27
  with:
28
28
  prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
29
29
  files: "*"
@@ -1,6 +1,6 @@
1
1
  repos:
2
2
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
- rev: v4.5.0
3
+ rev: v4.6.0
4
4
  hooks:
5
5
  - id: check-added-large-files
6
6
  - id: check-yaml
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edge-containers-cli
3
- Version: 3.4.1
3
+ Version: 3.5.0
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
@@ -220,6 +220,7 @@ Requires-Dist: requests
220
220
  Requires-Dist: ruamel.yaml
221
221
  Requires-Dist: jinja2
222
222
  Requires-Dist: polars
223
+ Requires-Dist: textual
223
224
  Provides-Extra: dev
224
225
  Requires-Dist: copier; extra == "dev"
225
226
  Requires-Dist: pipdeptree; extra == "dev"
@@ -20,6 +20,7 @@ dependencies = [
20
20
  "ruamel.yaml",
21
21
  "jinja2",
22
22
  "polars",
23
+ "textual",
23
24
  ]
24
25
 
25
26
  dynamic = ["version"]
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '3.4.1'
16
- __version_tuple__ = version_tuple = (3, 4, 1)
15
+ __version__ = version = '3.5.0'
16
+ __version_tuple__ = version_tuple = (3, 5, 0)
@@ -12,7 +12,7 @@ import edge_containers_cli.globals as globals
12
12
  import edge_containers_cli.shell as shell
13
13
  from edge_containers_cli.cmds.k8s_commands import check_namespace
14
14
  from edge_containers_cli.docker import Docker
15
- from edge_containers_cli.git import create_svc_graph
15
+ from edge_containers_cli.git import create_version_map
16
16
  from edge_containers_cli.logging import log
17
17
  from edge_containers_cli.utils import cleanup_temp
18
18
 
@@ -46,14 +46,14 @@ def read_cached_dict(cache_folder: str, cached_file: str) -> dict:
46
46
 
47
47
 
48
48
  def fetch_service_graph(beamline_repo: str) -> dict:
49
- svc_graph = read_cached_dict(url_encode(beamline_repo), globals.IOC_CACHE)
50
- if not svc_graph:
49
+ version_map = read_cached_dict(url_encode(beamline_repo), globals.IOC_CACHE)
50
+ if not version_map:
51
51
  tmp_dir = Path(tempfile.mkdtemp())
52
- svc_graph = create_svc_graph(beamline_repo, tmp_dir)
53
- cache_dict(url_encode(beamline_repo), globals.IOC_CACHE, svc_graph)
52
+ version_map = create_version_map(beamline_repo, tmp_dir)
53
+ cache_dict(url_encode(beamline_repo), globals.IOC_CACHE, version_map)
54
54
  cleanup_temp(tmp_dir)
55
55
 
56
- return svc_graph
56
+ return version_map
57
57
 
58
58
 
59
59
  def avail_services(ctx: typer.Context) -> list[str]:
@@ -77,8 +77,8 @@ def avail_versions(ctx: typer.Context) -> list[str]:
77
77
 
78
78
  # This block prevents getting a stack trace during autocompletion
79
79
  try:
80
- svc_graph = fetch_service_graph(beamline_repo)
81
- svc_versions = svc_graph[service_name]
80
+ version_map = fetch_service_graph(beamline_repo)
81
+ svc_versions = version_map[service_name]
82
82
  return svc_versions
83
83
  except KeyError:
84
84
  log.error("IOC not found")
@@ -15,11 +15,34 @@ from edge_containers_cli.autocomplete import (
15
15
  )
16
16
  from edge_containers_cli.cmds.k8s_commands import K8sCommands
17
17
  from edge_containers_cli.cmds.local_commands import LocalCommands
18
- from edge_containers_cli.git import create_svc_graph
18
+ from edge_containers_cli.cmds.monitor import MonitorApp
19
+ from edge_containers_cli.git import create_version_map
20
+ from edge_containers_cli.globals import EC_K8S_NAMESPACE
19
21
  from edge_containers_cli.logging import log
20
22
  from edge_containers_cli.utils import cleanup_temp, drop_path
21
23
 
22
- cli = typer.Typer(pretty_exceptions_show_locals=False)
24
+
25
+ class ErrorHandlingTyper(typer.Typer):
26
+ def __call__(self, *args, **kwargs):
27
+ try:
28
+ super().__call__(*args, **kwargs)
29
+ except NotImplementedError:
30
+ typer.echo("This function is not available for the current namespace")
31
+
32
+
33
+ cli = ErrorHandlingTyper(pretty_exceptions_show_locals=False)
34
+
35
+
36
+ def commands(ctx):
37
+ """
38
+ Construct the appropriate Commands class for the local or K8S namespace
39
+ """
40
+ if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
41
+ commands = LocalCommands(ctx.obj)
42
+ else:
43
+ commands = K8sCommands(ctx.obj)
44
+
45
+ return commands
23
46
 
24
47
 
25
48
  @cli.command()
@@ -33,10 +56,20 @@ def ps(
33
56
  ),
34
57
  ):
35
58
  """List the IOCs/services running in the current namespace"""
36
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
37
- LocalCommands(ctx.obj).ps(all, wide)
38
- else:
39
- K8sCommands(ctx.obj).ps(all, wide)
59
+ commands(ctx).ps(all, wide)
60
+
61
+
62
+ @cli.command()
63
+ def monitor(
64
+ ctx: typer.Context,
65
+ all: bool = typer.Option(
66
+ False, "-a", "--all", help="list stopped IOCs/services as well as running ones"
67
+ ),
68
+ ):
69
+ """Open IOC monitor TUI."""
70
+ cmds = commands(ctx)
71
+ app = MonitorApp(EC_K8S_NAMESPACE, cmds, all)
72
+ app.run()
40
73
 
41
74
 
42
75
  @cli.command()
@@ -47,7 +80,7 @@ def env(
47
80
  ),
48
81
  ):
49
82
  """List all relevant environment variables"""
50
- LocalCommands(ctx.obj).environment(verbose == verbose)
83
+ commands(ctx).environment(verbose == verbose)
51
84
 
52
85
 
53
86
  @cli.command()
@@ -60,10 +93,7 @@ def attach(
60
93
  """
61
94
  Attach to the console of a live service
62
95
  """
63
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
64
- LocalCommands(ctx.obj, service_name).attach()
65
- else:
66
- K8sCommands(ctx.obj, service_name).attach()
96
+ commands(ctx).attach(service_name)
67
97
 
68
98
 
69
99
  @cli.command()
@@ -76,10 +106,7 @@ def delete(
76
106
  """
77
107
  Remove a helm deployment from the cluster
78
108
  """
79
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
80
- LocalCommands(ctx.obj, service_name).delete()
81
- else:
82
- K8sCommands(ctx.obj, service_name).delete()
109
+ commands(ctx).delete(service_name)
83
110
 
84
111
 
85
112
  @cli.command()
@@ -99,10 +126,7 @@ def template(
99
126
  print out the helm template generated from a local service instance
100
127
  """
101
128
  args = f"{args} --debug"
102
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
103
- typer.echo("Not applicable to local deployments")
104
- else:
105
- K8sCommands(ctx.obj).template(svc_instance, args)
129
+ commands(ctx).template(svc_instance, args)
106
130
 
107
131
 
108
132
  @cli.command()
@@ -123,11 +147,7 @@ def deploy_local(
123
147
  """
124
148
  Deploy a local IOC/service helm chart directly to the cluster with dated beta version
125
149
  """
126
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
127
- LocalCommands(ctx.obj).deploy_local(svc_instance, yes, args)
128
- else:
129
- args = args if not wait else args + " --wait"
130
- K8sCommands(ctx.obj).deploy_local(svc_instance, yes, args)
150
+ commands(ctx).deploy_local(svc_instance, yes, args)
131
151
 
132
152
 
133
153
  @cli.command()
@@ -149,14 +169,9 @@ def deploy(
149
169
  """
150
170
  Pull an IOC/service helm chart version from the domain repo and deploy it to the cluster
151
171
  """
172
+ args = args if not wait else args + " --wait"
152
173
  service_name = drop_path(service_name)
153
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
154
- LocalCommands(ctx.obj, service_name).deploy(service_name, version, args)
155
- else:
156
- args = args if not wait else args + " --wait"
157
- K8sCommands(ctx.obj, service_name, check=False).deploy(
158
- service_name, version, args
159
- )
174
+ commands(ctx).deploy(service_name, version, args)
160
175
 
161
176
 
162
177
  @cli.command()
@@ -165,11 +180,11 @@ def list(
165
180
  ):
166
181
  """List all IOCs/services available in the helm registry"""
167
182
  tmp_dir = Path(tempfile.mkdtemp())
168
- svc_graph = create_svc_graph(ctx.obj.beamline_repo, tmp_dir)
169
- svc_list = natsorted(svc_graph.keys())
170
- log.debug(f"svc_graph = {svc_graph}")
183
+ version_map = create_version_map(ctx.obj.beamline_repo, tmp_dir)
184
+ svc_list = natsorted(version_map.keys())
185
+ log.debug(f"version_map = {version_map}")
171
186
 
172
- versions = [natsorted(svc_graph[svc])[-1] for svc in svc_list]
187
+ versions = [natsorted(version_map[svc])[-1] for svc in svc_list]
173
188
  services_df = polars.from_dict({"name": svc_list, "version": versions})
174
189
  print(services_df)
175
190
 
@@ -185,9 +200,9 @@ def instances(
185
200
  ):
186
201
  """List all versions of the IOC/service available in the helm registry"""
187
202
  tmp_dir = Path(tempfile.mkdtemp())
188
- svc_graph = create_svc_graph(ctx.obj.beamline_repo, tmp_dir)
203
+ version_map = create_version_map(ctx.obj.beamline_repo, tmp_dir)
189
204
  try:
190
- svc_list = svc_graph[service_name]
205
+ svc_list = version_map[service_name]
191
206
  except KeyError:
192
207
  svc_list = []
193
208
 
@@ -208,14 +223,12 @@ def exec(
208
223
  ),
209
224
  ):
210
225
  """Execute a bash prompt in a running container"""
211
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
212
- LocalCommands(ctx.obj, service_name).exec()
213
- else:
214
- K8sCommands(ctx.obj, service_name).exec()
226
+ commands(ctx).exec(service_name)
215
227
 
216
228
 
217
229
  @cli.command()
218
230
  def log_history(
231
+ ctx: typer.Context,
219
232
  service_name: str = typer.Argument(
220
233
  ...,
221
234
  help="Name of the IOC/service to inspect",
@@ -223,7 +236,7 @@ def log_history(
223
236
  ),
224
237
  ):
225
238
  """Open historical logs for an IOC/service"""
226
- K8sCommands(None, service_name).log_history()
239
+ commands(ctx).log_history(service_name)
227
240
 
228
241
 
229
242
  @cli.command()
@@ -241,10 +254,7 @@ def logs(
241
254
  follow: bool = typer.Option(False, "--follow", "-f", help="Follow the log stream"),
242
255
  ):
243
256
  """Show logs for current and previous instances of an IOC/service"""
244
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
245
- LocalCommands(ctx.obj, service_name).logs(prev, follow)
246
- else:
247
- K8sCommands(ctx.obj, service_name).logs(prev, follow)
257
+ commands(ctx).logs(service_name, prev, follow)
248
258
 
249
259
 
250
260
  @cli.command()
@@ -255,10 +265,7 @@ def restart(
255
265
  ),
256
266
  ):
257
267
  """Restart an IOC/service"""
258
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
259
- LocalCommands(ctx.obj, service_name).restart()
260
- else:
261
- K8sCommands(ctx.obj, service_name).restart()
268
+ commands(ctx).restart(service_name)
262
269
 
263
270
 
264
271
  @cli.command()
@@ -270,10 +277,7 @@ def start(
270
277
  ):
271
278
  """Start an IOC/service"""
272
279
  log.debug("Starting IOC/service with LOCAL={ctx.obj.namespace == " "}")
273
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
274
- LocalCommands(ctx.obj, service_name).start()
275
- else:
276
- K8sCommands(ctx.obj, service_name).start()
280
+ commands(ctx).start(service_name)
277
281
 
278
282
 
279
283
  @cli.command()
@@ -286,10 +290,7 @@ def stop(
286
290
  ),
287
291
  ):
288
292
  """Stop an IOC/service"""
289
- if ctx.obj.namespace == globals.LOCAL_NAMESPACE:
290
- LocalCommands(ctx.obj, service_name).stop()
291
- else:
292
- K8sCommands(ctx.obj, service_name).stop()
293
+ commands(ctx).stop(service_name)
293
294
 
294
295
 
295
296
  @cli.command()
@@ -0,0 +1,86 @@
1
+ import webbrowser
2
+ from pathlib import Path
3
+
4
+ import polars
5
+ import typer
6
+
7
+ import edge_containers_cli.globals as globals
8
+ import edge_containers_cli.shell as shell
9
+ from edge_containers_cli.logging import log
10
+
11
+
12
+ class Commands:
13
+ """
14
+ A base class for K8SCommands and LocalCommands
15
+
16
+ Implements the common functionality but defers specialist functions to
17
+ the subclasss
18
+
19
+ Allows the CLI or the TUI to call functions without worrying about local
20
+ vs Kubernetes containers
21
+ """
22
+
23
+ def __init__(self, ctx: globals.Context):
24
+ self.namespace = ctx.namespace
25
+ self.beamline_repo = ctx.beamline_repo
26
+
27
+ def attach(self, service_name):
28
+ raise NotImplementedError
29
+
30
+ def delete(self, service_name):
31
+ raise NotImplementedError
32
+
33
+ def template(self, svc_instance: Path, args: str):
34
+ raise NotImplementedError
35
+
36
+ def deploy_local(self, svc_instance: Path, yes: bool, args: str):
37
+ raise NotImplementedError
38
+
39
+ def deploy(self, service_name: str, version: str, args: str):
40
+ raise NotImplementedError
41
+
42
+ def exec(self, service_name: str):
43
+ raise NotImplementedError
44
+
45
+ def logs(self, service_name: str, prev: bool, follow: bool):
46
+ raise NotImplementedError
47
+
48
+ def restart(self, service_name: str):
49
+ raise NotImplementedError
50
+
51
+ def start(self, service_name: str):
52
+ raise NotImplementedError
53
+
54
+ def stop(self, service_name: str):
55
+ raise NotImplementedError
56
+
57
+ def get_services(self, all: bool) -> polars.DataFrame:
58
+ raise NotImplementedError
59
+
60
+ def ps(self, all: bool, wide: bool):
61
+ select_data = self.get_services(all)
62
+ if not wide:
63
+ select_data.drop_in_place("image")
64
+ print(select_data)
65
+
66
+ def environment(self, verbose: bool):
67
+ """
68
+ declare the environment settings for ec
69
+ """
70
+ ns = self.namespace
71
+
72
+ if ns == globals.LOCAL_NAMESPACE:
73
+ typer.echo("ioc commands deploy to the local docker/podman instance")
74
+ else:
75
+ typer.echo(f"ioc commands deploy to the {ns} namespace the K8S cluster")
76
+
77
+ typer.echo("\nEC environment variables:")
78
+ shell.run_command("env | grep '^EC_'", interactive=False, show=True)
79
+
80
+ def log_history(self, service_name):
81
+ if not globals.EC_LOG_URL:
82
+ log.error("EC_LOG_URL environment not set")
83
+ raise typer.Exit(1)
84
+
85
+ url = globals.EC_LOG_URL.format(service_name=service_name)
86
+ webbrowser.open(url)
@@ -3,6 +3,7 @@ from pathlib import Path
3
3
  from typing import Optional
4
4
 
5
5
  import typer
6
+ from ruamel.yaml import YAML
6
7
 
7
8
  import edge_containers_cli.globals as globals
8
9
  import edge_containers_cli.shell as shell
@@ -92,15 +93,19 @@ class Helm:
92
93
 
93
94
  with chdir(service_folder):
94
95
  shell.run_command(
95
- f"helm dependency update {service_folder}; "
96
- f"helm package {service_folder} --app-version {self.version}",
96
+ f"helm package {service_folder} -u --app-version {self.version}",
97
97
  interactive=False,
98
98
  )
99
- # find the packaged chart
100
- chart_file = list(service_folder.glob("*.tgz"))[0]
99
+
100
+ # Determine package name
101
+ with open("Chart.yaml") as fp:
102
+ chart_yaml = YAML(typ="safe").load(fp)
103
+ package_path = (
104
+ service_folder / f'{chart_yaml["name"]}-{chart_yaml["version"]}.tgz'
105
+ )
101
106
 
102
107
  # use helm to install the chart
103
- self._install(chart_file)
108
+ self._install(package_path)
104
109
 
105
110
  def _install(self, helm_chart: Path):
106
111
  """
@@ -4,7 +4,6 @@ implements commands for deploying and managing service instances in the k8s clus
4
4
  Relies on the Helm class for deployment aspects.
5
5
  """
6
6
 
7
- import webbrowser
8
7
  from datetime import datetime
9
8
  from io import StringIO
10
9
  from pathlib import Path
@@ -15,6 +14,7 @@ import typer
15
14
 
16
15
  import edge_containers_cli.globals as globals
17
16
  import edge_containers_cli.shell as shell
17
+ from edge_containers_cli.cmds.commands import Commands
18
18
  from edge_containers_cli.cmds.helm import Helm
19
19
  from edge_containers_cli.cmds.kubectl import jsonpath_deploy_info, jsonpath_pod_info
20
20
  from edge_containers_cli.logging import log
@@ -59,43 +59,35 @@ def check_namespace(namespace: Optional[str]):
59
59
  log.info("domain = %s", namespace)
60
60
 
61
61
 
62
- class K8sCommands:
62
+ class K8sCommands(Commands):
63
63
  """
64
64
  A class for implementing the Kubernetes based commands
65
65
  """
66
66
 
67
67
  def __init__(
68
68
  self,
69
- ctx: Optional[globals.Context],
70
- service_name: str = "",
71
- check: bool = True,
69
+ ctx: globals.Context,
70
+ # check: bool = True,
72
71
  ):
73
- self.namespace: str = ""
74
- self.beamline_repo: str = ""
75
- # TODO isnt ctx always set??
76
- if ctx is not None:
77
- namespace = ctx.namespace
78
- check_namespace(namespace)
79
- if service_name != "" and check:
80
- self.fullname = check_service(service_name, namespace)
81
- self.namespace = namespace
82
- self.beamline_repo = ctx.beamline_repo
83
- self.service_name: str = service_name
84
-
85
- def attach(self):
72
+ super().__init__(ctx)
73
+ check_namespace(self.namespace)
74
+
75
+ def attach(self, service_name):
76
+ fullname = check_service(service_name, self.namespace)
86
77
  shell.run_command(
87
- f"kubectl -it -n {self.namespace} attach {self.fullname}",
78
+ f"kubectl -it -n {self.namespace} attach {fullname}",
88
79
  interactive=True,
89
80
  )
90
81
 
91
- def delete(self):
82
+ def delete(self, service_name):
83
+ check_service(service_name, self.namespace)
92
84
  if not typer.confirm(
93
- f"This will remove all versions of {self.service_name} "
85
+ f"This will remove all versions of {service_name} "
94
86
  "from the cluster. Are you sure ?"
95
87
  ):
96
88
  raise typer.Abort()
97
89
 
98
- shell.run_command(f"helm delete -n {self.namespace} {self.service_name}")
90
+ shell.run_command(f"helm delete -n {self.namespace} {service_name}")
99
91
 
100
92
  def template(self, svc_instance: Path, args: str):
101
93
  datetime.strftime(datetime.now(), "%Y.%-m.%-d-b%-H.%-M")
@@ -127,48 +119,37 @@ class K8sCommands:
127
119
  )
128
120
  chart.deploy()
129
121
 
130
- def exec(self):
131
- shell.run_command(
132
- f"kubectl -it -n {self.namespace} exec {self.fullname} -- bash"
133
- )
134
-
135
- def log_history(self):
136
- if not globals.EC_LOG_URL:
137
- log.error("EC_LOG_URL environment not set")
138
- raise typer.Exit(1)
122
+ def exec(self, service_name):
123
+ fullname = check_service(service_name, self.namespace)
124
+ shell.run_command(f"kubectl -it -n {self.namespace} exec {fullname} -- bash")
139
125
 
140
- url = globals.EC_LOG_URL.format(service_name=self.service_name)
141
- webbrowser.open(url)
142
-
143
- def logs(self, prev: bool, follow: bool):
126
+ def logs(self, service_name: str, prev: bool, follow: bool):
127
+ fullname = check_service(service_name, self.namespace)
144
128
  previous = "-p" if prev else ""
145
129
  fol = "-f" if follow else ""
146
130
 
147
131
  shell.run_command(
148
- f"kubectl -n {self.namespace} logs {self.fullname} {previous} {fol}"
132
+ f"kubectl -n {self.namespace} logs {fullname} {previous} {fol}"
149
133
  )
150
134
 
151
- def restart(self):
135
+ def restart(self, service_name):
136
+ check_service(service_name, self.namespace)
152
137
  pod_name = shell.run_command(
153
- f"kubectl get -n {self.namespace} pod -l app={self.service_name} -o name",
138
+ f"kubectl get -n {self.namespace} pod -l app={service_name} -o name",
154
139
  interactive=False,
155
140
  )
156
141
  shell.run_command(f"kubectl delete -n {self.namespace} {pod_name}")
157
142
 
158
- def start(self):
159
- shell.run_command(
160
- f"kubectl scale -n {self.namespace} {self.fullname} --replicas=1"
161
- )
143
+ def start(self, service_name):
144
+ fullname = check_service(service_name, self.namespace)
145
+ shell.run_command(f"kubectl scale -n {self.namespace} {fullname} --replicas=1")
162
146
 
163
- def stop(self):
147
+ def stop(self, service_name):
148
+ fullname = check_service(service_name, self.namespace)
164
149
  """Stop an IOC"""
165
- shell.run_command(
166
- f"kubectl scale -n {self.namespace} {self.fullname} --replicas=0 "
167
- )
168
-
169
- def ps(self, all: bool, wide: bool):
170
- """List all IOCs and Services in the current namespace"""
150
+ shell.run_command(f"kubectl scale -n {self.namespace} {fullname} --replicas=0 ")
171
151
 
152
+ def get_services(self, all: bool) -> polars.DataFrame:
172
153
  services_df = polars.DataFrame()
173
154
 
174
155
  # Gives all services (running & not running) and their image
@@ -232,6 +213,11 @@ class K8sCommands:
232
213
  if not all:
233
214
  services_df = services_df.filter(polars.col("running").eq(True))
234
215
  log.debug(services_df)
216
+ return services_df
217
+
218
+ def ps(self, all: bool, wide: bool):
219
+ """List all IOCs and Services in the current namespace"""
220
+ services_df = self.get_services(all)
235
221
  if not wide:
236
222
  services_df.drop_in_place("image")
237
223
  log.debug(services_df)