edge-containers-cli 4.1.0__tar.gz → 4.1.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 (107) hide show
  1. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.copier-answers.yml +3 -3
  2. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.devcontainer/devcontainer.json +1 -1
  3. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/CONTRIBUTING.md +1 -1
  4. edge_containers_cli-4.1.1/.github/ISSUE_TEMPLATE/bug_report.md +21 -0
  5. edge_containers_cli-4.1.1/.github/ISSUE_TEMPLATE/issue.md +13 -0
  6. edge_containers_cli-4.1.1/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +8 -0
  7. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/pages/index.html +1 -1
  8. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/pages/make_switcher.py +7 -3
  9. edge_containers_cli-4.1.1/.github/workflows/_container.yml +60 -0
  10. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/workflows/_pypi.yml +0 -5
  11. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/workflows/_release.yml +1 -1
  12. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/workflows/ci.yml +8 -2
  13. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.gitignore +1 -0
  14. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.pre-commit-config.yaml +1 -0
  15. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.vscode/extensions.json +1 -1
  16. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.vscode/launch.json +6 -2
  17. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.vscode/settings.json +2 -1
  18. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.vscode/tasks.json +1 -1
  19. edge_containers_cli-4.1.1/Dockerfile +31 -0
  20. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/PKG-INFO +2 -2
  21. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/README.md +1 -1
  22. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/explanations/decisions.rst +1 -1
  23. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/how-to/make-release.rst +1 -1
  24. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/images/dls-logo.svg +1 -1
  25. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/pyproject.toml +18 -10
  26. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/_version.py +2 -2
  27. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/autocomplete.py +2 -2
  28. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/backend.py +8 -4
  29. edge_containers_cli-4.1.1/src/edge_containers_cli/cmds/demo_commands.py +135 -0
  30. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/cmds/monitor.py +4 -4
  31. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/cmds/monitor.tcss +1 -1
  32. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/definitions.py +1 -0
  33. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli.egg-info/PKG-INFO +2 -2
  34. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli.egg-info/SOURCES.txt +6 -1
  35. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/conftest.py +10 -0
  36. edge_containers_cli-4.1.1/tests/test_demo.py +32 -0
  37. edge_containers_cli-4.1.0/Dockerfile +0 -13
  38. edge_containers_cli-4.1.0/catalog-info.yaml +0 -10
  39. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/actions/install_requirements/action.yml +0 -0
  40. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/dependabot.yml +0 -0
  41. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/workflows/_check.yml +0 -0
  42. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/workflows/_dist.yml +0 -0
  43. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/workflows/_test.yml +0 -0
  44. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/.github/workflows/_tox.yml +0 -0
  45. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/LICENSE +0 -0
  46. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/conf.py +0 -0
  47. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/explanations/decisions/0001-record-architecture-decisions.rst +0 -0
  48. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst +0 -0
  49. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/how-to/build-docs.rst +0 -0
  50. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/how-to/contribute.rst +0 -0
  51. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/how-to/lint.rst +0 -0
  52. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/how-to/pin-requirements.rst +0 -0
  53. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/how-to/run-tests.rst +0 -0
  54. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/how-to/static-analysis.rst +0 -0
  55. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/how-to/test-container.rst +0 -0
  56. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/how-to/update-tools.rst +0 -0
  57. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/index.rst +0 -0
  58. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/reference/standards.rst +0 -0
  59. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/developer/tutorials/dev-install.rst +0 -0
  60. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/genindex.rst +0 -0
  61. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/images/dls-favicon.ico +0 -0
  62. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/index.rst +0 -0
  63. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/user/explanations/docs-structure.rst +0 -0
  64. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/user/how-to/run-container.rst +0 -0
  65. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/user/index.rst +0 -0
  66. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/user/reference/api.rst +0 -0
  67. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/docs/user/tutorials/installation.rst +0 -0
  68. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/setup.cfg +0 -0
  69. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/__init__.py +0 -0
  70. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/__main__.py +0 -0
  71. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/cli.py +0 -0
  72. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/cmds/__init__.py +0 -0
  73. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/cmds/argo_commands.py +0 -0
  74. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/cmds/commands.py +0 -0
  75. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/cmds/helm.py +0 -0
  76. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/cmds/k8s_commands.py +0 -0
  77. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/git.py +0 -0
  78. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/globals.py +0 -0
  79. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/logging.py +0 -0
  80. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/shell.py +0 -0
  81. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli/utils.py +0 -0
  82. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli.egg-info/dependency_links.txt +0 -0
  83. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli.egg-info/entry_points.txt +0 -0
  84. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli.egg-info/requires.txt +0 -0
  85. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/src/edge_containers_cli.egg-info/top_level.txt +0 -0
  86. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/__init__.py +0 -0
  87. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/argocd.yaml +0 -0
  88. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-deployment/apps/values.yaml +0 -0
  89. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/bl01t-ea-test-01/Chart.yaml +0 -0
  90. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/bl01t-ea-test-01/config/ioc.db +0 -0
  91. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/bl01t-ea-test-01/config/ioc.yaml +0 -0
  92. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/bl01t-ea-test-01/templates/configmap.yaml +0 -0
  93. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/bl01t-ea-test-01/values.yaml +0 -0
  94. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/bl01t-ea-test-02/Chart.yaml +0 -0
  95. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/bl01t-ea-test-02/values.yaml +0 -0
  96. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/dls-aravis/Chart.yaml +0 -0
  97. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/dls-aravis/config/ioc.yaml +0 -0
  98. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/dls-aravis/templates/configmap.yaml +0 -0
  99. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/dls-aravis/values.yaml +0 -0
  100. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/bl01t-services/services/values.yaml +0 -0
  101. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/cli.yaml +0 -0
  102. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/k8s.yaml +0 -0
  103. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/data/yaml.yaml +0 -0
  104. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/test_argocd.py +0 -0
  105. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/test_cli.py +0 -0
  106. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/test_k8s.py +0 -0
  107. {edge_containers_cli-4.1.0 → edge_containers_cli-4.1.1}/tests/test_unit.py +0 -0
@@ -1,15 +1,15 @@
1
1
  # Changes here will be overwritten by Copier
2
- _commit: 1.3.0
2
+ _commit: 2.3.0
3
3
  _src_path: gh:DiamondLightSource/python-copier-template
4
4
  author_email: giles.knap@gmail.com
5
5
  author_name: Giles Knap
6
- component_owner: group:default/sscc
7
6
  description: CLI for deploying and managing epics containers IOCs and services
8
7
  distribution_name: edge-containers-cli
9
- docker: false
8
+ docker: true
10
9
  docs_type: README
11
10
  git_platform: github.com
12
11
  github_org: epics-containers
13
12
  package_name: edge_containers_cli
13
+ pypi: true
14
14
  repo_name: edge-containers-cli
15
15
  type_checker: pyright
@@ -43,4 +43,4 @@
43
43
  "workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind",
44
44
  // After the container is created, install the python project in editable form
45
45
  "postCreateCommand": "pip install $([ -f dev-requirements.txt ] && echo '-c dev-requirements.txt') -e '.[dev]' && pre-commit install"
46
- }
46
+ }
@@ -24,4 +24,4 @@ It is recommended that developers use a [vscode devcontainer](https://code.visua
24
24
 
25
25
  This project was created using the [Diamond Light Source Copier Template](https://github.com/DiamondLightSource/python-copier-template) for Python projects.
26
26
 
27
- For more information on common tasks like setting up a developer environment, running the tests, and setting a pre-commit hook, see the template's [How-to guides](https://diamondlightsource.github.io/python-copier-template/1.3.0/how-to.html).
27
+ For more information on common tasks like setting up a developer environment, running the tests, and setting a pre-commit hook, see the template's [How-to guides](https://diamondlightsource.github.io/python-copier-template/2.3.0/how-to.html).
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: Bug Report
3
+ about: The template to use for reporting bugs and usability issues
4
+ title: " "
5
+ labels: 'bug'
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ Describe the bug, including a clear and concise description of the expected behavior, the actual behavior and the context in which you encountered it (ideally include details of your environment).
11
+
12
+ ## Steps To Reproduce
13
+ Steps to reproduce the behavior:
14
+ 1. Go to '...'
15
+ 2. Click on '....'
16
+ 3. Scroll down to '....'
17
+ 4. See error
18
+
19
+
20
+ ## Acceptance Criteria
21
+ - Specific criteria that will be used to judge if the issue is fixed
@@ -0,0 +1,13 @@
1
+ ---
2
+ name: Issue
3
+ about: The standard template to use for feature requests, design discussions and tasks
4
+ title: " "
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ A brief description of the issue, including specific stakeholders and the business case where appropriate
11
+
12
+ ## Acceptance Criteria
13
+ - Specific criteria that will be used to judge if the issue is fixed
@@ -0,0 +1,8 @@
1
+ Fixes #ISSUE
2
+
3
+ ### Instructions to reviewer on how to test:
4
+ 1. Do thing x
5
+ 2. Confirm thing y happens
6
+
7
+ ### Checks for reviewer
8
+ - [ ] Would the PR title make sense to a user on a set of release notes
@@ -8,4 +8,4 @@
8
8
  <link rel="canonical" href="main/index.html">
9
9
  </head>
10
10
 
11
- </html>
11
+ </html>
@@ -1,12 +1,14 @@
1
+ """Make switcher.json to allow docs to switch between different versions."""
2
+
1
3
  import json
2
4
  import logging
3
5
  from argparse import ArgumentParser
4
6
  from pathlib import Path
5
7
  from subprocess import CalledProcessError, check_output
6
- from typing import Optional
7
8
 
8
9
 
9
10
  def report_output(stdout: bytes, label: str) -> list[str]:
11
+ """Print and return something received frm stdout."""
10
12
  ret = stdout.decode().strip().split("\n")
11
13
  print(f"{label}: {ret}")
12
14
  return ret
@@ -24,7 +26,7 @@ def get_sorted_tags_list() -> list[str]:
24
26
  return report_output(stdout, "Tags list")
25
27
 
26
28
 
27
- def get_versions(ref: str, add: Optional[str]) -> list[str]:
29
+ def get_versions(ref: str, add: str | None) -> list[str]:
28
30
  """Generate the file containing the list of all GitHub Pages builds."""
29
31
  # Get the directories (i.e. builds) from the GitHub Pages branch
30
32
  try:
@@ -53,7 +55,8 @@ def get_versions(ref: str, add: Optional[str]) -> list[str]:
53
55
  return versions
54
56
 
55
57
 
56
- def write_json(path: Path, repository: str, versions: str):
58
+ def write_json(path: Path, repository: str, versions: list[str]):
59
+ """Write the JSON switcher to path."""
57
60
  org, repo_name = repository.split("/")
58
61
  struct = [
59
62
  {"version": version, "url": f"https://{org}.github.io/{repo_name}/{version}/"}
@@ -65,6 +68,7 @@ def write_json(path: Path, repository: str, versions: str):
65
68
 
66
69
 
67
70
  def main(args=None):
71
+ """Parse args and write switcher."""
68
72
  parser = ArgumentParser(
69
73
  description="Make a versions.json file from gh-pages directories"
70
74
  )
@@ -0,0 +1,60 @@
1
+ on:
2
+ workflow_call:
3
+
4
+ jobs:
5
+ build:
6
+ runs-on: ubuntu-latest
7
+
8
+ steps:
9
+ - name: Checkout
10
+ uses: actions/checkout@v4
11
+ with:
12
+ # Need this to get version number from last tag
13
+ fetch-depth: 0
14
+
15
+ - name: Set up Docker Buildx
16
+ id: buildx
17
+ uses: docker/setup-buildx-action@v3
18
+
19
+ - name: Log in to GitHub Docker Registry
20
+ if: github.event_name != 'pull_request'
21
+ uses: docker/login-action@v3
22
+ with:
23
+ registry: ghcr.io
24
+ username: ${{ github.actor }}
25
+ password: ${{ secrets.GITHUB_TOKEN }}
26
+
27
+ - name: Build and export to Docker local cache
28
+ uses: docker/build-push-action@v6
29
+ env:
30
+ DOCKER_BUILD_RECORD_UPLOAD: false
31
+ with:
32
+ context: .
33
+ # Need load and tags so we can test it below
34
+ load: true
35
+ tags: tag_for_testing
36
+
37
+ - name: Test cli works in cached runtime image
38
+ run: docker run --rm tag_for_testing --help
39
+
40
+ - name: Create tags for publishing image
41
+ id: meta
42
+ uses: docker/metadata-action@v5
43
+ with:
44
+ images: ghcr.io/${{ github.repository }}
45
+ tags: |
46
+ type=ref,event=tag
47
+ type=raw,value=latest
48
+
49
+ - name: Push cached image to container registry
50
+ if: github.ref_type == 'tag'
51
+ uses: docker/build-push-action@v6
52
+ env:
53
+ DOCKER_BUILD_RECORD_UPLOAD: false
54
+ # This does not build the image again, it will find the image in the
55
+ # Docker cache and publish it
56
+ with:
57
+ context: .
58
+ push: true
59
+ tags: ${{ steps.meta.outputs.tags }}
60
+ labels: ${{ steps.meta.outputs.labels }}
@@ -1,8 +1,5 @@
1
1
  on:
2
2
  workflow_call:
3
- secrets:
4
- PYPI_TOKEN:
5
- required: true
6
3
 
7
4
  jobs:
8
5
  upload:
@@ -18,5 +15,3 @@ jobs:
18
15
 
19
16
  - name: Publish to PyPI using trusted publishing
20
17
  uses: pypa/gh-action-pypi-publish@release/v1
21
- with:
22
- password: ${{ secrets.PYPI_TOKEN }}
@@ -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@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v0.1.15
26
+ uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8
27
27
  with:
28
28
  prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
29
29
  files: "*"
@@ -34,6 +34,14 @@ jobs:
34
34
  secrets:
35
35
  CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
36
36
 
37
+ container:
38
+ needs: check
39
+ if: needs.check.outputs.branch-pr == ''
40
+ uses: ./.github/workflows/_container.yml
41
+ permissions:
42
+ contents: read
43
+ packages: write
44
+
37
45
  dist:
38
46
  needs: check
39
47
  if: needs.check.outputs.branch-pr == ''
@@ -45,8 +53,6 @@ jobs:
45
53
  uses: ./.github/workflows/_pypi.yml
46
54
  permissions:
47
55
  id-token: write
48
- secrets:
49
- PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
50
56
 
51
57
  release:
52
58
  if: github.ref_type == 'tag'
@@ -55,6 +55,7 @@ cov.xml
55
55
 
56
56
  # Sphinx documentation
57
57
  docs/_build/
58
+ docs/_api
58
59
 
59
60
  # PyBuilder
60
61
  target/
@@ -5,6 +5,7 @@ repos:
5
5
  - id: check-added-large-files
6
6
  - id: check-yaml
7
7
  - id: check-merge-conflict
8
+ - id: end-of-file-fixer
8
9
 
9
10
  - repo: local
10
11
  hooks:
@@ -2,4 +2,4 @@
2
2
  "recommendations": [
3
3
  "ms-vscode-remote.remote-containers",
4
4
  ]
5
- }
5
+ }
@@ -6,7 +6,7 @@
6
6
  "configurations": [
7
7
  {
8
8
  "name": "Debug Unit Test",
9
- "type": "python",
9
+ "type": "debugpy",
10
10
  "request": "launch",
11
11
  "justMyCode": false,
12
12
  "program": "${file}",
@@ -14,6 +14,10 @@
14
14
  "debug-test"
15
15
  ],
16
16
  "console": "integratedTerminal",
17
+ "env": {
18
+ // Enable break on exception when debugging tests (see: tests/conftest.py)
19
+ "PYTEST_RAISE": "1",
20
+ },
17
21
  }
18
22
  ]
19
- }
23
+ }
@@ -5,7 +5,8 @@
5
5
  "editor.codeActionsOnSave": {
6
6
  "source.organizeImports": "explicit"
7
7
  },
8
+ "files.insertFinalNewline": true,
8
9
  "[python]": {
9
10
  "editor.defaultFormatter": "charliermarsh.ruff",
10
11
  },
11
- }
12
+ }
@@ -13,4 +13,4 @@
13
13
  "problemMatcher": [],
14
14
  }
15
15
  ]
16
- }
16
+ }
@@ -0,0 +1,31 @@
1
+ # The devcontainer should use the developer target and run as root with podman
2
+ # or docker with user namespaces.
3
+ ARG PYTHON_VERSION=3.11
4
+ FROM python:${PYTHON_VERSION} as developer
5
+
6
+ # Add any system dependencies for the developer/build environment here
7
+ RUN apt-get update && apt-get install -y --no-install-recommends \
8
+ graphviz \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ # Set up a virtual environment and put it in PATH
12
+ RUN python -m venv /venv
13
+ ENV PATH=/venv/bin:$PATH
14
+
15
+ # The build stage installs the context into the venv
16
+ FROM developer as build
17
+ COPY . /context
18
+ WORKDIR /context
19
+ RUN touch dev-requirements.txt && pip install -c dev-requirements.txt .
20
+
21
+ # The runtime stage copies the built venv into a slim runtime container
22
+ FROM python:${PYTHON_VERSION}-slim as runtime
23
+ # Add apt-get system dependecies for runtime here if needed
24
+ COPY --from=build /venv/ /venv/
25
+ ENV PATH=/venv/bin:$PATH
26
+ RUN pip install textual-dev
27
+
28
+ # change this entrypoint if it is not the same as the repo
29
+ # Usage: serve "ec -b DEMO monitor" -p 8081
30
+ ENTRYPOINT ["textual", "serve"]
31
+ CMD ["--version"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edge-containers-cli
3
- Version: 4.1.0
3
+ Version: 4.1.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
@@ -250,6 +250,7 @@ https://epics-containers.github.io/
250
250
  Source | <https://github.com/epics-containers/edge-containers-cli>
251
251
  :---: | :---:
252
252
  PyPI | `pip install edge-containers-cli`
253
+ Docker | `docker run ghcr.io/epics-containers/edge-containers-cli:latest`
253
254
  Releases | <https://github.com/epics-containers/edge-containers-cli/releases>
254
255
 
255
256
 
@@ -258,4 +259,3 @@ and perform the following::
258
259
 
259
260
  pip install edge-containers-cli
260
261
  ec --version
261
-
@@ -15,6 +15,7 @@ https://epics-containers.github.io/
15
15
  Source | <https://github.com/epics-containers/edge-containers-cli>
16
16
  :---: | :---:
17
17
  PyPI | `pip install edge-containers-cli`
18
+ Docker | `docker run ghcr.io/epics-containers/edge-containers-cli:latest`
18
19
  Releases | <https://github.com/epics-containers/edge-containers-cli/releases>
19
20
 
20
21
 
@@ -23,4 +24,3 @@ and perform the following::
23
24
 
24
25
  pip install edge-containers-cli
25
26
  ec --version
26
-
@@ -14,4 +14,4 @@ Below is the list of our current ADRs.
14
14
  :maxdepth: 1
15
15
  :glob:
16
16
 
17
- decisions/*
17
+ decisions/*
@@ -13,4 +13,4 @@ To make a new release, please follow this checklist:
13
13
  Note that tagging and pushing to the main branch has the same effect except that
14
14
  you will not get the option to edit the release notes.
15
15
 
16
- .. _release: https://github.com/epics-containers/edge-containers-cli/releases
16
+ .. _release: https://github.com/epics-containers/edge-containers-cli/releases
@@ -8,4 +8,4 @@
8
8
  <path id="path2859" d="m156.09 651.68-0.30524-2.1354c1.4474 0.12317 2.8387 0.4409 4.1468 0.93101l-2.4011 1.8011c-0.67345 0.5049-1.3214 0.23639-1.4405-0.5967" fill="#fddd04" />
9
9
  <path id="path2861" d="m148.46 656.04-7.3723 0.918c1.3908-2.2598 3.3397-4.1371 5.6539-5.4455l2.3151 3.0873c0.5049 0.67295 0.23639 1.3212-0.5967 1.4402" fill="#fddd04" />
10
10
  </g>
11
- </svg>
11
+ </svg>
@@ -1,5 +1,5 @@
1
1
  [build-system]
2
- requires = ["setuptools>=64", "setuptools_scm[toml]>=6.2"]
2
+ requires = ["setuptools>=64", "setuptools_scm[toml]>=8"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
@@ -54,9 +54,10 @@ name = "Giles Knap"
54
54
 
55
55
 
56
56
  [tool.setuptools_scm]
57
- write_to = "src/edge_containers_cli/_version.py"
57
+ version_file = "src/edge_containers_cli/_version.py"
58
58
 
59
59
  [tool.pyright]
60
+ typeCheckingMode = "standard"
60
61
  reportMissingImports = false # Ignore missing stubs in imported modules
61
62
 
62
63
  [tool.pytest.ini_options]
@@ -100,7 +101,7 @@ allowlist_externals =
100
101
  pre-commit
101
102
  pyright
102
103
  commands =
103
- pre-commit: pre-commit run --all-files {posargs}
104
+ pre-commit: pre-commit run --all-files --show-diff-on-failure {posargs}
104
105
  type-checking: pyright src tests {posargs}
105
106
  tests: pytest --cov=edge_containers_cli --cov-report term --cov-report xml:cov.xml {posargs}
106
107
  """
@@ -115,11 +116,18 @@ lint.ignore = [
115
116
  "UP007", # Do not complain about Optional[] (TODO: remove once typer is patched)
116
117
  ]
117
118
  lint.select = [
118
- "B", # flake8-bugbear - https://docs.astral.sh/ruff/rules/#flake8-bugbear-b
119
- "C4", # flake8-comprehensions - https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4
120
- "E", # pycodestyle errors - https://docs.astral.sh/ruff/rules/#error-e
121
- "F", # pyflakes rules - https://docs.astral.sh/ruff/rules/#pyflakes-f
122
- "W", # pycodestyle warnings - https://docs.astral.sh/ruff/rules/#warning-w
123
- "I", # isort - https://docs.astral.sh/ruff/rules/#isort-i
124
- "UP", # pyupgrade - https://docs.astral.sh/ruff/rules/#pyupgrade-up
119
+ "B", # flake8-bugbear - https://docs.astral.sh/ruff/rules/#flake8-bugbear-b
120
+ "C4", # flake8-comprehensions - https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4
121
+ "E", # pycodestyle errors - https://docs.astral.sh/ruff/rules/#error-e
122
+ "F", # pyflakes rules - https://docs.astral.sh/ruff/rules/#pyflakes-f
123
+ "W", # pycodestyle warnings - https://docs.astral.sh/ruff/rules/#warning-w
124
+ "I", # isort - https://docs.astral.sh/ruff/rules/#isort-i
125
+ "UP", # pyupgrade - https://docs.astral.sh/ruff/rules/#pyupgrade-up
126
+ "SLF", # self - https://docs.astral.sh/ruff/settings/#lintflake8-self
125
127
  ]
128
+
129
+ [tool.ruff.lint.per-file-ignores]
130
+ # By default, private member access is allowed in tests
131
+ # See https://github.com/DiamondLightSource/python-copier-template/issues/154
132
+ # Remove this line to forbid private member access in tests
133
+ "tests/**/*" = ["SLF001"]
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '4.1.0'
16
- __version_tuple__ = version_tuple = (4, 1, 0)
15
+ __version__ = version = '4.1.1'
16
+ __version_tuple__ = version_tuple = (4, 1, 1)
@@ -81,7 +81,7 @@ def force_plain_completion() -> list[str]:
81
81
  def running_svc(ctx: typer.Context) -> list[str]:
82
82
  autocomplete_backend_init(ctx)
83
83
  try:
84
- return ec_backend.commands._running_services()
84
+ return ec_backend.commands._running_services() # noqa: SLF001
85
85
  except (CommandError, ShellError) as e:
86
86
  typer.echo(f"\n{e}", nl=False, err=True)
87
87
  return []
@@ -90,7 +90,7 @@ def running_svc(ctx: typer.Context) -> list[str]:
90
90
  def all_svc(ctx: typer.Context) -> list[str]:
91
91
  autocomplete_backend_init(ctx)
92
92
  try:
93
- return ec_backend.commands._all_services()
93
+ return ec_backend.commands._all_services() # noqa: SLF001
94
94
  except (CommandError, ShellError) as e:
95
95
  typer.echo(f"\n{e}", nl=False, err=True)
96
96
  return []
@@ -4,6 +4,7 @@ Manage a backend for the project
4
4
 
5
5
  from edge_containers_cli.cmds.argo_commands import ArgoCommands
6
6
  from edge_containers_cli.cmds.commands import Commands
7
+ from edge_containers_cli.cmds.demo_commands import DemoCommands
7
8
  from edge_containers_cli.cmds.k8s_commands import K8sCommands
8
9
  from edge_containers_cli.definitions import ECBackends, ECContext
9
10
  from edge_containers_cli.utils import public_methods
@@ -36,10 +37,13 @@ class Backend:
36
37
 
37
38
  def set_backend(self, backend: ECBackends):
38
39
  self._value = backend
39
- if backend == ECBackends.K8S:
40
- self._Commands = K8sCommands
41
- elif backend == ECBackends.ARGOCD:
42
- self._Commands = ArgoCommands
40
+ match backend:
41
+ case ECBackends.DEMO:
42
+ self._Commands = DemoCommands
43
+ case ECBackends.K8S:
44
+ self._Commands = K8sCommands
45
+ case ECBackends.ARGOCD:
46
+ self._Commands = ArgoCommands
43
47
 
44
48
  def set_context(self, context: ECContext):
45
49
  """
@@ -0,0 +1,135 @@
1
+ """
2
+ implements commands for deploying and managing service instances suing argocd
3
+
4
+ Relies on the Helm class for deployment aspects.
5
+ """
6
+
7
+ import time
8
+ from datetime import datetime
9
+
10
+ import polars
11
+
12
+ from edge_containers_cli.cmds.commands import CommandError, Commands, ServicesDataFrame
13
+ from edge_containers_cli.definitions import ECContext
14
+ from edge_containers_cli.globals import TIME_FORMAT
15
+
16
+ DELAY = 0.0
17
+
18
+
19
+ def process_t(time_string) -> str:
20
+ time_stamp = datetime.strptime(time_string, "%Y-%m-%dT%H:%M:%SZ")
21
+ return datetime.strftime(time_stamp, TIME_FORMAT)
22
+
23
+
24
+ sample_data = {
25
+ "name": ["demo-ea-01", "demo-ea-02", "demo-ea-03"], # type: ignore
26
+ "version": ["2024.10.1", "2024.10.1b", "2024.10.1"],
27
+ "ready": [True, True, False],
28
+ "deployed": [
29
+ process_t("2024-10-22T11:23:10Z"),
30
+ process_t("2024-10-28T14:53:55Z"),
31
+ process_t("2024-10-22T12:51:50Z"),
32
+ ],
33
+ }
34
+ sample_ServicesDataFrame = ServicesDataFrame(polars.from_dict(sample_data))
35
+
36
+
37
+ def demo_wrapper():
38
+ """Using closure to display once"""
39
+ called = False
40
+
41
+ def decorator(function):
42
+ """Called selectively to avoid breaking autocompletion"""
43
+
44
+ def wrapper(*args, **kwargs):
45
+ nonlocal called
46
+ if not called:
47
+ called = True
48
+ print("***RUNNING IN DEMO MODE***")
49
+ return function(*args, **kwargs)
50
+
51
+ return wrapper
52
+
53
+ return decorator
54
+
55
+
56
+ demo_message = demo_wrapper()
57
+
58
+
59
+ class DemoCommands(Commands):
60
+ """
61
+ A class for implementing the Kubernetes based commands
62
+ """
63
+
64
+ def __init__(
65
+ self,
66
+ ctx: ECContext,
67
+ ):
68
+ self._target = "Demo Beamline"
69
+ self._target_valid = False
70
+ self._stateDF = sample_ServicesDataFrame
71
+
72
+ @demo_message
73
+ def logs(self, service_name, prev):
74
+ self._logs(service_name, prev)
75
+
76
+ @demo_message
77
+ def log_history(self, service_name):
78
+ pass
79
+
80
+ @demo_message
81
+ def ps(self, running_only):
82
+ self._ps(running_only)
83
+
84
+ @demo_message
85
+ def restart(self, service_name):
86
+ self.stop(service_name, False)
87
+ self.start(service_name, False)
88
+
89
+ @demo_message
90
+ def start(self, service_name, temp):
91
+ self._check_service(service_name)
92
+ time.sleep(DELAY)
93
+ self._stateDF = self._stateDF.with_columns(
94
+ polars.when(polars.col("name") == service_name)
95
+ .then(True)
96
+ .otherwise(polars.col("ready"))
97
+ .alias("ready")
98
+ )
99
+
100
+ @demo_message
101
+ def stop(self, service_name, temp):
102
+ self._check_service(service_name)
103
+ time.sleep(DELAY)
104
+ self._stateDF = self._stateDF.with_columns(
105
+ polars.when(polars.col("name") == service_name)
106
+ .then(False)
107
+ .otherwise(polars.col("ready"))
108
+ .alias("ready")
109
+ )
110
+
111
+ def _get_logs(self, service_name, prev) -> str:
112
+ self._check_service(service_name)
113
+ logs_list = ["Lorem ipsum dolor sit amet"] * 25
114
+ return "\n".join(logs_list)
115
+
116
+ def _get_services(self, running_only) -> ServicesDataFrame:
117
+ if running_only:
118
+ return ServicesDataFrame(self._stateDF.filter(polars.col("ready").eq(True)))
119
+ else:
120
+ return ServicesDataFrame(self._stateDF)
121
+
122
+ def _check_service(self, service_name: str):
123
+ """
124
+ validate that there is a app with the given service_name
125
+ """
126
+ services_list = self._get_services(running_only=False)["name"]
127
+ if service_name in services_list:
128
+ pass
129
+ else:
130
+ raise CommandError(
131
+ f"Service '{service_name}' not found in '{self._target}'"
132
+ )
133
+
134
+ def _validate_target(self):
135
+ pass
@@ -233,7 +233,7 @@ class IocTable(Widget):
233
233
 
234
234
  self.commands = commands
235
235
  self.running_only = running_only
236
- self.iocs_df = self.commands._get_services(self.running_only)
236
+ self.iocs_df = self.commands._get_services(self.running_only) # noqa: SLF001
237
237
 
238
238
  self._polling = True
239
239
  self._poll_thread = Thread(target=self._poll_services)
@@ -244,7 +244,7 @@ class IocTable(Widget):
244
244
  while self._polling:
245
245
  # ioc list data table update loop
246
246
  print()
247
- self.iocs_df = self.commands._get_services(self.running_only)
247
+ self.iocs_df = self.commands._get_services(self.running_only) # noqa: SLF001
248
248
  sleep(1.0)
249
249
 
250
250
  def stop(self):
@@ -385,7 +385,7 @@ class MonitorApp(App):
385
385
  Binding("r", "restart_ioc", "Restart IOC"),
386
386
  Binding("l", "ioc_logs", "IOC Logs"),
387
387
  Binding("o", "sort", "Sort"),
388
- # Binding("d", "toggle_dark", "Toggle dark mode"),
388
+ Binding("d", "toggle_dark", "Toggle dark mode"),
389
389
  ]
390
390
 
391
391
  def __init__(
@@ -480,7 +480,7 @@ class MonitorApp(App):
480
480
  ready = self._get_highlighted_cell("ready") == "True"
481
481
 
482
482
  if ready:
483
- command = self.commands._get_logs
483
+ command = self.commands._get_logs # noqa: SLF001
484
484
  self.push_screen(LogsScreen(command, service_name))
485
485
 
486
486
  def action_sort(self, col_name: str = "") -> None:
@@ -48,4 +48,4 @@ LogsScreen {
48
48
  align: center middle;
49
49
  height: auto;
50
50
  width: auto;
51
- }
51
+ }
@@ -5,6 +5,7 @@ from enum import Enum
5
5
  class ECBackends(str, Enum):
6
6
  ARGOCD = "ARGOCD"
7
7
  K8S = "K8S"
8
+ DEMO = "DEMO"
8
9
 
9
10
 
10
11
  class ECLogLevels(str, Enum):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edge-containers-cli
3
- Version: 4.1.0
3
+ Version: 4.1.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
@@ -250,6 +250,7 @@ https://epics-containers.github.io/
250
250
  Source | <https://github.com/epics-containers/edge-containers-cli>
251
251
  :---: | :---:
252
252
  PyPI | `pip install edge-containers-cli`
253
+ Docker | `docker run ghcr.io/epics-containers/edge-containers-cli:latest`
253
254
  Releases | <https://github.com/epics-containers/edge-containers-cli/releases>
254
255
 
255
256
 
@@ -258,4 +259,3 @@ and perform the following::
258
259
 
259
260
  pip install edge-containers-cli
260
261
  ec --version
261
-
@@ -4,15 +4,18 @@
4
4
  Dockerfile
5
5
  LICENSE
6
6
  README.md
7
- catalog-info.yaml
8
7
  pyproject.toml
9
8
  .devcontainer/devcontainer.json
10
9
  .github/CONTRIBUTING.md
11
10
  .github/dependabot.yml
11
+ .github/ISSUE_TEMPLATE/bug_report.md
12
+ .github/ISSUE_TEMPLATE/issue.md
13
+ .github/PULL_REQUEST_TEMPLATE/pull_request_template.md
12
14
  .github/actions/install_requirements/action.yml
13
15
  .github/pages/index.html
14
16
  .github/pages/make_switcher.py
15
17
  .github/workflows/_check.yml
18
+ .github/workflows/_container.yml
16
19
  .github/workflows/_dist.yml
17
20
  .github/workflows/_pypi.yml
18
21
  .github/workflows/_release.yml
@@ -69,6 +72,7 @@ src/edge_containers_cli.egg-info/top_level.txt
69
72
  src/edge_containers_cli/cmds/__init__.py
70
73
  src/edge_containers_cli/cmds/argo_commands.py
71
74
  src/edge_containers_cli/cmds/commands.py
75
+ src/edge_containers_cli/cmds/demo_commands.py
72
76
  src/edge_containers_cli/cmds/helm.py
73
77
  src/edge_containers_cli/cmds/k8s_commands.py
74
78
  src/edge_containers_cli/cmds/monitor.py
@@ -77,6 +81,7 @@ tests/__init__.py
77
81
  tests/conftest.py
78
82
  tests/test_argocd.py
79
83
  tests/test_cli.py
84
+ tests/test_demo.py
80
85
  tests/test_k8s.py
81
86
  tests/test_unit.py
82
87
  tests/data/argocd.yaml
@@ -213,3 +213,13 @@ def ARGOCD(mocker, data):
213
213
  file = Path(__file__).parent / "data" / "argocd.yaml"
214
214
  yaml = YAML(typ="safe").load(file)
215
215
  return SimpleNamespace(**yaml)
216
+
217
+
218
+ @fixture()
219
+ def DEMO(mocker):
220
+ mocker.patch.dict(
221
+ os.environ,
222
+ {
223
+ "EC_CLI_BACKEND": "DEMO",
224
+ },
225
+ )
@@ -0,0 +1,32 @@
1
+ def test_logs(mock_run, DEMO):
2
+ mock_run.run_cli("logs demo-ea-01")
3
+
4
+
5
+ def test_log_history(mock_run, DEMO):
6
+ mock_run.run_cli("log-history demo-ea-01")
7
+
8
+
9
+ def test_restart(mock_run, DEMO):
10
+ mock_run.run_cli("restart demo-ea-01")
11
+
12
+
13
+ def test_start(mock_run, DEMO):
14
+ mock_run.run_cli("start demo-ea-01")
15
+
16
+
17
+ def test_stop(mock_run, DEMO):
18
+ mock_run.run_cli("stop demo-ea-01")
19
+
20
+
21
+ def test_ps(mock_run, DEMO):
22
+ expect = (
23
+ "| name | version | ready | deployed |\n"
24
+ "|------------|------------|-------|----------------------|\n"
25
+ "| demo-ea-01 | 2024.10.1 | true | 2024-10-22T11:23:10Z |\n"
26
+ "| demo-ea-02 | 2024.10.1b | true | 2024-10-28T14:53:55Z |\n"
27
+ "| demo-ea-03 | 2024.10.1 | false | 2024-10-22T12:51:50Z |\n"
28
+ )
29
+
30
+ res = mock_run.run_cli("ps")
31
+
32
+ assert expect in res
@@ -1,13 +0,0 @@
1
- # The devcontainer should use the developer target and run as root with podman
2
- # or docker with user namespaces.
3
- ARG PYTHON_VERSION=3.11
4
- FROM python:${PYTHON_VERSION} as developer
5
-
6
- # Add any system dependencies for the developer/build environment here
7
- RUN apt-get update && apt-get install -y --no-install-recommends \
8
- graphviz \
9
- && rm -rf /var/lib/apt/lists/*
10
-
11
- # Set up a virtual environment and put it in PATH
12
- RUN python -m venv /venv
13
- ENV PATH=/venv/bin:$PATH
@@ -1,10 +0,0 @@
1
- apiVersion: backstage.io/v1alpha1
2
- kind: Component
3
- metadata:
4
- name: edge-containers-cli
5
- title: edge-containers-cli
6
- description: CLI for deploying and managing epics containers IOCs and services
7
- spec:
8
- type: documentation
9
- lifecycle: experimental
10
- owner: group:default/sscc