diff --git a/.github/workflows/build_fedora_docker.yaml b/.github/workflows/build_fedora_docker.yaml new file mode 100644 index 00000000..618e9781 --- /dev/null +++ b/.github/workflows/build_fedora_docker.yaml @@ -0,0 +1,70 @@ +name: Build Fedora Image + +on: + push: + branches: + - main + paths: + - ".github/workflows/cd.yaml" + - "pipelines/serpro/*" + - "pyproject.toml" + - "Dockerfile-fedora" + pull_request: + branches: + - main + paths: + - ".github/workflows/cd_staging.yaml" + - "pipelines/serpro/*" + - "pyproject.toml" + - "Dockerfile-fedora" +env: + GKE_PROJECT_ID: ${{ secrets.GKE_PROJECT_ID }} + GKE_SA_KEY: ${{ secrets.GKE_SA_KEY }} + GKE_CLUSTER: ${{ secrets.GKE_APP_CLUSTER_NAME }} + GKE_ZONE: ${{ secrets.GKE_CLUSTER_ZONE }} + IMAGE_NAME: gcr.io/rj-smtr/pipelines-fedora + +jobs: + build-container: + name: Build Fedora Image + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Python version + uses: actions/setup-python@v2 + with: + python-version: "3.9" + + - run: |- + pip install --no-cache-dir -r requirements.txt + + # - name: Update image tag in constants + # run: |- + # python .github/workflows/scripts/replace_docker_tag.py gcr.io/${{ env.GKE_PROJECT_ID }}/${{ env.IMAGE_NAME }}:${{ github.sha }} + + # Setup gcloud CLI + - name: Setup Google Cloud CLI + uses: google-github-actions/setup-gcloud@v0.2.1 + with: + service_account_key: ${{ secrets.GKE_SA_KEY }} + project_id: ${{ secrets.GKE_PROJECT_ID}} + export_default_credentials: true + + - name: Get GKE credentials + uses: google-github-actions/get-gke-credentials@v0.2.1 + with: + cluster_name: ${{ env.GKE_CLUSTER }} + location: ${{ env.GKE_ZONE }} + credentials: ${{ secrets.GKE_SA_KEY }} + + # Configure Docker to use the gcloud command-line tool as a credential + # helper for authentication + - run: |- + gcloud --quiet auth configure-docker + + - name: Build and publish image + run: | + docker build -t $IMAGE_NAME:${{ github.sha}} . -f Dockerfile-fedora + docker push $IMAGE_NAME:${{ github.sha }} \ No newline at end of file diff --git a/.github/workflows/cd-docs.yaml b/.github/workflows/cd-docs.yaml index 575a2215..3ebbb8fd 100644 --- a/.github/workflows/cd-docs.yaml +++ b/.github/workflows/cd-docs.yaml @@ -4,7 +4,6 @@ on: push: branches: - main - - staging/* env: GKE_PROJECT_ID: ${{ secrets.GKE_PROJECT_ID }} diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml index 58a7eb72..e02950dc 100644 --- a/.github/workflows/cd.yaml +++ b/.github/workflows/cd.yaml @@ -46,6 +46,10 @@ jobs: run: |- python .github/workflows/scripts/replace_docker_tag.py ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }} ${{ github.sha }} + - name: Update image tag in constants + run: |- + python .github/workflows/scripts/replace_docker_tag.py fedora gcr.io/rj-smtr/pipelines-fedora ${{ github.sha }} + - name: Get changed files for code tree analysis id: files uses: Ana06/get-changed-files@v2.1.0 @@ -69,6 +73,14 @@ jobs: repo-token: ${{ secrets.GITHUB_TOKEN }} verbose: true + - name: Wait for Docker image to be available + uses: lewagon/wait-on-check-action@v1.3.1 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + check-name: 'Build Fedora Image' + repo-token: ${{ secrets.GITHUB_TOKEN }} + verbose: true + - name: Register Prefect flows run: |- python .github/workflows/scripts/register_flows.py --project $PREFECT__SERVER__PROJECT --path pipelines/ --schedule --filter-affected-flows \ No newline at end of file diff --git a/.github/workflows/cd_staging.yaml b/.github/workflows/cd_staging.yaml index d875d773..3e5702a7 100644 --- a/.github/workflows/cd_staging.yaml +++ b/.github/workflows/cd_staging.yaml @@ -46,7 +46,12 @@ jobs: - name: Update image tag in constants run: |- - python .github/workflows/scripts/replace_docker_tag.py ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }} ${{ github.sha }} + python .github/workflows/scripts/replace_docker_tag.py debian ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }} ${{ github.sha }} + + - name: Update image tag in constants + run: |- + python .github/workflows/scripts/replace_docker_tag.py fedora gcr.io/rj-smtr/pipelines-fedora ${{ github.sha }} + - name: Get changed files for code tree analysis id: files @@ -71,6 +76,14 @@ jobs: repo-token: ${{ secrets.GITHUB_TOKEN }} verbose: true + - name: Wait for Docker image to be available + uses: lewagon/wait-on-check-action@v1.3.1 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + check-name: 'Build Fedora Image' + repo-token: ${{ secrets.GITHUB_TOKEN }} + verbose: true + - name: Register Prefect flows run: |- python .github/workflows/scripts/register_flows.py --project $PREFECT__SERVER__PROJECT --path pipelines/ --no-schedule --filter-affected-flows \ No newline at end of file diff --git a/.github/workflows/scripts/replace_docker_tag.py b/.github/workflows/scripts/replace_docker_tag.py index a340a551..b6be1966 100644 --- a/.github/workflows/scripts/replace_docker_tag.py +++ b/.github/workflows/scripts/replace_docker_tag.py @@ -11,16 +11,18 @@ FILE_PATH = Path("./pipelines/constants.py") REPLACE_TAG = "AUTO_REPLACE_DOCKER_TAG" REPLACE_IMAGE = "AUTO_REPLACE_DOCKER_IMAGE" +REPLACE_FEDORA_IMAGE = "AUTO_REPLACE_FEDORA_IMAGE" +REPLACE_FEDORA_TAG = "AUTO_REPLACE_FEDORA_TAG" def get_name_version_from_args() -> List[str]: """ Returns the version from the command line arguments. """ - if len(argv) != 3: - print("Usage: replace_docker_tag.py ") + if len(argv) != 4: + print("Usage: replace_docker_tag.py ") exit(1) - return argv[1], argv[2] + return argv[1], argv[2], argv[3] def replace_in_text(orig_text: str, find_text: str, replace_text: str) -> str: @@ -30,18 +32,25 @@ def replace_in_text(orig_text: str, find_text: str, replace_text: str) -> str: return orig_text.replace(find_text, replace_text) -def update_file(file_path: Path, image_name: str, version: str) -> None: +def update_file(file_path: Path, image_name: str, version: str, mode: str = None) -> None: """ Updates the `DOCKER_TAG` variable in the `constants.py` file. """ with file_path.open("r") as file: text = file.read() - text = replace_in_text(text, REPLACE_TAG, version) - text = replace_in_text(text, REPLACE_IMAGE, image_name) + if mode.lower() == "fedora": + replace_tag = REPLACE_FEDORA_TAG + replace_image = REPLACE_FEDORA_IMAGE + else: + replace_tag = REPLACE_TAG + replace_image = REPLACE_IMAGE + print(f"Will replace {replace_image}:{replace_tag} -> {image_name}:{version}") + text = replace_in_text(text, replace_tag, version) + text = replace_in_text(text, replace_image, image_name) with file_path.open("w") as file: file.write(text) if __name__ == "__main__": - image_name, version = get_name_version_from_args() - update_file(FILE_PATH, image_name, version) + mode, image_name, version = get_name_version_from_args() + update_file(FILE_PATH, image_name, version, mode=mode) diff --git a/.gitignore b/.gitignore index fa7f85e7..27632eb9 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,9 @@ ENV/ env.bak/ venv.bak/ +# DBT +queries/profiles + # Spyder project settings .spyderproject .spyproject diff --git a/Dockerfile-fedora b/Dockerfile-fedora new file mode 100644 index 00000000..49ebdcc8 --- /dev/null +++ b/Dockerfile-fedora @@ -0,0 +1,25 @@ +# Build arguments +# ARG PYTHON_VERSION=3.10-slim + +# Start Python image +FROM fedora:latest +# RUN python3 --version +RUN dnf -y install python3.10 && dnf clean all +RUN yum install java -y +RUN yum install make -y +# RUN dnf remove python3.12 +# Setting environment with prefect version +ARG PREFECT_VERSION=1.4.1 +ENV PREFECT_VERSION $PREFECT_VERSION + +# Setup virtual environment and prefect +ENV VIRTUAL_ENV=/opt/venv +RUN python3.10 -m venv $VIRTUAL_ENV +ENV PATH="$VIRTUAL_ENV/bin:$PATH" +RUN python3.10 -m pip install --no-cache-dir -U "pip>=21.2.4" "prefect==$PREFECT_VERSION" + +# Install requirements +WORKDIR /app +COPY . . +RUN python3.10 -m pip install --prefer-binary --no-cache-dir -U . +RUN python3 -m pip install jaydebeapi diff --git a/pipelines/constants.py b/pipelines/constants.py index 32043924..542dd438 100644 --- a/pipelines/constants.py +++ b/pipelines/constants.py @@ -19,6 +19,9 @@ class constants(Enum): # pylint: disable=c0103 DOCKER_TAG = "AUTO_REPLACE_DOCKER_TAG" DOCKER_IMAGE_NAME = "AUTO_REPLACE_DOCKER_IMAGE" DOCKER_IMAGE = f"{DOCKER_IMAGE_NAME}:{DOCKER_TAG}" + DOCKER_FEDORA_TAG = "AUTO_REPLACE_FEDORA_TAG" + DOCKER_FEDORA_IMAGE_NAME = "AUTO_REPLACE_FEDORA_IMAGE" + DOCKER_IMAGE_FEDORA = f"{DOCKER_FEDORA_IMAGE_NAME}:{DOCKER_FEDORA_TAG}" GCS_FLOWS_BUCKET = "datario-public" # PROJECT_NAME = {"dev": "rj-smtr-dev", "prod": "rj-smtr"} # DEFAULT_BUCKET_NAME = {"dev": "br-rj-smtr-dev", "prod": "br-rj-smtr"} diff --git a/pipelines/flows.py b/pipelines/flows.py index 1a915ff2..457da8d9 100644 --- a/pipelines/flows.py +++ b/pipelines/flows.py @@ -19,4 +19,5 @@ from pipelines.migration.controle_financeiro.flows import * # noqa from pipelines.migration.projeto_subsidio_sppo.flows import * # noqa from pipelines.migration.veiculo.flows import * # noqa +from pipelines.serpro.flows import * # noqa from pipelines.treatment.bilhetagem.flows import * # noqa diff --git a/pipelines/serpro/__init__.py b/pipelines/serpro/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pipelines/serpro/flows.py b/pipelines/serpro/flows.py new file mode 100644 index 00000000..2e0585b2 --- /dev/null +++ b/pipelines/serpro/flows.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from prefect.run_configs import KubernetesRun +from prefect.storage import GCS +from prefeitura_rio.pipelines_utils.custom import Flow + +from pipelines.constants import constants as smtr_constants +from pipelines.serpro.tasks import wait_sleeping +from pipelines.serpro.utils import handler_setup_serpro + +with Flow("SMTR - Teste Conexão Serpro") as flow: + # setup_serpro() + wait_sleeping() + +flow.storage = GCS(smtr_constants.GCS_FLOWS_BUCKET.value) +flow.run_config = KubernetesRun( + image=smtr_constants.DOCKER_IMAGE_FEDORA.value, + labels=[smtr_constants.RJ_SMTR_AGENT_LABEL.value], +) +flow.state_handlers = [handler_setup_serpro] diff --git a/pipelines/serpro/tasks.py b/pipelines/serpro/tasks.py new file mode 100644 index 00000000..aec6afe3 --- /dev/null +++ b/pipelines/serpro/tasks.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +from time import sleep + +from prefect import task + +from pipelines.utils.jdbc import JDBC + + +@task +def wait_sleeping(interval_seconds: int = 54000, wait=None): + sleep(interval_seconds) + + +@task +def get_db_object(secret_path="radar_serpro", environment: str = "dev"): + return JDBC(db_params_secret_path=secret_path, environment=environment) diff --git a/pipelines/serpro/utils.py b/pipelines/serpro/utils.py new file mode 100644 index 00000000..d0ec87da --- /dev/null +++ b/pipelines/serpro/utils.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +import os + +from prefect.engine.state import State + +from pipelines.utils.secret import get_secret +from pipelines.utils.utils import log + + +def setup_serpro(secret_path: str = "radar_serpro"): + data = get_secret(secret_path=secret_path)["setup.sh"] + log("Got Secret") + os.popen("touch setup.sh") + with open("setup.sh", "w") as f: + f.write(data) + return os.popen("sh setup.sh") + + +def handler_setup_serpro(obj, old_state: State, new_state: State) -> State: + """ + State handler that will inject BD credentials into the environment. + """ + if new_state.is_running(): + setup_serpro() + return new_state diff --git a/pipelines/utils/jdbc.py b/pipelines/utils/jdbc.py new file mode 100644 index 00000000..9a4e9b39 --- /dev/null +++ b/pipelines/utils/jdbc.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +from typing import List + +import jaydebeapi as jdb + +from pipelines.utils.secret import get_secret + + +class JDBC: + def __init__(self, db_params_secret_path: str, environment: str = "staging") -> None: + self._environment = environment + self._secret_path = db_params_secret_path + self._conn_kwargs = self.get_conn_kwargs() + self._connection = self.connect() + self._cursor = self.get_cursor() + + def get_conn_kwargs(self): + + data = get_secret(secret_path=self._secret_path, environment=self._environment) + conn_kwargs = dict( + jclassname=data["jclassname"], + user=data["user"], + password=data["password"], + url=data["url"], + jars=[data["jars"]], + ) + return conn_kwargs + + def connect(self): + data = get_secret(secret_path=self._secret_path, environment=self._environment) + + return jdb.connect( + jclassname=data["jclassname"], + url=data["url"], + jars=rf"{data['jars']}", + driver_args=[data["user"], data["password"]], + ) + + def get_cursor(self): + """ + Returns a cursor for the JDBC database. + """ + return self._connection.cursor() + + def execute_query(self, query: str) -> None: + """ + Execute query on the JDBC database. + + Args: + query: The query to execute. + """ + self._cursor.execute(query) + + def get_columns(self) -> List[str]: + """ + Returns the column names of the JDBC database. + """ + return [column[0] for column in self._cursor.description] + + def fetch_batch(self, batch_size: int) -> List[List]: + """ + Fetches a batch of rows from the JDBC database. + """ + return [list(item) for item in self._cursor.fetchmany(batch_size)] + + def fetch_all(self) -> List[List]: + """ + Fetches all rows from the JDBC database. + """ + return [list(item) for item in self._cursor.fetchall()] diff --git a/pipelines/utils/secret.py b/pipelines/utils/secret.py index ad35e519..22f9e4d7 100644 --- a/pipelines/utils/secret.py +++ b/pipelines/utils/secret.py @@ -19,7 +19,7 @@ def get_secret(secret_path: str = "/", secret_name: str = None, environment: str if not secret_path.startswith("/"): secret_path = f"/{secret_path}" if secret_path and not secret_name: - secrets = client.get_all_secrets(path=secret_path) + secrets = client.get_all_secrets(path=secret_path, environment=environment) return {s.secret_name.lower(): s.secret_value for s in secrets} secret = client.get_secret(secret_name=secret_name, path=secret_path, environment=environment) return {secret_name.lower(): secret.secret_value} diff --git a/poetry.lock b/poetry.lock index 3e3c8e8f..9031d4c7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "agate" @@ -1382,6 +1382,21 @@ pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib" plugins = ["setuptools"] requirements-deprecated-finder = ["pip-api", "pipreqs"] +[[package]] +name = "jaydebeapi" +version = "1.2.3" +description = "Use JDBC database drivers from Python 2/3 or Jython with a DB-API." +optional = false +python-versions = "*" +files = [ + {file = "JayDeBeApi-1.2.3-py2-none-any.whl", hash = "sha256:fbfbc7e41d7b35af08df6376a73637820c71a1373b40244b135bd07f3e865c81"}, + {file = "JayDeBeApi-1.2.3-py3-none-any.whl", hash = "sha256:d6256bdad1e14414225fbc839f7d56922ea3abc06153f3a57490fee909fecd64"}, + {file = "JayDeBeApi-1.2.3.tar.gz", hash = "sha256:f25e9307fbb5960cb035394c26e37731b64cc465b197c4344cee85ec450ab92f"}, +] + +[package.dependencies] +JPype1 = {version = "*", markers = "python_version > \"2.7\" and platform_python_implementation != \"Jython\""} + [[package]] name = "jinja2" version = "3.1.2" @@ -1399,6 +1414,45 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jpype1" +version = "1.5.0" +description = "A Python to Java bridge." +optional = false +python-versions = ">=3.7" +files = [ + {file = "JPype1-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7b6b1af3f9e0033080e3532c2686a224cd14706f36c14ef36160a2a1db751a17"}, + {file = "JPype1-1.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ed36803734b812c78ca9228dd3291128ac80b2a1d06c293d60b5c2f049040b4"}, + {file = "JPype1-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a02b2f05621c119d35f4acc501b4261eeb48a4af7cc13d9afc2e9eb316c4bd29"}, + {file = "JPype1-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:0b40c76e075d4fed2c83340bb30b7b95bbc396fd370c564c6b608faab00ea4ef"}, + {file = "JPype1-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:85a31b30b482eaf788b21af421e0750aa0be7758307314178143a76632b0ad04"}, + {file = "JPype1-1.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20f0229d7aaa04c480a7fa271cbd161ded58cecd838ba52a4e01bea21b60a058"}, + {file = "JPype1-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ef976e0f3b2e9604469f449f30bb2031941a159a0637f4c16adb2c5076f3e81"}, + {file = "JPype1-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:2bc987205ff8d2d8e36dfbef05430e0638e85d4fee1166ba58ebfa6f7a67cdf8"}, + {file = "JPype1-1.5.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8714bfaf09d6877160bc7ac97812016ccb09f6d7ba5ea2a9f519178aefcca93f"}, + {file = "JPype1-1.5.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1696196a8b6ea2f8ad3280249014406de919088494b94a84581da01752d98dca"}, + {file = "JPype1-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8649b526eccb4047881ad60bdb1974eb71a09cdb7f8bda17c96fdc0f9a3f2d1e"}, + {file = "JPype1-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:9aafc00b00bf8c1b624081e5d4ab87f7752e6c7ee6a141cfc332250b05c6d42f"}, + {file = "JPype1-1.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccb9c786e9b709c6390c89e200036b2080bf668cce118561a0cfd74eae43903f"}, + {file = "JPype1-1.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa5a27cba59865f034259657fd322ca0a5cde82e691a1180c6a8040d2e0c0788"}, + {file = "JPype1-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cff64ac1980d899841cbc561b097eeec8106b34d70c42342b211b83005562f88"}, + {file = "JPype1-1.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:439e006a3a74bd26e15ab6bca873e3572087667b5525cb82244a1945dd607d80"}, + {file = "JPype1-1.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b437ce6fadaf5562576b2b5919fa0a5174a92f70a7d903f0faf8dff6f34199fa"}, + {file = "JPype1-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:a01eba1fdf5869e46dc7336a8ff2a97a66d209c8d5f23a64f7f23b70e55ffc0f"}, + {file = "JPype1-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e8d9bdd137e7cecabebd46ce7d3539fd53745018974d0bc3ec0a3634c2e53af5"}, + {file = "JPype1-1.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9f8f01474186bf69bf05dd9a5ef4d5b2159980cfc9d8da91e021d682cc32552"}, + {file = "JPype1-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7aa1469d75f9b310f709b61bb2faa4cef4cbd4d670531ad1d1bb53e29cfda05"}, + {file = "JPype1-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:6bfdc101c56cab0b6b16e974fd8cbb0b3f7f14178286b8b55413c5d82d5f2bea"}, + {file = "JPype1-1.5.0.tar.gz", hash = "sha256:425a6e1966afdd5848b60c2688bcaeb7e40ba504a686f1114589668e0631e878"}, +] + +[package.dependencies] +packaging = "*" + +[package.extras] +docs = ["readthedocs-sphinx-ext", "sphinx", "sphinx-rtd-theme"] +tests = ["pytest"] + [[package]] name = "jsonschema" version = "4.20.0" @@ -2825,7 +2879,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3642,4 +3695,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.11" -content-hash = "63916f4608ce386360d6407898cdde87a540c8eaeee929e872ae0342ce4db413" +content-hash = "5d5ac7e559d00768e8d9a1e0e867be0ff587de81f8f2268697c35ccadcc310e0" diff --git a/pyproject.toml b/pyproject.toml index 6b56c451..27011dc3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -152,6 +152,9 @@ networkx = "^3.1" loguru = "^0.7.0" typer = "^0.9.0" +[tool.poetry.group.extras.dependencies] +jaydebeapi = "1.2.3" + [tool.black] line-length = 100 target-version = ["py310"] diff --git a/requirements.txt b/requirements.txt index 9715c794..d6b61e6f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -45,6 +45,7 @@ importlib-metadata==6.11.0 importlib-resources==6.1.1 infisical==1.5.0 isodate==0.6.1 +JayDeBeApi==1.2.3 Jinja2==3.1.2 jsonschema==4.20.0 jsonschema-specifications==2023.11.2