[epa-orchestrator] epa-orchestrator charm for installing epa-orchestrator snap

The epa-orchestrator charm is an operator designed to configure and install epa-orchestrator snap.

Change-Id: Ib74ec522a67f8f06996d8ff4fdd1c87ae9311de3
Signed-off-by: Ahmad Hassan <ahmad.hassan@canonical.com>
This commit is contained in:
Ahmad Hassan
2025-06-24 16:02:58 +05:00
parent 0d41be650d
commit b9e31079a2
23 changed files with 1128 additions and 87 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
.cursor
venv/ venv/
build/ build/
.idea/ .idea/

View File

@@ -0,0 +1,6 @@
external-libraries:
- charms.operator_libs_linux.v2.snap
- charms.tempo_k8s.v2.tracing
- charms.tempo_k8s.v1.charm_tracing
internal-libraries: []
templates: []

View File

@@ -0,0 +1,35 @@
# Contributing
To make contributions to this charm, you'll need a working [development setup](https://juju.is/docs/sdk/dev-setup).
You can create an environment for development with `tox`:
```shell
virtualenv venv
source venv/bin/activate
```
## Testing
This project uses `tox` for managing test environments. There are some pre-configured environments
that can be used for linting and formatting code when you're preparing contributions to the charm:
```shell
tox run -e fmt
tox run -e linters
tox run -e pep8
tox -e py3 -- epa-orchestrator
```
## Smoke testing
```shell
tox -e func -- --smoke --test-directory=/root/sunbeam-charms/tests/machine/
```
## Build the charm
Build the charm in this git repository using:
```shell
tox -e build -- epa-orchestrator
```

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2025 ahmad
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,13 @@
# epa-orchestrator
## Description
The epa-orchestrator charm is an operator designed to manage the EPA (Enhanced Platform Awareness) orchestrator service as part of an OpenStack deployment. This charm installs and configures the epa-orchestrator snap, which provides enhanced platform awareness capabilities for OpenStack cloud.
### Testing
Run the unit tests:
```bash
tox -e py3 -- epa-orchestrator
```

View File

@@ -0,0 +1,15 @@
# Copyright 2025 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit tests for charm."""

View File

@@ -0,0 +1,46 @@
type: charm
name: epa-orchestrator
title: Epa Orchestrator
summary: Deploy the epa-orchestrator snap.
description: |
Configures the epa-orchestrator snap as a part of the openstack deployment.
assumes:
- juju >= 3.1
base: ubuntu@24.04
platforms:
amd64:
config:
options:
snap-name:
default: epa-orchestrator
type: string
description: The name of the snap to install.
snap-channel:
default: latest/edge
type: string
description: The channel of the snap to install.
requires:
tracing:
interface: tracing
optional: true
limit: 1
parts:
charm:
build-packages:
- git
- libffi-dev
- libssl-dev
- rustc-1.80
- cargo-1.80
- pkg-config
charm-binary-python-packages:
- cryptography
- jsonschema
- pydantic
- jinja2
build-snaps: [astral-uv]
override-build: |
uv export --frozen --no-hashes --format=requirements-txt -o requirements.txt
craftctl default
charm-requirements: [requirements.txt]

View File

@@ -0,0 +1,17 @@
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.
[project]
name = "epa-orchestrator"
version = "2025.1"
requires-python = "~=3.12.0"
dependencies = [
"cryptography",
"jinja2",
"jsonschema",
"pydantic",
"ops",
"tenacity", # From ops_sunbeam
"opentelemetry-api~=1.21.0", # charm_tracing library -> opentelemetry-sdk requires 1.21.0
]

View File

@@ -0,0 +1,3 @@
# This file is used to trigger a build.
# Change uuid to trigger a new build.
29a571a6-411d-49f0-80fb-07fa8c4f7e49

View File

@@ -0,0 +1,64 @@
#!/usr/bin/env python3
# Copyright 2023 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""EPA Orchestrator Charm operator.
This charm is used to install the epa-orchestrator snap as a part of the openstack deployment.
"""
import logging
import charms.operator_libs_linux.v2.snap as snap
import ops
import ops_sunbeam.charm as sunbeam_charm
import ops_sunbeam.tracing as sunbeam_tracing
logger = logging.getLogger(__name__)
@sunbeam_tracing.trace_sunbeam_charm(extra_types=(snap.SnapCache, snap.Snap))
class EpaOrchestratorCharm(sunbeam_charm.OSBaseOperatorCharmSnap):
"""Charm the service."""
service_name = "epa-orchestrator"
@property
def snap_name(self) -> str:
"""Returns the snap name."""
return str(self.model.config["snap-name"])
@property
def snap_channel(self) -> str:
"""Returns the snap channel."""
return str(self.model.config["snap-channel"])
def ensure_services_running(self) -> None:
"""Override to prevent service start - this snap has no services."""
logger.debug(
"Skipping service start - %s snap has no services", self.snap_name
)
pass
def stop_services(self) -> None:
"""Override to prevent service stop - this snap has no services."""
logger.debug(
"Skipping service stop - %s snap has no services", self.snap_name
)
pass
if __name__ == "__main__": # pragma: nocover
ops.main(EpaOrchestratorCharm)

View File

@@ -0,0 +1,15 @@
# Copyright 2025 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit tests for charm."""

View File

@@ -0,0 +1,88 @@
# Copyright 2023 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for EPA Orchestrator charm."""
import charm
import ops_sunbeam.test_utils as test_utils
class _EpaOrchestratorCharm(charm.EpaOrchestratorCharm):
"""EPA Orchestrator test charm."""
def __init__(self, framework):
super().__init__(framework)
class TestEpaOrchestratorCharm(test_utils.CharmTestCase):
"""Test charm to test EPA Orchestrator charm."""
PATCHES = []
def setUp(self):
"""Setup EPA Orchestrator tests."""
super().setUp(charm, self.PATCHES)
self.harness = test_utils.get_harness(
_EpaOrchestratorCharm,
container_calls=self.container_calls,
)
self.addCleanup(self.harness.cleanup)
def initial_setup(self):
"""Setting up configuration."""
self.harness.update_config(
{"snap-name": "epa-orchestrator", "snap-channel": "latest/edge"}
)
self.harness.begin_with_initial_hooks()
def test_snap_name_property_default(self):
"""Test snap_name property returns default value."""
self.harness.begin()
self.assertEqual(self.harness.charm.snap_name, "epa-orchestrator")
def test_snap_channel_property(self):
"""Test snap_channel property returns configured channel."""
self.harness.begin()
self.harness.update_config({"snap-channel": "latest/edge"})
self.assertEqual(self.harness.charm.snap_channel, "latest/edge")
def test_snap_channel_property_default(self):
"""Test snap_channel property returns default value."""
self.harness.begin()
self.assertEqual(self.harness.charm.snap_channel, "latest/edge")
def test_ensure_services_running_no_op(self):
"""Test ensure_services_running is a no-op and doesn't raise errors."""
self.harness.begin()
# This should not raise any exceptions
result = self.harness.charm.ensure_services_running()
# Should return None (no-op)
self.assertIsNone(result)
def test_stop_services_no_op(self):
"""Test stop_services is a no-op and doesn't raise errors."""
self.harness.begin()
# This should not raise any exceptions
result = self.harness.charm.stop_services()
# Should return None (no-op)
self.assertIsNone(result)

382
charms/epa-orchestrator/uv.lock generated Normal file
View File

@@ -0,0 +1,382 @@
version = 1
revision = 2
requires-python = ">=3.12.0, <3.13"
[[package]]
name = "annotated-types"
version = "0.7.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
]
[[package]]
name = "attrs"
version = "25.3.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" },
]
[[package]]
name = "cffi"
version = "1.17.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pycparser" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" },
{ url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" },
{ url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" },
{ url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" },
{ url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" },
{ url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" },
{ url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" },
{ url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" },
{ url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" },
{ url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" },
{ url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" },
]
[[package]]
name = "cryptography"
version = "45.0.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fe/c8/a2a376a8711c1e11708b9c9972e0c3223f5fc682552c82d8db844393d6ce/cryptography-45.0.4.tar.gz", hash = "sha256:7405ade85c83c37682c8fe65554759800a4a8c54b2d96e0f8ad114d31b808d57", size = 744890, upload-time = "2025-06-10T00:03:51.297Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/1c/92637793de053832523b410dbe016d3f5c11b41d0cf6eef8787aabb51d41/cryptography-45.0.4-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:425a9a6ac2823ee6e46a76a21a4e8342d8fa5c01e08b823c1f19a8b74f096069", size = 7055712, upload-time = "2025-06-10T00:02:38.826Z" },
{ url = "https://files.pythonhosted.org/packages/ba/14/93b69f2af9ba832ad6618a03f8a034a5851dc9a3314336a3d71c252467e1/cryptography-45.0.4-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:680806cf63baa0039b920f4976f5f31b10e772de42f16310a6839d9f21a26b0d", size = 4205335, upload-time = "2025-06-10T00:02:41.64Z" },
{ url = "https://files.pythonhosted.org/packages/67/30/fae1000228634bf0b647fca80403db5ca9e3933b91dd060570689f0bd0f7/cryptography-45.0.4-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4ca0f52170e821bc8da6fc0cc565b7bb8ff8d90d36b5e9fdd68e8a86bdf72036", size = 4431487, upload-time = "2025-06-10T00:02:43.696Z" },
{ url = "https://files.pythonhosted.org/packages/6d/5a/7dffcf8cdf0cb3c2430de7404b327e3db64735747d641fc492539978caeb/cryptography-45.0.4-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f3fe7a5ae34d5a414957cc7f457e2b92076e72938423ac64d215722f6cf49a9e", size = 4208922, upload-time = "2025-06-10T00:02:45.334Z" },
{ url = "https://files.pythonhosted.org/packages/c6/f3/528729726eb6c3060fa3637253430547fbaaea95ab0535ea41baa4a6fbd8/cryptography-45.0.4-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:25eb4d4d3e54595dc8adebc6bbd5623588991d86591a78c2548ffb64797341e2", size = 3900433, upload-time = "2025-06-10T00:02:47.359Z" },
{ url = "https://files.pythonhosted.org/packages/d9/4a/67ba2e40f619e04d83c32f7e1d484c1538c0800a17c56a22ff07d092ccc1/cryptography-45.0.4-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:ce1678a2ccbe696cf3af15a75bb72ee008d7ff183c9228592ede9db467e64f1b", size = 4464163, upload-time = "2025-06-10T00:02:49.412Z" },
{ url = "https://files.pythonhosted.org/packages/7e/9a/b4d5aa83661483ac372464809c4b49b5022dbfe36b12fe9e323ca8512420/cryptography-45.0.4-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:49fe9155ab32721b9122975e168a6760d8ce4cffe423bcd7ca269ba41b5dfac1", size = 4208687, upload-time = "2025-06-10T00:02:50.976Z" },
{ url = "https://files.pythonhosted.org/packages/db/b7/a84bdcd19d9c02ec5807f2ec2d1456fd8451592c5ee353816c09250e3561/cryptography-45.0.4-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2882338b2a6e0bd337052e8b9007ced85c637da19ef9ecaf437744495c8c2999", size = 4463623, upload-time = "2025-06-10T00:02:52.542Z" },
{ url = "https://files.pythonhosted.org/packages/d8/84/69707d502d4d905021cac3fb59a316344e9f078b1da7fb43ecde5e10840a/cryptography-45.0.4-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:23b9c3ea30c3ed4db59e7b9619272e94891f8a3a5591d0b656a7582631ccf750", size = 4332447, upload-time = "2025-06-10T00:02:54.63Z" },
{ url = "https://files.pythonhosted.org/packages/f3/ee/d4f2ab688e057e90ded24384e34838086a9b09963389a5ba6854b5876598/cryptography-45.0.4-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b0a97c927497e3bc36b33987abb99bf17a9a175a19af38a892dc4bbb844d7ee2", size = 4572830, upload-time = "2025-06-10T00:02:56.689Z" },
{ url = "https://files.pythonhosted.org/packages/70/d4/994773a261d7ff98034f72c0e8251fe2755eac45e2265db4c866c1c6829c/cryptography-45.0.4-cp311-abi3-win32.whl", hash = "sha256:e00a6c10a5c53979d6242f123c0a97cff9f3abed7f064fc412c36dc521b5f257", size = 2932769, upload-time = "2025-06-10T00:02:58.467Z" },
{ url = "https://files.pythonhosted.org/packages/5a/42/c80bd0b67e9b769b364963b5252b17778a397cefdd36fa9aa4a5f34c599a/cryptography-45.0.4-cp311-abi3-win_amd64.whl", hash = "sha256:817ee05c6c9f7a69a16200f0c90ab26d23a87701e2a284bd15156783e46dbcc8", size = 3410441, upload-time = "2025-06-10T00:03:00.14Z" },
{ url = "https://files.pythonhosted.org/packages/ce/0b/2488c89f3a30bc821c9d96eeacfcab6ff3accc08a9601ba03339c0fd05e5/cryptography-45.0.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:964bcc28d867e0f5491a564b7debb3ffdd8717928d315d12e0d7defa9e43b723", size = 7031836, upload-time = "2025-06-10T00:03:01.726Z" },
{ url = "https://files.pythonhosted.org/packages/fe/51/8c584ed426093aac257462ae62d26ad61ef1cbf5b58d8b67e6e13c39960e/cryptography-45.0.4-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6a5bf57554e80f75a7db3d4b1dacaa2764611ae166ab42ea9a72bcdb5d577637", size = 4195746, upload-time = "2025-06-10T00:03:03.94Z" },
{ url = "https://files.pythonhosted.org/packages/5c/7d/4b0ca4d7af95a704eef2f8f80a8199ed236aaf185d55385ae1d1610c03c2/cryptography-45.0.4-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:46cf7088bf91bdc9b26f9c55636492c1cce3e7aaf8041bbf0243f5e5325cfb2d", size = 4424456, upload-time = "2025-06-10T00:03:05.589Z" },
{ url = "https://files.pythonhosted.org/packages/1d/45/5fabacbc6e76ff056f84d9f60eeac18819badf0cefc1b6612ee03d4ab678/cryptography-45.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7bedbe4cc930fa4b100fc845ea1ea5788fcd7ae9562e669989c11618ae8d76ee", size = 4198495, upload-time = "2025-06-10T00:03:09.172Z" },
{ url = "https://files.pythonhosted.org/packages/55/b7/ffc9945b290eb0a5d4dab9b7636706e3b5b92f14ee5d9d4449409d010d54/cryptography-45.0.4-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:eaa3e28ea2235b33220b949c5a0d6cf79baa80eab2eb5607ca8ab7525331b9ff", size = 3885540, upload-time = "2025-06-10T00:03:10.835Z" },
{ url = "https://files.pythonhosted.org/packages/7f/e3/57b010282346980475e77d414080acdcb3dab9a0be63071efc2041a2c6bd/cryptography-45.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:7ef2dde4fa9408475038fc9aadfc1fb2676b174e68356359632e980c661ec8f6", size = 4452052, upload-time = "2025-06-10T00:03:12.448Z" },
{ url = "https://files.pythonhosted.org/packages/37/e6/ddc4ac2558bf2ef517a358df26f45bc774a99bf4653e7ee34b5e749c03e3/cryptography-45.0.4-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:6a3511ae33f09094185d111160fd192c67aa0a2a8d19b54d36e4c78f651dc5ad", size = 4198024, upload-time = "2025-06-10T00:03:13.976Z" },
{ url = "https://files.pythonhosted.org/packages/3a/c0/85fa358ddb063ec588aed4a6ea1df57dc3e3bc1712d87c8fa162d02a65fc/cryptography-45.0.4-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:06509dc70dd71fa56eaa138336244e2fbaf2ac164fc9b5e66828fccfd2b680d6", size = 4451442, upload-time = "2025-06-10T00:03:16.248Z" },
{ url = "https://files.pythonhosted.org/packages/33/67/362d6ec1492596e73da24e669a7fbbaeb1c428d6bf49a29f7a12acffd5dc/cryptography-45.0.4-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5f31e6b0a5a253f6aa49be67279be4a7e5a4ef259a9f33c69f7d1b1191939872", size = 4325038, upload-time = "2025-06-10T00:03:18.4Z" },
{ url = "https://files.pythonhosted.org/packages/53/75/82a14bf047a96a1b13ebb47fb9811c4f73096cfa2e2b17c86879687f9027/cryptography-45.0.4-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:944e9ccf67a9594137f942d5b52c8d238b1b4e46c7a0c2891b7ae6e01e7c80a4", size = 4560964, upload-time = "2025-06-10T00:03:20.06Z" },
{ url = "https://files.pythonhosted.org/packages/cd/37/1a3cba4c5a468ebf9b95523a5ef5651244693dc712001e276682c278fc00/cryptography-45.0.4-cp37-abi3-win32.whl", hash = "sha256:c22fe01e53dc65edd1945a2e6f0015e887f84ced233acecb64b4daadb32f5c97", size = 2924557, upload-time = "2025-06-10T00:03:22.563Z" },
{ url = "https://files.pythonhosted.org/packages/2a/4b/3256759723b7e66380397d958ca07c59cfc3fb5c794fb5516758afd05d41/cryptography-45.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:627ba1bc94f6adf0b0a2e35d87020285ead22d9f648c7e75bb64f367375f3b22", size = 3395508, upload-time = "2025-06-10T00:03:24.586Z" },
]
[[package]]
name = "deprecated"
version = "1.2.18"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "wrapt" },
]
sdist = { url = "https://files.pythonhosted.org/packages/98/97/06afe62762c9a8a86af0cfb7bfdab22a43ad17138b07af5b1a58442690a2/deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d", size = 2928744, upload-time = "2025-01-27T10:46:25.7Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6e/c6/ac0b6c1e2d138f1002bcf799d330bd6d85084fece321e662a14223794041/Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec", size = 9998, upload-time = "2025-01-27T10:46:09.186Z" },
]
[[package]]
name = "epa-orchestrator"
version = "2025.1"
source = { virtual = "." }
dependencies = [
{ name = "cryptography" },
{ name = "jinja2" },
{ name = "jsonschema" },
{ name = "opentelemetry-api" },
{ name = "ops" },
{ name = "pydantic" },
{ name = "tenacity" },
]
[package.metadata]
requires-dist = [
{ name = "cryptography" },
{ name = "jinja2" },
{ name = "jsonschema" },
{ name = "opentelemetry-api", specifier = "~=1.21.0" },
{ name = "ops" },
{ name = "pydantic" },
{ name = "tenacity" },
]
[[package]]
name = "importlib-metadata"
version = "6.11.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "zipp" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ee/eb/58c2ab27ee628ad801f56d4017fe62afab0293116f6d0b08f1d5bd46e06f/importlib_metadata-6.11.0.tar.gz", hash = "sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443", size = 54593, upload-time = "2023-12-03T17:33:10.693Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/59/9b/ecce94952ab5ea74c31dcf9ccf78ccd484eebebef06019bf8cb579ab4519/importlib_metadata-6.11.0-py3-none-any.whl", hash = "sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b", size = 23427, upload-time = "2023-12-03T17:33:08.965Z" },
]
[[package]]
name = "jinja2"
version = "3.1.6"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markupsafe" },
]
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
]
[[package]]
name = "jsonschema"
version = "4.24.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
{ name = "jsonschema-specifications" },
{ name = "referencing" },
{ name = "rpds-py" },
]
sdist = { url = "https://files.pythonhosted.org/packages/bf/d3/1cf5326b923a53515d8f3a2cd442e6d7e94fcc444716e879ea70a0ce3177/jsonschema-4.24.0.tar.gz", hash = "sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196", size = 353480, upload-time = "2025-05-26T18:48:10.459Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a2/3d/023389198f69c722d039351050738d6755376c8fd343e91dc493ea485905/jsonschema-4.24.0-py3-none-any.whl", hash = "sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d", size = 88709, upload-time = "2025-05-26T18:48:08.417Z" },
]
[[package]]
name = "jsonschema-specifications"
version = "2025.4.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "referencing" },
]
sdist = { url = "https://files.pythonhosted.org/packages/bf/ce/46fbd9c8119cfc3581ee5643ea49464d168028cfb5caff5fc0596d0cf914/jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608", size = 15513, upload-time = "2025-04-23T12:34:07.418Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/01/0e/b27cdbaccf30b890c40ed1da9fd4a3593a5cf94dae54fb34f8a4b74fcd3f/jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", size = 18437, upload-time = "2025-04-23T12:34:05.422Z" },
]
[[package]]
name = "markupsafe"
version = "3.0.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" },
{ url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" },
{ url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" },
{ url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" },
{ url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" },
{ url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" },
{ url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" },
{ url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" },
{ url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" },
{ url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" },
]
[[package]]
name = "opentelemetry-api"
version = "1.21.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "deprecated" },
{ name = "importlib-metadata" },
]
sdist = { url = "https://files.pythonhosted.org/packages/4d/aa/1a10f310275fdd05a1062d4a8a641a5f041db2377956a80ff3c4dc325a6c/opentelemetry_api-1.21.0.tar.gz", hash = "sha256:d6185fd5043e000075d921822fd2d26b953eba8ca21b1e2fa360dd46a7686316", size = 56674, upload-time = "2023-11-07T23:16:23.155Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/51/3a/945e6c21f405ac4ea526f91ee09cc1568c04e0c95d3392903e6984c8f0e0/opentelemetry_api-1.21.0-py3-none-any.whl", hash = "sha256:4bb86b28627b7e41098f0e93280fe4892a1abed1b79a19aec6f928f39b17dffb", size = 57947, upload-time = "2023-11-07T23:15:46.656Z" },
]
[[package]]
name = "ops"
version = "2.22.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "importlib-metadata" },
{ name = "opentelemetry-api" },
{ name = "pyyaml" },
{ name = "websocket-client" },
]
sdist = { url = "https://files.pythonhosted.org/packages/1f/44/b13d1722ea3211390a9ba3c65acb7c8806168858d8568dcb52192fff161d/ops-2.22.0.tar.gz", hash = "sha256:bd1cd1229e83efb8ae2d97d8878c7db3deceb6819eb5a38fb6e235a959528ec2", size = 500975, upload-time = "2025-05-29T04:18:46.521Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/19/09/9636766721d4d34fc0fc768d0c74f006a772368d5e68ceba6b9c32407ce5/ops-2.22.0-py3-none-any.whl", hash = "sha256:ad44326bc065e33357b47e1cf4c73e811b2fdb3c89dd0c9bdf421a7a028bdcf7", size = 182680, upload-time = "2025-05-29T04:18:44.01Z" },
]
[[package]]
name = "pycparser"
version = "2.22"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" },
]
[[package]]
name = "pydantic"
version = "2.11.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "annotated-types" },
{ name = "pydantic-core" },
{ name = "typing-extensions" },
{ name = "typing-inspection" },
]
sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" },
]
[[package]]
name = "pydantic-core"
version = "2.33.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" },
{ url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" },
{ url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" },
{ url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" },
{ url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" },
{ url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" },
{ url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" },
{ url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" },
{ url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" },
{ url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" },
{ url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" },
{ url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" },
{ url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" },
{ url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" },
]
[[package]]
name = "pyyaml"
version = "6.0.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" },
{ url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" },
{ url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" },
{ url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" },
{ url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" },
{ url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" },
{ url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" },
{ url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" },
{ url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" },
]
[[package]]
name = "referencing"
version = "0.36.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
{ name = "rpds-py" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744, upload-time = "2025-01-25T08:48:16.138Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775, upload-time = "2025-01-25T08:48:14.241Z" },
]
[[package]]
name = "rpds-py"
version = "0.25.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/8c/a6/60184b7fc00dd3ca80ac635dd5b8577d444c57e8e8742cecabfacb829921/rpds_py-0.25.1.tar.gz", hash = "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3", size = 27304, upload-time = "2025-05-21T12:46:12.502Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/81/28ab0408391b1dc57393653b6a0cf2014cc282cc2909e4615e63e58262be/rpds_py-0.25.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c", size = 364647, upload-time = "2025-05-21T12:43:28.559Z" },
{ url = "https://files.pythonhosted.org/packages/2c/9a/7797f04cad0d5e56310e1238434f71fc6939d0bc517192a18bb99a72a95f/rpds_py-0.25.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b", size = 350454, upload-time = "2025-05-21T12:43:30.615Z" },
{ url = "https://files.pythonhosted.org/packages/69/3c/93d2ef941b04898011e5d6eaa56a1acf46a3b4c9f4b3ad1bbcbafa0bee1f/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa", size = 389665, upload-time = "2025-05-21T12:43:32.629Z" },
{ url = "https://files.pythonhosted.org/packages/c1/57/ad0e31e928751dde8903a11102559628d24173428a0f85e25e187defb2c1/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda", size = 403873, upload-time = "2025-05-21T12:43:34.576Z" },
{ url = "https://files.pythonhosted.org/packages/16/ad/c0c652fa9bba778b4f54980a02962748479dc09632e1fd34e5282cf2556c/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309", size = 525866, upload-time = "2025-05-21T12:43:36.123Z" },
{ url = "https://files.pythonhosted.org/packages/2a/39/3e1839bc527e6fcf48d5fec4770070f872cdee6c6fbc9b259932f4e88a38/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b", size = 416886, upload-time = "2025-05-21T12:43:38.034Z" },
{ url = "https://files.pythonhosted.org/packages/7a/95/dd6b91cd4560da41df9d7030a038298a67d24f8ca38e150562644c829c48/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea", size = 390666, upload-time = "2025-05-21T12:43:40.065Z" },
{ url = "https://files.pythonhosted.org/packages/64/48/1be88a820e7494ce0a15c2d390ccb7c52212370badabf128e6a7bb4cb802/rpds_py-0.25.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65", size = 425109, upload-time = "2025-05-21T12:43:42.263Z" },
{ url = "https://files.pythonhosted.org/packages/cf/07/3e2a17927ef6d7720b9949ec1b37d1e963b829ad0387f7af18d923d5cfa5/rpds_py-0.25.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c", size = 567244, upload-time = "2025-05-21T12:43:43.846Z" },
{ url = "https://files.pythonhosted.org/packages/d2/e5/76cf010998deccc4f95305d827847e2eae9c568099c06b405cf96384762b/rpds_py-0.25.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd", size = 596023, upload-time = "2025-05-21T12:43:45.932Z" },
{ url = "https://files.pythonhosted.org/packages/52/9a/df55efd84403736ba37a5a6377b70aad0fd1cb469a9109ee8a1e21299a1c/rpds_py-0.25.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb", size = 561634, upload-time = "2025-05-21T12:43:48.263Z" },
{ url = "https://files.pythonhosted.org/packages/ab/aa/dc3620dd8db84454aaf9374bd318f1aa02578bba5e567f5bf6b79492aca4/rpds_py-0.25.1-cp312-cp312-win32.whl", hash = "sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe", size = 222713, upload-time = "2025-05-21T12:43:49.897Z" },
{ url = "https://files.pythonhosted.org/packages/a3/7f/7cef485269a50ed5b4e9bae145f512d2a111ca638ae70cc101f661b4defd/rpds_py-0.25.1-cp312-cp312-win_amd64.whl", hash = "sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192", size = 235280, upload-time = "2025-05-21T12:43:51.893Z" },
{ url = "https://files.pythonhosted.org/packages/99/f2/c2d64f6564f32af913bf5f3f7ae41c7c263c5ae4c4e8f1a17af8af66cd46/rpds_py-0.25.1-cp312-cp312-win_arm64.whl", hash = "sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728", size = 225399, upload-time = "2025-05-21T12:43:53.351Z" },
]
[[package]]
name = "tenacity"
version = "9.1.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" },
]
[[package]]
name = "typing-extensions"
version = "4.14.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" },
]
[[package]]
name = "typing-inspection"
version = "0.4.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" },
]
[[package]]
name = "websocket-client"
version = "1.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e6/30/fba0d96b4b5fbf5948ed3f4681f7da2f9f64512e1d303f94b4cc174c24a5/websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da", size = 54648, upload-time = "2024-04-23T22:16:16.976Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", size = 58826, upload-time = "2024-04-23T22:16:14.422Z" },
]
[[package]]
name = "wrapt"
version = "1.17.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531, upload-time = "2025-01-14T10:35:45.465Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a1/bd/ab55f849fd1f9a58ed7ea47f5559ff09741b25f00c191231f9f059c83949/wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", size = 53799, upload-time = "2025-01-14T10:33:57.4Z" },
{ url = "https://files.pythonhosted.org/packages/53/18/75ddc64c3f63988f5a1d7e10fb204ffe5762bc663f8023f18ecaf31a332e/wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", size = 38821, upload-time = "2025-01-14T10:33:59.334Z" },
{ url = "https://files.pythonhosted.org/packages/48/2a/97928387d6ed1c1ebbfd4efc4133a0633546bec8481a2dd5ec961313a1c7/wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", size = 38919, upload-time = "2025-01-14T10:34:04.093Z" },
{ url = "https://files.pythonhosted.org/packages/73/54/3bfe5a1febbbccb7a2f77de47b989c0b85ed3a6a41614b104204a788c20e/wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", size = 88721, upload-time = "2025-01-14T10:34:07.163Z" },
{ url = "https://files.pythonhosted.org/packages/25/cb/7262bc1b0300b4b64af50c2720ef958c2c1917525238d661c3e9a2b71b7b/wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", size = 80899, upload-time = "2025-01-14T10:34:09.82Z" },
{ url = "https://files.pythonhosted.org/packages/2a/5a/04cde32b07a7431d4ed0553a76fdb7a61270e78c5fd5a603e190ac389f14/wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", size = 89222, upload-time = "2025-01-14T10:34:11.258Z" },
{ url = "https://files.pythonhosted.org/packages/09/28/2e45a4f4771fcfb109e244d5dbe54259e970362a311b67a965555ba65026/wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", size = 86707, upload-time = "2025-01-14T10:34:12.49Z" },
{ url = "https://files.pythonhosted.org/packages/c6/d2/dcb56bf5f32fcd4bd9aacc77b50a539abdd5b6536872413fd3f428b21bed/wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", size = 79685, upload-time = "2025-01-14T10:34:15.043Z" },
{ url = "https://files.pythonhosted.org/packages/80/4e/eb8b353e36711347893f502ce91c770b0b0929f8f0bed2670a6856e667a9/wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", size = 87567, upload-time = "2025-01-14T10:34:16.563Z" },
{ url = "https://files.pythonhosted.org/packages/17/27/4fe749a54e7fae6e7146f1c7d914d28ef599dacd4416566c055564080fe2/wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", size = 36672, upload-time = "2025-01-14T10:34:17.727Z" },
{ url = "https://files.pythonhosted.org/packages/15/06/1dbf478ea45c03e78a6a8c4be4fdc3c3bddea5c8de8a93bc971415e47f0f/wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", size = 38865, upload-time = "2025-01-14T10:34:19.577Z" },
{ url = "https://files.pythonhosted.org/packages/2d/82/f56956041adef78f849db6b289b282e72b55ab8045a75abad81898c28d19/wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", size = 23594, upload-time = "2025-01-14T10:35:44.018Z" },
]
[[package]]
name = "zipp"
version = "3.23.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" },
]

View File

@@ -598,6 +598,14 @@ class TestOSBaseOperatorCharmSnap(test_utils.CharmTestCase):
self.harness.begin() self.harness.begin()
self.addCleanup(self.harness.cleanup) self.addCleanup(self.harness.cleanup)
def test_snap_name_property(self):
"""Test snap_name property returns configured snap name."""
self.assertEqual(self.harness.charm.snap_name, "mysnap")
def test_snap_channel_property_default(self):
"""Test snap_channel property returns default value."""
self.assertEqual(self.harness.charm.snap_channel, "latest/stable")
def test_set_snap_data(self) -> None: def test_set_snap_data(self) -> None:
"""Test snap set data.""" """Test snap set data."""
charm = self.harness.charm charm = self.harness.charm

View File

@@ -37,7 +37,7 @@ from jinja2 import (
test_directories = [dir_.name for dir_ in list(Path("tests").glob('*')) if dir_.name != "local"] test_directories = [dir_.name for dir_ in list(Path("tests").glob('*')) if dir_.name != "local"]
built_charms = glob.glob("*.charm") built_charms = glob.glob("*.charm")
context = { context = {
charm.rstrip(".charm").replace("-", "_"): True for charm in built_charms charm.replace(".charm", "").replace("-", "_"): True for charm in built_charms
} }
print(f"Using context: {context}") print(f"Using context: {context}")

View File

@@ -0,0 +1,14 @@
# Copyright (c) 2025 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

View File

@@ -0,0 +1,80 @@
# Copyright (c) 2025 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import subprocess
import zaza.model as model
import zaza.openstack.charm_tests.test_utils as test_utils
class EpaOrchestratorTest(test_utils.BaseCharmTest):
"""Charm tests for epa-orchestrator."""
snap_name = "epa-orchestrator"
@classmethod
def setUpClass(cls):
"""Run class setup for running tests."""
super(EpaOrchestratorTest, cls).setUpClass(
application_name="epa-orchestrator"
)
def _get_units(self) -> list[str]:
"""Get the units."""
return [unit.name for unit in model.get_units(self.application_name)]
def _run_ssh_command(self, unit: str, command: list[str]):
"""Run a command on a unit via SSH."""
cmd = ["juju", "ssh", unit] + command
try:
stdout = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
return stdout.decode("utf-8").strip()
except subprocess.CalledProcessError as e:
logging.exception("Failed to run command on %s: %s", unit, e.output)
self.fail("Failed to run command on {}: {}".format(unit, e.output))
def _check_snap_installed(self, unit: str, snap_name: str) -> bool:
"""Check if a snap is installed on the unit."""
try:
output = self._run_ssh_command(unit, ["snap", "list", snap_name])
return snap_name in output
except Exception:
return False
def test_100_snap_installed(self):
"""Test that the epa-orchestrator snap is installed."""
units = self._get_units()
for unit in units:
with self.subTest(unit=unit):
logging.info("Checking if snap %s is installed on %s", self.snap_name, unit)
self.assertTrue(
self._check_snap_installed(unit, self.snap_name),
f"Snap {self.snap_name} is not installed on {unit}"
)
def test_200_charm_status_active(self):
"""Test that all units are in active status."""
units = self._get_units()
for unit in units:
with self.subTest(unit=unit):
model.block_until_unit_wl_status(unit, "active", timeout=60 * 5)
status = model.get_status()
unit_status = status.applications[self.application_name]["units"][unit]
current_status = unit_status.workload_status.status
self.assertEqual(
current_status,
"active",
f"Unit {unit} is not in active status, current: {current_status}"
)

View File

@@ -4,7 +4,7 @@ variables:
machines: machines:
'0': '0':
constraints: *constraints constraints: *constraints
base: ubuntu@22.04 base: ubuntu@24.04
applications: applications:
sunbeam-machine: sunbeam-machine:
@@ -14,7 +14,7 @@ applications:
charm: ch:sunbeam-machine charm: ch:sunbeam-machine
channel: 2025.1/edge channel: 2025.1/edge
{% endif -%} {% endif -%}
base: ubuntu@22.04 base: ubuntu@24.04
constraints: *constraints constraints: *constraints
scale: 1 scale: 1
to: to:
@@ -26,20 +26,32 @@ applications:
charm: ch:sunbeam-clusterd charm: ch:sunbeam-clusterd
channel: 2025.1/edge channel: 2025.1/edge
{% endif -%} {% endif -%}
base: ubuntu@22.04 base: ubuntu@24.04
constraints: *constraints constraints: *constraints
scale: 1 scale: 1
to: to:
- '0' - '0'
tls-operator: tls-operator:
charm: self-signed-certificates charm: self-signed-certificates
channel: latest/beta channel: 1/beta
base: ubuntu@22.04 base: ubuntu@24.04
scale: 1 scale: 1
options: options:
ca-common-name: internal-ca ca-common-name: internal-ca
to: to:
- '0' - '0'
epa-orchestrator:
{% if epa_orchestrator is defined and epa_orchestrator is sameas true -%}
charm: ../../../epa-orchestrator.charm
{% else -%}
charm: ch:epa-orchestrator
channel: latest/edge
{% endif -%}
base: ubuntu@24.04
constraints: *constraints
scale: 1
to:
- '0'
relations: relations:
- - tls-operator:certificates - - tls-operator:certificates

View File

@@ -6,6 +6,7 @@ configure:
- zaza.charm_tests.noop.setup.basic_setup - zaza.charm_tests.noop.setup.basic_setup
tests: tests:
- zaza.sunbeam.charm_tests.clusterd.tests.ClusterdTest - zaza.sunbeam.charm_tests.clusterd.tests.ClusterdTest
- zaza.sunbeam.charm_tests.epa_orchestrator.tests.EpaOrchestratorTest
tests_options: tests_options:
trust: trust:
- smoke - smoke
@@ -26,3 +27,6 @@ target_deploy_status:
tls-operator: tls-operator:
workload-status: active workload-status: active
workload-status-message-regex: '^$' workload-status-message-regex: '^$'
epa-orchestrator:
workload-status: active
workload-status-message-regex: '^$'

View File

@@ -142,6 +142,18 @@
- rebuild - rebuild
vars: vars:
charm: cinder-ceph-k8s charm: cinder-ceph-k8s
- job:
name: charm-build-epa-orchestrator
description: Build sunbeam epa-orchestrator charm
run: playbooks/charm/build.yaml
timeout: 3600
match-on-config-updates: false
files:
- ops-sunbeam/ops_sunbeam/*
- charms/epa-orchestrator/*
- rebuild
vars:
charm: epa-orchestrator
- job: - job:
name: charm-build-horizon-k8s name: charm-build-horizon-k8s
description: Build sunbeam horizon-k8s charm description: Build sunbeam horizon-k8s charm
@@ -601,10 +613,13 @@
soft: true soft: true
- name: charm-build-sunbeam-clusterd - name: charm-build-sunbeam-clusterd
soft: true soft: true
- name: charm-build-epa-orchestrator
soft: true
files: files:
- ops-sunbeam/ops_sunbeam/ - ops-sunbeam/ops_sunbeam/
- charms/sunbeam-machine/ - charms/sunbeam-machine/
- charms/sunbeam-clusterd/ - charms/sunbeam-clusterd/
- charms/epa-orchestrator/
- rebuild - rebuild
- zuul.d/zuul.yaml - zuul.d/zuul.yaml
vars: vars:
@@ -612,6 +627,7 @@
charm_jobs: charm_jobs:
- charm-build-sunbeam-machine - charm-build-sunbeam-machine
- charm-build-sunbeam-clusterd - charm-build-sunbeam-clusterd
- charm-build-epa-orchestrator
test_dir: tests/machine test_dir: tests/machine
- job: - job:
@@ -705,6 +721,19 @@
- charmhub_token - charmhub_token
timeout: 3600 timeout: 3600
- job:
name: publish-charm-epa-orchestrator
description: |
Publish epa-orchestrator built in gate pipeline.
run: playbooks/charm/publish.yaml
files:
- ops-sunbeam/ops_sunbeam/
- charms/epa-orchestrator/
- rebuild
secrets:
- charmhub_token
timeout: 3600
- job: - job:
name: publish-charm-designate-bind-k8s name: publish-charm-designate-bind-k8s
description: | description: |

View File

@@ -60,6 +60,8 @@
nodeset: ubuntu-jammy nodeset: ubuntu-jammy
- charm-build-cinder-volume-ceph: - charm-build-cinder-volume-ceph:
nodeset: ubuntu-jammy nodeset: ubuntu-jammy
- charm-build-epa-orchestrator:
nodeset: ubuntu-jammy
- charm-build-horizon-k8s: - charm-build-horizon-k8s:
nodeset: ubuntu-jammy nodeset: ubuntu-jammy
- charm-build-heat-k8s: - charm-build-heat-k8s:
@@ -123,6 +125,8 @@
nodeset: ubuntu-jammy nodeset: ubuntu-jammy
- charm-build-cinder-volume-ceph: - charm-build-cinder-volume-ceph:
nodeset: ubuntu-jammy nodeset: ubuntu-jammy
- charm-build-epa-orchestrator:
nodeset: ubuntu-jammy
- charm-build-horizon-k8s: - charm-build-horizon-k8s:
nodeset: ubuntu-jammy nodeset: ubuntu-jammy
- charm-build-heat-k8s: - charm-build-heat-k8s:
@@ -190,6 +194,8 @@
nodeset: ubuntu-jammy nodeset: ubuntu-jammy
- publish-charm-cinder-volume-ceph: - publish-charm-cinder-volume-ceph:
nodeset: ubuntu-jammy nodeset: ubuntu-jammy
- publish-charm-epa-orchestrator:
nodeset: ubuntu-jammy
- publish-charm-horizon-k8s: - publish-charm-horizon-k8s:
nodeset: ubuntu-jammy nodeset: ubuntu-jammy
- publish-charm-heat-k8s: - publish-charm-heat-k8s:

View File

@@ -1,85 +1,85 @@
- secret: - secret:
name: charmhub_token name: charmhub_token
data: data:
# Generated on 2025-05-06T09:43:50+00:00 with 90 days ttl # Generated on 2025-06-26T07:38:31+00:00 with 90 days ttl
value: !encrypted/pkcs1-oaep value: !encrypted/pkcs1-oaep
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- WcPYaXXmJH97/WRhrGZ+ndSMb7sGrl+qr1lHAk+rE/N47IkwoFi3oqg5m1CjVq8BqvAp+ - MMSWA0wsAms9XtBHQHLI9neQW2TgFVu/LGCFFizCtK9WR92EVLXKFSIlNC6vQF1aREdCC
aCNQTvEsvqMi5AqhxPIqrFmD/lkjF1MloybERIBqr/Y3043LyJbxYPSq3hRbRW4KhoDMW rtgPos7FNcEkV9miObaPczyFbiCmZQatCd6dTnW7Un96LFLgh3GksjYxO5A8nnOu5fSQi
/EBgROqquyOmipUDUW4h4wzRNwGZb9MmyWutzU/w0ihLrZmwdaknUhI/3HPBfvTnZpNQp jG3FRz24aj5WtRlRkAWMpQZNcBJ4mSriYoMjHDbfSpp8HHQVpKuQWn1dwqYdGr6JLEJsF
KGIMd53aFmPt5WrN8GoH/qKWT4EneZEsGHgoEgAeN37GXRbtZv5X+vcTRjQSaETcQWlk6 efsaW3lDO3uUEZjYN9g4bdAKy/hUPWQ95TbtrnZeEC+bv+EsrNi0QemIAuwKCv2I09uOP
kSKEkOq3ibCUXLpGKmGzHIR88BHbyH0Xs8nZDy/Gm5OFQOjQxHngOv87n8pDBjALpV7oC ndfPdFS/mDN8Oo0AFf0Rmo0S5/jdcFiB4JJVoDIxKvN+6YVOYDQdNF3+Qzzd5pO8KxwOg
Idg6b6jcQBYrcP2rcKoofaNXIKUkroHEIMUDw/TaLiFWVdFhZu7QBmCSDJzWMmWKfn7CL aQcYbXJFpolET8FGKAE7zESvXs3Iibmu0SACXFFV1fLb70N6v0L1Ja+CblIVv7Alcwpg4
ZzCPnffTN1gmcX9djjmHw28PUqShFCEfePq+QCROie1MJ/4U87YVgBIC+cYm9WZJ7eADO cxueSKbilINiW7Cz68GGQ2XOPBUonxpRCsNGsp2UyMRPDmYh2FkwSF+F5lkpVJZNu7DtH
0E5s0rxbVLXk9icWrsY59X9ieyqf6n2fW5cq9WHmhzN8LL6JzibTE6i2RhQeUCzhy/dVD gb4LYkUuZ7EMOdILPuc825F5Ca6I+2cYNlstXPN2g3gkex9HMwoS+YmdZTvtBqr2wX4ch
LFQw2Wknv3uhsiiA95YjrMv+JC9Zl/gqsw79Mf2TSb6bl4rum/+GgjHLEjWlIxspEz5OU tkeOhIMlRKyT3151F02Ub2AuXMaOQHDn1ZX59XVAjF4S06cowvN74Nppqqf3RPkxk7iDX
7HnylTk3ZTpg5m1ufWd1e7etWUDfxOL4d0c3WzcuHqoKkU5e572ENznJnwm1yE= MFGVCcBAhtvUNenMtt7n7SYQPwsSHtnY8lbqYHaj1HsXWJzi0bso0d7enVd7fE=

View File

@@ -50,3 +50,4 @@
sunbeam-clusterd: 2025.1/edge sunbeam-clusterd: 2025.1/edge
tempest-k8s: 2025.1/edge tempest-k8s: 2025.1/edge
watcher-k8s: 2025.1/edge watcher-k8s: 2025.1/edge
epa-orchestrator: 2025.1/edge