From e7fa62ebf7671640469761003492b6c59079a999 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 10:12:13 +0100 Subject: [PATCH 01/16] Bump aquasecurity/trivy-action from 0.16.0 to 0.16.1 (#2244) Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.16.0 to 0.16.1. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.16.0...0.16.1) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy-zenml-core.yml | 2 +- .github/workflows/trivy-zenserver.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/trivy-zenml-core.yml b/.github/workflows/trivy-zenml-core.yml index db25b9b4b66..3f67011ef3f 100644 --- a/.github/workflows/trivy-zenml-core.yml +++ b/.github/workflows/trivy-zenml-core.yml @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@v4.1.1 - name: zenml-Trivy vulnerability scanner - uses: aquasecurity/trivy-action@0.16.0 + uses: aquasecurity/trivy-action@0.16.1 with: image-ref: "docker.io/zenmldocker/zenml:latest" format: "sarif" diff --git a/.github/workflows/trivy-zenserver.yml b/.github/workflows/trivy-zenserver.yml index e3e8f8a6100..655571619a6 100644 --- a/.github/workflows/trivy-zenserver.yml +++ b/.github/workflows/trivy-zenserver.yml @@ -15,7 +15,7 @@ jobs: uses: actions/checkout@v4.1.1 - name: zenserver-Trivy vulnerability scanner - uses: aquasecurity/trivy-action@0.16.0 + uses: aquasecurity/trivy-action@0.16.1 with: image-ref: "docker.io/zenmldocker/zenml-server:latest" format: "sarif" From 60aef386a0a666de6565f8cd094fb2760ff82b35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 10:16:43 +0100 Subject: [PATCH 02/16] Bump crate-ci/typos from 1.16.26 to 1.17.0 (#2245) Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.16.26 to 1.17.0. - [Release notes](https://github.com/crate-ci/typos/releases) - [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md) - [Commits](https://github.com/crate-ci/typos/compare/v1.16.26...v1.17.0) --- updated-dependencies: - dependency-name: crate-ci/typos dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/setup-python-environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/setup-python-environment.yml b/.github/workflows/setup-python-environment.yml index 15c6190b338..3d95564838c 100644 --- a/.github/workflows/setup-python-environment.yml +++ b/.github/workflows/setup-python-environment.yml @@ -108,7 +108,7 @@ jobs: bash scripts/lint.sh - name: Spelling checker - uses: crate-ci/typos@v1.16.26 + uses: crate-ci/typos@v1.17.0 with: files: "." config: ./.typos.toml From 32477fc5938e2078d92a85e9f901ece34be899b7 Mon Sep 17 00:00:00 2001 From: Alex Strick van Linschoten Date: Tue, 9 Jan 2024 13:28:32 +0100 Subject: [PATCH 03/16] Add YAML formatting standardisation to formatting & linting scripts (#2224) * add yamlfix dev dependency * Fix formatting and linting issues This commit fixes formatting issues in the `format.sh` script and adds a step to standardize/format CI yaml files. It also adds a check for yaml formatting errors in the `lint.sh` script. * apply yamlfix formatting * apply yamlfix formatting to tests folder * update scripts to include test files * handle failing template tests * Auto-update of Starter template * Auto-update of E2E template * Auto-update of NLP template * formatting for examples * Auto-update of Starter template * Auto-update of E2E template * formatting for template push * Auto-update of Starter template * Auto-update of E2E template * Auto-update of NLP template * update templates script to format for yaml as well * format examples * install yamlfix in workflow directly * fix scarf-check script --------- Co-authored-by: GitHub Actions --- .github/ISSUE_TEMPLATE/bug_report.yml | 21 ++-- .github/ISSUE_TEMPLATE/config.yml | 1 + .github/actions/setup_environment/action.yml | 64 ++++++------- .github/branch-labels.yml | 9 +- .github/codecov.yml | 12 +-- .github/dependabot.yml | 24 +++-- .github/teams.yml | 3 +- .github/workflows/ci.yml | 78 +++++---------- .github/workflows/codeql.yml | 19 ++-- .github/workflows/image-optimiser.yml | 11 +-- .github/workflows/integration-test.yml | 95 ++++++------------- .github/workflows/mixpanel-test-data.yml | 8 +- .github/workflows/nightly_build.yml | 56 +++++------ .github/workflows/pr_labeler.yml | 16 ++-- .github/workflows/publish_api_docs.yml | 19 ++-- .github/workflows/publish_docker_image.yml | 11 +-- .github/workflows/publish_helm_chart.yml | 23 ++--- .github/workflows/publish_to_pypi.yml | 14 +-- .github/workflows/publish_to_pypi_nightly.yml | 41 ++++---- .github/workflows/release.yml | 67 +++++-------- .github/workflows/scarf-check.yml | 8 +- .../workflows/setup-python-environment.yml | 68 +++++-------- .github/workflows/templates-test.yml | 53 ++++------- .github/workflows/trivy-zenml-core.yml | 19 ++-- .github/workflows/trivy-zenserver.yml | 17 ++-- .../update-templates-to-examples.yml | 85 ++++++----------- pyproject.toml | 4 +- scripts/format.sh | 16 ++++ scripts/lint.sh | 16 ++++ tests/harness/cfg/deployments.yaml | 7 +- tests/harness/cfg/environments.yaml | 28 ++---- tests/harness/cfg/requirements.yaml | 14 +-- tests/harness/cfg/tests.yaml | 91 +++++------------- 33 files changed, 387 insertions(+), 631 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index f09ad3581f7..105845476b2 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,13 +1,13 @@ +--- name: Bug Report description: File a bug report -title: "[BUG]: " -labels: ["bug"] +title: '[BUG]: ' +labels: [bug] body: - type: markdown attributes: value: | Thanks for taking the time to fill out this bug report! - - type: input id: contact attributes: @@ -16,16 +16,16 @@ body: placeholder: your@awesome.com validations: required: false - - type: textarea id: system-information attributes: label: System Information description: zenml info -a -s - placeholder: "Copy paste the output of the above command here. If using ZenML < 0.36.0, then remove the `-s` flag above. If using ZenML version < 0.8.0, then paste in Python version, OS, ZenML version, and installed integrations." + placeholder: Copy paste the output of the above command here. If using ZenML + < 0.36.0, then remove the `-s` flag above. If using ZenML version < 0.8.0, + then paste in Python version, OS, ZenML version, and installed integrations. validations: required: true - - type: textarea id: what-happened attributes: @@ -34,12 +34,12 @@ body: placeholder: A clear and concise description of what the bug is. validations: required: true - - type: textarea id: reproduce attributes: label: Reproduction steps - description: "How do you trigger this bug? Please walk us through it step by step." + description: How do you trigger this bug? Please walk us through it step by + step. value: | 1. 2. @@ -47,14 +47,13 @@ body: ... validations: required: false - - type: textarea id: logs attributes: label: Relevant log output - description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + description: Please copy and paste any relevant log output. This will be automatically + formatted into code, so no need for backticks. render: shell - - type: checkboxes id: terms attributes: diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index a4c62f33489..2248e22aaaa 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,3 +1,4 @@ +--- blank_issues_enabled: true contact_links: - name: Feature Request diff --git a/.github/actions/setup_environment/action.yml b/.github/actions/setup_environment/action.yml index f8c7f98e86a..375c28d7782 100644 --- a/.github/actions/setup_environment/action.yml +++ b/.github/actions/setup_environment/action.yml @@ -1,81 +1,75 @@ -name: "Install ZenML" -description: "Install ZenML, most integrations, loads/uploads cached venv and pip download cache if applicable" +--- +name: Install ZenML +description: Install ZenML, most integrations, loads/uploads cached venv and pip download + cache if applicable inputs: cache_version: - description: 'Value gets appended to the cache key and will therefore invalidate the cache if it changes' + description: Value gets appended to the cache key and will therefore invalidate + the cache if it changes required: true python-version: - description: 'Python version' + description: Python version type: string required: true os: - description: 'OS' + description: OS type: string required: true install_integrations: - description: 'Install ZenML integrations' + description: Install ZenML integrations type: string required: false default: 'yes' runners_cache_access_key_id: - description: 'Runner cache AWS access key ID' + description: Runner cache AWS access key ID required: true runners_cache_secret_access_key: - description: 'Runner cache AWS secret access key' + description: Runner cache AWS secret access key required: true - - runs: - using: "composite" + using: composite steps: - name: Set up Python uses: actions/setup-python@v5.0.0 with: python-version: ${{ inputs.python-version }} - - name: Delete error-causing bash shell: bash if: ${{ inputs.os == 'windows-latest' }} run: rm.exe "C:/WINDOWS/system32/bash.EXE" - - name: Set path to bash for example runner shell: bash if: ${{ inputs.os == 'windows-latest' }} run: | echo "SHELL_EXECUTABLE=C:\Program Files\Git\bin\bash.exe" >> $GITHUB_ENV - - name: Configure git (non-Windows) if: ${{ inputs.os != 'windows-latest' }} shell: bash run: | git config --global user.email "info@zenml.io" git config --global user.name "ZenML GmbH" - - name: Configure git (Windows) if: ${{ inputs.os == 'windows-latest' }} shell: bash run: | "C:\Program Files\Git\bin\git.exe" config --global user.email "info@zenml.io" "C:\Program Files\Git\bin\git.exe" config --global user.name "ZenML GmbH" - - name: Get current week shell: bash id: date run: echo "::set-output name=week::$(date +'calendar-week-%W')" - - - uses: syphar/restore-virtualenv@v1 - if : ${{ inputs.os != 'ubuntu-dind-runners' }} + if: ${{ inputs.os != 'ubuntu-dind-runners' }} id: cache-virtualenv with: - requirement_files: 'pyproject.toml' + requirement_files: pyproject.toml # The virtualenv cache is invalidated when: # - manually triggered by means of a custom cache version token # - on a weekly basis # - any of the integration requirements change (a hash of the # __init__.py files is included in the cache key) - custom_cache_key_element: ${{ inputs.cache_version }}-${{steps.date.outputs.week}}-${{inputs.install_integrations}}-${{ hashFiles('src/zenml/integrations/*/__init__.py') }} - + custom_cache_key_element: ${{ inputs.cache_version }}-${{steps.date.outputs.week}}-${{inputs.install_integrations}}-${{ + hashFiles('src/zenml/integrations/*/__init__.py') }} - uses: tespkg/actions-cache@v1 if: ${{ inputs.os == 'ubuntu-dind-runners' }} id: custom-cache-pip @@ -84,10 +78,12 @@ runs: AWS_SECRET_ACCESS_KEY: ${{ inputs.runners_cache_secret_access_key }} with: endpoint: minio-service.minio.svc.cluster.local # optional - insecure: true # optional, use http instead of https. default false - bucket: "caching" # required - use-fallback: false # optional, use github actions cache fallback, default false - key: ${{ inputs.os }}-${{ inputs.cache_version }}-${{ inputs.python-version }}-${{steps.date.outputs.week}}-${{inputs.install_integrations}}-${{ hashFiles('src/zenml/integrations/*/__init__.py') }} + insecure: true # optional, use http instead of https. default false + bucket: caching # required + use-fallback: false # optional, use github actions cache fallback, default false + key: ${{ inputs.os }}-${{ inputs.cache_version }}-${{ inputs.python-version + }}-${{steps.date.outputs.week}}-${{inputs.install_integrations}}-${{ hashFiles('src/zenml/integrations/*/__init__.py') + }} path: | ~/.cache/pip restore-keys: | @@ -97,38 +93,36 @@ runs: # - uses: syphar/restore-pip-download-cache@v1 # with: # requirement_files: 'pyproject.toml' - # # The pip download cache can be updated on a weekly basis as new packages - # # don't appear that often + # # The pip download cache can be updated on a weekly basis as new packages + # # don't appear that often # custom_cache_key_element: ${{ inputs.cache_version }}-${{ inputs.python-version }}-${{steps.date.outputs.week}} - - name: Install Terraform (Windows) if: ${{ inputs.os == 'windows-latest' }} shell: bash run: choco install terraform -y - - name: Install Terraform (Mac) if: ${{ inputs.os == 'macos-latest' }} shell: bash run: | brew tap hashicorp/tap brew install hashicorp/tap/terraform - - name: Install ZenML and dependencies - if: steps.cache-virtualenv.outputs.cache-hit != 'true' && steps.custom-cache-pip.outputs.cache-hit != 'true' + if: steps.cache-virtualenv.outputs.cache-hit != 'true' && steps.custom-cache-pip.outputs.cache-hit + != 'true' shell: bash run: | scripts/install-zenml-dev.sh --integrations ${{ inputs.install_integrations }} # if using a cached virtualenv, just refresh the ZenML installation - name: Refresh ZenML installation - if: steps.cache-virtualenv.outputs.cache-hit == 'true' || steps.custom-cache-pip.outputs.cache-hit == 'true' + if: steps.cache-virtualenv.outputs.cache-hit == 'true' || steps.custom-cache-pip.outputs.cache-hit + == 'true' shell: bash run: | scripts/install-zenml-dev.sh --integrations ${{ inputs.install_integrations }} - - name: Check Python environment shell: bash - run: | + run: |- zenml integration list pip list pip check || true diff --git a/.github/branch-labels.yml b/.github/branch-labels.yml index 355519e29a7..438488a4717 100644 --- a/.github/branch-labels.yml +++ b/.github/branch-labels.yml @@ -1,4 +1,5 @@ -enhancement: 'feature/*' -bug: ['bugfix/*', 'bug/*'] -backport: 'backport/*' -documentation: ['documentation/*', 'docs/*'] +--- +enhancement: feature/* +bug: [bugfix/*, bug/*] +backport: backport/* +documentation: [documentation/*, docs/*] diff --git a/.github/codecov.yml b/.github/codecov.yml index fc3e2ca19e6..94c4758913d 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -1,16 +1,14 @@ +--- codecov: branch: main - -comment: false # don't comment on PRs +comment: false # don't comment on PRs github_checks: false - coverage: status: project: default: - threshold: 1% # allow coverage to drop by 1% before failing the PR - - patch: off + threshold: 1% # allow coverage to drop by 1% before failing the PR + patch: false # do not run coverage on changes - changes: off \ No newline at end of file + changes: false diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0fe158987f2..0ac1e67cc46 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,15 +1,13 @@ +--- version: 2 updates: -- package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - day: "tuesday" - time: "09:00" - timezone: "Europe/Amsterdam" - reviewers: - - "strickvl" - labels: - - "dependencies" - - "internal" - target-branch: "develop" + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + day: tuesday + time: 09:00 + timezone: Europe/Amsterdam + reviewers: [strickvl] + labels: [dependencies, internal] + target-branch: develop diff --git a/.github/teams.yml b/.github/teams.yml index 8cf241f9c2d..223702517da 100644 --- a/.github/teams.yml +++ b/.github/teams.yml @@ -1,3 +1,4 @@ +--- internal: - '@htahir1' - '@hamza-zenml' @@ -11,7 +12,7 @@ internal: - '@AlexejPenner' - '@stefannica' - '@jwwwb' - - '@wjayesh' + - '@wjayesh' - '@ayush714' - '@safoinme' - '@fa9r' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6f2c5f1c13..59f7f4a42dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,20 +1,18 @@ +--- name: Build, Lint, Unit, Integration and Templates Tests - on: workflow_dispatch: workflow_call: push: - branches: ["main"] - paths-ignore: ["docs/**", "docker/**", "*", "!pyproject.toml", "**.md"] + branches: [main] + paths-ignore: [docs/**, docker/**, '*', '!pyproject.toml', '**.md'] pull_request: types: [opened, synchronize, ready_for_review] - paths-ignore: ["docs/**", "docker/**", "*", "!pyproject.toml", "**.md"] - + paths-ignore: [docs/**, docker/**, '*', '!pyproject.toml', '**.md'] concurrency: # New commit on branch cancels running workflows of the same branch group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true - jobs: mlstacks-compatibility-check: if: github.event.pull_request.draft == false @@ -22,142 +20,118 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4.1.1 - - name: Set up Python uses: actions/setup-python@v5.0.0 with: - python-version: "3.8" - + python-version: '3.8' - name: Install current package as editable run: | pip install -U pip pip install -e . - - name: Install mlstacks package run: pip install mlstacks - - name: Check for broken dependencies run: pip check - - custom-ubuntu-runners-setup-and-test-python: if: github.event.pull_request.draft == false strategy: matrix: os: [ubuntu-dind-runners] - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ['3.8', '3.9', '3.10', '3.11'] fail-fast: false uses: ./.github/workflows/setup-python-environment.yml with: python-version: ${{ matrix.python-version }} os: ${{ matrix.os }} secrets: inherit - windows-setup-and-test-python: if: github.event.pull_request.draft == false strategy: matrix: os: [windows-latest] - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ['3.8', '3.9', '3.10', '3.11'] fail-fast: false uses: ./.github/workflows/setup-python-environment.yml with: python-version: ${{ matrix.python-version }} os: ${{ matrix.os }} secrets: inherit - macos-setup-and-test-python: if: github.event.pull_request.draft == false strategy: matrix: os: [macos-latest] - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ['3.8', '3.9', '3.10', '3.11'] fail-fast: false uses: ./.github/workflows/setup-python-environment.yml with: python-version: ${{ matrix.python-version }} os: ${{ matrix.os }} secrets: inherit - update-templates-to-examples: # this doesn't work on forked repositories (i.e. outside contributors) # so we disable template updates for those PRs / branches if: github.event.pull_request.head.repo.full_name == 'zenml-io/zenml' uses: ./.github/workflows/update-templates-to-examples.yml with: - python-version: "3.8" + python-version: '3.8' os: ubuntu-latest secrets: inherit - - windows-integration-test: - needs: - - windows-setup-and-test-python + needs: [windows-setup-and-test-python] strategy: matrix: os: [windows-latest] - python-version: ["3.8", "3.9", "3.10", "3.11"] - test_environment: ["default"] - + python-version: ['3.8', '3.9', '3.10', '3.11'] + test_environment: [default] fail-fast: false - uses: ./.github/workflows/integration-test.yml with: os: ${{ matrix.os }} python-version: ${{ matrix.python-version }} test_environment: ${{ matrix.test_environment }} secrets: inherit - macos-integration-test: - needs: - - macos-setup-and-test-python + needs: [macos-setup-and-test-python] strategy: matrix: os: [macos-latest] - python-version: ["3.8", "3.9", "3.10", "3.11"] - test_environment: ["default"] - + python-version: ['3.8', '3.9', '3.10', '3.11'] + test_environment: [default] fail-fast: false - uses: ./.github/workflows/integration-test.yml with: os: ${{ matrix.os }} python-version: ${{ matrix.python-version }} test_environment: ${{ matrix.test_environment }} secrets: inherit - custom-ubuntu-runners-integration-test: - needs: - - custom-ubuntu-runners-setup-and-test-python + needs: [custom-ubuntu-runners-setup-and-test-python] strategy: matrix: os: [ubuntu-dind-runners] # Disabled temporarily while CI is overhauled - python-version: ["3.8", "3.9", "3.10"] + python-version: ['3.8', '3.9', '3.10'] # python-version: ["3.8", "3.9", "3.10", "3.11"] test_environment: - [ - "default", - "docker-server-docker-orchestrator-mysql", - "docker-server-docker-orchestrator-mariadb", - ] + - default + - docker-server-docker-orchestrator-mysql + - docker-server-docker-orchestrator-mariadb exclude: # docker is time-consuming to run, so we only run it on 3.8 - test_environment: docker-server-docker-orchestrator-mysql - python-version: "3.9" + python-version: '3.9' - test_environment: docker-server-docker-orchestrator-mysql - python-version: "3.10" + python-version: '3.10' - test_environment: docker-server-docker-orchestrator-mysql - python-version: "3.11" + python-version: '3.11' - test_environment: docker-server-docker-orchestrator-mariadb - python-version: "3.9" + python-version: '3.9' - test_environment: docker-server-docker-orchestrator-mariadb - python-version: "3.10" + python-version: '3.10' - test_environment: docker-server-docker-orchestrator-mariadb - python-version: "3.11" - + python-version: '3.11' fail-fast: false - uses: ./.github/workflows/integration-test.yml with: os: ${{ matrix.os }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 388c67bcd6e..1c6fbf9d60b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,33 +1,29 @@ -name: "CodeQL vulnerability check" - +--- +name: CodeQL vulnerability check on: push: - branches: ["main", "develop"] + branches: [main, develop] pull_request: # The branches below must be a subset of the branches above - branches: ["develop"] + branches: [develop] types: [opened] - jobs: analyze: if: github.event.pull_request.draft == false name: Analyze - runs-on: 'ubuntu-latest' + runs-on: ubuntu-latest timeout-minutes: 360 permissions: actions: read contents: read security-events: write - strategy: fail-fast: false matrix: - language: ["python"] - + language: [python] steps: - name: Checkout repository uses: actions/checkout@v4.1.1 - - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: @@ -38,8 +34,7 @@ jobs: # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality - - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: - category: "/language:${{matrix.language}}" + category: /language:${{matrix.language}} diff --git a/.github/workflows/image-optimiser.yml b/.github/workflows/image-optimiser.yml index b793fd39f1b..c64ca19ddc3 100644 --- a/.github/workflows/image-optimiser.yml +++ b/.github/workflows/image-optimiser.yml @@ -1,23 +1,20 @@ +--- name: Compress Images on: pull_request: # Run Image Actions when JPG, JPEG, PNG or WebP files are added or changed. # See https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#onpushpull_requestpaths for reference. - paths: - - '**.jpg' - - '**.jpeg' - - '**.png' - - '**.webp' + paths: ['**.jpg', '**.jpeg', '**.png', '**.webp'] jobs: build: # Only run on non-draft PRs within the same repository. - if: github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.draft == false + if: github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.draft + == false name: calibreapp/image-actions runs-on: ubuntu-latest steps: - name: Checkout Repo uses: actions/checkout@v4.1.1 - - name: Compress Images uses: calibreapp/image-actions@1.1.0 with: diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 83f44c12c64..cc72b30b24a 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -1,55 +1,50 @@ +--- name: Integration Tests - on: workflow_call: inputs: os: - description: 'OS' + description: OS type: string required: true python-version: - description: 'Python version' + description: Python version type: string required: true test_environment: - description: 'The test environment' + description: The test environment type: string required: true enable_tmate: - description: 'Enable tmate session for debugging' + description: Enable tmate session for debugging type: string required: false - default: "never" + default: never tmate_timeout: - description: 'Timeout for tmate session (minutes)' + description: Timeout for tmate session (minutes) type: number required: false default: 30 - workflow_dispatch: inputs: os: - description: 'OS' + description: OS type: choice - options: + options: - ubuntu-latest - macos-latest - windows-latest - ubuntu-dind-runners required: false - default: 'ubuntu-latest' + default: ubuntu-latest python-version: - description: 'Python version' + description: Python version type: choice - options: - - '3.8' - - '3.9' - - '3.10' - - '3.11' + options: ['3.8', '3.9', '3.10', '3.11'] required: false default: '3.8' test_environment: - description: 'The test environment' + description: The test environment type: choice options: # Default ZenML deployments @@ -68,25 +63,19 @@ on: - docker-server-airflow-orchestrator-mysql - docker-server-airflow-orchestrator-mariadb required: false - default: 'default' + default: default enable_tmate: - description: 'Enable tmate session for debugging' + description: Enable tmate session for debugging type: choice - options: - - 'no' - - 'on-failure' - - 'always' - - 'before-tests' + options: [no, on-failure, always, before-tests] required: false default: 'no' tmate_timeout: - description: 'Timeout for tmate session (minutes)' + description: Timeout for tmate session (minutes) type: number required: false default: 30 - jobs: - integration-and-template-tests: name: integration-and-template-tests runs-on: ${{ inputs.os }} @@ -95,12 +84,11 @@ jobs: env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: 'utf-8' + PYTHONIOENCODING: utf-8 # on MAC OS, we need to set this environment variable # to fix problems with the fork() calls (see this thread # for more information: http://sealiesoftware.com/blog/archive/2017/6/5/Objective-C_and_fork_in_macOS_1013.html) OBJC_DISABLE_INITIALIZE_FORK_SAFETY: 'YES' - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_US_EAST_1_ENV_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_US_EAST_1_ENV_SECRET_ACCESS_KEY }} AWS_US_EAST_1_SERVER_URL: ${{ secrets.AWS_US_EAST_1_SERVER_URL }} @@ -110,11 +98,9 @@ jobs: GCP_US_EAST4_SERVER_USERNAME: ${{ secrets.GCP_US_EAST4_SERVER_USERNAME }} GCP_US_EAST4_SERVER_PASSWORD: ${{ secrets.GCP_US_EAST4_SERVER_PASSWORD }} if: ${{ ! startsWith(github.event.head_commit.message, 'GitBook:') }} - defaults: run: shell: bash - steps: - name: Maximize space for Docker uses: easimon/maximize-build-space@v10 @@ -125,34 +111,31 @@ jobs: remove-android: 'true' remove-haskell: 'true' build-mount-path: /var/lib/docker/ - if: inputs.os=='ubuntu-latest' && (contains(inputs.test_environment, 'docker') || contains(inputs.test_environment, 'kubeflow') || contains(inputs.test_environment, 'airflow') || contains(inputs.test_environment, 'kubernetes')) - + if: inputs.os=='ubuntu-latest' && (contains(inputs.test_environment, 'docker') + || contains(inputs.test_environment, 'kubeflow') || contains(inputs.test_environment, + 'airflow') || contains(inputs.test_environment, 'kubernetes')) - name: Reload Docker - run: - sudo systemctl restart docker - if: inputs.os=='ubuntu-latest' && (contains(inputs.test_environment, 'docker') || contains(inputs.test_environment, 'kubeflow') || contains(inputs.test_environment, 'airflow') || contains(inputs.test_environment, 'kubernetes')) - + run: sudo systemctl restart docker + if: inputs.os=='ubuntu-latest' && (contains(inputs.test_environment, 'docker') + || contains(inputs.test_environment, 'kubeflow') || contains(inputs.test_environment, + 'airflow') || contains(inputs.test_environment, 'kubernetes')) - uses: actions/checkout@v4.1.1 - - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: role-to-assume: ${{ secrets.AWS_US_EAST_1_ENV_ROLE_ARN }} aws-region: us-east-1 if: contains(inputs.test_environment, 'aws') - - name: Configure GCP credentials - uses: 'google-github-actions/auth@v2' + uses: google-github-actions/auth@v2 with: - credentials_json: '${{ secrets.GCP_US_EAST4_ENV_CREDENTIALS }}' + credentials_json: ${{ secrets.GCP_US_EAST4_ENV_CREDENTIALS }} if: contains(inputs.test_environment, 'gcp') - - - name: 'Set up gcloud SDK' - uses: 'google-github-actions/setup-gcloud@v1' + - name: Set up gcloud SDK + uses: google-github-actions/setup-gcloud@v1 with: - install_components: 'gke-gcloud-auth-plugin' + install_components: gke-gcloud-auth-plugin if: contains(inputs.test_environment, 'gcp') - - name: Setup environment uses: ./.github/actions/setup_environment with: @@ -161,23 +144,18 @@ jobs: os: ${{ inputs.os }} runners_cache_access_key_id: ${{ secrets.RUNNERS_CACHE_ACCESS_KEY_ID }} runners_cache_secret_access_key: ${{ secrets.RUNNERS_CACHE_SECRET_ACCESS_KEY }} - - name: Install docker-compose for non-default environments if: inputs.test_environment != 'default' run: pip install docker-compose - - name: Install Linux System Dependencies if: inputs.os=='ubuntu-latest' run: sudo apt install graphviz - - name: Install MacOS System Dependencies if: runner.os=='macOS' run: brew install graphviz - - name: Install Windows System Dependencies if: runner.os=='Windows' run: choco install graphviz - - name: Install Docker and Colima on MacOS if: runner.os=='macOS' run: | @@ -193,41 +171,34 @@ jobs: # This is required for the Docker Python SDK to work sudo ln -sf $HOME/.colima/default/docker.sock /var/run/docker.sock - - name: Install kubectl on Linux run: | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" sudo install -o root -g 0 -m 0755 kubectl /usr/local/bin/kubectl if: inputs.os=='ubuntu-latest' - - name: Install kubectl on MacOS run: | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl" sudo install -o root -g 0 -m 0755 kubectl /usr/local/bin/kubectl if: runner.os=='macOS' - - name: Install K3D run: | curl -s https://raw.githubusercontent.com/rancher/k3d/main/install.sh | bash if: runner.os!='Windows' && contains(inputs.test_environment, 'kubeflow') - - name: Login to Amazon ECR id: login-ecr run: | aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 715803424590.dkr.ecr.us-east-1.amazonaws.com if: contains(inputs.test_environment, 'aws') - - name: Login to Amazon EKS id: login-eks run: | aws eks --region us-east-1 update-kubeconfig --name zenml-ci-cluster --alias zenml-ci-aws-us-east-1 if: contains(inputs.test_environment, 'aws') - - name: Login to Google ECR run: | gcloud auth configure-docker --project zenml-ci if: contains(inputs.test_environment, 'gcp') - - name: Login to Google GKE uses: google-github-actions/get-gke-credentials@v2 with: @@ -235,25 +206,21 @@ jobs: location: us-east4 project_id: zenml-ci if: contains(inputs.test_environment, 'gcp') - - name: Setup tmate session before tests if: ${{ inputs.enable_tmate == 'before-tests' }} uses: mxschmitt/action-tmate@v3.17 with: timeout-minutes: ${{ inputs.tmate_timeout }} - - name: Test run: | bash scripts/test-coverage-xml.sh integration ${{ inputs.test_environment }} - - name: Setup tmate session after tests if: ${{ inputs.enable_tmate == 'always' || (inputs.enable_tmate == 'on-failure' && failure()) }} uses: mxschmitt/action-tmate@v3.17 with: timeout-minutes: ${{ inputs.tmate_timeout }} - - name: Verify Python Env unaffected - run: | + run: |- zenml integration list pip list pip check || true diff --git a/.github/workflows/mixpanel-test-data.yml b/.github/workflows/mixpanel-test-data.yml index f4d0a5401c5..dbab5c394f2 100644 --- a/.github/workflows/mixpanel-test-data.yml +++ b/.github/workflows/mixpanel-test-data.yml @@ -1,11 +1,10 @@ +--- name: Post mocked events to Segment - on: workflow_dispatch: schedule: # run this on a schedule at 5:30 in the morning every day - - cron: '30 5 * * *' - + - cron: 30 5 * * * jobs: post_mocked_data: runs-on: ubuntu-latest @@ -15,16 +14,13 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v4.1.1 - - name: Set up Python uses: actions/setup-python@v5.0.0 with: python-version: 3.8 - - name: Install dependencies run: | python -m pip install --upgrade pip python -m pip install analytics-python - - name: Post fake metadata to segment run: python3 scripts/mixpanel_filters_test.py diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml index b82604bbfe4..2af33516990 100644 --- a/.github/workflows/nightly_build.yml +++ b/.github/workflows/nightly_build.yml @@ -1,36 +1,32 @@ +--- name: Nightly Build - on: workflow_dispatch: schedule: # Run this workflow every day at midnight - - cron: '30 0 * * *' - + - cron: 30 0 * * * jobs: - setup-and-test: - uses: ./.github/workflows/setup-python-environment.yml - with: - os: "ubuntu-latest" - python-version: "3.8" - git-ref: "develop" - secrets: inherit - - publish-python-package: - needs: setup-and-test - uses: ./.github/workflows/publish_to_pypi_nightly.yml - secrets: inherit - - wait-for-package-release: - runs-on: ubuntu-latest - needs: publish-python-package - steps: - - name: Sleep for 4 minutes - run: sleep 240 - shell: bash - - publish-docker-image: - needs: wait-for-package-release - uses: ./.github/workflows/publish_docker_image.yml - with: - config_file: release-cloudbuild-nightly.yaml - secrets: inherit + setup-and-test: + uses: ./.github/workflows/setup-python-environment.yml + with: + os: ubuntu-latest + python-version: '3.8' + git-ref: develop + secrets: inherit + publish-python-package: + needs: setup-and-test + uses: ./.github/workflows/publish_to_pypi_nightly.yml + secrets: inherit + wait-for-package-release: + runs-on: ubuntu-latest + needs: publish-python-package + steps: + - name: Sleep for 4 minutes + run: sleep 240 + shell: bash + publish-docker-image: + needs: wait-for-package-release + uses: ./.github/workflows/publish_docker_image.yml + with: + config_file: release-cloudbuild-nightly.yaml + secrets: inherit diff --git a/.github/workflows/pr_labeler.yml b/.github/workflows/pr_labeler.yml index 15c1f110f78..b142a27d238 100644 --- a/.github/workflows/pr_labeler.yml +++ b/.github/workflows/pr_labeler.yml @@ -1,9 +1,9 @@ +--- # https://github.com/marketplace/actions/team-labeler-action # https://github.com/TimonVS/pr-labeler-action on: pull_request: types: [opened] - name: pr-label jobs: pr-labeler: @@ -12,12 +12,10 @@ jobs: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: JulienKode/team-labeler-action@v1.1.0 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" - - - uses: TimonVS/pr-labeler-action@v4.1.1 - with: - configuration-path: .github/branch-labels.yml + - uses: JulienKode/team-labeler-action@v1.1.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - uses: TimonVS/pr-labeler-action@v4.1.1 + with: + configuration-path: .github/branch-labels.yml diff --git a/.github/workflows/publish_api_docs.yml b/.github/workflows/publish_api_docs.yml index f6aa5a4e03e..dd1f5538745 100644 --- a/.github/workflows/publish_api_docs.yml +++ b/.github/workflows/publish_api_docs.yml @@ -1,12 +1,11 @@ +--- # This is a basic workflow that publishes the website name: Publish API Docs - # Controls when the action will run. on: push: branches: - - "release/**" - + - release/** # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # This workflow contains a single job called "publish" @@ -16,25 +15,21 @@ jobs: env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: "utf-8" - + PYTHONIOENCODING: utf-8 steps: - uses: actions/checkout@v4.1.1 with: - fetch-depth: 0 # fetch all commits/branches including gh-pages - + fetch-depth: 0 # fetch all commits/branches including gh-pages - name: Get the version from the github branch name id: get_version run: | BRANCH='${{github.ref_name}}' echo ::set-output name=VERSION::${BRANCH#release/} - - uses: actions/setup-node@v4.0.1 with: - node-version: "14" + node-version: '14' - run: npm install - run: npm install html-minifier -g - - name: Setup environment uses: ./.github/actions/setup_environment with: @@ -43,12 +38,10 @@ jobs: os: ubuntu-latest # We need to install integrations in a different way to avoid conflicts install_integrations: 'no' - - name: Setup git user run: | git config --global user.name 'Code Monkey' git config --global user.email 'codemonkey@zenml.io' - - name: Runs docs generation - run: | + run: |- bash scripts/generate-docs.sh -s src/zenml/ --push --latest -v ${{ steps.get_version.outputs.VERSION }} diff --git a/.github/workflows/publish_docker_image.yml b/.github/workflows/publish_docker_image.yml index cd8ca3b5b7e..415be048eb9 100644 --- a/.github/workflows/publish_docker_image.yml +++ b/.github/workflows/publish_docker_image.yml @@ -1,14 +1,13 @@ +--- name: Publish Docker images - on: workflow_call: inputs: config_file: - description: 'YAML config for Google Cloud Build' + description: YAML config for Google Cloud Build required: false type: string - default: "release-cloudbuild.yaml" - + default: release-cloudbuild.yaml jobs: publish_to_docker: name: Publish Docker 🐋 image 🖼️ to Dockerhub @@ -16,11 +15,9 @@ jobs: env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: 'utf-8' - + PYTHONIOENCODING: utf-8 steps: - uses: actions/checkout@v4.1.1 - - name: Get the version from the github tag ref id: get_version run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} diff --git a/.github/workflows/publish_helm_chart.yml b/.github/workflows/publish_helm_chart.yml index 8c41e49cd43..5d7a17d2e6f 100644 --- a/.github/workflows/publish_helm_chart.yml +++ b/.github/workflows/publish_helm_chart.yml @@ -1,24 +1,20 @@ +--- # package and push the zenml helm chart to the ECR repository name: Publish Helm Chart - -on: +on: workflow_call: workflow_dispatch: - jobs: publish_to_ecr: name: Publish Helm Chart 🛞 to ECR ☁️ runs-on: ubuntu-latest - permissions: - contents: "read" - id-token: "write" - + contents: read + id-token: write env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: 'utf-8' - + PYTHONIOENCODING: utf-8 steps: - name: Checkout repo uses: actions/checkout@v4.1.1 @@ -28,13 +24,11 @@ jobs: - name: Add tag version to Chart.yaml run: | sed -i "s/version: .*/version: \"${{ github.ref_name }}\"/" src/zenml/zen_server/deploy/helm/Chart.yaml - - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v2 with: role-to-assume: arn:aws:iam::715803424590:role/gh-action-role-zenml-helm aws-region: us-east-1 - - name: Login to Amazon ECR Public id: login-ecr-public uses: aws-actions/amazon-ecr-login@v2 @@ -42,18 +36,17 @@ jobs: mask-password: 'true' registry-type: public - #TODO: revisit the pinned helm version + find a higher version + # TODO: revisit the pinned helm version + find a higher version - name: install helm with version 3.9.2 uses: azure/setup-helm@v3.5 with: - version: "v3.9.2" # default is latest (stable) + version: v3.9.2 # default is latest (stable) id: install-helm - - name: Package and push helm chart to Amazon ECR Public env: REGISTRY: ${{ steps.login-ecr-public.outputs.registry }} REGISTRY_ALIAS: zenml REPOSITORY: zenml - run: | + run: |- helm package src/zenml/zen_server/deploy/helm helm push $REPOSITORY-${{ github.ref_name }}.tgz oci://$REGISTRY/$REGISTRY_ALIAS diff --git a/.github/workflows/publish_to_pypi.yml b/.github/workflows/publish_to_pypi.yml index e32fe5593f4..494ce77f750 100644 --- a/.github/workflows/publish_to_pypi.yml +++ b/.github/workflows/publish_to_pypi.yml @@ -1,8 +1,7 @@ +--- name: Publish Pypi package - on: workflow_call: - jobs: publish_to_pypi: name: Publish Python 🐍 package 📦 to PyPI @@ -10,36 +9,29 @@ jobs: env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: 'utf-8' - + PYTHONIOENCODING: utf-8 steps: - uses: actions/checkout@v4.1.1 - - name: Get the version from the github tag ref id: get_version run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} - - name: Set up Python uses: actions/setup-python@v5.0.0 with: python-version: '3.8' - - name: Install Poetry uses: snok/install-poetry@v1.3.4 with: virtualenvs-create: true virtualenvs-in-project: true - - name: Include latest dashboard run: bash scripts/install-dashboard.sh - - name: publish env: PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} - run: | + run: |- if [ "$(cat src/zenml/VERSION)" = "$(echo ${GITHUB_REF} | sed 's|refs/tags/||g')" ]; then ./scripts/publish.sh; else echo "Version mismatch between src/zenml/VERSION and branch tag" && exit 1; fi - diff --git a/.github/workflows/publish_to_pypi_nightly.yml b/.github/workflows/publish_to_pypi_nightly.yml index 2e6e54293ec..c8ac84cac61 100644 --- a/.github/workflows/publish_to_pypi_nightly.yml +++ b/.github/workflows/publish_to_pypi_nightly.yml @@ -1,8 +1,7 @@ +--- name: Publish Nightly PyPI package - on: workflow_call: - jobs: publish_to_pypi: name: Publish Nightly Python 🐍 package 📦 to PyPI @@ -10,53 +9,45 @@ jobs: env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: 'utf-8' - + PYTHONIOENCODING: utf-8 steps: - uses: actions/checkout@v4.1.1 with: - ref: 'develop' - + ref: develop - name: Set up Python uses: actions/setup-python@v5.0.0 with: python-version: '3.8' - - name: Install Poetry uses: snok/install-poetry@v1.3.4 with: virtualenvs-create: true virtualenvs-in-project: true - - name: Set nightly version run: | - # Extract the current version - CURRENT_VERSION=$(poetry version -s) - - # Get the current date in the format of YYYY-MM-DD - DATE=$(date +"%Y%m%d") + # Extract the current version + CURRENT_VERSION=$(poetry version -s) - # Combine the current version with the date to form - # the new version string - NIGHTLY_VERSION="${CURRENT_VERSION}.dev${DATE}" + # Get the current date in the format of YYYY-MM-DD + DATE=$(date +"%Y%m%d") - # Set the nightly version - echo "NIGHTLY_VERSION=$NIGHTLY_VERSION" >> $GITHUB_ENV + # Combine the current version with the date to form + # the new version string + NIGHTLY_VERSION="${CURRENT_VERSION}.dev${DATE}" + # Set the nightly version + echo "NIGHTLY_VERSION=$NIGHTLY_VERSION" >> $GITHUB_ENV - name: Modify pyproject.toml for nightly release run: | - # Change the package name to `zenml-nightly` - sed -i 's/name = "zenml"/name = "zenml-nightly"/' pyproject.toml - - # Update the version to the nightly version - poetry version $NIGHTLY_VERSION + # Change the package name to `zenml-nightly` + sed -i 's/name = "zenml"/name = "zenml-nightly"/' pyproject.toml + # Update the version to the nightly version + poetry version $NIGHTLY_VERSION - name: Include latest dashboard run: bash scripts/install-dashboard.sh - - name: publish env: PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} run: bash scripts/publish.sh - diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e480a8d7211..3f653c71bef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,76 +1,63 @@ +--- # This is a basic workflow to help you get started with Actions name: Release Package & Docker Image - # Controls when the action will run. Triggers the workflow on push of a tag on: push: - tags: - - '*' - + tags: ['*'] jobs: setup-and-test: uses: ./.github/workflows/setup-python-environment.yml with: - os: "ubuntu-latest" - python-version: "3.8" + os: ubuntu-latest + python-version: '3.8' secrets: inherit - mlstacks-compatibility-check: needs: setup-and-test runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4.1.1 - - name: Set up Python uses: actions/setup-python@v5.0.0 with: - python-version: "3.8" - + python-version: '3.8' - name: Install current package as editable run: pip install -e . - - name: Install mlstacks package run: pip install mlstacks - - name: Check for broken dependencies run: pip check - mysql-db-migration-testing: runs-on: ubuntu-dind-runners - steps: - - name: Checkout code - uses: actions/checkout@v4.1.1 - - - name: Set up Python 3.9 - uses: actions/setup-python@v5.0.0 - with: - python-version: "3.9" - - - name: Test migrations across versions - run: bash scripts/test-migrations.sh mysql - + - name: Checkout code + uses: actions/checkout@v4.1.1 + - name: Set up Python 3.9 + uses: actions/setup-python@v5.0.0 + with: + python-version: '3.9' + - name: Test migrations across versions + run: bash scripts/test-migrations.sh mysql sqlite-db-migration-testing: runs-on: ubuntu-dind-runners - steps: - - name: Checkout code - uses: actions/checkout@v4.1.1 - - - name: Set up Python 3.9 - uses: actions/setup-python@v5.0.0 - with: - python-version: "3.9" - - - name: Test migrations across versions - run: bash scripts/test-migrations.sh sqlite - + - name: Checkout code + uses: actions/checkout@v4.1.1 + - name: Set up Python 3.9 + uses: actions/setup-python@v5.0.0 + with: + python-version: '3.9' + - name: Test migrations across versions + run: bash scripts/test-migrations.sh sqlite publish-python-package: - needs: [setup-and-test, mlstacks-compatibility-check, sqlite-db-migration-testing, mysql-db-migration-testing] + needs: + - setup-and-test + - mlstacks-compatibility-check + - sqlite-db-migration-testing + - mysql-db-migration-testing uses: ./.github/workflows/publish_to_pypi.yml secrets: inherit - wait-for-package-release: runs-on: ubuntu-latest needs: publish-python-package @@ -78,12 +65,10 @@ jobs: - name: Sleep for 4 minutes run: sleep 240 shell: bash - publish-docker-image: needs: wait-for-package-release uses: ./.github/workflows/publish_docker_image.yml secrets: inherit - publish-helm-chart: needs: publish-docker-image uses: ./.github/workflows/publish_helm_chart.yml diff --git a/.github/workflows/scarf-check.yml b/.github/workflows/scarf-check.yml index 3301e8c5316..ae0d3ba27bc 100644 --- a/.github/workflows/scarf-check.yml +++ b/.github/workflows/scarf-check.yml @@ -1,20 +1,20 @@ +--- name: Scarf checker on: workflow_dispatch: pull_request: types: [opened, synchronize, ready_for_review] # Run when md files are involved in the PR. - paths: - - '**.md' + paths: ['**.md'] jobs: check-for-scarf: # Only run on non-draft PRs within the same repository. - if: github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.draft == false + if: github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.draft + == false name: check-for-scarf runs-on: ubuntu-latest steps: - name: Checkout Repo uses: actions/checkout@v4.1.1 - - name: Check for scarf run: bash scripts/scarf-checker.sh diff --git a/.github/workflows/setup-python-environment.yml b/.github/workflows/setup-python-environment.yml index 3d95564838c..a290febbce5 100644 --- a/.github/workflows/setup-python-environment.yml +++ b/.github/workflows/setup-python-environment.yml @@ -1,70 +1,60 @@ +--- name: Setup Python Environment, Lint and Unit Test - on: workflow_call: inputs: os: - description: 'OS' + description: OS type: string required: true python-version: - description: 'Python version' + description: Python version type: string required: true enable_tmate: - description: 'Enable tmate session for debugging' + description: Enable tmate session for debugging type: string required: false - default: "never" + default: never install_integrations: - description: 'Install ZenML integrations' + description: Install ZenML integrations type: string required: false default: 'yes' git-ref: - description: 'Git branch or ref' + description: Git branch or ref type: string required: false default: '' - workflow_dispatch: inputs: os: - description: 'OS' + description: OS type: choice - options: + options: - ubuntu-latest - macos-latest - windows-latest - ubuntu-dind-runners required: false - default: 'ubuntu-latest' + default: ubuntu-latest python-version: - description: 'Python version' + description: Python version type: choice - options: - - '3.8' - - '3.9' - - '3.10' - - '3.11' + options: ['3.8', '3.9', '3.10', '3.11'] required: false default: '3.8' enable_tmate: - description: 'Enable tmate session for debugging' + description: Enable tmate session for debugging type: choice - options: - - 'no' - - 'on-failure' - - 'always' - - 'before-tests' + options: [no, on-failure, always, before-tests] required: false default: 'no' git-ref: - description: 'Git branch or ref' + description: Git branch or ref type: string required: false default: '' - jobs: setup-and-test: name: setup-and-test @@ -72,23 +62,20 @@ jobs: env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: 'utf-8' + PYTHONIOENCODING: utf-8 # on MAC OS, we need to set this environment variable # to fix problems with the fork() calls (see this thread # for more information: http://sealiesoftware.com/blog/archive/2017/6/5/Objective-C_and_fork_in_macOS_1013.html) - OBJC_DISABLE_INITIALIZE_FORK_SAFETY: "YES" + OBJC_DISABLE_INITIALIZE_FORK_SAFETY: 'YES' # Exit if it's a commit from Gitbook if: ${{ ! startsWith(github.event.head_commit.message, 'GitBook:') }} - defaults: run: shell: bash - steps: - uses: actions/checkout@v4.1.1 with: ref: ${{ github.event.inputs.git-ref || github.ref }} - - name: Setup environment uses: ./.github/actions/setup_environment with: @@ -98,64 +85,55 @@ jobs: install_integrations: ${{ inputs.install_integrations }} runners_cache_access_key_id: ${{ secrets.RUNNERS_CACHE_ACCESS_KEY_ID }} runners_cache_secret_access_key: ${{ secrets.RUNNERS_CACHE_SECRET_ACCESS_KEY }} - - name: Setup tmate session before tests if: ${{ inputs.enable_tmate == 'before-tests' }} uses: mxschmitt/action-tmate@v3.17 - - name: Lint check run: | bash scripts/lint.sh - - name: Spelling checker uses: crate-ci/typos@v1.17.0 with: - files: "." + files: . config: ./.typos.toml # Only run the spell check on ubuntu-latest and python 3.8 if: ${{ inputs.os == 'ubuntu-dind-runners' && inputs.python-version == '3.8' }} - - name: Docstring check run: bash scripts/docstring.sh # Only run the docstring check on ubuntu-latest and python 3.8 if: ${{ inputs.os == 'ubuntu-dind-runners' && inputs.python-version == '3.8' }} - - name: Security check run: bash scripts/check-security.sh - - name: Markdown link check uses: gaurav-nelson/github-action-markdown-link-check@1.0.15 with: use-quiet-mode: 'yes' use-verbose-mode: 'no' - folder-path: './examples, ./docs/book, ./src' - file-path: './README.md, ./LICENSE, ./RELEASE_NOTES.md, CODE-OF-CONDUCT.md, CONTRIBUTING.md, CLA.md, RELEASE_NOTES.md, ROADMAP.md' + folder-path: ./examples, ./docs/book, ./src + file-path: ./README.md, ./LICENSE, ./RELEASE_NOTES.md, CODE-OF-CONDUCT.md, + CONTRIBUTING.md, CLA.md, RELEASE_NOTES.md, ROADMAP.md config-file: .github/workflows/markdown_check_config.json continue-on-error: true # Only run the markdown link check on ubuntu-latest and python 3.8 if: ${{ inputs.os == 'ubuntu-dind-runners' && inputs.python-version == '3.8' }} - - name: Check for alembic branch divergence env: ZENML_DEBUG: 0 run: | bash scripts/check-alembic-branches.sh - - name: Run unit tests run: | bash scripts/test-coverage-xml.sh unit # - name: Upload coverage - # # only do it for python 3.8, we don't need to do it for every version + # # only do it for python 3.8, we don't need to do it for every version # if: ${{ inputs.os == 'ubuntu-dind-runners' && inputs.python-version == '3.8' }} # uses: codecov/codecov-action@v2 - - name: Setup tmate session after tests if: ${{ inputs.enable_tmate == 'always' || (inputs.enable_tmate == 'on-failure' && failure()) }} uses: mxschmitt/action-tmate@v3.17 - - name: Verify Python Env unaffected - run: | + run: |- zenml integration list pip list pip check || true diff --git a/.github/workflows/templates-test.yml b/.github/workflows/templates-test.yml index b0b0bf0d6f0..04ca12fe62e 100644 --- a/.github/workflows/templates-test.yml +++ b/.github/workflows/templates-test.yml @@ -1,75 +1,62 @@ +--- name: Run tests on templates - on: workflow_call: inputs: os: - description: 'OS' + description: OS type: string required: true python-version: - description: 'Python version' + description: Python version type: string required: true - workflow_dispatch: inputs: os: - description: 'OS' + description: OS type: choice - options: - - ubuntu-latest - - macos-latest - - windows-latest + options: [ubuntu-latest, macos-latest, windows-latest] required: false - default: 'ubuntu-latest' + default: ubuntu-latest python-version: - description: 'Python version' + description: Python version type: choice - options: - - '3.8' - - '3.9' - - '3.10' - - '3.11' + options: ['3.8', '3.9', '3.10', '3.11'] required: false default: '3.8' - jobs: all-template-tests: name: all-template-tests runs-on: ${{ inputs.os }} strategy: - matrix: - stack-name: [local] - template-repo: [ - {repo: zenml-io/zenml-project-templates, path: .github/actions/starter_template_test}, - {repo: zenml-io/template-e2e-batch, path: .github/actions/e2e_template_test}, - {repo: zenml-io/template-nlp, path: .github/actions/nlp_template_test} - ] - fail-fast: false + matrix: + stack-name: [local] + template-repo: + - {repo: zenml-io/zenml-project-templates, path: .github/actions/starter_template_test} + - {repo: zenml-io/template-e2e-batch, path: .github/actions/e2e_template_test} + - {repo: zenml-io/template-nlp, path: .github/actions/nlp_template_test} + fail-fast: false env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: "utf-8" - OBJC_DISABLE_INITIALIZE_FORK_SAFETY: "YES" + PYTHONIOENCODING: utf-8 + OBJC_DISABLE_INITIALIZE_FORK_SAFETY: 'YES' if: ${{ ! startsWith(github.event.head_commit.message, 'GitBook:') }} - defaults: run: shell: bash - steps: - name: Run template tests for ${{ matrix.template-repo.repo }} uses: jenseng/dynamic-uses@v1 with: uses: ${{ matrix.template-repo.repo }}/${{ matrix.template-repo.path }}@main - with: '{ "python-version": "${{ inputs.python-version }}", "stack-name": "${{ matrix.stack-name }}", "ref-zenml": "${{ github.ref }}" }' - + with: '{ "python-version": "${{ inputs.python-version }}", "stack-name": + "${{ matrix.stack-name }}", "ref-zenml": "${{ github.ref }}" }' - name: message-on-error if: failure() - run: | + run: |- echo "::error title=${{ matrix.template-repo.repo }} project template testing failed with new version of ZenML core!::\ Breaking changes affecting templates have been introduced. To mitigate this issue,\ please make the code in ${{ matrix.template-repo.repo }} compatible with new version of\ ZenML core, release it and update release tag in zenml.cli.base.ZENML_PROJECT_TEMPLATES" - diff --git a/.github/workflows/trivy-zenml-core.yml b/.github/workflows/trivy-zenml-core.yml index 3f67011ef3f..36c9fa8cc1f 100644 --- a/.github/workflows/trivy-zenml-core.yml +++ b/.github/workflows/trivy-zenml-core.yml @@ -1,12 +1,10 @@ +--- name: Trivy ZenML (core) Scan - on: push: - branches: ["main"] + branches: [main] schedule: - - cron: '0 4 * * 1' # At 04:00 on Monday - - + - cron: 0 4 * * 1 # At 04:00 on Monday jobs: trivy-scan: name: Trivy zenml scan & analysis @@ -14,16 +12,13 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4.1.1 - - name: zenml-Trivy vulnerability scanner uses: aquasecurity/trivy-action@0.16.1 with: - image-ref: "docker.io/zenmldocker/zenml:latest" - format: "sarif" - output: "trivy-results-zenml.sarif" - + image-ref: docker.io/zenmldocker/zenml:latest + format: sarif + output: trivy-results-zenml.sarif - name: Upload Trivy zenml scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 with: - sarif_file: "trivy-results-zenml.sarif" - + sarif_file: trivy-results-zenml.sarif diff --git a/.github/workflows/trivy-zenserver.yml b/.github/workflows/trivy-zenserver.yml index 655571619a6..0c26ed2a3dc 100644 --- a/.github/workflows/trivy-zenserver.yml +++ b/.github/workflows/trivy-zenserver.yml @@ -1,11 +1,10 @@ +--- name: Trivy ZenServer Scan - on: push: - branches: ["main"] + branches: [main] schedule: - - cron: '0 4 * * 1' # At 04:00 on Monday - + - cron: 0 4 * * 1 # At 04:00 on Monday jobs: trivy-scan: name: Trivy ZenServer scan & analysis @@ -13,15 +12,13 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4.1.1 - - name: zenserver-Trivy vulnerability scanner uses: aquasecurity/trivy-action@0.16.1 with: - image-ref: "docker.io/zenmldocker/zenml-server:latest" - format: "sarif" - output: "trivy-results-zenserver.sarif" - + image-ref: docker.io/zenmldocker/zenml-server:latest + format: sarif + output: trivy-results-zenserver.sarif - name: Upload Trivy zenserver scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 with: - sarif_file: "trivy-results-zenserver.sarif" + sarif_file: trivy-results-zenserver.sarif diff --git a/.github/workflows/update-templates-to-examples.yml b/.github/workflows/update-templates-to-examples.yml index 8f6a9f7cb5d..6e242a6c62c 100644 --- a/.github/workflows/update-templates-to-examples.yml +++ b/.github/workflows/update-templates-to-examples.yml @@ -1,40 +1,34 @@ +--- name: Auto-update all templates - on: workflow_call: inputs: os: - description: 'OS' + description: OS type: string required: true python-version: - description: 'Python version' + description: Python version type: string required: true - workflow_dispatch: inputs: os: - description: 'OS' + description: OS type: choice - options: + options: - ubuntu-latest - macos-latest - windows-latest - ubuntu-dind-runners required: false - default: 'ubuntu-latest' + default: ubuntu-latest python-version: - description: 'Python version' + description: Python version type: choice - options: - - '3.8' - - '3.9' - - '3.10' - - '3.11' + options: ['3.8', '3.9', '3.10', '3.11'] required: false default: '3.8' - jobs: update-e2e-batch-template-to-examples: name: update-e2e-batch-template-to-examples @@ -42,14 +36,13 @@ jobs: env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: "utf-8" - OBJC_DISABLE_INITIALIZE_FORK_SAFETY: "YES" - if: github.event_name == 'pull_request' && ! startsWith(github.event.head_commit.message, 'GitBook:') - + PYTHONIOENCODING: utf-8 + OBJC_DISABLE_INITIALIZE_FORK_SAFETY: 'YES' + if: github.event_name == 'pull_request' && ! startsWith(github.event.head_commit.message, + 'GitBook:') defaults: run: shell: bash - steps: - name: Run template tests for zenml-io/template-e2e-batch uses: zenml-io/template-e2e-batch/.github/actions/e2e_template_test@main @@ -57,12 +50,10 @@ jobs: python-version: ${{ inputs.python-version }} stack-name: local ref-zenml: ${{ github.ref }} - ref-template: '2023.12.12' # Make sure it is aligned with ZENML_PROJECT_TEMPLATES from src/zenml/cli/base.py - + ref-template: 2023.12.12 # Make sure it is aligned with ZENML_PROJECT_TEMPLATES from src/zenml/cli/base.py - name: Clean-up run: | rm -rf ./local_checkout - - name: message-on-error if: failure() run: | @@ -70,18 +61,16 @@ jobs: Breaking changes affecting templates have been introduced. To mitigate this issue,\ please make the code in zenml-io/template-e2e-batch compatible with new version of\ ZenML core, release it and update release tag in zenml.cli.base.ZENML_PROJECT_TEMPLATES" - - uses: actions/checkout@v4.1.1 with: ref: ${{ github.event.pull_request.head.ref }} - - name: Check-out fresh E2E template run: | rm -rf examples/e2e mkdir -p examples/e2e printf 'info@zenml.io' | zenml init --path examples/e2e --template e2e_batch --template-with-defaults + pip install yamlfix bash scripts/format.sh - - name: Check for changes id: check_changes run: | @@ -92,7 +81,6 @@ jobs: echo "Active Git changes found." echo "changes=true" >> $GITHUB_OUTPUT fi - - name: Commit and push template if: steps.check_changes.outputs.changes == 'true' run: | @@ -101,7 +89,6 @@ jobs: git add . git commit -am "Auto-update of E2E template" git push origin HEAD:${{ github.event.pull_request.head.ref }} - - name: Create PR comment if: steps.check_changes.outputs.changes == 'true' uses: actions/github-script@v7.0.1 @@ -114,22 +101,19 @@ jobs: repo: context.repo.repo, body: 'E2E template updates in `examples/e2e` have been pushed.' }) - - update-nlp-template-to-examples: name: update-nlp-template-to-examples runs-on: ${{ inputs.os }} env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: "utf-8" - OBJC_DISABLE_INITIALIZE_FORK_SAFETY: "YES" - if: github.event_name == 'pull_request' && ! startsWith(github.event.head_commit.message, 'GitBook:') - + PYTHONIOENCODING: utf-8 + OBJC_DISABLE_INITIALIZE_FORK_SAFETY: 'YES' + if: github.event_name == 'pull_request' && ! startsWith(github.event.head_commit.message, + 'GitBook:') defaults: run: shell: bash - steps: - name: Run template tests for zenml-io/template-nlp uses: zenml-io/template-nlp/.github/actions/nlp_template_test@main @@ -137,12 +121,10 @@ jobs: python-version: ${{ inputs.python-version }} stack-name: local ref-zenml: ${{ github.ref }} - ref-template: '0.45.0' # Make sure it is aligned with ZENML_PROJECT_TEMPLATES from src/zenml/cli/base.py - + ref-template: 0.45.0 # Make sure it is aligned with ZENML_PROJECT_TEMPLATES from src/zenml/cli/base.py - name: Clean-up run: | rm -rf ./local_checkout - - name: message-on-error if: failure() run: | @@ -150,17 +132,15 @@ jobs: Breaking changes affecting templates have been introduced. To mitigate this issue,\ please make the code in zenml-io/template-nlp compatible with new version of\ ZenML core, release it and update release tag in zenml.cli.base.ZENML_PROJECT_TEMPLATES" - - uses: actions/checkout@v4.1.1 with: ref: ${{ github.event.pull_request.head.ref }} - - name: Check-out fresh NLP template run: | mkdir -p examples/nlp-case printf 'info@zenml.io' | zenml init --path examples/nlp-case --template nlp --template-with-defaults + pip install yamlfix bash scripts/format.sh - - name: Check for changes id: check_changes run: | @@ -171,7 +151,6 @@ jobs: echo "Active Git changes found." echo "changes=true" >> $GITHUB_OUTPUT fi - - name: Commit and push template if: steps.check_changes.outputs.changes == 'true' run: | @@ -180,7 +159,6 @@ jobs: git add . git commit -am "Auto-update of NLP template" git push origin HEAD:${{ github.event.pull_request.head.ref }} - - name: Create PR comment if: steps.check_changes.outputs.changes == 'true' uses: actions/github-script@v7.0.1 @@ -193,22 +171,19 @@ jobs: repo: context.repo.repo, body: 'NLP template updates in `examples/nlp-case` have been pushed.' }) - - update-starter-template-to-examples: name: update-starter-template-to-examples runs-on: ${{ inputs.os }} env: ZENML_DEBUG: 1 ZENML_ANALYTICS_OPT_IN: false - PYTHONIOENCODING: "utf-8" - OBJC_DISABLE_INITIALIZE_FORK_SAFETY: "YES" - if: github.event_name == 'pull_request' && ! startsWith(github.event.head_commit.message, 'GitBook:') - + PYTHONIOENCODING: utf-8 + OBJC_DISABLE_INITIALIZE_FORK_SAFETY: 'YES' + if: github.event_name == 'pull_request' && ! startsWith(github.event.head_commit.message, + 'GitBook:') defaults: run: shell: bash - steps: - name: Run template tests for zenml-io/template-starter uses: zenml-io/template-starter/.github/actions/starter_template_test@main @@ -216,12 +191,10 @@ jobs: python-version: ${{ inputs.python-version }} stack-name: local ref-zenml: ${{ github.ref }} - ref-template: '2023.12.18' # Make sure it is aligned with ZENML_PROJECT_TEMPLATES from src/zenml/cli/base.py - + ref-template: 2023.12.18 # Make sure it is aligned with ZENML_PROJECT_TEMPLATES from src/zenml/cli/base.py - name: Clean-up run: | rm -rf ./local_checkout - - name: message-on-error if: failure() run: | @@ -230,18 +203,16 @@ jobs: Breaking changes affecting templates have been introduced. To mitigate this issue,\ please make the code in zenml-io/template-starter compatible with new version of\ ZenML core, release it and update release tag in zenml.cli.base.ZENML_PROJECT_TEMPLATES" - - uses: actions/checkout@v4.1.1 with: ref: ${{ github.event.pull_request.head.ref }} - - name: Check-out fresh Starter template run: | rm -rf examples/quickstart mkdir -p examples/quickstart printf 'info@zenml.io' | zenml init --path examples/quickstart --template starter --template-with-defaults + pip install yamlfix bash scripts/format.sh - - name: Check for changes id: check_changes run: | @@ -252,7 +223,6 @@ jobs: echo "Active Git changes found." echo "changes=true" >> $GITHUB_OUTPUT fi - - name: Commit and push template if: steps.check_changes.outputs.changes == 'true' run: | @@ -261,13 +231,12 @@ jobs: git add . git commit -am "Auto-update of Starter template" git push origin HEAD:${{ github.event.pull_request.head.ref }} - - name: Create PR comment if: steps.check_changes.outputs.changes == 'true' uses: actions/github-script@v7.0.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} - script: | + script: |- github.issues.createComment({ issue_number: ${{ github.event.pull_request.number }}, owner: context.repo.owner, diff --git a/pyproject.toml b/pyproject.toml index 89b2e5cf1e2..b1cef290a0f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,7 +77,6 @@ ipinfo = { version = ">=4.4.3", optional = true } # Optional dependencies for project templates copier = { version = ">=8.1.0", optional = true } jinja2-time = { version = "^0.2.0", optional = true } -ruff = { version = "0.1.7", optional = true } # Optional terraform dependency for stack recipes and ZenServer deployments python-terraform = { version = "^0.10.1", optional = true } @@ -130,6 +129,8 @@ tox = { version = "^3.24.3", optional = true } hypothesis = { version = "^6.43.1", optional = true } typing-extensions = { version = ">=3.7.4", optional = true } darglint = { version = "^1.8.1", optional = true } +ruff = { version = "0.1.7", optional = true } +yamlfix = { version = "^1.16.0", optional = true } # pytest pytest = { version = "^7.4.0", optional = true } @@ -202,6 +203,7 @@ connectors-azure = [ dev = [ "bandit", "ruff", + "yamlfix", "coverage", "pytest", "mypy", diff --git a/scripts/format.sh b/scripts/format.sh index 189cfff85d4..be090370036 100755 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -1,6 +1,7 @@ #!/bin/sh -e set -x +# Default source directories SRC=${1:-"src/zenml tests examples docs/mkdocstrings_helper.py scripts"} export ZENML_DEBUG=1 @@ -13,6 +14,21 @@ ruff $SRC --select F401,F841 --fix --exclude "__init__.py" --isolated ruff $SRC --select I --fix --ignore D ruff format $SRC +# Flag check for skipping yamlfix +SKIP_YAMLFIX=false +for arg in "$@" +do + if [ "$arg" = "--no-yamlfix" ]; then + SKIP_YAMLFIX=true + break + fi +done + +# standardises / formats CI yaml files +if [ "$SKIP_YAMLFIX" = false ]; then + yamlfix .github tests +fi + set +x # Adds scarf snippet to docs files where it is missing # Text to be searched in each file diff --git a/scripts/lint.sh b/scripts/lint.sh index 039c6970e10..21076880260 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -3,6 +3,7 @@ set -e set -x set -o pipefail +# Default source directories SRC=${1:-"src/zenml tests examples"} SRC_NO_TESTS=${1:-"src/zenml tests/harness"} TESTS_EXAMPLES=${1:-"tests examples"} @@ -13,6 +14,21 @@ ruff $SRC_NO_TESTS # TODO: Fix docstrings in tests and examples and remove the `--extend-ignore D` flag ruff $TESTS_EXAMPLES --extend-ignore D +# Flag check for skipping yamlfix +SKIP_YAMLFIX=false +for arg in "$@" +do + if [ "$arg" = "--no-yamlfix" ]; then + SKIP_YAMLFIX=true + break + fi +done + +# checks for yaml formatting errors +if [ "$SKIP_YAMLFIX" = false ]; then + yamlfix --check .github tests +fi + # autoflake replacement: checks for unused imports and variables ruff $SRC --select F401,F841 --exclude "__init__.py" --isolated diff --git a/tests/harness/cfg/deployments.yaml b/tests/harness/cfg/deployments.yaml index 6785bde6e9d..36379970289 100644 --- a/tests/harness/cfg/deployments.yaml +++ b/tests/harness/cfg/deployments.yaml @@ -1,3 +1,4 @@ +--- # A list of ZenML deployments, either local or remote (external), that # can be included in test environments to be used to run automated tests or # passed to pytest directly using the `--deployment` command line argument. @@ -61,19 +62,16 @@ # value indicates that it doesn't. # deployments: - - name: default description: >- Default deployment. server: none database: sqlite - - name: client-mysql description: >- Local client connected directly to MySQL running in container. server: none database: mysql - - name: client-mariadb description: >- Local client connected directly to MariaDB running in container. @@ -92,7 +90,6 @@ deployments: database: sqlite capabilities: server: true - - name: docker-server description: >- Local ZenML server running in docker using the default SQLite database. @@ -100,7 +97,6 @@ deployments: database: sqlite capabilities: server: true - - name: docker-server-mysql description: >- Local ZenML server and MySQL both running in docker with docker-compose. @@ -108,7 +104,6 @@ deployments: database: mysql capabilities: server: true - - name: docker-server-mariadb description: >- Local ZenML server and MariaDB both running in docker with docker-compose. diff --git a/tests/harness/cfg/environments.yaml b/tests/harness/cfg/environments.yaml index 4d5c64fa992..6451953c5f9 100644 --- a/tests/harness/cfg/environments.yaml +++ b/tests/harness/cfg/environments.yaml @@ -1,3 +1,4 @@ +--- # Environments couple together a deployment with an optional set of # requirements to be configured on the deployment. The deployment entry # can be a reference to a global deployment entry by name or an inline @@ -34,7 +35,6 @@ # inherited from environment requirements. # environments: - - name: default description: >- Default deployment with local orchestrator and all local @@ -47,7 +47,6 @@ environments: - mlflow-local-deployer capabilities: synchronized: true - - name: default-docker-orchestrator description: >- Default deployment with docker orchestrator and all local @@ -58,9 +57,7 @@ environments: - mlflow-local-tracker - mlflow-local-registry - mlflow-local-deployer - mandatory_requirements: - - docker-local - + mandatory_requirements: [docker-local] - name: default-airflow-orchestrator description: >- Default server deployment with airflow local orchestrator and all local @@ -122,9 +119,7 @@ environments: - mlflow-local-tracker - mlflow-local-registry - mlflow-local-deployer - mandatory_requirements: - - airflow-local - + mandatory_requirements: [airflow-local] - name: docker-server-mysql description: >- Server docker-compose deployment with local orchestrator and all local @@ -137,7 +132,6 @@ environments: - mlflow-local-deployer capabilities: synchronized: true - - name: docker-server-docker-orchestrator-mysql description: >- Server docker-compose deployment with docker orchestrator and all local @@ -148,9 +142,7 @@ environments: - mlflow-local-tracker - mlflow-local-registry - mlflow-local-deployer - mandatory_requirements: - - docker-local - + mandatory_requirements: [docker-local] - name: docker-server-airflow-orchestrator-mysql description: >- Server docker-compose deployment with local airflow orchestrator and all @@ -161,9 +153,7 @@ environments: - mlflow-local-tracker - mlflow-local-registry - mlflow-local-deployer - mandatory_requirements: - - airflow-local - + mandatory_requirements: [airflow-local] - name: docker-server-mariadb description: >- Server docker-compose deployment with local orchestrator and all local @@ -176,7 +166,6 @@ environments: - mlflow-local-deployer capabilities: synchronized: true - - name: docker-server-docker-orchestrator-mariadb description: >- Server docker-compose deployment with docker orchestrator and all local @@ -187,9 +176,7 @@ environments: - mlflow-local-tracker - mlflow-local-registry - mlflow-local-deployer - mandatory_requirements: - - docker-local - + mandatory_requirements: [docker-local] - name: docker-server-airflow-orchestrator-mariadb description: >- Server docker-compose deployment with local airflow orchestrator and all @@ -200,5 +187,4 @@ environments: - mlflow-local-tracker - mlflow-local-registry - mlflow-local-deployer - mandatory_requirements: - - airflow-local + mandatory_requirements: [airflow-local] diff --git a/tests/harness/cfg/requirements.yaml b/tests/harness/cfg/requirements.yaml index 69c8e193b91..d44bf724c7c 100644 --- a/tests/harness/cfg/requirements.yaml +++ b/tests/harness/cfg/requirements.yaml @@ -1,3 +1,4 @@ +--- # Software requirements and stack components that are needed # by tests can be defined globally here and referenced by name in # environments or per-test configurations or passed to pytest directly using the @@ -120,8 +121,7 @@ requirements: # Local docker orchestrator - name: docker-local - system_tools: - - docker + system_tools: [docker] stacks: - name: docker-local type: orchestrator @@ -132,10 +132,8 @@ requirements: # Local airflow orchestrator - name: airflow-local - system_tools: - - docker - packages: - - apache-airflow-providers-docker + system_tools: [docker] + packages: [apache-airflow-providers-docker] stacks: - name: airflow-local type: orchestrator @@ -166,9 +164,7 @@ requirements: # Local mlflow model deployer - name: mlflow-local-deployer - system_os: - - linux - - macos + system_os: [linux, macos] stacks: - name: mlflow-local type: model_deployer diff --git a/tests/harness/cfg/tests.yaml b/tests/harness/cfg/tests.yaml index f9a3014cd67..2db7ee1ba81 100644 --- a/tests/harness/cfg/tests.yaml +++ b/tests/harness/cfg/tests.yaml @@ -1,3 +1,4 @@ +--- # Test configurations specify which requirements are needed for the test to run. # These requirements refer to both software packages and ZenML stack components. # @@ -40,73 +41,56 @@ # flavor: seldon # ``` tests: - - module: tests.integration.functional.test_zen_server_api requirements: - capabilities: server: true - - module: tests.integration.examples.test_deepchecks requirements: - - integrations: - - sklearn + - integrations: [sklearn] stacks: - type: data_validator flavor: deepchecks - capabilities: synchronized: true - - module: tests.integration.examples.test_evidently requirements: - - integrations: - - sklearn - packages: - - pyarrow + - integrations: [sklearn] + packages: [pyarrow] stacks: - type: data_validator flavor: evidently - capabilities: synchronized: true - - module: tests.integration.examples.test_great_expectations requirements: - - integrations: - - sklearn + - integrations: [sklearn] stacks: - type: data_validator flavor: great_expectations - capabilities: synchronized: true - - module: tests.integration.examples.test_tensorflow requirements: - - integrations: - - tensorflow - - tensorboard + - integrations: [tensorflow, tensorboard] - capabilities: synchronized: true - - module: tests.integration.examples.test_sklearn requirements: - - integrations: - - sklearn + - integrations: [sklearn] - capabilities: synchronized: true - - module: tests.integration.examples.test_mlflow_tracking requirements: - - integrations: - - tensorflow + - integrations: [tensorflow] stacks: - type: experiment_tracker flavor: mlflow - capabilities: synchronized: true - - module: tests.integration.examples.test_mlflow_registry requirements: - - integrations: - - tensorflow + - integrations: [tensorflow] stacks: - type: experiment_tracker flavor: mlflow @@ -116,78 +100,54 @@ tests: flavor: mlflow - capabilities: synchronized: true - - module: tests.integration.examples.test_neural_prophet requirements: - - integrations: - - neural_prophet + - integrations: [neural_prophet] - capabilities: synchronized: true - - module: tests.integration.examples.test_pytorch requirements: - - integrations: - - pytorch - packages: - - torchvision + - integrations: [pytorch] + packages: [torchvision] - capabilities: synchronized: true - - module: tests.integration.examples.test_whylogs requirements: - - integrations: - - sklearn + - integrations: [sklearn] stacks: - type: data_validator flavor: whylogs - system_os: - - linux - - macos + system_os: [linux, macos] - capabilities: synchronized: true - - module: tests.integration.examples.test_xgboost requirements: - - integrations: - - xgboost + - integrations: [xgboost] - capabilities: synchronized: true - - module: tests.integration.examples.test_huggingface requirements: - - integrations: - - huggingface - - tensorflow + - integrations: [huggingface, tensorflow] - capabilities: synchronized: true - - module: tests.integration.examples.test_lightgbm requirements: - - integrations: - - lightgbm + - integrations: [lightgbm] - capabilities: synchronized: true - - module: tests.integration.examples.test_scipy requirements: - - integrations: - - sklearn + - integrations: [sklearn] - capabilities: synchronized: true - - module: tests.integration.examples.test_facets requirements: - - integrations: - - facets - - sklearn + - integrations: [facets, sklearn] - capabilities: synchronized: true - - module: tests.integration.examples.test_mlflow_deployment requirements: - - integrations: - - tensorflow - - mlflow + - integrations: [tensorflow, mlflow] stacks: - type: experiment_tracker flavor: mlflow @@ -195,13 +155,9 @@ tests: flavor: mlflow - capabilities: synchronized: true - - module: tests.integration.examples.test_slack requirements: - - integrations: - - sklearn - - mlflow - - slack + - integrations: [sklearn, mlflow, slack] stacks: - type: experiment_tracker flavor: mlflow @@ -211,12 +167,9 @@ tests: flavor: slack - capabilities: synchronized: true - - module: tests.integration.examples.test_seldon requirements: - - integrations: - - sklearn - - tensorflow + - integrations: [sklearn, tensorflow] stacks: - type: model_deployer flavor: seldon From 8ae5a0cd904f40b5802079a18d22d9bf60c6fb9f Mon Sep 17 00:00:00 2001 From: Alex Strick van Linschoten Date: Tue, 9 Jan 2024 16:48:03 +0100 Subject: [PATCH 04/16] Remove text annotation (#2246) --- examples/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/README.md b/examples/README.md index 1f19f0d13f5..82006bf5342 100644 --- a/examples/README.md +++ b/examples/README.md @@ -31,7 +31,6 @@ this. | e2e | Trains one or more scikit-learn classification models to make predictions on tabular classification datasets | scikit-learn | ✅ | | generative_chat | LEGACY: constructs a vector store to be used by a LLM-based chatbot based on documentation and data from a variety of sources | langchain, llama-index, slack | | | label_studio_annotation | LEGACY: shows how to use the Label Studio integration for annotation in a computer-vision use case and series of pipelines | label_studio, pillow | | -| label_studio_text_annotation | LEGACY: shows how to use the Label Studio integration in a NLP / text-based use case and series of pipelines | label_studio | | ## ❓ Questions / Further Assistance From 10305514a71de52a8c0d72deaf545ac45f5519dd Mon Sep 17 00:00:00 2001 From: Alex Strick van Linschoten Date: Tue, 9 Jan 2024 19:41:58 +0100 Subject: [PATCH 05/16] Add MariaDB migration testing (#2170) * update script to handle mariadb migration testing * WIP * reformat temporary script * parameterize DB startup delay * add a check for mysql vs mariadb * try another way to isolate mariadb vs mysql * try a different mariadb connection path * Fix database connection URL in test-migrations.sh script * Adjust settings for MySQL and MariaDB engines in migration script * log values * temporarily disable full CI runs for testing * print values * trying a different connection approach * trying innodb * Add support for MariaDB in primary key modification * split mariadb from mysql db migration testing * split mariadb from mysql db migration testing (core) * Remove support for MariaDB and add version 0.53.1 * Split out mariadb from mysql in migration testing * add latest zenml version * Update migration testing scripts for different databases * restore the CI to working state * formatting * use zenml init * reformat yml * revert to copier instantiation * add conditional check for version >= 0.43.0 * compare set of vals instead of complicated semantic check * remove extra cd * update mariadb script * add test flag to init command * remove (extra) analytics opt-out * Add additional template versions for testing migrations * enable the CI again * Add comment explaining pre-template-versions --- .github/workflows/release.yml | 16 +++- scripts/test-migrations-mariadb.sh | 86 +++++++++++++++++++ ...migrations.sh => test-migrations-mysql.sh} | 26 ++++-- 3 files changed, 119 insertions(+), 9 deletions(-) create mode 100755 scripts/test-migrations-mariadb.sh rename scripts/{test-migrations.sh => test-migrations-mysql.sh} (77%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3f653c71bef..5489bf5bdad 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,7 +38,7 @@ jobs: with: python-version: '3.9' - name: Test migrations across versions - run: bash scripts/test-migrations.sh mysql + run: bash scripts/test-migrations-mysql.sh mysql sqlite-db-migration-testing: runs-on: ubuntu-dind-runners steps: @@ -49,13 +49,25 @@ jobs: with: python-version: '3.9' - name: Test migrations across versions - run: bash scripts/test-migrations.sh sqlite + run: bash scripts/test-migrations-mysql.sh sqlite + mariadb-db-migration-testing: + runs-on: ubuntu-dind-runners + steps: + - name: Checkout code + uses: actions/checkout@v4.1.1 + - name: Set up Python 3.9 + uses: actions/setup-python@v4.8.0 + with: + python-version: '3.9' + - name: Test migrations across versions + run: bash scripts/test-migrations-mariadb.sh publish-python-package: needs: - setup-and-test - mlstacks-compatibility-check - sqlite-db-migration-testing - mysql-db-migration-testing + - mariadb-db-migration-testing uses: ./.github/workflows/publish_to_pypi.yml secrets: inherit wait-for-package-release: diff --git a/scripts/test-migrations-mariadb.sh b/scripts/test-migrations-mariadb.sh new file mode 100755 index 00000000000..eb5234d7aa1 --- /dev/null +++ b/scripts/test-migrations-mariadb.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +DB="mariadb" +DB_STARTUP_DELAY=30 # Time in seconds to wait for the database container to start + +function run_tests_for_version() { + set -e # Exit immediately if a command exits with a non-zero status + local VERSION=$1 + + echo "===== Testing version $VERSION =====" + + mkdir test_starter + zenml init --template starter --path test_starter --template-with-defaults --test + cd test_starter + + export ZENML_ANALYTICS_OPT_IN=false + export ZENML_DEBUG=true + + echo "===== Installing sklearn integration =====" + zenml integration install sklearn -y + + echo "===== Running starter template pipeline =====" + python3 run.py + # Add additional CLI tests here + zenml version + + # Confirm DB works and is accessible + zenml pipeline runs list + + cd .. + rm -rf test_starter + echo "===== Finished testing version $VERSION =====" +} + +echo "===== Testing MariaDB =====" +# run a mariadb instance in docker +docker run --name mariadb -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=password mariadb:10.6 +# mariadb takes a while to start up +sleep $DB_STARTUP_DELAY + +# List of versions to test +VERSIONS=("0.54.0") + +# Start completely fresh +rm -rf ~/.config/zenml + +for VERSION in "${VERSIONS[@]}" +do + set -e # Exit immediately if a command exits with a non-zero status + # Create a new virtual environment + python3 -m venv ".venv-$VERSION" + source ".venv-$VERSION/bin/activate" + + # Install the specific version + pip3 install -U pip setuptools wheel + pip3 install "zenml[templates,server]==$VERSION" + + zenml connect --url mysql://127.0.0.1/zenml --username root --password password + + # Run the tests for this version + run_tests_for_version $VERSION + + zenml disconnect + sleep 5 + + deactivate +done + +# Test the most recent migration with MariaDB +echo "===== TESTING CURRENT BRANCH =====" +set -e +python3 -m venv ".venv-current-branch" +source ".venv-current-branch/bin/activate" + +pip3 install -U pip setuptools wheel +pip3 install -e ".[templates,server]" +pip3 install importlib_metadata + +zenml connect --url mysql://127.0.0.1/zenml --username root --password password + +run_tests_for_version current_branch_mariadb + +zenml disconnect +docker rm -f mariadb + +deactivate diff --git a/scripts/test-migrations.sh b/scripts/test-migrations-mysql.sh similarity index 77% rename from scripts/test-migrations.sh rename to scripts/test-migrations-mysql.sh index 7c152eda94b..7c57261dc28 100755 --- a/scripts/test-migrations.sh +++ b/scripts/test-migrations-mysql.sh @@ -1,6 +1,8 @@ #!/bin/bash DB="sqlite" +DB_STARTUP_DELAY=30 # Time in seconds to wait for the database container to start + if [ -z "$1" ]; then echo "No argument passed, using default: $DB" else @@ -10,12 +12,20 @@ fi function run_tests_for_version() { set -e # Exit immediately if a command exits with a non-zero status local VERSION=$1 + # versions pre-templates and pre-init test flag + # (zenml init --test allows for a non-interactive init) + local PRE_TEMPLATE_VERSIONS=("0.40.0" "0.40.3" "0.41.0" "0.43.0" "0.44.1" "0.44.3" "0.45.2" "0.45.3" "0.45.4" "0.45.5" "0.45.6" "0.46.0" "0.47.0") echo "===== Testing version $VERSION =====" - # Initialize zenml with the appropriate template - # hardcoded to 0.43.0 since this is the latest template-starter repo - # release tag - copier copy -l --trust -r release/0.43.0 https://github.com/zenml-io/template-starter.git test_starter + + # Check if VERSION is in PRE_TEMPLATE_VERSIONS + if printf '%s\n' "${PRE_TEMPLATE_VERSIONS[@]}" | grep -q "^$VERSION$"; then + copier copy -l --trust -r release/0.43.0 https://github.com/zenml-io/template-starter.git test_starter + else + mkdir test_starter + zenml init --template starter --path test_starter --template-with-defaults --test + fi + cd test_starter export ZENML_ANALYTICS_OPT_IN=false @@ -37,17 +47,18 @@ function run_tests_for_version() { echo "===== Finished testing version $VERSION =====" } + + if [ "$1" == "mysql" ]; then echo "===== Testing MySQL =====" # run a mysql instance in docker docker run --name mysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=password mysql:latest - # mysql takes a while to start up - sleep 30 + sleep $DB_STARTUP_DELAY fi # List of versions to test -VERSIONS=("0.40.0" "0.40.3" "0.41.0" "0.43.0" "0.44.1" "0.44.3" "0.45.2" "0.45.3" "0.45.4" "0.45.5" "0.45.6" "0.46.0" "0.47.0" "0.50.0" "0.51.0" "0.52.0") +VERSIONS=("0.40.0" "0.40.3" "0.41.0" "0.43.0" "0.44.1" "0.44.3" "0.45.2" "0.45.3" "0.45.4" "0.45.5" "0.45.6" "0.46.0" "0.47.0" "0.50.0" "0.51.0" "0.52.0" "0.53.0" "0.53.1" "0.54.0") # Start completely fresh rm -rf ~/.config/zenml @@ -95,6 +106,7 @@ done # Test the most recent migration with MySQL +echo "===== TESTING CURRENT BRANCH =====" set -e python3 -m venv ".venv-current-branch" source ".venv-current-branch/bin/activate" From 5e47b81ffc9694ef514c1ef7bc7ca811761c9301 Mon Sep 17 00:00:00 2001 From: Andrei Vishniakov <31008759+avishniakov@users.noreply.github.com> Date: Wed, 10 Jan 2024 09:07:22 +0100 Subject: [PATCH 06/16] Delete artifact links from model version via Client, ModelVersion and API (#2191) * typo * client and ModelVersion implementations * adding endpoints * split endpoints * lint * coderabbitai feedback * lint * Apply suggestions from code review Co-authored-by: Alex Strick van Linschoten * finish renaming * renaming leftover * move deletion to sql --------- Co-authored-by: Alex Strick van Linschoten --- src/zenml/client.py | 49 ++++++++++++- src/zenml/model/model_version.py | 63 +++++++++++++++++ src/zenml/models/v2/core/model_version.py | 2 +- .../routers/model_versions_endpoints.py | 26 ++++++- src/zenml/zen_stores/rest_zen_store.py | 16 +++++ src/zenml/zen_stores/sql_zen_store.py | 41 ++++++++++- src/zenml/zen_stores/zen_store_interface.py | 13 ++++ .../functional/model/test_model_version.py | 69 +++++++++++++++++++ .../functional/zen_stores/test_zen_store.py | 28 +++++++- 9 files changed, 299 insertions(+), 8 deletions(-) diff --git a/src/zenml/client.py b/src/zenml/client.py index eb6506bc5ed..c8bad22ddee 100644 --- a/src/zenml/client.py +++ b/src/zenml/client.py @@ -2948,7 +2948,7 @@ def delete_artifact_version( database, not the actual object stored in the artifact store. Args: - name_id_or_prefix: The ID or name or prefix of the artifact to + name_id_or_prefix: The ID of artifact version or name or prefix of the artifact to delete. version: The version of the artifact to delete. delete_metadata: If True, delete the metadata of the artifact @@ -5003,8 +5003,6 @@ def update_model_version( ################################################# # Model Versions Artifacts - # - # Only view capabilities are exposed via client. ################################################# def list_model_version_artifact_links( @@ -5074,6 +5072,51 @@ def list_model_version_artifact_links( hydrate=hydrate, ) + def delete_model_version_artifact_link( + self, model_version_id: UUID, artifact_version_id: UUID + ) -> None: + """Delete model version to artifact link in Model Control Plane. + + Args: + model_version_id: The id of the model version holding the link. + artifact_version_id: The id of the artifact version to be deleted. + + Raises: + RuntimeError: If more than one artifact link is found for given filters. + """ + artifact_links = self.list_model_version_artifact_links( + model_version_id=model_version_id, + artifact_version_id=artifact_version_id, + ) + if artifact_links.items: + if artifact_links.total > 1: + raise RuntimeError( + "More than one artifact link found for give model version " + f"`{model_version_id}` and artifact version " + f"`{artifact_version_id}`. This should not be happening and " + "might indicate a corrupted state of your ZenML database. " + "Please seek support via Community Slack." + ) + self.zen_store.delete_model_version_artifact_link( + model_version_id=model_version_id, + model_version_artifact_link_name_or_id=artifact_links.items[ + 0 + ].id, + ) + + def delete_all_model_version_artifact_links( + self, model_version_id: UUID, only_links: bool + ) -> None: + """Delete all model version to artifact links in Model Control Plane. + + Args: + model_version_id: The id of the model version holding the link. + only_links: If true, only delete the link to the artifact. + """ + self.zen_store.delete_all_model_version_artifact_links( + model_version_id, only_links + ) + ################################################# # Model Versions Pipeline Runs # diff --git a/src/zenml/model/model_version.py b/src/zenml/model/model_version.py index 5755d456499..b1afb31fa84 100644 --- a/src/zenml/model/model_version.py +++ b/src/zenml/model/model_version.py @@ -346,6 +346,69 @@ def metadata(self) -> Dict[str, "MetadataType"]: for name, response in response.run_metadata.items() } + def delete_artifact( + self, + name: str, + version: Optional[str] = None, + only_link: bool = True, + delete_metadata: bool = True, + delete_from_artifact_store: bool = False, + ) -> None: + """Delete the artifact linked to this model version. + + Args: + name: The name of the artifact to delete. + version: The version of the artifact to delete (None for latest/non-versioned) + only_link: Whether to only delete the link to the artifact. + delete_metadata: Whether to delete the metadata of the artifact. + delete_from_artifact_store: Whether to delete the artifact from the artifact store. + """ + from zenml.client import Client + from zenml.models import ArtifactVersionResponse + + artifact_version = self.get_artifact(name, version) + if isinstance(artifact_version, ArtifactVersionResponse): + client = Client() + client.delete_model_version_artifact_link( + model_version_id=self.id, + artifact_version_id=artifact_version.id, + ) + if not only_link: + client.delete_artifact_version( + name_id_or_prefix=artifact_version.id, + delete_metadata=delete_metadata, + delete_from_artifact_store=delete_from_artifact_store, + ) + + def delete_all_artifacts( + self, + only_link: bool = True, + delete_from_artifact_store: bool = False, + ) -> None: + """Delete all artifacts linked to this model version. + + Args: + only_link: Whether to only delete the link to the artifact. + delete_from_artifact_store: Whether to delete the artifact from the artifact store. + """ + from zenml.client import Client + + client = Client() + + if not only_link and delete_from_artifact_store: + mv = self._get_model_version() + artifact_responses = mv.data_artifacts + artifact_responses.update(mv.model_artifacts) + artifact_responses.update(mv.deployment_artifacts) + + for artifact_ in artifact_responses.values(): + for artifact_response_ in artifact_.values(): + client._delete_artifact_from_artifact_store( + artifact_version=artifact_response_ + ) + + client.delete_all_model_version_artifact_links(self.id, only_link) + ######################### # Internal methods # ######################### diff --git a/src/zenml/models/v2/core/model_version.py b/src/zenml/models/v2/core/model_version.py index 8bc76545f18..dc1377fcd74 100644 --- a/src/zenml/models/v2/core/model_version.py +++ b/src/zenml/models/v2/core/model_version.py @@ -388,7 +388,7 @@ def data_artifacts( } @property - def endpoint_artifacts( + def deployment_artifacts( self, ) -> Dict[str, Dict[str, "ArtifactVersionResponse"]]: """Get all deployment artifacts linked to this model version. diff --git a/src/zenml/zen_server/routers/model_versions_endpoints.py b/src/zenml/zen_server/routers/model_versions_endpoints.py index f6357b0da34..ddde60e35f9 100644 --- a/src/zenml/zen_server/routers/model_versions_endpoints.py +++ b/src/zenml/zen_server/routers/model_versions_endpoints.py @@ -240,7 +240,7 @@ def delete_model_version_artifact_link( model_version_artifact_link_name_or_id: Union[str, UUID], _: AuthContext = Security(authorize), ) -> None: - """Deletes a model version link. + """Deletes a model version to artifact link. Args: model_version_id: ID of the model version containing the link. @@ -256,6 +256,30 @@ def delete_model_version_artifact_link( ) +@router.delete( + "/{model_version_id}" + ARTIFACTS, + responses={401: error_response, 404: error_response, 422: error_response}, +) +@handle_exceptions +def delete_all_model_version_artifact_links( + model_version_id: UUID, + only_links: bool = True, + _: AuthContext = Security(authorize), +) -> None: + """Deletes all model version to artifact links. + + Args: + model_version_id: ID of the model version containing links. + only_links: Whether to only delete the link to the artifact. + """ + model_version = zen_store().get_model_version(model_version_id) + verify_permission_for_model(model_version, action=Action.UPDATE) + + zen_store().delete_all_model_version_artifact_links( + model_version_id, only_links + ) + + ############################## # Model Version Pipeline Runs ############################## diff --git a/src/zenml/zen_stores/rest_zen_store.py b/src/zenml/zen_stores/rest_zen_store.py index 866105675c3..3df596c58df 100644 --- a/src/zenml/zen_stores/rest_zen_store.py +++ b/src/zenml/zen_stores/rest_zen_store.py @@ -2836,6 +2836,22 @@ def delete_model_version_artifact_link( route=f"{MODEL_VERSIONS}/{model_version_id}{ARTIFACTS}", ) + def delete_all_model_version_artifact_links( + self, + model_version_id: UUID, + only_links: bool = True, + ) -> None: + """Deletes all links between model version and an artifact. + + Args: + model_version_id: ID of the model version containing the link. + only_links: Flag deciding whether to delete only links or all. + """ + self.delete( + f"{MODEL_VERSIONS}/{model_version_id}{ARTIFACTS}", + params={"only_links": only_links}, + ) + # ---------------------- Model Versions Pipeline Runs ---------------------- def create_model_version_pipeline_run_link( diff --git a/src/zenml/zen_stores/sql_zen_store.py b/src/zenml/zen_stores/sql_zen_store.py index c38dbb69c16..e26747576b7 100644 --- a/src/zenml/zen_stores/sql_zen_store.py +++ b/src/zenml/zen_stores/sql_zen_store.py @@ -50,7 +50,7 @@ OperationalError, ) from sqlalchemy.orm import noload -from sqlmodel import Session, SQLModel, create_engine, or_, select +from sqlmodel import Session, SQLModel, col, create_engine, delete, or_, select from sqlmodel.sql.expression import Select, SelectOfScalar from zenml.analytics.enums import AnalyticsEvent @@ -1624,7 +1624,7 @@ def get_artifact_version( if artifact_version is None: raise KeyError( f"Unable to get artifact version with ID " - f"{artifact_version_id}: No artifact versionwith this ID " + f"{artifact_version_id}: No artifact version with this ID " f"found." ) return artifact_version.to_model(hydrate=hydrate) @@ -6827,6 +6827,43 @@ def delete_model_version_artifact_link( session.delete(model_version_artifact_link) session.commit() + def delete_all_model_version_artifact_links( + self, + model_version_id: UUID, + only_links: bool = True, + ) -> None: + """Deletes all model version to artifact links. + + Args: + model_version_id: ID of the model version containing the link. + only_links: Whether to only delete the link to the artifact. + """ + with Session(self.engine) as session: + if not only_links: + artifact_version_ids = session.execute( + select( + ModelVersionArtifactSchema.artifact_version_id + ).where( + ModelVersionArtifactSchema.model_version_id + == model_version_id + ) + ).fetchall() + session.execute( + delete(ArtifactVersionSchema).where( + col(ArtifactVersionSchema.id).in_( + [a[0] for a in artifact_version_ids] + ) + ), + ) + session.execute( + delete(ModelVersionArtifactSchema).where( + ModelVersionArtifactSchema.model_version_id + == model_version_id + ) + ) + + session.commit() + # ---------------------- Model Versions Pipeline Runs ---------------------- def create_model_version_pipeline_run_link( diff --git a/src/zenml/zen_stores/zen_store_interface.py b/src/zenml/zen_stores/zen_store_interface.py index b3d7a20f3aa..35d7d89083c 100644 --- a/src/zenml/zen_stores/zen_store_interface.py +++ b/src/zenml/zen_stores/zen_store_interface.py @@ -2199,6 +2199,19 @@ def delete_model_version_artifact_link( KeyError: specified ID or name not found. """ + @abstractmethod + def delete_all_model_version_artifact_links( + self, + model_version_id: UUID, + only_links: bool = True, + ) -> None: + """Deletes all model version to artifact links. + + Args: + model_version_id: ID of the model version containing the link. + only_links: Flag deciding whether to delete only links or all. + """ + # -------------------- Model Versions Pipeline Runs -------------------- @abstractmethod diff --git a/tests/integration/functional/model/test_model_version.py b/tests/integration/functional/model/test_model_version.py index 83150fe4991..f0eaae0c926 100644 --- a/tests/integration/functional/model/test_model_version.py +++ b/tests/integration/functional/model/test_model_version.py @@ -68,6 +68,12 @@ def step_metadata_logging_functional(): assert get_step_context().model_version.metadata["foo"] == "bar" +@step +def simple_producer() -> str: + """Simple producer step.""" + return "foo" + + @step def consume_from_model_version( is_consume: bool, @@ -393,6 +399,69 @@ def my_pipeline(): assert len(mv.metadata) == 1 assert mv.metadata["foo"] == "bar" + @pytest.mark.parametrize("delete_artifacts", [False, True]) + def test_deletion_of_links( + self, clean_client: "Client", delete_artifacts: bool + ): + """Test that user can delete artifact links (with artifacts) from ModelVersion.""" + + @pipeline( + model_version=ModelVersion( + name=MODEL_NAME, + ), + enable_cache=False, + ) + def _inner_pipeline(): + simple_producer() + simple_producer(id="other_named_producer") + + _inner_pipeline() + + mv = ModelVersion(name=MODEL_NAME, version="latest") + artifact_ids = mv._get_model_version().data_artifact_ids + assert len(artifact_ids) == 2 + + # delete run to enable artifacts deletion + run = clean_client.get_pipeline( + name_id_or_prefix="_inner_pipeline" + ).last_run + clean_client.delete_pipeline_run(run.id) + + mv.delete_artifact( + only_link=not delete_artifacts, + name="_inner_pipeline::other_named_producer::output", + ) + assert len(mv._get_model_version().data_artifact_ids) == 1 + versions_ = artifact_ids[ + "_inner_pipeline::other_named_producer::output" + ]["1"] + if delete_artifacts: + with pytest.raises(KeyError): + clean_client.get_artifact_version(versions_) + else: + assert clean_client.get_artifact_version(versions_).id == versions_ + + _inner_pipeline() + mv = ModelVersion(name=MODEL_NAME, version="latest") + artifact_ids = mv._get_model_version().data_artifact_ids + assert len(artifact_ids) == 2 + + # delete run to enable artifacts deletion + run = clean_client.get_pipeline( + name_id_or_prefix="_inner_pipeline" + ).last_run + clean_client.delete_pipeline_run(run.id) + + mv.delete_all_artifacts(only_link=not delete_artifacts) + assert len(mv._get_model_version().data_artifact_ids) == 0 + for versions_ in artifact_ids.values(): + for id_ in versions_.values(): + if delete_artifacts: + with pytest.raises(KeyError): + clean_client.get_artifact_version(id_) + else: + assert clean_client.get_artifact_version(id_).id == id_ + def test_that_artifacts_are_not_linked_to_models_outside_of_the_context( self, clean_client: "Client" ): diff --git a/tests/integration/functional/zen_stores/test_zen_store.py b/tests/integration/functional/zen_stores/test_zen_store.py index cbc1613cee5..6d7e7813d18 100644 --- a/tests/integration/functional/zen_stores/test_zen_store.py +++ b/tests/integration/functional/zen_stores/test_zen_store.py @@ -4210,6 +4210,32 @@ def test_link_delete_found(self): ) assert len(mvls) == 0 + def test_link_delete_all(self): + with ModelVersionContext(True, create_artifacts=2) as ( + model_version, + artifacts, + ): + zs = Client().zen_store + for artifact in artifacts: + zs.create_model_version_artifact_link( + ModelVersionArtifactRequest( + user=model_version.user.id, + workspace=model_version.workspace.id, + model=model_version.model.id, + model_version=model_version.id, + artifact_version=artifact.id, + ) + ) + zs.delete_all_model_version_artifact_links( + model_version_id=model_version.id, + ) + mvls = zs.list_model_version_artifact_links( + model_version_artifact_link_filter_model=ModelVersionArtifactFilter( + model_version_id=model_version.id + ), + ) + assert len(mvls) == 0 + def test_link_delete_not_found(self): with ModelVersionContext(True) as model_version: zs = Client().zen_store @@ -4318,7 +4344,7 @@ def test_link_list_populated(self): ) assert ( mv.get_deployment_artifact(artifacts[2].name, "1") - == mv.endpoint_artifacts[artifacts[2].name]["1"] + == mv.deployment_artifacts[artifacts[2].name]["1"] ) From ad05fb5c00ec10002c11badc7293a71b2df09be2 Mon Sep 17 00:00:00 2001 From: Andrei Vishniakov <31008759+avishniakov@users.noreply.github.com> Date: Thu, 11 Jan 2024 08:50:58 +0100 Subject: [PATCH 07/16] Default/Non-Default step params produce conflict with yaml ones as defaults are set in code (#2247) * fix for default/non-default params in step * extend test case * Update tests/integration/functional/pipelines/test_pipeline_config.py Co-authored-by: Alex Strick van Linschoten * Auto-update of Starter template * wandb lint * skip yamlfix on windows --------- Co-authored-by: Alex Strick van Linschoten Co-authored-by: GitHub Actions --- .../workflows/setup-python-environment.yml | 2 + scripts/lint.sh | 20 ++++++---- .../wandb_experiment_tracker.py | 2 +- .../wandb_experiment_tracker_flavor.py | 2 +- src/zenml/new/pipelines/pipeline.py | 3 ++ src/zenml/steps/base_step.py | 8 +++- src/zenml/steps/step_invocation.py | 11 ++++++ .../pipelines/test_pipeline_config.py | 39 +++++++++++++++++++ tests/unit/orchestrators/test_cache_utils.py | 1 + 9 files changed, 76 insertions(+), 12 deletions(-) diff --git a/.github/workflows/setup-python-environment.yml b/.github/workflows/setup-python-environment.yml index a290febbce5..bad2f33d979 100644 --- a/.github/workflows/setup-python-environment.yml +++ b/.github/workflows/setup-python-environment.yml @@ -89,6 +89,8 @@ jobs: if: ${{ inputs.enable_tmate == 'before-tests' }} uses: mxschmitt/action-tmate@v3.17 - name: Lint check + env: + OS: ${{ inputs.os }} run: | bash scripts/lint.sh - name: Spelling checker diff --git a/scripts/lint.sh b/scripts/lint.sh index 21076880260..b6576a3532d 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -15,14 +15,18 @@ ruff $SRC_NO_TESTS ruff $TESTS_EXAMPLES --extend-ignore D # Flag check for skipping yamlfix -SKIP_YAMLFIX=false -for arg in "$@" -do - if [ "$arg" = "--no-yamlfix" ]; then - SKIP_YAMLFIX=true - break - fi -done +if [ "$OS" = "windows-latest" ]; then + SKIP_YAMLFIX=true +else + SKIP_YAMLFIX=false + for arg in "$@" + do + if [ "$arg" = "--no-yamlfix" ]; then + SKIP_YAMLFIX=true + break + fi + done +fi # checks for yaml formatting errors if [ "$SKIP_YAMLFIX" = false ]; then diff --git a/src/zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py b/src/zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py index 4689d1117dd..e52e1e88ae6 100644 --- a/src/zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py +++ b/src/zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py @@ -133,7 +133,7 @@ def _initialize_wandb( self, run_name: str, tags: List[str], - settings: Union["Settings", Dict[str, Any], None] = None, # type: ignore + settings: Union["Settings", Dict[str, Any], None] = None, ) -> None: """Initializes a wandb run. diff --git a/src/zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py b/src/zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py index 626a9e1c8d9..f3e2157f205 100644 --- a/src/zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +++ b/src/zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py @@ -58,7 +58,7 @@ class WandbExperimentTrackerSettings(BaseSettings): @validator("settings", pre=True) def _convert_settings( cls, - value: Union[Dict[str, Any], "Settings"], # type: ignore + value: Union[Dict[str, Any], "Settings"], ) -> Dict[str, Any]: """Converts settings to a dictionary. diff --git a/src/zenml/new/pipelines/pipeline.py b/src/zenml/new/pipelines/pipeline.py index 2cc7e9e4987..b5006ad1ae8 100644 --- a/src/zenml/new/pipelines/pipeline.py +++ b/src/zenml/new/pipelines/pipeline.py @@ -1260,6 +1260,7 @@ def add_step_invocation( input_artifacts: Dict[str, StepArtifact], external_artifacts: Dict[str, "ExternalArtifact"], parameters: Dict[str, Any], + default_parameters: Dict[str, Any], upstream_steps: Set[str], custom_id: Optional[str] = None, allow_id_suffix: bool = True, @@ -1271,6 +1272,7 @@ def add_step_invocation( input_artifacts: The input artifacts for the invocation. external_artifacts: The external artifacts for the invocation. parameters: The parameters for the invocation. + default_parameters: The default parameters for the invocation. upstream_steps: The upstream steps for the invocation. custom_id: Custom ID to use for the invocation. allow_id_suffix: Whether a suffix can be appended to the invocation @@ -1306,6 +1308,7 @@ def add_step_invocation( input_artifacts=input_artifacts, external_artifacts=external_artifacts, parameters=parameters, + default_parameters=default_parameters, upstream_steps=upstream_steps, pipeline=self, ) diff --git a/src/zenml/steps/base_step.py b/src/zenml/steps/base_step.py index e93add1dc0a..23eac3367c6 100644 --- a/src/zenml/steps/base_step.py +++ b/src/zenml/steps/base_step.py @@ -443,6 +443,7 @@ def _parse_call_args( Dict[str, "StepArtifact"], Dict[str, "ExternalArtifact"], Dict[str, Any], + Dict[str, Any], ]: """Parses the call args for the step entrypoint. @@ -470,6 +471,7 @@ def _parse_call_args( artifacts = {} external_artifacts = {} parameters = {} + default_parameters = {} for key, value in bound_args.arguments.items(): self.entrypoint_definition.validate_input(key=key, value=value) @@ -510,9 +512,9 @@ def _parse_call_args( and key not in external_artifacts and key not in self.configuration.parameters ): - parameters[key] = value + default_parameters[key] = value - return artifacts, external_artifacts, parameters + return artifacts, external_artifacts, parameters, default_parameters def __call__( self, @@ -548,6 +550,7 @@ def __call__( input_artifacts, external_artifacts, parameters, + default_parameters, ) = self._parse_call_args(*args, **kwargs) upstream_steps = { @@ -563,6 +566,7 @@ def __call__( input_artifacts=input_artifacts, external_artifacts=external_artifacts, parameters=parameters, + default_parameters=default_parameters, upstream_steps=upstream_steps, custom_id=id, allow_id_suffix=not id, diff --git a/src/zenml/steps/step_invocation.py b/src/zenml/steps/step_invocation.py index f6f74034723..4e3583514a8 100644 --- a/src/zenml/steps/step_invocation.py +++ b/src/zenml/steps/step_invocation.py @@ -32,6 +32,7 @@ def __init__( input_artifacts: Dict[str, "StepArtifact"], external_artifacts: Dict[str, "ExternalArtifact"], parameters: Dict[str, Any], + default_parameters: Dict[str, Any], upstream_steps: Set[str], pipeline: "Pipeline", ) -> None: @@ -43,6 +44,7 @@ def __init__( input_artifacts: The input artifacts for the invocation. external_artifacts: The external artifacts for the invocation. parameters: The parameters for the invocation. + default_parameters: The default parameters for the invocation. upstream_steps: The upstream steps for the invocation. pipeline: The parent pipeline of the invocation. """ @@ -51,6 +53,7 @@ def __init__( self.input_artifacts = input_artifacts self.external_artifacts = external_artifacts self.parameters = parameters + self.default_parameters = default_parameters self.invocation_upstream_steps = upstream_steps self.pipeline = pipeline @@ -129,6 +132,14 @@ def finalize(self, parameters_to_ignore: Set[str]) -> "StepConfiguration": for key, value in self.parameters.items() if key not in parameters_to_ignore } + parameters_to_apply.update( + { + key: value + for key, value in self.default_parameters.items() + if key not in parameters_to_ignore + and key not in parameters_to_apply + } + ) self.step.configure(parameters=parameters_to_apply) external_artifacts: Dict[str, ExternalArtifactConfiguration] = {} diff --git a/tests/integration/functional/pipelines/test_pipeline_config.py b/tests/integration/functional/pipelines/test_pipeline_config.py index cf9b060cdf5..1562d947884 100644 --- a/tests/integration/functional/pipelines/test_pipeline_config.py +++ b/tests/integration/functional/pipelines/test_pipeline_config.py @@ -196,6 +196,17 @@ def assert_input_params(bar: str): assert bar == "bar" +@step +def assert_input_params_with_defaults( + bar: str, + foo: str = "some default value", + this_will_be_default: str = "bar", +): + assert bar == "bar" + assert foo == "bar" + assert this_will_be_default == "bar" + + def test_pipeline_config_from_file_works_with_pipeline_parameters( clean_workspace, tmp_path ): @@ -283,3 +294,31 @@ def assert_input_params_pipe(foo: str): "`assert_input_params_pipe` conflict with parameter passed in runtime", ): p(foo="foo") + + +def test_pipeline_config_from_file_works_with_pipeline_parameters_on_conflict_with_default_parameters( + clean_workspace, tmp_path +): + """Test that the pipeline will not fail with error. + + If configured with parameters from a yaml file for the steps + and same parameters are set with some defaults in the code. + """ + config_path = tmp_path / "config.yaml" + file_config = { + "steps": { + "assert_input_params_with_defaults": { + "parameters": {"foo": "bar", "bar": "bar"} + } + }, + "enable_cache": False, + } + config_path.write_text(yaml.dump(file_config)) + + @pipeline(enable_cache=False) + def assert_input_params_pipe(): + assert_input_params_with_defaults() + + p = assert_input_params_pipe.with_options(config_path=str(config_path)) + + p() diff --git a/tests/unit/orchestrators/test_cache_utils.py b/tests/unit/orchestrators/test_cache_utils.py index 7585fe865e3..1d879d73cf2 100644 --- a/tests/unit/orchestrators/test_cache_utils.py +++ b/tests/unit/orchestrators/test_cache_utils.py @@ -38,6 +38,7 @@ def _compile_step(step: BaseStep) -> Step: input_artifacts={}, external_artifacts={}, parameters={}, + default_parameters={}, upstream_steps=set(), pipeline=pipeline, ) From f3a9838b1cb560a0b173577f8a7d498428c7ca2d Mon Sep 17 00:00:00 2001 From: Andrei Vishniakov <31008759+avishniakov@users.noreply.github.com> Date: Thu, 11 Jan 2024 08:51:14 +0100 Subject: [PATCH 08/16] Prune of unused artifacts links via client (#2192) * prune artifacts in client * more tests * remove branching * Update src/zenml/client.py Co-authored-by: Alex Strick van Linschoten * Update tests/integration/functional/test_client.py Co-authored-by: Alex Strick van Linschoten * Update tests/integration/functional/test_client.py Co-authored-by: Alex Strick van Linschoten * nits * resolve branching * `prune_artifact_versions` in SQLStore * lint * wandb lint * skip yamlfix on windows --------- Co-authored-by: Alex Strick van Linschoten --- src/zenml/client.py | 23 +++++++ src/zenml/zen_server/rbac/endpoint_utils.py | 16 +++++ src/zenml/zen_server/rbac/models.py | 1 + .../routers/artifact_version_endpoints.py | 22 +++++++ src/zenml/zen_stores/rest_zen_store.py | 13 ++++ src/zenml/zen_stores/sql_zen_store.py | 61 ++++++++++++++++++- src/zenml/zen_stores/zen_store_interface.py | 11 ++++ tests/integration/functional/test_client.py | 54 ++++++++++++++++ 8 files changed, 200 insertions(+), 1 deletion(-) diff --git a/src/zenml/client.py b/src/zenml/client.py index c8bad22ddee..c06dff4b476 100644 --- a/src/zenml/client.py +++ b/src/zenml/client.py @@ -2789,6 +2789,29 @@ def delete_artifact( self.zen_store.delete_artifact(artifact_id=artifact.id) logger.info(f"Deleted artifact '{artifact.name}'.") + def prune_artifacts( + self, + only_versions: bool = True, + delete_from_artifact_store: bool = False, + ) -> None: + """Delete all unused artifacts and artifact versions. + + Args: + only_versions: Only delete artifact versions, keeping artifacts + delete_from_artifact_store: Delete data from artifact metadata + """ + if delete_from_artifact_store: + unused_artifact_versions = depaginate( + partial(self.list_artifact_versions, only_unused=True) + ) + for unused_artifact_version in unused_artifact_versions: + self._delete_artifact_from_artifact_store( + unused_artifact_version + ) + + self.zen_store.prune_artifact_versions(only_versions) + logger.info("All unused artifacts and artifact versions deleted.") + # --------------------------- Artifact Versions --------------------------- def get_artifact_version( diff --git a/src/zenml/zen_server/rbac/endpoint_utils.py b/src/zenml/zen_server/rbac/endpoint_utils.py index 1f7b37bd10d..a0fc037342c 100644 --- a/src/zenml/zen_server/rbac/endpoint_utils.py +++ b/src/zenml/zen_server/rbac/endpoint_utils.py @@ -148,3 +148,19 @@ def verify_permissions_and_delete_entity( model = get_method(id) verify_permission_for_model(model, action=Action.DELETE) delete_method(model.id) + + +def verify_permissions_and_prune_entities( + resource_type: ResourceType, + prune_method: Callable[..., None], + **kwargs: Any, +) -> None: + """Verify permissions and prune entities of certain type. + + Args: + resource_type: The resource type of the entities to prune. + prune_method: The method to prune the entities. + kwargs: Keyword arguments to pass to the prune method. + """ + verify_permission(resource_type=resource_type, action=Action.PRUNE) + prune_method(**kwargs) diff --git a/src/zenml/zen_server/rbac/models.py b/src/zenml/zen_server/rbac/models.py index 96deda7bc47..b9ea5f4eb07 100644 --- a/src/zenml/zen_server/rbac/models.py +++ b/src/zenml/zen_server/rbac/models.py @@ -29,6 +29,7 @@ class Action(StrEnum): UPDATE = "update" DELETE = "delete" READ_SECRET_VALUE = "read_secret_value" + PRUNE = "prune" # Service connectors CLIENT = "client" diff --git a/src/zenml/zen_server/routers/artifact_version_endpoints.py b/src/zenml/zen_server/routers/artifact_version_endpoints.py index 9319002b2c7..c79330554ba 100644 --- a/src/zenml/zen_server/routers/artifact_version_endpoints.py +++ b/src/zenml/zen_server/routers/artifact_version_endpoints.py @@ -33,6 +33,7 @@ verify_permissions_and_create_entity, verify_permissions_and_delete_entity, verify_permissions_and_get_entity, + verify_permissions_and_prune_entities, verify_permissions_and_update_entity, ) from zenml.zen_server.rbac.models import ResourceType @@ -194,6 +195,27 @@ def delete_artifact_version( ) +@artifact_version_router.delete( + "/", + responses={401: error_response, 404: error_response, 422: error_response}, +) +@handle_exceptions +def prune_artifact_versions( + only_versions: bool = True, + _: AuthContext = Security(authorize), +) -> None: + """Prunes unused artifact versions and their artifacts. + + Args: + only_versions: Only delete artifact versions, keeping artifacts + """ + verify_permissions_and_prune_entities( + resource_type=ResourceType.ARTIFACT_VERSION, + prune_method=zen_store().prune_artifact_versions, + only_versions=only_versions, + ) + + @artifact_version_router.get( "/{artifact_version_id}" + VISUALIZE, response_model=LoadedVisualization, diff --git a/src/zenml/zen_stores/rest_zen_store.py b/src/zenml/zen_stores/rest_zen_store.py index 3df596c58df..d2cb81cad98 100644 --- a/src/zenml/zen_stores/rest_zen_store.py +++ b/src/zenml/zen_stores/rest_zen_store.py @@ -817,6 +817,19 @@ def delete_artifact_version(self, artifact_version_id: UUID) -> None: resource_id=artifact_version_id, route=ARTIFACT_VERSIONS ) + def prune_artifact_versions( + self, + only_versions: bool = True, + ) -> None: + """Prunes unused artifact versions and their artifacts. + + Args: + only_versions: Only delete artifact versions, keeping artifacts + """ + self.delete( + path=ARTIFACT_VERSIONS, params={"only_versions": only_versions} + ) + # ------------------------ Artifact Visualizations ------------------------ def get_artifact_visualization( diff --git a/src/zenml/zen_stores/sql_zen_store.py b/src/zenml/zen_stores/sql_zen_store.py index e26747576b7..10accb8d1fc 100644 --- a/src/zenml/zen_stores/sql_zen_store.py +++ b/src/zenml/zen_stores/sql_zen_store.py @@ -50,7 +50,16 @@ OperationalError, ) from sqlalchemy.orm import noload -from sqlmodel import Session, SQLModel, col, create_engine, delete, or_, select +from sqlmodel import ( + Session, + SQLModel, + and_, + col, + create_engine, + delete, + or_, + select, +) from sqlmodel.sql.expression import Select, SelectOfScalar from zenml.analytics.enums import AnalyticsEvent @@ -1731,6 +1740,56 @@ def delete_artifact_version(self, artifact_version_id: UUID) -> None: session.delete(artifact_version) session.commit() + def prune_artifact_versions( + self, + only_versions: bool = True, + ) -> None: + """Prunes unused artifact versions and their artifacts. + + Args: + only_versions: Only delete artifact versions, keeping artifacts + """ + with Session(self.engine) as session: + unused_artifact_versions = [ + a[0] + for a in session.execute( + select(ArtifactVersionSchema.id).where( + and_( + col(ArtifactVersionSchema.id).notin_( + select(StepRunOutputArtifactSchema.artifact_id) + ), + col(ArtifactVersionSchema.id).notin_( + select(StepRunInputArtifactSchema.artifact_id) + ), + ) + ) + ).fetchall() + ] + session.execute( + delete(ArtifactVersionSchema).where( + col(ArtifactVersionSchema.id).in_( + unused_artifact_versions + ), + ) + ) + if not only_versions: + unused_artifacts = [ + a[0] + for a in session.execute( + select(ArtifactSchema.id).where( + col(ArtifactSchema.id).notin_( + select(ArtifactVersionSchema.artifact_id) + ) + ) + ).fetchall() + ] + session.execute( + delete(ArtifactSchema).where( + col(ArtifactSchema.id).in_(unused_artifacts) + ) + ) + session.commit() + # ------------------------ Artifact Visualizations ------------------------ def get_artifact_visualization( diff --git a/src/zenml/zen_stores/zen_store_interface.py b/src/zenml/zen_stores/zen_store_interface.py index 35d7d89083c..4a8bbb4e3c4 100644 --- a/src/zenml/zen_stores/zen_store_interface.py +++ b/src/zenml/zen_stores/zen_store_interface.py @@ -504,6 +504,17 @@ def delete_artifact_version(self, artifact_version_id: UUID) -> None: KeyError: if the artifact version doesn't exist. """ + @abstractmethod + def prune_artifact_versions( + self, + only_versions: bool = True, + ) -> None: + """Prunes unused artifact versions and their artifacts. + + Args: + only_versions: Only delete artifact versions, keeping artifacts + """ + # -------------------- Artifact Visualization -------------------- @abstractmethod diff --git a/tests/integration/functional/test_client.py b/tests/integration/functional/test_client.py index 543a5f35bca..5398b6fd3df 100644 --- a/tests/integration/functional/test_client.py +++ b/tests/integration/functional/test_client.py @@ -27,6 +27,7 @@ int_plus_one_test_step, ) from tests.integration.functional.utils import sample_name +from zenml import ExternalArtifact from zenml.client import Client from zenml.config.pipeline_spec import PipelineSpec from zenml.config.source import Source @@ -1128,6 +1129,59 @@ def test_basic_crud_for_entity( pass +class TestArtifact: + def test_prune_full(self, clean_client: "Client"): + """Test that artifact pruning works.""" + artifact_id = ExternalArtifact(value="foo").upload_by_value() + artifact = clean_client.get_artifact_version(artifact_id) + assert artifact is not None + clean_client.prune_artifacts( + only_versions=False, delete_from_artifact_store=True + ) + # artifact version, artifact and data are deleted + with pytest.raises(KeyError): + clean_client.get_artifact_version(artifact_id) + with pytest.raises(KeyError): + assert ( + clean_client.get_artifact(artifact.artifact.id).id + == artifact.artifact.id + ) + assert not os.path.exists(artifact.uri) + + def test_prune_data_and_version(self, clean_client: "Client"): + """Test that artifact pruning works with delete_from_artifact_store flag.""" + artifact_id = ExternalArtifact(value="foo").upload_by_value() + artifact = clean_client.get_artifact_version(artifact_id) + assert artifact is not None + clean_client.prune_artifacts( + only_versions=False, delete_from_artifact_store=False + ) + # artifact version and artifact are deleted, data is kept + with pytest.raises(KeyError): + clean_client.get_artifact_version(artifact_id) + with pytest.raises(KeyError): + assert ( + clean_client.get_artifact(artifact.artifact.id).id + == artifact.artifact.id + ) + assert os.path.exists(artifact.uri) + + def test_prune_only_artifact_version(self, clean_client: "Client"): + """Test that artifact pruning works with only versions flag.""" + artifact_id = ExternalArtifact(value="foo").upload_by_value() + artifact = clean_client.get_artifact_version(artifact_id) + assert artifact is not None + clean_client.prune_artifacts(only_versions=True) + # artifact version is deleted, rest kept + with pytest.raises(KeyError): + clean_client.get_artifact_version(artifact_id) + assert ( + clean_client.get_artifact(artifact.artifact.id).id + == artifact.artifact.id + ) + assert os.path.exists(artifact.uri) + + class TestModel: MODEL_NAME = "foo" From 250e65cb306163d4ebc379ea950919826c33a620 Mon Sep 17 00:00:00 2001 From: Safoine El Khabich <34200873+safoinme@users.noreply.github.com> Date: Thu, 11 Jan 2024 15:47:06 +0100 Subject: [PATCH 09/16] Rename nlp example (#2221) * rename nlp case * rename to e2e_nlp * Add HuggingFace and Skypilot deployment steps --- .../update-templates-to-examples.yml | 2 +- .../.assets/00_pipelines_composition.png | Bin .../{nlp-case => e2e_nlp}/.copier-answers.yml | 8 +-- examples/{nlp-case => e2e_nlp}/.dockerignore | 0 examples/{nlp-case => e2e_nlp}/LICENSE | 0 examples/{nlp-case => e2e_nlp}/Makefile | 0 examples/{nlp-case => e2e_nlp}/README.md | 30 +++------ examples/{nlp-case => e2e_nlp}/config.yaml | 0 .../{nlp-case => e2e_nlp}/gradio/Dockerfile | 0 .../{nlp-case => e2e_nlp}/gradio/__init__.py | 0 examples/{nlp-case => e2e_nlp}/gradio/app.py | 0 .../gradio/requirements.txt | 0 .../{nlp-case => e2e_nlp}/gradio/serve.yaml | 0 .../pipelines/__init__.py | 0 .../pipelines/deploying.py | 13 +++- .../pipelines/promoting.py | 0 .../pipelines/training.py | 0 .../{nlp-case => e2e_nlp}/requirements.txt | 0 examples/{nlp-case => e2e_nlp}/run.py | 0 .../{nlp-case => e2e_nlp}/steps/__init__.py | 2 + .../steps/alerts/__init__.py | 0 .../steps/alerts/notify_on.py | 0 .../steps/dataset_loader/__init__.py | 0 .../steps/dataset_loader/data_loader.py | 0 .../steps/deploying/__init__.py | 6 ++ .../steps/deploying/huggingface_deployment.py | 63 ++++++++++++++++++ .../steps/deploying/local_deployment.py | 0 .../steps/deploying/save_model.py | 0 .../steps/deploying/skypilot_deployment.py | 53 +++++++++++++++ .../steps/promotion/__init__.py | 0 .../steps/promotion/promote_get_metrics.py | 0 .../promote_metric_compare_promoter.py | 0 .../steps/register/__init__.py | 0 .../steps/register/model_log_register.py | 0 .../steps/tokenizer_loader/__init__.py | 0 .../tokenizer_loader/tokenizer_loader.py | 0 .../steps/tokenzation/__init__.py | 0 .../steps/tokenzation/tokenization.py | 0 .../steps/training/__init__.py | 0 .../steps/training/model_trainer.py | 0 examples/{nlp-case => e2e_nlp}/utils/misc.py | 0 41 files changed, 150 insertions(+), 27 deletions(-) rename examples/{nlp-case => e2e_nlp}/.assets/00_pipelines_composition.png (100%) rename examples/{nlp-case => e2e_nlp}/.copier-answers.yml (80%) rename examples/{nlp-case => e2e_nlp}/.dockerignore (100%) rename examples/{nlp-case => e2e_nlp}/LICENSE (100%) rename examples/{nlp-case => e2e_nlp}/Makefile (100%) rename examples/{nlp-case => e2e_nlp}/README.md (94%) rename examples/{nlp-case => e2e_nlp}/config.yaml (100%) rename examples/{nlp-case => e2e_nlp}/gradio/Dockerfile (100%) rename examples/{nlp-case => e2e_nlp}/gradio/__init__.py (100%) rename examples/{nlp-case => e2e_nlp}/gradio/app.py (100%) rename examples/{nlp-case => e2e_nlp}/gradio/requirements.txt (100%) rename examples/{nlp-case => e2e_nlp}/gradio/serve.yaml (100%) rename examples/{nlp-case => e2e_nlp}/pipelines/__init__.py (100%) rename examples/{nlp-case => e2e_nlp}/pipelines/deploying.py (89%) rename examples/{nlp-case => e2e_nlp}/pipelines/promoting.py (100%) rename examples/{nlp-case => e2e_nlp}/pipelines/training.py (100%) rename examples/{nlp-case => e2e_nlp}/requirements.txt (100%) rename examples/{nlp-case => e2e_nlp}/run.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/__init__.py (95%) rename examples/{nlp-case => e2e_nlp}/steps/alerts/__init__.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/alerts/notify_on.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/dataset_loader/__init__.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/dataset_loader/data_loader.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/deploying/__init__.py (86%) create mode 100644 examples/e2e_nlp/steps/deploying/huggingface_deployment.py rename examples/{nlp-case => e2e_nlp}/steps/deploying/local_deployment.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/deploying/save_model.py (100%) create mode 100644 examples/e2e_nlp/steps/deploying/skypilot_deployment.py rename examples/{nlp-case => e2e_nlp}/steps/promotion/__init__.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/promotion/promote_get_metrics.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/promotion/promote_metric_compare_promoter.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/register/__init__.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/register/model_log_register.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/tokenizer_loader/__init__.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/tokenizer_loader/tokenizer_loader.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/tokenzation/__init__.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/tokenzation/tokenization.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/training/__init__.py (100%) rename examples/{nlp-case => e2e_nlp}/steps/training/model_trainer.py (100%) rename examples/{nlp-case => e2e_nlp}/utils/misc.py (100%) diff --git a/.github/workflows/update-templates-to-examples.yml b/.github/workflows/update-templates-to-examples.yml index 6e242a6c62c..02974f1ae7f 100644 --- a/.github/workflows/update-templates-to-examples.yml +++ b/.github/workflows/update-templates-to-examples.yml @@ -169,7 +169,7 @@ jobs: issue_number: ${{ github.event.pull_request.number }}, owner: context.repo.owner, repo: context.repo.repo, - body: 'NLP template updates in `examples/nlp-case` have been pushed.' + body: 'NLP template updates in `examples/e2e_nlp` have been pushed.' }) update-starter-template-to-examples: name: update-starter-template-to-examples diff --git a/examples/nlp-case/.assets/00_pipelines_composition.png b/examples/e2e_nlp/.assets/00_pipelines_composition.png similarity index 100% rename from examples/nlp-case/.assets/00_pipelines_composition.png rename to examples/e2e_nlp/.assets/00_pipelines_composition.png diff --git a/examples/nlp-case/.copier-answers.yml b/examples/e2e_nlp/.copier-answers.yml similarity index 80% rename from examples/nlp-case/.copier-answers.yml rename to examples/e2e_nlp/.copier-answers.yml index f62d7fafb31..2fd034ee4c8 100644 --- a/examples/nlp-case/.copier-answers.yml +++ b/examples/e2e_nlp/.copier-answers.yml @@ -1,12 +1,12 @@ # Changes here will be overwritten by Copier -_commit: 0.45.0 -_src_path: gh:zenml-io/template-nlp +_commit: 0.45.0-17-gbd996ed +_src_path: template-nlp accelerator: cpu cloud_of_choice: aws dataset: airline_reviews deploy_locally: true -deploy_to_huggingface: false -deploy_to_skypilot: false +deploy_to_huggingface: true +deploy_to_skypilot: true email: '' full_name: ZenML GmbH metric_compare_promotion: true diff --git a/examples/nlp-case/.dockerignore b/examples/e2e_nlp/.dockerignore similarity index 100% rename from examples/nlp-case/.dockerignore rename to examples/e2e_nlp/.dockerignore diff --git a/examples/nlp-case/LICENSE b/examples/e2e_nlp/LICENSE similarity index 100% rename from examples/nlp-case/LICENSE rename to examples/e2e_nlp/LICENSE diff --git a/examples/nlp-case/Makefile b/examples/e2e_nlp/Makefile similarity index 100% rename from examples/nlp-case/Makefile rename to examples/e2e_nlp/Makefile diff --git a/examples/nlp-case/README.md b/examples/e2e_nlp/README.md similarity index 94% rename from examples/nlp-case/README.md rename to examples/e2e_nlp/README.md index 948b6ef908e..812691d327b 100644 --- a/examples/nlp-case/README.md +++ b/examples/e2e_nlp/README.md @@ -1,11 +1,14 @@ # ZenML NLP project This is a comprehensive supervised ML project built with the -ZenML framework and its integration. The project trains one or more -scikit-learn classification models to make predictions on the tabular -classification datasets provided by the scikit-learn library. The project was -generated from the [NLP ZenML project template](https://github.com/zenml-io/template-nlp). +ZenML framework and its integration. The project will be +a comprehensive starting point for anyone looking to build +and deploy NLP models using the ZenML framework by streamlining +the process of training, promoting, and deploying NLP models +with a focus on reproducibility, scalability, and ease of use. +The project was generated from the [NLP ZenML project template](https://github.com/zenml-io/template-nlp). with the following properties: + - Project name: ZenML NLP project - Technical Name: nlp_use_case - Version: `0.0.1` @@ -16,6 +19,8 @@ Settings of your project are: - Accelerator: `cpu` - Trained model promotion to `staging` based on accuracy metric vs currently deployed model - Local deployment enabled +- Deployment to HuggingFace Hub enabled +- Deployment to SkyPilot enabled - Dataset: `airline_reviews` - Model: `distilbert-base-uncased` - Notifications about failures enabled @@ -181,20 +186,3 @@ The project loosely follows [the recommended ZenML project structure](https://do ├── config.yaml # ZenML configuration file └── run.py # CLI tool to run pipelines on ZenML Stack ``` - - - - - - - - - - - - -integrations -├── README.md # this file -├── requirements.txt # extra Python dependencies -└── run.py # CLI tool to run pipelines on ZenML Stack -``` \ No newline at end of file diff --git a/examples/nlp-case/config.yaml b/examples/e2e_nlp/config.yaml similarity index 100% rename from examples/nlp-case/config.yaml rename to examples/e2e_nlp/config.yaml diff --git a/examples/nlp-case/gradio/Dockerfile b/examples/e2e_nlp/gradio/Dockerfile similarity index 100% rename from examples/nlp-case/gradio/Dockerfile rename to examples/e2e_nlp/gradio/Dockerfile diff --git a/examples/nlp-case/gradio/__init__.py b/examples/e2e_nlp/gradio/__init__.py similarity index 100% rename from examples/nlp-case/gradio/__init__.py rename to examples/e2e_nlp/gradio/__init__.py diff --git a/examples/nlp-case/gradio/app.py b/examples/e2e_nlp/gradio/app.py similarity index 100% rename from examples/nlp-case/gradio/app.py rename to examples/e2e_nlp/gradio/app.py diff --git a/examples/nlp-case/gradio/requirements.txt b/examples/e2e_nlp/gradio/requirements.txt similarity index 100% rename from examples/nlp-case/gradio/requirements.txt rename to examples/e2e_nlp/gradio/requirements.txt diff --git a/examples/nlp-case/gradio/serve.yaml b/examples/e2e_nlp/gradio/serve.yaml similarity index 100% rename from examples/nlp-case/gradio/serve.yaml rename to examples/e2e_nlp/gradio/serve.yaml diff --git a/examples/nlp-case/pipelines/__init__.py b/examples/e2e_nlp/pipelines/__init__.py similarity index 100% rename from examples/nlp-case/pipelines/__init__.py rename to examples/e2e_nlp/pipelines/__init__.py diff --git a/examples/nlp-case/pipelines/deploying.py b/examples/e2e_nlp/pipelines/deploying.py similarity index 89% rename from examples/nlp-case/pipelines/deploying.py rename to examples/e2e_nlp/pipelines/deploying.py index 932c771bba4..cc4fa2abd77 100644 --- a/examples/nlp-case/pipelines/deploying.py +++ b/examples/e2e_nlp/pipelines/deploying.py @@ -19,6 +19,8 @@ from steps import ( deploy_locally, + deploy_to_huggingface, + deploy_to_skypilot, notify_on_failure, notify_on_success, save_model_to_deploy, @@ -87,7 +89,16 @@ def nlp_use_case_deploy_pipeline( tokenizer_name_or_path=tokenizer_name_or_path, after=["save_model_to_deploy"], ) - last_step_name = "deploy_locally" + ########## Deploy to HuggingFace ########## + deploy_to_huggingface( + repo_name=repo_name, + after=["save_model_to_deploy"], + ) + ########## Deploy to Skypilot ########## + deploy_to_skypilot( + after=["save_model_to_deploy"], + ) + last_step_name = "deploy_to_skypilot" notify_on_success(after=[last_step_name]) ### YOUR CODE ENDS HERE ### diff --git a/examples/nlp-case/pipelines/promoting.py b/examples/e2e_nlp/pipelines/promoting.py similarity index 100% rename from examples/nlp-case/pipelines/promoting.py rename to examples/e2e_nlp/pipelines/promoting.py diff --git a/examples/nlp-case/pipelines/training.py b/examples/e2e_nlp/pipelines/training.py similarity index 100% rename from examples/nlp-case/pipelines/training.py rename to examples/e2e_nlp/pipelines/training.py diff --git a/examples/nlp-case/requirements.txt b/examples/e2e_nlp/requirements.txt similarity index 100% rename from examples/nlp-case/requirements.txt rename to examples/e2e_nlp/requirements.txt diff --git a/examples/nlp-case/run.py b/examples/e2e_nlp/run.py similarity index 100% rename from examples/nlp-case/run.py rename to examples/e2e_nlp/run.py diff --git a/examples/nlp-case/steps/__init__.py b/examples/e2e_nlp/steps/__init__.py similarity index 95% rename from examples/nlp-case/steps/__init__.py rename to examples/e2e_nlp/steps/__init__.py index 68a8d4287c8..7188c33fe86 100644 --- a/examples/nlp-case/steps/__init__.py +++ b/examples/e2e_nlp/steps/__init__.py @@ -36,4 +36,6 @@ from .deploying import ( save_model_to_deploy, deploy_locally, + deploy_to_huggingface, + deploy_to_skypilot, ) diff --git a/examples/nlp-case/steps/alerts/__init__.py b/examples/e2e_nlp/steps/alerts/__init__.py similarity index 100% rename from examples/nlp-case/steps/alerts/__init__.py rename to examples/e2e_nlp/steps/alerts/__init__.py diff --git a/examples/nlp-case/steps/alerts/notify_on.py b/examples/e2e_nlp/steps/alerts/notify_on.py similarity index 100% rename from examples/nlp-case/steps/alerts/notify_on.py rename to examples/e2e_nlp/steps/alerts/notify_on.py diff --git a/examples/nlp-case/steps/dataset_loader/__init__.py b/examples/e2e_nlp/steps/dataset_loader/__init__.py similarity index 100% rename from examples/nlp-case/steps/dataset_loader/__init__.py rename to examples/e2e_nlp/steps/dataset_loader/__init__.py diff --git a/examples/nlp-case/steps/dataset_loader/data_loader.py b/examples/e2e_nlp/steps/dataset_loader/data_loader.py similarity index 100% rename from examples/nlp-case/steps/dataset_loader/data_loader.py rename to examples/e2e_nlp/steps/dataset_loader/data_loader.py diff --git a/examples/nlp-case/steps/deploying/__init__.py b/examples/e2e_nlp/steps/deploying/__init__.py similarity index 86% rename from examples/nlp-case/steps/deploying/__init__.py rename to examples/e2e_nlp/steps/deploying/__init__.py index faeba00221b..eee0e0e0590 100644 --- a/examples/nlp-case/steps/deploying/__init__.py +++ b/examples/e2e_nlp/steps/deploying/__init__.py @@ -19,3 +19,9 @@ from .save_model import save_model_to_deploy from .local_deployment import deploy_locally + + +from .huggingface_deployment import deploy_to_huggingface + + +from .skypilot_deployment import deploy_to_skypilot diff --git a/examples/e2e_nlp/steps/deploying/huggingface_deployment.py b/examples/e2e_nlp/steps/deploying/huggingface_deployment.py new file mode 100644 index 00000000000..2e9786cd0c8 --- /dev/null +++ b/examples/e2e_nlp/steps/deploying/huggingface_deployment.py @@ -0,0 +1,63 @@ +# Apache Software License 2.0 +# +# Copyright (c) ZenML GmbH 2024. All rights reserved. +# +# 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 os + +from huggingface_hub import HfApi + +from zenml import step +from zenml.client import Client +from zenml.logger import get_logger + +# Initialize logger +logger = get_logger(__name__) + + +@step() +def deploy_to_huggingface( + repo_name: str, +): + """ + This step deploy the model to huggingface. + + Args: + repo_name: The name of the repo to create/use on huggingface. + """ + ### ADD YOUR OWN CODE HERE - THIS IS JUST AN EXAMPLE ### + secret = Client().get_secret("huggingface_creds") + assert secret, "No secret found with name 'huggingface_creds'. Please create one that includes your `username` and `token`." + token = secret.secret_values["token"] + api = HfApi(token=token) + hf_repo = api.create_repo( + repo_id=repo_name, repo_type="space", space_sdk="gradio", exist_ok=True + ) + zenml_repo_root = Client().root + if not zenml_repo_root: + logger.warning( + "You're running the `deploy_to_huggingface` step outside of a ZenML repo. " + "Since the deployment step to huggingface is all about pushing the repo to huggingface, " + "this step will not work outside of a ZenML repo where the gradio folder is present." + ) + raise + gradio_folder_path = os.path.join(zenml_repo_root, "gradio") + space = api.upload_folder( + folder_path=gradio_folder_path, + repo_id=hf_repo.repo_id, + repo_type="space", + ) + logger.info(f"Space created: {space}") + ### YOUR CODE ENDS HERE ### diff --git a/examples/nlp-case/steps/deploying/local_deployment.py b/examples/e2e_nlp/steps/deploying/local_deployment.py similarity index 100% rename from examples/nlp-case/steps/deploying/local_deployment.py rename to examples/e2e_nlp/steps/deploying/local_deployment.py diff --git a/examples/nlp-case/steps/deploying/save_model.py b/examples/e2e_nlp/steps/deploying/save_model.py similarity index 100% rename from examples/nlp-case/steps/deploying/save_model.py rename to examples/e2e_nlp/steps/deploying/save_model.py diff --git a/examples/e2e_nlp/steps/deploying/skypilot_deployment.py b/examples/e2e_nlp/steps/deploying/skypilot_deployment.py new file mode 100644 index 00000000000..099dc582d82 --- /dev/null +++ b/examples/e2e_nlp/steps/deploying/skypilot_deployment.py @@ -0,0 +1,53 @@ +# Apache Software License 2.0 +# +# Copyright (c) ZenML GmbH 2024. All rights reserved. +# +# 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 os +import re + +import sky + +from zenml import step +from zenml.client import Client +from zenml.logger import get_logger + +# Initialize logger +logger = get_logger(__name__) + + +@step() +def deploy_to_skypilot(): + """ + This step deploy the model to a VM using SkyPilot. + + This step requires `skypilot` to be installed. + aswell as a configured cloud account locally (e.g. AWS, GCP, Azure). + """ + ### ADD YOUR OWN CODE HERE - THIS IS JUST AN EXAMPLE ### + zenml_repo_root = Client().root + if not zenml_repo_root: + logger.warning( + "You're running the `deploy_to_huggingface` step outside of a ZenML repo. " + "Since the deployment step to huggingface is all about pushing the repo to huggingface, " + "this step will only work within a ZenML repo where the gradio folder is present." + ) + raise + gradio_task_yaml = os.path.join(zenml_repo_root, "gradio", "serve.yaml") + task = sky.Task.from_yaml(gradio_task_yaml) + cluster_name = re.sub(r"[^a-zA-Z0-9]+", "-", "nlp_use_case-cluster") + sky.launch(task, cluster_name=cluster_name, detach_setup=True) + ### YOUR CODE ENDS HERE ### diff --git a/examples/nlp-case/steps/promotion/__init__.py b/examples/e2e_nlp/steps/promotion/__init__.py similarity index 100% rename from examples/nlp-case/steps/promotion/__init__.py rename to examples/e2e_nlp/steps/promotion/__init__.py diff --git a/examples/nlp-case/steps/promotion/promote_get_metrics.py b/examples/e2e_nlp/steps/promotion/promote_get_metrics.py similarity index 100% rename from examples/nlp-case/steps/promotion/promote_get_metrics.py rename to examples/e2e_nlp/steps/promotion/promote_get_metrics.py diff --git a/examples/nlp-case/steps/promotion/promote_metric_compare_promoter.py b/examples/e2e_nlp/steps/promotion/promote_metric_compare_promoter.py similarity index 100% rename from examples/nlp-case/steps/promotion/promote_metric_compare_promoter.py rename to examples/e2e_nlp/steps/promotion/promote_metric_compare_promoter.py diff --git a/examples/nlp-case/steps/register/__init__.py b/examples/e2e_nlp/steps/register/__init__.py similarity index 100% rename from examples/nlp-case/steps/register/__init__.py rename to examples/e2e_nlp/steps/register/__init__.py diff --git a/examples/nlp-case/steps/register/model_log_register.py b/examples/e2e_nlp/steps/register/model_log_register.py similarity index 100% rename from examples/nlp-case/steps/register/model_log_register.py rename to examples/e2e_nlp/steps/register/model_log_register.py diff --git a/examples/nlp-case/steps/tokenizer_loader/__init__.py b/examples/e2e_nlp/steps/tokenizer_loader/__init__.py similarity index 100% rename from examples/nlp-case/steps/tokenizer_loader/__init__.py rename to examples/e2e_nlp/steps/tokenizer_loader/__init__.py diff --git a/examples/nlp-case/steps/tokenizer_loader/tokenizer_loader.py b/examples/e2e_nlp/steps/tokenizer_loader/tokenizer_loader.py similarity index 100% rename from examples/nlp-case/steps/tokenizer_loader/tokenizer_loader.py rename to examples/e2e_nlp/steps/tokenizer_loader/tokenizer_loader.py diff --git a/examples/nlp-case/steps/tokenzation/__init__.py b/examples/e2e_nlp/steps/tokenzation/__init__.py similarity index 100% rename from examples/nlp-case/steps/tokenzation/__init__.py rename to examples/e2e_nlp/steps/tokenzation/__init__.py diff --git a/examples/nlp-case/steps/tokenzation/tokenization.py b/examples/e2e_nlp/steps/tokenzation/tokenization.py similarity index 100% rename from examples/nlp-case/steps/tokenzation/tokenization.py rename to examples/e2e_nlp/steps/tokenzation/tokenization.py diff --git a/examples/nlp-case/steps/training/__init__.py b/examples/e2e_nlp/steps/training/__init__.py similarity index 100% rename from examples/nlp-case/steps/training/__init__.py rename to examples/e2e_nlp/steps/training/__init__.py diff --git a/examples/nlp-case/steps/training/model_trainer.py b/examples/e2e_nlp/steps/training/model_trainer.py similarity index 100% rename from examples/nlp-case/steps/training/model_trainer.py rename to examples/e2e_nlp/steps/training/model_trainer.py diff --git a/examples/nlp-case/utils/misc.py b/examples/e2e_nlp/utils/misc.py similarity index 100% rename from examples/nlp-case/utils/misc.py rename to examples/e2e_nlp/utils/misc.py From a1824a1f3aaea0fd509500c31bb6869c3840a760 Mon Sep 17 00:00:00 2001 From: Stefan Nica Date: Thu, 11 Jan 2024 20:39:39 +0100 Subject: [PATCH 10/16] Support refreshing service connector credentials in the Vertex step operator to support long-running jobs (#2198) * Refresh creds on Vertex step operator job polling * Fix docstring error --- .../step_operators/vertex_step_operator.py | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/zenml/integrations/gcp/step_operators/vertex_step_operator.py b/src/zenml/integrations/gcp/step_operators/vertex_step_operator.py index 4428de7478e..18ca23edce3 100644 --- a/src/zenml/integrations/gcp/step_operators/vertex_step_operator.py +++ b/src/zenml/integrations/gcp/step_operators/vertex_step_operator.py @@ -21,6 +21,7 @@ import time from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, cast +from google.api_core.exceptions import ServerError from google.cloud import aiplatform from zenml import __version__ @@ -186,7 +187,6 @@ def launch( Raises: RuntimeError: If the run fails. - ConnectionError: If the run fails due to a connection error. """ resource_settings = info.config.resource_settings if resource_settings.cpu_count or resource_settings.memory: @@ -300,27 +300,30 @@ def launch( try: response = client.get_custom_job(name=job_id) retry_count = 0 - # Handle transient connection error. - except ConnectionError as err: + # Handle transient connection errors and credential expiration by + # recreating the Python API client. + except (ConnectionError, ServerError) as err: if retry_count < CONNECTION_ERROR_RETRY_LIMIT: retry_count += 1 logger.warning( - "ConnectionError (%s) encountered when polling job: " - "%s. Trying to recreate the API client.", - err, - job_id, + f"Error encountered when polling job " + f"{job_id}: {err}\nRetrying...", ) + # This call will refresh the credentials if they expired. + credentials, project_id = self._get_authentication() # Recreate the Python API client. client = aiplatform.gapic.JobServiceClient( - client_options=client_options + credentials=credentials, client_options=client_options ) else: - logger.error( + logger.exception( "Request failed after %s retries.", CONNECTION_ERROR_RETRY_LIMIT, ) - raise - + raise RuntimeError( + f"Request failed after {CONNECTION_ERROR_RETRY_LIMIT} " + f"retries: {err}" + ) if response.state in VERTEX_JOB_STATES_FAILED: err_msg = ( "Job '{}' did not succeed. Detailed response {}.".format( From 1edad9275209bb1cf5f65db1b8d22207fcbaa28a Mon Sep 17 00:00:00 2001 From: Stefan Nica Date: Fri, 12 Jan 2024 09:07:39 +0100 Subject: [PATCH 11/16] Refactor secrets stores to store all secret metadata in the DB (#2193) * Refactored secrets stores to store all secret metadata in the DB * Fixed linter errors * Ensure backwards-compatibility with existing REST secrets store configurations * Fix linter errors * Add migration script * Fix migration script * Fix docstrings * Add missing DB revision * Remove secrets from DB before migration * Fix bugs found by unit tests and manual tests * Fix remaining unit test failures * Fix db revision head split * Updated secrets store docs with required permissions * Rebased DB migrations on top of latest * Fixed docstrings * Move all eprecated code to the DB migration script * Fix docstrings --- docker/zenml-server-hf-spaces.Dockerfile | 1 - .../zenml-self-hosted/deploy-with-docker.md | 62 +- .../zenml-self-hosted/deploy-with-helm.md | 61 ++ .../component-guide/artifact-stores/s3.md | 2 +- src/zenml/config/store_config.py | 27 +- src/zenml/enums.py | 11 +- .../gcp_service_connector.py | 38 +- src/zenml/models/v2/core/secret.py | 19 + src/zenml/zen_server/deploy/deployer.py | 4 - .../deploy/helm/templates/server-db-job.yaml | 2 - .../helm/templates/server-deployment.yaml | 2 - src/zenml/zen_server/deploy/helm/values.yaml | 10 - src/zenml/zen_stores/base_zen_store.py | 84 +- src/zenml/zen_stores/enums.py | 27 - src/zenml/zen_stores/migrations/alembic.py | 10 +- src/zenml/zen_stores/migrations/env.py | 2 +- ...c1b9c04da1_make_secrets_values_optional.py | 35 + .../7b651bf6822e_track_secrets_in_db.py | 715 ++++++++++++++++++ src/zenml/zen_stores/rest_zen_store.py | 160 +++- .../zen_stores/schemas/secret_schemas.py | 97 ++- .../secrets_stores/aws_secrets_store.py | 585 ++------------ .../secrets_stores/azure_secrets_store.py | 425 ++--------- .../secrets_stores/base_secrets_store.py | 325 +------- .../secrets_stores/gcp_secrets_store.py | 457 ++--------- .../secrets_stores/hashicorp_secrets_store.py | 437 ++--------- .../secrets_stores/rest_secrets_store.py | 266 ------- .../secrets_stores/secrets_store_interface.py | 115 +-- .../service_connector_secrets_store.py | 12 +- .../secrets_stores/sql_secrets_store.py | 277 +------ src/zenml/zen_stores/sql_zen_store.py | 455 ++++++++++- src/zenml/zen_stores/zen_store_interface.py | 119 +++ .../zen_stores/test_secrets_store.py | 63 +- .../functional/zen_stores/test_zen_store.py | 26 +- .../functional/zen_stores/utils.py | 11 +- 34 files changed, 2096 insertions(+), 2846 deletions(-) delete mode 100644 src/zenml/zen_stores/enums.py create mode 100644 src/zenml/zen_stores/migrations/versions/1ac1b9c04da1_make_secrets_values_optional.py create mode 100644 src/zenml/zen_stores/migrations/versions/7b651bf6822e_track_secrets_in_db.py delete mode 100644 src/zenml/zen_stores/secrets_stores/rest_secrets_store.py diff --git a/docker/zenml-server-hf-spaces.Dockerfile b/docker/zenml-server-hf-spaces.Dockerfile index 8f211ca96c4..e56c2b7a5c0 100644 --- a/docker/zenml-server-hf-spaces.Dockerfile +++ b/docker/zenml-server-hf-spaces.Dockerfile @@ -42,7 +42,6 @@ ENV ZENML_SERVER_DEPLOYMENT_TYPE="hf_spaces" # ENV ZENML_SECRETS_STORE_AWS_ACCESS_KEY_ID="" # ENV ZENML_SECRETS_STORE_AWS_SECRET_ACCESS_KEY="" # ENV ZENML_SECRETS_STORE_AWS_SESSION_TOKEN="" -# ENV ZENML_SECRETS_STORE_SECRET_LIST_REFRESH_TIMEOUT="" # # GCP Secrets Store Configuration # ENV ZENML_SECRETS_STORE_PROJECT_ID="" diff --git a/docs/book/deploying-zenml/zenml-self-hosted/deploy-with-docker.md b/docs/book/deploying-zenml/zenml-self-hosted/deploy-with-docker.md index cd0f5385620..77b7a30e2d7 100644 --- a/docs/book/deploying-zenml/zenml-self-hosted/deploy-with-docker.md +++ b/docs/book/deploying-zenml/zenml-self-hosted/deploy-with-docker.md @@ -76,11 +76,35 @@ These configuration options are only relevant if you're using the AWS Secrets Ma * **ZENML\_SECRETS\_STORE\_TYPE:** Set this to `aws` in order to set this type of secret store. -The AWS Secrets Store uses the ZenML AWS Service Connector under the hood to authenticate with the AWS Secrets Manager API. This means that you can use any of the [authentication methods supported by the AWS Service Connector](https://docs.zenml.io/stacks-and-components/auth-management/aws-service-connector#authentication-methods) to authenticate with the AWS Secrets Manager API. The following configuration options are supported: +The AWS Secrets Store uses the ZenML AWS Service Connector under the hood to authenticate with the AWS Secrets Manager API. This means that you can use any of the [authentication methods supported by the AWS Service Connector](https://docs.zenml.io/stacks-and-components/auth-management/aws-service-connector#authentication-methods) to authenticate with the AWS Secrets Manager API. + +The minimum set of permissions that must be attached to the implicit or configured AWS credentials are: `secretsmanager:CreateSecret`, `secretsmanager:GetSecretValue`, `secretsmanager:DescribeSecret`, `secretsmanager:PutSecretValue`, `secretsmanager:TagResource` and `secretsmanager:DeleteSecret` and they must be associated with secrets that have a name starting with `zenml/` in the target region and account. The following IAM policy example can be used as a starting point: + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "ZenMLSecretsStore", + "Effect": "Allow", + "Action": [ + "secretsmanager:CreateSecret", + "secretsmanager:GetSecretValue", + "secretsmanager:DescribeSecret", + "secretsmanager:PutSecretValue", + "secretsmanager:TagResource", + "secretsmanager:DeleteSecret" + ], + "Resource": "arn:aws:secretsmanager:::secret:zenml/*" + } + ] +} +``` + +The following configuration options are supported: * **ZENML\_SECRETS\_STORE\_AUTH\_METHOD**: The AWS Service Connector authentication method to use (e.g. `secret-key` or `iam-role`). * **ZENML\_SECRETS\_STORE\_AUTH\_CONFIG**: The AWS Service Connector configuration, in JSON format (e.g. `{"role_arn": "arn:aws:iam::123456789012:role/MyRole"}`). -* **ZENML\_SECRETS\_STORE\_SECRET\_LIST\_REFRESH\_TIMEOUT**: AWS' [Secrets Manager](https://aws.amazon.com/secrets-manager) has a known issue where it does not immediately reflect new and updated secrets in the `list_secrets` results. To work around this issue, you can set this refresh timeout value to a non-zero value to get the ZenML server to wait after creating or updating an AWS secret until the changes are reflected in the secrets returned by `list_secrets` or the number of seconds specified by this value has elapsed. Defaults to `0` (disabled). Should not be set to a high value as it may cause thread starvation in the ZenML server on high load. > **Note:** The remaining configuration options are deprecated and may be removed in a future release. Instead, you should set the `ZENML_SECRETS_STORE_AUTH_METHOD` and `ZENML_SECRETS_STORE_AUTH_CONFIG` variables to use the AWS Service Connector authentication method. @@ -94,6 +118,40 @@ These configuration options are only relevant if you're using the GCP Secrets Ma * **ZENML\_SECRETS\_STORE\_TYPE:** Set this to `gcp` in order to set this type of secret store. +The minimum set of permissions that must be attached to the implicit or configured GCP credentials are as follows: + +* `secretmanager.secrets.create` for the target GCP project (i.e. no condition on the name prefix) +* `secretmanager.secrets.get`, `secretmanager.secrets.update`, `secretmanager.versions.access`, `secretmanager.versions.add` and `secretmanager.secrets.delete` for the target GCP project and for secrets that have a name starting with `zenml-` + +This can be achieved by creating two custom IAM roles and attaching them to the principal (e.g. user or service account) that will be used to access the GCP Secrets Manager API with a condition configured when attaching the second role to limit access to secrets with a name prefix of `zenml-`. The following `gcloud` CLI command examples can be used as a starting point: + +```bash +gcloud iam roles create ZenMLServerSecretsStoreCreator \ + --project \ + --title "ZenML Server Secrets Store Creator" \ + --description "Allow the ZenML Server to create new secrets" \ + --stage GA \ + --permissions "secretmanager.secrets.create" + +gcloud iam roles create ZenMLServerSecretsStoreEditor \ + --project \ + --title "ZenML Server Secrets Store Editor" \ + --description "Allow the ZenML Server to manage its secrets" \ + --stage GA \ + --permissions "secretmanager.secrets.get,secretmanager.secrets.update,secretmanager.versions.access,secretmanager.versions.add,secretmanager.secrets.delete" + +gcloud projects add-iam-policy-binding \ + --member serviceAccount: \ + --role projects//roles/ZenMLServerSecretsStoreCreator \ + --condition None + +# NOTE: use the GCP project NUMBER, not the project ID in the condition +gcloud projects add-iam-policy-binding \ + --member serviceAccount: \ + --role projects//roles/ZenMLServerSecretsStoreEditor \ + --condition 'title=limit_access_zenml,description="Limit access to secrets with prefix zenml-",expression=resource.name.startsWith("projects//secrets/zenml-")' +``` + The GCP Secrets Store uses the ZenML GCP Service Connector under the hood to authenticate with the GCP Secrets Manager API. This means that you can use any of the [authentication methods supported by the GCP Service Connector](https://docs.zenml.io/stacks-and-components/auth-management/gcp-service-connector#authentication-methods) to authenticate with the GCP Secrets Manager API. The following configuration options are supported: * **ZENML\_SECRETS\_STORE\_AUTH\_METHOD**: The GCP Service Connector authentication method to use (e.g. `service-account`). diff --git a/docs/book/deploying-zenml/zenml-self-hosted/deploy-with-helm.md b/docs/book/deploying-zenml/zenml-self-hosted/deploy-with-helm.md index 852938a014d..29181f0ea51 100644 --- a/docs/book/deploying-zenml/zenml-self-hosted/deploy-with-helm.md +++ b/docs/book/deploying-zenml/zenml-self-hosted/deploy-with-helm.md @@ -314,6 +314,29 @@ This method requires you to configure a DNS service like AWS Route 53 or Google Unless explicitly disabled or configured otherwise, the ZenML server will use the SQL database as a secrets store backend. If you want to use the AWS Secrets Manager instead, you need to configure it in the Helm values. Depending on where you deploy your ZenML server and how your Kubernetes cluster is configured, you may also need to provide the AWS credentials needed to access the AWS Secrets Manager API. +The minimum set of permissions that must be attached to the implicit or configured AWS credentials are: `secretsmanager:CreateSecret`, `secretsmanager:GetSecretValue`, `secretsmanager:DescribeSecret`, `secretsmanager:PutSecretValue`, `secretsmanager:TagResource` and `secretsmanager:DeleteSecret` and they must be associated with secrets that have a name starting with `zenml/` in the target region and account. The following IAM policy example can be used as a starting point: + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "ZenMLSecretsStore", + "Effect": "Allow", + "Action": [ + "secretsmanager:CreateSecret", + "secretsmanager:GetSecretValue", + "secretsmanager:DescribeSecret", + "secretsmanager:PutSecretValue", + "secretsmanager:TagResource", + "secretsmanager:DeleteSecret" + ], + "Resource": "arn:aws:secretsmanager:::secret:zenml/*" + } + ] +} +``` + The AWS Secrets Store uses the ZenML AWS Service Connector under the hood to authenticate with the AWS Secrets Manager API. This means that you can use any of the [authentication methods supported by the AWS Service Connector](https://docs.zenml.io/stacks-and-components/auth-management/aws-service-connector#authentication-methods) to authenticate with the AWS Secrets Manager API: @@ -347,6 +370,8 @@ The AWS Secrets Store uses the ZenML AWS Service Connector under the hood to aut aws_access_key_id: aws_secret_access_key: ``` + + {% endtab %} {% tab title="GCP" %} @@ -354,6 +379,40 @@ The AWS Secrets Store uses the ZenML AWS Service Connector under the hood to aut Unless explicitly disabled or configured otherwise, the ZenML server will use the SQL database as a secrets store backend. If you want to use the GCP Secrets Manager instead, you need to configure it in the Helm values. Depending on where you deploy your ZenML server and how your Kubernetes cluster is configured, you may also need to provide the GCP credentials needed to access the GCP Secrets Manager API. +The minimum set of permissions that must be attached to the implicit or configured GCP credentials are as follows: + +* `secretmanager.secrets.create` for the target GCP project (i.e. no condition on the name prefix) +* `secretmanager.secrets.get`, `secretmanager.secrets.update`, `secretmanager.versions.access`, `secretmanager.versions.add` and `secretmanager.secrets.delete` for the target GCP project and for secrets that have a name starting with `zenml-` + +This can be achieved by creating two custom IAM roles and attaching them to the principal (e.g. user or service account) that will be used to access the GCP Secrets Manager API with a condition configured when attaching the second role to limit access to secrets with a name prefix of `zenml-`. The following `gcloud` CLI command examples can be used as a starting point: + +```bash +gcloud iam roles create ZenMLServerSecretsStoreCreator \ + --project \ + --title "ZenML Server Secrets Store Creator" \ + --description "Allow the ZenML Server to create new secrets" \ + --stage GA \ + --permissions "secretmanager.secrets.create" + +gcloud iam roles create ZenMLServerSecretsStoreEditor \ + --project \ + --title "ZenML Server Secrets Store Editor" \ + --description "Allow the ZenML Server to manage its secrets" \ + --stage GA \ + --permissions "secretmanager.secrets.get,secretmanager.secrets.update,secretmanager.versions.access,secretmanager.versions.add,secretmanager.secrets.delete" + +gcloud projects add-iam-policy-binding \ + --member serviceAccount: \ + --role projects//roles/ZenMLServerSecretsStoreCreator \ + --condition None + +# NOTE: use the GCP project NUMBER, not the project ID in the condition +gcloud projects add-iam-policy-binding \ + --member serviceAccount: \ + --role projects//roles/ZenMLServerSecretsStoreEditor \ + --condition 'title=limit_access_zenml,description="Limit access to secrets with prefix zenml-",expression=resource.name.startsWith("projects//secrets/zenml-")' +``` + The GCP Secrets Store uses the ZenML GCP Service Connector under the hood to authenticate with the GCP Secrets Manager API. This means that you can use any of the [authentication methods supported by the GCP Service Connector](https://docs.zenml.io/stacks-and-components/auth-management/gcp-service-connector#authentication-methods) to authenticate with the GCP Secrets Manager API: @@ -408,6 +467,8 @@ The GCP Secrets Store uses the ZenML GCP Service Connector under the hood to aut iam.gke.io/gcp-service-account: @.iam.gserviceaccount.com ``` + + {% endtab %} {% tab title="Azure" %} diff --git a/docs/book/stacks-and-components/component-guide/artifact-stores/s3.md b/docs/book/stacks-and-components/component-guide/artifact-stores/s3.md index 6897a62ad5d..45cfcd16617 100644 --- a/docs/book/stacks-and-components/component-guide/artifact-stores/s3.md +++ b/docs/book/stacks-and-components/component-guide/artifact-stores/s3.md @@ -223,7 +223,7 @@ This method has some advantages over the implicit authentication method: * you can combine the S3 artifact store with other stack components that are not running in AWS > **Note**: When you create the IAM user for your AWS access key, please remember to grant the created IAM user -> permissions to read and write to your S3 bucket (the permissions are "s3:PutObject", "s3:GetObject", "s3:ListBucket", "s3:DeleteObject") +> permissions to read and write to your S3 bucket (i.e. at a minimum: `s3:PutObject`, `s3:GetObject`, `s3:ListBucket`, `s3:DeleteObject`) After having set up the IAM user and generated the access key, as described in the [AWS documentation](https://aws.amazon.com/premiumsupport/knowledge-center/create-access-key/), you can register the diff --git a/src/zenml/config/store_config.py b/src/zenml/config/store_config.py index 91ede9e6577..a80d10c79e3 100644 --- a/src/zenml/config/store_config.py +++ b/src/zenml/config/store_config.py @@ -14,9 +14,9 @@ """Functionality to support ZenML store configurations.""" from pathlib import PurePath -from typing import Optional +from typing import Any, Dict, Optional -from pydantic import BaseModel +from pydantic import BaseModel, root_validator from zenml.config.secrets_store_config import SecretsStoreConfiguration from zenml.enums import StoreType @@ -92,6 +92,29 @@ def supports_url_scheme(cls, url: str) -> bool: """ return True + @root_validator(pre=True) + def validate_secrets_store(cls, values: Dict[str, Any]) -> Dict[str, Any]: + """Validate the secrets store configuration. + + Args: + values: The values of the store configuration. + + Returns: + The values of the store configuration. + """ + if values.get("secrets_store") is None: + return values + + # Remove the legacy REST secrets store configuration since it is no + # longer supported/needed + secrets_store = values["secrets_store"] + if isinstance(secrets_store, dict): + secrets_store_type = secrets_store.get("type") + if secrets_store_type == "rest": + del values["secrets_store"] + + return values + class Config: """Pydantic configuration class.""" diff --git a/src/zenml/enums.py b/src/zenml/enums.py index 2a3d43173f6..d2657a4104b 100644 --- a/src/zenml/enums.py +++ b/src/zenml/enums.py @@ -133,15 +133,10 @@ class StoreType(StrEnum): class SecretsStoreType(StrEnum): - """Secrets Store Backend Types. + """Secrets Store Backend Types.""" - NOTE: this is a superset of the StoreType values because the set of secrets - store backends includes all the backends supported for zen stores. - """ - - NONE = "none" # indicates that the secrets store is disabled - SQL = StoreType.SQL.value - REST = StoreType.REST.value + NONE = "none" # indicates that no secrets store is used + SQL = "sql" AWS = "aws" GCP = "gcp" AZURE = "azure" diff --git a/src/zenml/integrations/gcp/service_connectors/gcp_service_connector.py b/src/zenml/integrations/gcp/service_connectors/gcp_service_connector.py index 917d137d6a1..577f935dbf0 100644 --- a/src/zenml/integrations/gcp/service_connectors/gcp_service_connector.py +++ b/src/zenml/integrations/gcp/service_connectors/gcp_service_connector.py @@ -36,7 +36,7 @@ from google.cloud import container_v1, storage from google.oauth2 import credentials as gcp_credentials from google.oauth2 import service_account as gcp_service_account -from pydantic import Field, SecretStr, validator +from pydantic import Field, SecretStr, root_validator, validator from zenml.constants import ( DOCKER_REGISTRY_RESOURCE_TYPE, @@ -86,6 +86,24 @@ class GCPUserAccountCredentials(AuthenticationConfig): "distribute the user account credentials JSON to clients instead.", ) + @root_validator(pre=True) + def validate_user_account_dict( + cls, values: Dict[str, Any] + ) -> Dict[str, Any]: + """Convert the user account credentials to JSON if given in dict format. + + Args: + values: The configuration values. + + Returns: + The validated configuration values. + """ + if isinstance(values.get("user_account_json"), dict): + values["user_account_json"] = json.dumps( + values["user_account_json"] + ) + return values + @validator("user_account_json") def validate_user_account_json(cls, v: SecretStr) -> SecretStr: """Validate the user account credentials JSON. @@ -146,6 +164,24 @@ class GCPServiceAccountCredentials(AuthenticationConfig): "distribute the service account key JSON to clients instead.", ) + @root_validator(pre=True) + def validate_service_account_dict( + cls, values: Dict[str, Any] + ) -> Dict[str, Any]: + """Convert the service account credentials to JSON if given in dict format. + + Args: + values: The configuration values. + + Returns: + The validated configuration values. + """ + if isinstance(values.get("service_account_json"), dict): + values["service_account_json"] = json.dumps( + values["service_account_json"] + ) + return values + @validator("service_account_json") def validate_service_account_json(cls, v: SecretStr) -> SecretStr: """Validate the service account credentials JSON. diff --git a/src/zenml/models/v2/core/secret.py b/src/zenml/models/v2/core/secret.py index d8401ba26fc..f1922a9bb96 100644 --- a/src/zenml/models/v2/core/secret.py +++ b/src/zenml/models/v2/core/secret.py @@ -84,6 +84,17 @@ class SecretUpdate(SecretRequest): default=None, title="The scope of the secret." ) + def get_secret_values_update(self) -> Dict[str, Optional[str]]: + """Returns a dictionary with the secret values to update. + + Returns: + A dictionary with the secret values to update. + """ + return { + k: v.get_secret_value() if v is not None else None + for k, v in self.values.items() + } + # ------------------ Response Model ------------------ @@ -197,6 +208,14 @@ def remove_secrets(self) -> None: """Removes all secret values from the secret but keep the keys.""" self.get_body().values = {k: None for k in self.values.keys()} + def set_secrets(self, values: Dict[str, str]) -> None: + """Sets the secret values of the secret. + + Args: + values: The secret values to set. + """ + self.get_body().values = {k: SecretStr(v) for k, v in values.items()} + # ------------------ Filter Model ------------------ diff --git a/src/zenml/zen_server/deploy/deployer.py b/src/zenml/zen_server/deploy/deployer.py index 0ef53f27cd3..4a87d777727 100644 --- a/src/zenml/zen_server/deploy/deployer.py +++ b/src/zenml/zen_server/deploy/deployer.py @@ -31,9 +31,6 @@ ServerProviderNotFoundError, ) from zenml.zen_stores.rest_zen_store import RestZenStoreConfiguration -from zenml.zen_stores.secrets_stores.rest_secrets_store import ( - RestSecretsStoreConfiguration, -) logger = get_logger(__name__) @@ -256,7 +253,6 @@ def connect_to_server( username=username, password=password, verify_ssl=verify_ssl, - secrets_store=RestSecretsStoreConfiguration(), ) if gc.store == store_config: diff --git a/src/zenml/zen_server/deploy/helm/templates/server-db-job.yaml b/src/zenml/zen_server/deploy/helm/templates/server-db-job.yaml index d3fbff15fc6..55471731b4a 100644 --- a/src/zenml/zen_server/deploy/helm/templates/server-db-job.yaml +++ b/src/zenml/zen_server/deploy/helm/templates/server-db-job.yaml @@ -89,8 +89,6 @@ spec: - name: ZENML_SECRETS_STORE_REGION_NAME value: {{ .Values.zenml.secretsStore.aws.region_name | quote }} {{- end }} - - name: ZENML_SECRETS_STORE_SECRET_LIST_REFRESH_TIMEOUT - value: {{ .Values.zenml.secretsStore.aws.secret_list_refresh_timeout | quote }} {{- else if eq .Values.zenml.secretsStore.type "gcp" }} - name: ZENML_SECRETS_STORE_AUTH_METHOD value: {{ .Values.zenml.secretsStore.gcp.authMethod | quote }} diff --git a/src/zenml/zen_server/deploy/helm/templates/server-deployment.yaml b/src/zenml/zen_server/deploy/helm/templates/server-deployment.yaml index 1ff1a3ad563..1f6d9925790 100644 --- a/src/zenml/zen_server/deploy/helm/templates/server-deployment.yaml +++ b/src/zenml/zen_server/deploy/helm/templates/server-deployment.yaml @@ -167,8 +167,6 @@ spec: - name: ZENML_SECRETS_STORE_REGION_NAME value: {{ .Values.zenml.secretsStore.aws.region_name | quote }} {{- end }} - - name: ZENML_SECRETS_STORE_SECRET_LIST_REFRESH_TIMEOUT - value: {{ .Values.zenml.secretsStore.aws.secret_list_refresh_timeout | quote }} {{- else if eq .Values.zenml.secretsStore.type "gcp" }} - name: ZENML_SECRETS_STORE_AUTH_METHOD value: {{ .Values.zenml.secretsStore.gcp.authMethod | quote }} diff --git a/src/zenml/zen_server/deploy/helm/values.yaml b/src/zenml/zen_server/deploy/helm/values.yaml index 6eb2974fa55..be2388b01c3 100644 --- a/src/zenml/zen_server/deploy/helm/values.yaml +++ b/src/zenml/zen_server/deploy/helm/values.yaml @@ -319,16 +319,6 @@ zenml: aws_secret_access_key: aws_session_token: - # The AWS Secrets Manager has a known issue where it does not immediately - # reflect new and updated secrets in the `list_secrets` results. To work - # around this issue, you can set this value to a non-zero value to - # get the ZenML server to wait after creating or updating an AWS secret - # until the changes are reflected in the secrets returned by - # `list_secrets` or the number of seconds specified by this value has - # elapsed. Should not be set to a high value as it may cause thread - # starvation in the ZenML server on high load. - secret_list_refresh_timeout: 0 - # GCP secrets store configuration. Only relevant if the `gcp` secrets store # type is configured. diff --git a/src/zenml/zen_stores/base_zen_store.py b/src/zenml/zen_stores/base_zen_store.py index 710a6d46c43..311e64c446e 100644 --- a/src/zenml/zen_stores/base_zen_store.py +++ b/src/zenml/zen_stores/base_zen_store.py @@ -16,10 +16,7 @@ from abc import ABC from typing import ( Any, - Callable, ClassVar, - Dict, - List, Optional, Tuple, Type, @@ -56,12 +53,6 @@ UserResponse, WorkspaceResponse, ) -from zenml.utils.proxy_utils import make_proxy_class -from zenml.zen_stores.enums import StoreEvent -from zenml.zen_stores.secrets_stores.base_secrets_store import BaseSecretsStore -from zenml.zen_stores.secrets_stores.secrets_store_interface import ( - SecretsStoreInterface, -) from zenml.zen_stores.secrets_stores.sql_secrets_store import ( SqlSecretsStoreConfiguration, ) @@ -70,11 +61,9 @@ logger = get_logger(__name__) -@make_proxy_class(SecretsStoreInterface, "_secrets_store") class BaseZenStore( BaseModel, ZenStoreInterface, - SecretsStoreInterface, ABC, ): """Base class for accessing and persisting ZenML core objects. @@ -84,8 +73,6 @@ class BaseZenStore( """ config: StoreConfiguration - _secrets_store: Optional[BaseSecretsStore] = None - _event_handlers: Dict[StoreEvent, List[Callable[..., Any]]] = {} TYPE: ClassVar[StoreType] CONFIG_TYPE: ClassVar[Type[StoreConfiguration]] @@ -243,23 +230,6 @@ def create_store( **kwargs, ) - secrets_store_config = store.config.secrets_store - - # Initialize the secrets store - if ( - secrets_store_config - and secrets_store_config.type != SecretsStoreType.NONE - ): - secrets_store_class = BaseSecretsStore.get_store_class( - secrets_store_config - ) - store._secrets_store = secrets_store_class( - zen_store=store, - config=secrets_store_config, - ) - # Update the config with the actual secrets store config - # to reflect the default values in the saved configuration - store.config.secrets_store = store._secrets_store.config return store @staticmethod @@ -307,15 +277,6 @@ def type(self) -> StoreType: """ return self.TYPE - @property - def secrets_store(self) -> Optional["BaseSecretsStore"]: - """The secrets store associated with this store. - - Returns: - The secrets store associated with this store. - """ - return self._secrets_store - def validate_active_config( self, active_workspace_name_or_id: Optional[Union[str, UUID]] = None, @@ -408,18 +369,21 @@ def get_store_info(self) -> ServerModel: Returns: Information about the store. """ + from zenml.zen_stores.sql_zen_store import SqlZenStore + server_config = ServerConfiguration.get_server_config() deployment_type = server_config.deployment_type auth_scheme = server_config.auth_scheme + secrets_store_type = SecretsStoreType.NONE + if isinstance(self, SqlZenStore): + secrets_store_type = self.secrets_store.type return ServerModel( id=GlobalConfiguration().user_id, version=zenml.__version__, deployment_type=deployment_type, database_type=ServerDatabaseType.OTHER, debug=IS_DEBUG_ENV, - secrets_store_type=self.secrets_store.type - if self.secrets_store - else SecretsStoreType.NONE, + secrets_store_type=secrets_store_type, auth_scheme=auth_scheme, ) @@ -487,42 +451,6 @@ def _get_default_stack( ) return default_stacks.items[0] - # -------------- - # Event Handlers - # -------------- - - def register_event_handler( - self, - event: StoreEvent, - handler: Callable[..., Any], - ) -> None: - """Register an external event handler. - - The handler will be called when the store event is triggered. - - Args: - event: The event to register the handler for. - handler: The handler function to register. - """ - self._event_handlers.setdefault(event, []).append(handler) - - def _trigger_event(self, event: StoreEvent, **kwargs: Any) -> None: - """Trigger an event and call all registered handlers. - - Args: - event: The event to trigger. - **kwargs: The event arguments. - """ - for handler in self._event_handlers.get(event, []): - try: - handler(event, **kwargs) - except Exception as e: - logger.error( - f"Silently ignoring error caught while triggering event " - f"store handler for event {event.value}: {e}", - exc_info=True, - ) - def get_external_user(self, user_id: UUID) -> UserResponse: """Get a user by external ID. diff --git a/src/zenml/zen_stores/enums.py b/src/zenml/zen_stores/enums.py deleted file mode 100644 index f35cfde6e76..00000000000 --- a/src/zenml/zen_stores/enums.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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. -"""Zen Store enums.""" - -from zenml.utils.enum_utils import StrEnum - - -class StoreEvent(StrEnum): - """Events that can be triggered by the store.""" - - # Triggered just before deleting a workspace. The workspace ID is passed as - # a `workspace_id` UUID argument. - WORKSPACE_DELETED = "workspace_deleted" - # Triggered just before deleting a user. The user ID is passed as - # a `user_id` UUID argument. - USER_DELETED = "user_deleted" diff --git a/src/zenml/zen_stores/migrations/alembic.py b/src/zenml/zen_stores/migrations/alembic.py index 731ccbd76b4..e2c2286a325 100644 --- a/src/zenml/zen_stores/migrations/alembic.py +++ b/src/zenml/zen_stores/migrations/alembic.py @@ -19,7 +19,15 @@ """ from pathlib import Path -from typing import Any, Callable, Dict, List, Optional, Sequence, Union +from typing import ( + Any, + Callable, + Dict, + List, + Optional, + Sequence, + Union, +) from alembic.config import Config from alembic.runtime.environment import EnvironmentContext diff --git a/src/zenml/zen_stores/migrations/env.py b/src/zenml/zen_stores/migrations/env.py index 7b60835a458..4923a3a4f66 100644 --- a/src/zenml/zen_stores/migrations/env.py +++ b/src/zenml/zen_stores/migrations/env.py @@ -37,7 +37,7 @@ def run_migrations() -> None: if store_cfg is None or store_cfg.type != StoreType.SQL: store_cfg = GlobalConfiguration().get_default_store() - store = SqlZenStore( # type: ignore + store = SqlZenStore( config=store_cfg, skip_default_registrations=True, skip_migrations=True, diff --git a/src/zenml/zen_stores/migrations/versions/1ac1b9c04da1_make_secrets_values_optional.py b/src/zenml/zen_stores/migrations/versions/1ac1b9c04da1_make_secrets_values_optional.py new file mode 100644 index 00000000000..9749e8f8e5c --- /dev/null +++ b/src/zenml/zen_stores/migrations/versions/1ac1b9c04da1_make_secrets_values_optional.py @@ -0,0 +1,35 @@ +"""make secrets values optional [1ac1b9c04da1]. + +Revision ID: 1ac1b9c04da1 +Revises: 0.54.0 +Create Date: 2023-12-22 23:06:32.466128 + +""" +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = "1ac1b9c04da1" +down_revision = "0.54.0" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + """Upgrade database schema and/or data, creating a new revision.""" + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("secret", schema=None) as batch_op: + batch_op.alter_column("values", existing_type=sa.TEXT(), nullable=True) + + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade database schema and/or data back to the previous revision.""" + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("secret", schema=None) as batch_op: + batch_op.alter_column( + "values", existing_type=sa.TEXT(), nullable=False + ) + + # ### end Alembic commands ### diff --git a/src/zenml/zen_stores/migrations/versions/7b651bf6822e_track_secrets_in_db.py b/src/zenml/zen_stores/migrations/versions/7b651bf6822e_track_secrets_in_db.py new file mode 100644 index 00000000000..d7732884d10 --- /dev/null +++ b/src/zenml/zen_stores/migrations/versions/7b651bf6822e_track_secrets_in_db.py @@ -0,0 +1,715 @@ +"""track secrets in db [7b651bf6822e]. + +Revision ID: 7b651bf6822e +Revises: 1ac1b9c04da1 +Create Date: 2023-12-22 20:56:18.131906 + +""" + +from abc import abstractmethod +from datetime import datetime +from typing import Any, Dict, List, Optional +from uuid import UUID + +import sqlalchemy as sa +from alembic import op +from pydantic import BaseModel + +from zenml.enums import StoreType +from zenml.logger import get_logger + +logger = get_logger(__name__) + +# revision identifiers, used by Alembic. + + +revision = "7b651bf6822e" +down_revision = "1ac1b9c04da1" +branch_labels = None +depends_on = None + + +ZENML_SECRET_LABEL = "zenml" +ZENML_SECRET_ID_LABEL = "zenml_secret_id" +ZENML_SECRET_NAME_LABEL = "zenml_secret_name" +ZENML_SECRET_SCOPE_LABEL = "zenml_secret_scope" +ZENML_SECRET_USER_LABEL = "zenml_secret_user" +ZENML_SECRET_WORKSPACE_LABEL = "zenml_secret_workspace" + + +class ZenMLSecretMetadata(BaseModel): + """ZenML secret metadata. + + This class reflects the structure of the ZenML secret metadata stored in the + backend secret (e.g. in secret tags/labels) at the time when the secret + metadata was migrated to the database. It is roughly aligned to the + structure of the ZenML SecretResponse model as it was at that time. + """ + + id: UUID + name: str + user_id: UUID + workspace_id: UUID + created: datetime + updated: datetime + scope: str + + +class BaseSecretsStoreBackend(BaseModel): + """Base class for accessing and listing ZenML secrets.""" + + server_id: UUID + client: Any + + def _get_secret_metadata( + self, + secret_id: Optional[UUID] = None, + ) -> Dict[str, str]: + """Get a dictionary with metadata that can be used as tags/labels. + + This utility method can be used with Secrets Managers that can + associate metadata (e.g. tags, labels) with a secret. The metadata can + be configured alongside each secret. + + NOTE: the ZENML_SECRET_LABEL is always included in the metadata to + distinguish ZenML secrets from other secrets that might be stored in + the same backend, as well as to distinguish between different ZenML + deployments using the same backend. Its value is set to the ZenML + deployment ID. + + Args: + secret_id: Optional secret ID to include in the metadata. + + Returns: + Dictionary with secret metadata information. + """ + # Always include the main ZenML label to distinguish ZenML secrets + # from other secrets that might be stored in the same backend and + # to distinguish between different ZenML deployments using the same + # backend. + metadata: Dict[str, str] = {ZENML_SECRET_LABEL: str(self.server_id)} + + # Include the secret ID if provided. + if secret_id is not None: + metadata[ZENML_SECRET_ID_LABEL] = str(secret_id) + + return metadata + + def _create_secret_from_metadata( + self, + metadata: Dict[str, str], + created: datetime, + updated: datetime, + ) -> ZenMLSecretMetadata: + """Create a ZenML secret metadata object from metadata stored in the secrets store backend. + + Args: + metadata: ZenML secret metadata collected from the backend secret + (e.g. from secret tags/labels). + created: The secret creation time. + updated: The secret last updated time. + + Returns: + The ZenML secret. + + Raises: + KeyError: If the secret does not have the required metadata, if it + is not managed by this ZenML instance or if it is linked to a + user or workspace that no longer exists. + """ + # Double-check that the secret is managed by this ZenML instance. + if metadata.get(ZENML_SECRET_LABEL) != str(self.server_id): + raise KeyError("Secret is not managed by this ZenML instance") + + # Recover the ZenML secret fields from the input secret metadata. + try: + secret_id = UUID(metadata[ZENML_SECRET_ID_LABEL]) + name = metadata[ZENML_SECRET_NAME_LABEL] + scope = metadata[ZENML_SECRET_SCOPE_LABEL] + workspace_id = UUID(metadata[ZENML_SECRET_WORKSPACE_LABEL]) + user_id = UUID(metadata[ZENML_SECRET_USER_LABEL]) + except KeyError as e: + raise KeyError( + f"Secret could not be retrieved: missing required metadata: {e}" + ) + + secret_model = ZenMLSecretMetadata( + id=secret_id, + name=name, + workspace_id=workspace_id, + user_id=user_id, + created=created, + updated=updated, + scope=scope, + ) + + return secret_model + + @abstractmethod + def list_secrets( + self, + ) -> List[ZenMLSecretMetadata]: + """List all ZenML secrets in the secrets store backend. + + Returns: + A list of all secrets. + """ + + +class AWSSecretsStoreBackend(BaseSecretsStoreBackend): + """AWS ZenML secrets store backend.""" + + @staticmethod + def _get_aws_secret_filters( + metadata: Dict[str, str], + ) -> List[Dict[str, str]]: + """Convert ZenML secret metadata to AWS secret filters. + + Args: + metadata: The ZenML secret metadata. + + Returns: + The AWS secret filters. + """ + aws_filters: List[Dict[str, Any]] = [] + for k, v in metadata.items(): + aws_filters.append( + { + "Key": "tag-key", + "Values": [ + k, + ], + } + ) + aws_filters.append( + { + "Key": "tag-value", + "Values": [ + str(v), + ], + } + ) + + return aws_filters + + def list_secrets( + self, + ) -> List[ZenMLSecretMetadata]: + """List all ZenML secrets in the AWS secrets store backend. + + Returns: + A list of all secrets. + + Raises: + RuntimeError: If the AWS Secrets Manager API returns an unexpected + error. + """ + from botocore.exceptions import ClientError + + # The metadata will always contain at least the filter criteria + # required to exclude everything but AWS secrets that belong to the + # current ZenML deployment. + metadata = self._get_secret_metadata() + aws_filters = self._get_aws_secret_filters(metadata) + + results: List[ZenMLSecretMetadata] = [] + + try: + # AWS Secrets Manager API pagination is wrapped around the + # `list_secrets` method call. We use it because we need to fetch all + # secrets matching the (partial) filter that we set up. Note that + # the pagination used here has nothing to do with the pagination + # that we do for the method caller. + paginator = self.client.get_paginator("list_secrets") + pages = paginator.paginate( + Filters=aws_filters, + PaginationConfig={ + "PageSize": 100, + }, + ) + + for page in pages: + for secret in page["SecretList"]: + try: + # Convert the AWS secret tags to a metadata dictionary. + unpacked_metadata: Dict[str, str] = { + tag["Key"]: tag["Value"] for tag in secret["Tags"] + } + + secret_model = self._create_secret_from_metadata( + metadata=unpacked_metadata, + created=secret["CreatedDate"], + updated=secret["LastChangedDate"], + ) + except KeyError: + # The _convert_aws_secret method raises a KeyError + # if the secret is not well formed. Here we pretend that + # the secret does not exist. + continue + + results.append(secret_model) + except ClientError as e: + raise RuntimeError(f"Error listing AWS secrets: {e}") + + return results + + +ZENML_GCP_DATE_FORMAT_STRING = "%Y-%m-%d-%H-%M-%S" +ZENML_GCP_SECRET_CREATED_KEY = "zenml-secret-created" +ZENML_GCP_SECRET_UPDATED_KEY = "zenml-secret-updated" + + +class GCPSecretsStoreBackend(BaseSecretsStoreBackend): + """GCP ZenML secrets store backend.""" + + project_id: str + + @property + def parent_name(self) -> str: + """Construct the GCP parent path to the secret manager. + + Returns: + The parent path to the secret manager + """ + return f"projects/{self.project_id}" + + def _convert_gcp_secret( + self, + labels: Dict[str, str], + ) -> ZenMLSecretMetadata: + """Create a ZenML secret model from data stored in an GCP secret. + + If the GCP secret cannot be converted, the method acts as if the + secret does not exist and raises a KeyError. + + Args: + labels: The GCP secret labels. + + Returns: + The ZenML secret model. + + Raises: + KeyError: if the GCP secret cannot be converted. + """ + # Recover the ZenML secret metadata from the AWS secret tags. + + # The GCP secret labels do not really behave like a dictionary: when + # a key is not found, it does not raise a KeyError, but instead + # returns an empty string. That's why we make this conversion. + label_dict = dict(labels) + + try: + created = datetime.strptime( + label_dict[ZENML_GCP_SECRET_CREATED_KEY], + ZENML_GCP_DATE_FORMAT_STRING, + ) + updated = datetime.strptime( + label_dict[ZENML_GCP_SECRET_UPDATED_KEY], + ZENML_GCP_DATE_FORMAT_STRING, + ) + except KeyError as e: + raise KeyError( + f"Invalid GCP secret: missing required tag '{e}'" + ) from e + + return self._create_secret_from_metadata( + metadata=label_dict, + created=created, + updated=updated, + ) + + def list_secrets(self) -> List[ZenMLSecretMetadata]: + """List all secrets. + + Returns: + A list of all secrets. + + Raises: + RuntimeError: if the GCP Secrets Manager API returns an unexpected + error. + """ + from google.cloud.secretmanager import SecretManagerServiceClient + + assert isinstance(self.client, SecretManagerServiceClient) + + try: + # get all the secrets and their labels from GCP + secrets = [] + for secret in self.client.list_secrets( + request={ + "parent": self.parent_name, + "filter": "", + } + ): + try: + secrets.append(self._convert_gcp_secret(secret.labels)) + except KeyError: + # keep going / ignore if this secret version doesn't exist + # or isn't a ZenML secret + continue + except Exception as e: + raise RuntimeError(f"Error listing GCP secrets: {e}") from e + + return secrets + + +ZENML_AZURE_SECRET_CREATED_KEY = "zenml_secret_created" +ZENML_AZURE_SECRET_UPDATED_KEY = "zenml_secret_updated" + + +class AzureSecretsStoreBackend(BaseSecretsStoreBackend): + """Azure ZenML secrets store backend.""" + + def _convert_azure_secret( + self, + tags: Dict[str, str], + ) -> ZenMLSecretMetadata: + """Create a ZenML secret model from data stored in an Azure secret. + + If the Azure secret cannot be converted, the method acts as if the + secret does not exist and raises a KeyError. + + Args: + tags: The Azure secret tags. + + Returns: + The ZenML secret. + + Raises: + KeyError: if the Azure secret cannot be converted. + """ + try: + created = datetime.fromisoformat( + tags[ZENML_AZURE_SECRET_CREATED_KEY], + ) + updated = datetime.fromisoformat( + tags[ZENML_AZURE_SECRET_UPDATED_KEY], + ) + except KeyError as e: + raise KeyError( + f"Secret could not be retrieved: missing required metadata: {e}" + ) + + return self._create_secret_from_metadata( + metadata=tags, + created=created, + updated=updated, + ) + + def list_secrets(self) -> List[ZenMLSecretMetadata]: + """List all secrets. + + Returns: + A list of all secrets. + + Raises: + RuntimeError: If the Azure Key Vault API returns an unexpected + error. + """ + from azure.core.exceptions import HttpResponseError + from azure.keyvault.secrets import SecretClient + + assert isinstance(self.client, SecretClient) + + results: List[ZenMLSecretMetadata] = [] + + try: + all_secrets = self.client.list_properties_of_secrets() + for secret_property in all_secrets: + try: + # NOTE: we do not include the secret values in the + # response. We would need a separate API call to fetch + # them for each secret, which would be very inefficient + # anyway. + assert secret_property.tags is not None + secret_model = self._convert_azure_secret( + tags=secret_property.tags, + ) + except KeyError: + # The _convert_azure_secret method raises a KeyError + # if the secret is tied to a workspace or user that no + # longer exists or if it is otherwise not valid. Here we + # pretend that the secret does not exist. + continue + + results.append(secret_model) + except HttpResponseError as e: + raise RuntimeError(f"Error listing Azure Key Vault secrets: {e}") + + return results + + +HVAC_ZENML_SECRET_NAME_PREFIX = "zenml" +ZENML_VAULT_SECRET_METADATA_KEY = "zenml_secret_metadata" +ZENML_VAULT_SECRET_CREATED_KEY = "zenml_secret_created" +ZENML_VAULT_SECRET_UPDATED_KEY = "zenml_secret_updated" + + +class HashiCorpVaultSecretsStoreBackend(BaseSecretsStoreBackend): + """HashiCorp Vault ZenML secrets store backend.""" + + def _convert_vault_secret( + self, + vault_secret: Dict[str, Any], + ) -> ZenMLSecretMetadata: + """Create a ZenML secret model from data stored in an HashiCorp Vault secret. + + If the HashiCorp Vault secret cannot be converted, the method acts as if + the secret does not exist and raises a KeyError. + + Args: + vault_secret: The HashiCorp Vault secret in JSON form. + + Returns: + The ZenML secret. + + Raises: + KeyError: if the HashiCorp Vault secret cannot be converted. + """ + try: + metadata = vault_secret[ZENML_VAULT_SECRET_METADATA_KEY] + created = datetime.fromisoformat( + vault_secret[ZENML_VAULT_SECRET_CREATED_KEY], + ) + updated = datetime.fromisoformat( + vault_secret[ZENML_VAULT_SECRET_UPDATED_KEY], + ) + except (KeyError, ValueError) as e: + raise KeyError( + f"Secret could not be retrieved: missing required metadata: {e}" + ) + + return self._create_secret_from_metadata( + metadata=metadata, + created=created, + updated=updated, + ) + + def list_secrets(self) -> List[ZenMLSecretMetadata]: + """List all secrets. + + Note that returned secrets do not include any secret values. To fetch + the secret values, use `get_secret`. + + Returns: + A list of all secrets. + + Raises: + RuntimeError: If the HashiCorp Vault API returns an unexpected + error. + """ + from hvac import Client # type: ignore[import-untyped] + from hvac.exceptions import ( # type: ignore[import-untyped] + InvalidPath, + VaultError, + ) + + assert isinstance(self.client, Client) + + results: List[ZenMLSecretMetadata] = [] + + try: + # List all ZenML secrets in the Vault + all_secrets = ( + self.client.secrets.kv.v2.list_secrets( + path=HVAC_ZENML_SECRET_NAME_PREFIX + ) + .get("data", {}) + .get("keys", []) + ) + except InvalidPath: + # no secrets created yet + pass + except VaultError as e: + raise RuntimeError(f"Error listing HashiCorp Vault secrets: {e}") + else: + # Convert the Vault secrets to ZenML secrets + for secret_uuid in all_secrets: + vault_secret_id = ( + f"{HVAC_ZENML_SECRET_NAME_PREFIX}/{secret_uuid}" + ) + try: + vault_secret = ( + self.client.secrets.kv.v2.read_secret( + path=vault_secret_id + ) + .get("data", {}) + .get("data", {}) + ) + except (InvalidPath, VaultError) as e: + logger.warning( + f"Error fetching secret with ID {vault_secret_id}: {e}", + ) + continue + + try: + secret_model = self._convert_vault_secret( + vault_secret, + ) + except KeyError as e: + # The _convert_vault_secret method raises a KeyError + # if the secret is not valid. Here we + # pretend that the secret does not exist. + logger.warning( + f"Error fetching secret with ID {vault_secret_id}: {e}", + ) + continue + + results.append(secret_model) + + return results + + +def upgrade() -> None: + """Upgrade database schema and/or data, creating a new revision. + + Raises: + NotImplementedError: If the secrets store type is not supported. + """ + from zenml.config.global_config import GlobalConfiguration + from zenml.enums import SecretsStoreType + from zenml.zen_stores.sql_zen_store import SqlZenStore + + store_cfg = GlobalConfiguration().store + + if store_cfg is None or store_cfg.type != StoreType.SQL: + return + + # We create a new SqlZenStore instance with the same configuration as the + # one used to run migrations, but we skip the default registrations and + # migrations. This is because we can't use the same store instance that is + # used to run migrations because it would create an infinite loop. + store = SqlZenStore( + config=store_cfg, + skip_default_registrations=True, + skip_migrations=True, + ) + + secrets_store = store.secrets_store + + if secrets_store.TYPE == SecretsStoreType.SQL: + # If the secrets store is already a SQL secrets store, we don't need + # to transfer secrets from the external secrets store to the db. + return + + # Transfer secrets from the external secrets store to the db + + conn = op.get_bind() + meta = sa.MetaData(bind=op.get_bind()) + meta.reflect(only=("secret", "user", "workspace", "identity")) + secrets = sa.Table("secret", meta) + users = sa.Table("user", meta) + workspaces = sa.Table("workspace", meta) + identity = sa.Table("identity", meta) + + # Extract the ZenML deployment ID from the identity table + server_id = UUID(conn.execute(identity.select()).first()["id"]) # type: ignore[index] + + # Initialize the secrets store backend based on the backend client extracted + # from the secrets store. + backend: BaseSecretsStoreBackend + if secrets_store.TYPE == SecretsStoreType.AWS: + from zenml.zen_stores.secrets_stores.aws_secrets_store import ( + AWSSecretsStore, + ) + + assert isinstance(secrets_store, AWSSecretsStore) + backend = AWSSecretsStoreBackend( + server_id=server_id, + client=secrets_store.client, + ) + elif secrets_store.TYPE == SecretsStoreType.GCP: + from zenml.zen_stores.secrets_stores.gcp_secrets_store import ( + GCPSecretsStore, + ) + + assert isinstance(secrets_store, GCPSecretsStore) + backend = GCPSecretsStoreBackend( + server_id=server_id, + client=secrets_store.client, + project_id=secrets_store.config.project_id, + ) + elif secrets_store.TYPE == SecretsStoreType.AZURE: + from zenml.zen_stores.secrets_stores.azure_secrets_store import ( + AzureSecretsStore, + ) + + assert isinstance(secrets_store, AzureSecretsStore) + backend = AzureSecretsStoreBackend( + server_id=server_id, + client=secrets_store.client, + ) + elif secrets_store.TYPE == SecretsStoreType.HASHICORP: + from zenml.zen_stores.secrets_stores.hashicorp_secrets_store import ( + HashiCorpVaultSecretsStore, + ) + + assert isinstance(secrets_store, HashiCorpVaultSecretsStore) + backend = HashiCorpVaultSecretsStoreBackend( + server_id=server_id, + client=secrets_store.client, + ) + else: + raise NotImplementedError( + f"Secrets store type {secrets_store.TYPE} not supported" + ) + + # List all secrets in the backend + external_secrets = backend.list_secrets() + + for secret in external_secrets: + logger.info( + f"Transferring secret '{secret.name}' from the " + f"{secrets_store.type} secrets store to the db." + ) + # Check if a user with the given ID exists in the db + user = conn.execute( + users.select().where( + users.c.id == str(secret.user_id).replace("-", "") + ) + ).first() + if user is None: + logger.warning( + f"User with ID {secret.user_id} not found in the db. " + f"Skipping secret '{secret.name}'." + ) + continue + # Check if a workspace with the given ID exists in the db + workspace = conn.execute( + workspaces.select().where( + workspaces.c.id == str(secret.workspace_id).replace("-", "") + ) + ).first() + if workspace is None: + logger.warning( + f"Workspace with ID {secret.workspace_id} not found in the db. " + f"Skipping secret '{secret.name}'." + ) + continue + + # Check if there is already a secret with the same ID in the db + # and delete it if there is. This can happen for example if the user has + # previously migrated the secrets from the db to an external secrets + # store and forgot to delete the secrets from the db. + conn.execute( + secrets.delete().where( + secrets.c.id == str(secret.id).replace("-", "") + ) + ) + conn.execute( + secrets.insert().values( + id=str(secret.id).replace("-", ""), + created=secret.created, + updated=secret.updated, + name=secret.name, + scope=secret.scope, + values=None, + workspace_id=str(secret.workspace_id).replace("-", ""), + user_id=str(secret.user_id).replace("-", ""), + ) + ) + + +def downgrade() -> None: + """Downgrade database schema and/or data back to the previous revision.""" + pass diff --git a/src/zenml/zen_stores/rest_zen_store.py b/src/zenml/zen_stores/rest_zen_store.py index d2cb81cad98..50e7c376060 100644 --- a/src/zenml/zen_stores/rest_zen_store.py +++ b/src/zenml/zen_stores/rest_zen_store.py @@ -37,7 +37,6 @@ import zenml from zenml.analytics import source_context from zenml.config.global_config import GlobalConfiguration -from zenml.config.secrets_store_config import SecretsStoreConfiguration from zenml.config.store_config import StoreConfiguration from zenml.constants import ( API, @@ -69,6 +68,7 @@ RUN_METADATA, RUNS, SCHEDULES, + SECRETS, SERVICE_ACCOUNTS, SERVICE_CONNECTOR_CLIENT, SERVICE_CONNECTOR_RESOURCES, @@ -85,7 +85,6 @@ ) from zenml.enums import ( OAuthGrantTypes, - SecretsStoreType, StoreType, ) from zenml.exceptions import ( @@ -164,6 +163,10 @@ ScheduleRequest, ScheduleResponse, ScheduleUpdate, + SecretFilter, + SecretRequest, + SecretResponse, + SecretUpdate, ServerModel, ServiceAccountFilter, ServiceAccountRequest, @@ -205,9 +208,6 @@ ) from zenml.zen_server.exceptions import exception_from_response from zenml.zen_stores.base_zen_store import BaseZenStore -from zenml.zen_stores.secrets_stores.rest_secrets_store import ( - RestSecretsStoreConfiguration, -) logger = get_logger(__name__) @@ -228,9 +228,6 @@ class RestZenStoreConfiguration(StoreConfiguration): Attributes: type: The type of the store. - secrets_store: The configuration of the secrets store to use. - This defaults to a REST secrets store that extends the REST ZenML - store. username: The username to use to connect to the Zen server. password: The password to use to connect to the Zen server. api_key: The service account API key to use to connect to the Zen @@ -247,8 +244,6 @@ class RestZenStoreConfiguration(StoreConfiguration): type: StoreType = StoreType.REST - secrets_store: Optional[SecretsStoreConfiguration] = None - username: Optional[str] = None password: Optional[str] = None api_key: Optional[str] = None @@ -256,31 +251,6 @@ class RestZenStoreConfiguration(StoreConfiguration): verify_ssl: Union[bool, str] = True http_timeout: int = DEFAULT_HTTP_TIMEOUT - @validator("secrets_store") - def validate_secrets_store( - cls, secrets_store: Optional[SecretsStoreConfiguration] - ) -> SecretsStoreConfiguration: - """Ensures that the secrets store uses an associated REST secrets store. - - Args: - secrets_store: The secrets store config to be validated. - - Returns: - The validated secrets store config. - - Raises: - ValueError: If the secrets store is not of type REST. - """ - if secrets_store is None: - secrets_store = RestSecretsStoreConfiguration() - elif secrets_store.type != SecretsStoreType.REST: - raise ValueError( - "The secrets store associated with a REST zen store must be " - f"of type REST, but is of type {secrets_store.type}." - ) - - return secrets_store - @root_validator def validate_credentials(cls, values: Dict[str, Any]) -> Dict[str, Any]: """Validates the credentials provided in the values dictionary. @@ -1683,6 +1653,126 @@ def delete_schedule(self, schedule_id: UUID) -> None: route=SCHEDULES, ) + # --------------------------- Secrets --------------------------- + + def create_secret(self, secret: SecretRequest) -> SecretResponse: + """Creates a new secret. + + The new secret is also validated against the scoping rules enforced in + the secrets store: + + - only one workspace-scoped secret with the given name can exist + in the target workspace. + - only one user-scoped secret with the given name can exist in the + target workspace for the target user. + + Args: + secret: The secret to create. + + Returns: + The newly created secret. + """ + return self._create_workspace_scoped_resource( + resource=secret, + route=SECRETS, + response_model=SecretResponse, + ) + + def get_secret( + self, secret_id: UUID, hydrate: bool = True + ) -> SecretResponse: + """Get a secret by ID. + + Args: + secret_id: The ID of the secret to fetch. + hydrate: Flag deciding whether to hydrate the output model(s) + by including metadata fields in the response. + + Returns: + The secret. + """ + return self._get_resource( + resource_id=secret_id, + route=SECRETS, + response_model=SecretResponse, + params={"hydrate": hydrate}, + ) + + def list_secrets( + self, secret_filter_model: SecretFilter, hydrate: bool = False + ) -> Page[SecretResponse]: + """List all secrets matching the given filter criteria. + + Note that returned secrets do not include any secret values. To fetch + the secret values, use `get_secret`. + + Args: + secret_filter_model: All filter parameters including pagination + params. + hydrate: Flag deciding whether to hydrate the output model(s) + by including metadata fields in the response. + + Returns: + A list of all secrets matching the filter criteria, with pagination + information and sorted according to the filter criteria. The + returned secrets do not include any secret values, only metadata. To + fetch the secret values, use `get_secret` individually with each + secret. + """ + return self._list_paginated_resources( + route=SECRETS, + response_model=SecretResponse, + filter_model=secret_filter_model, + params={"hydrate": hydrate}, + ) + + def update_secret( + self, secret_id: UUID, secret_update: SecretUpdate + ) -> SecretResponse: + """Updates a secret. + + Secret values that are specified as `None` in the update that are + present in the existing secret are removed from the existing secret. + Values that are present in both secrets are overwritten. All other + values in both the existing secret and the update are kept (merged). + + If the update includes a change of name or scope, the scoping rules + enforced in the secrets store are used to validate the update: + + - only one workspace-scoped secret with the given name can exist + in the target workspace. + - only one user-scoped secret with the given name can exist in the + target workspace for the target user. + + Args: + secret_id: The ID of the secret to be updated. + secret_update: The update to be applied. + + Returns: + The updated secret. + """ + return self._update_resource( + resource_id=secret_id, + resource_update=secret_update, + route=SECRETS, + response_model=SecretResponse, + # The default endpoint behavior is to replace all secret values + # with the values in the update. We want to merge the values + # instead. + params=dict(patch_values=True), + ) + + def delete_secret(self, secret_id: UUID) -> None: + """Delete a secret. + + Args: + secret_id: The id of the secret to delete. + """ + self._delete_resource( + resource_id=secret_id, + route=SECRETS, + ) + # --------------------------- Service Accounts --------------------------- def create_service_account( diff --git a/src/zenml/zen_stores/schemas/secret_schemas.py b/src/zenml/zen_stores/schemas/secret_schemas.py index adfaa0d3750..ae9cf7b0452 100644 --- a/src/zenml/zen_stores/schemas/secret_schemas.py +++ b/src/zenml/zen_stores/schemas/secret_schemas.py @@ -49,7 +49,7 @@ class SecretSchema(NamedSchema, table=True): scope: SecretScope - values: bytes = Field(sa_column=Column(TEXT, nullable=False)) + values: Optional[bytes] = Field(sa_column=Column(TEXT, nullable=True)) workspace_id: UUID = build_foreign_key_field( source=__tablename__, @@ -136,14 +136,11 @@ def _load_secret_values( def from_request( cls, secret: SecretRequest, - encryption_engine: Optional[AesGcmEngine] = None, ) -> "SecretSchema": """Create a `SecretSchema` from a `SecretRequest`. Args: secret: The `SecretRequest` from which to create the schema. - encryption_engine: The encryption engine to use to encrypt the - secret values. If None, the values will be base64 encoded. Returns: The created `SecretSchema`. @@ -154,64 +151,42 @@ def from_request( scope=secret.scope, workspace_id=secret.workspace, user_id=secret.user, - values=cls._dump_secret_values( - secret.secret_values, encryption_engine - ), + # Don't store secret values implicitly in the secret. The + # SQL secret store will call `store_secret_values` to store the + # values separately if SQL is used as the secrets store. + values=None, ) def update( self, secret_update: SecretUpdate, - encryption_engine: Optional[AesGcmEngine] = None, ) -> "SecretSchema": """Update a `SecretSchema` from a `SecretUpdate`. - The method also knows how to handle the `values` field of the secret - update model: It will update the existing values with the new values - and drop `None` values. - Args: secret_update: The `SecretUpdate` from which to update the schema. - encryption_engine: The encryption engine to use to encrypt the - secret values. If None, the values will be base64 encoded. Returns: The updated `SecretSchema`. """ + # Don't update the secret values implicitly in the secret. The + # SQL secret store will call `set_secret_values` to update the + # values separately if SQL is used as the secrets store. for field, value in secret_update.dict( - exclude_unset=True, exclude={"workspace", "user"} + exclude_unset=True, exclude={"workspace", "user", "values"} ).items(): - if field == "values": - existing_values = self._load_secret_values( - self.values, encryption_engine - ) - existing_values.update(secret_update.secret_values) - # Drop values removed in the update - for k, v in secret_update.values.items(): - if v is None and k in existing_values: - del existing_values[k] - self.values = self._dump_secret_values( - existing_values, encryption_engine - ) - else: - setattr(self, field, value) + setattr(self, field, value) self.updated = datetime.utcnow() return self def to_model( self, - encryption_engine: Optional[AesGcmEngine] = None, - include_values: bool = True, hydrate: bool = False, ) -> SecretResponse: """Converts a secret schema to a secret model. Args: - encryption_engine: The encryption engine to use to decrypt the - secret values. If None, the values will be base64 decoded. - include_values: Whether to include the secret values in the - response model or not. hydrate: Flag deciding whether to hydrate the output model(s) by including metadata fields in the response. @@ -224,14 +199,14 @@ def to_model( workspace=self.workspace.to_model(), ) + # Don't load the secret values implicitly in the secret. The + # SQL secret store will call `get_secret_values` to load the + # values separately if SQL is used as the secrets store. body = SecretResponseBody( user=self.user.to_model() if self.user else None, created=self.created, updated=self.updated, scope=self.scope, - values=self._load_secret_values(self.values, encryption_engine) - if include_values - else {}, ) return SecretResponse( id=self.id, @@ -239,3 +214,49 @@ def to_model( body=body, metadata=metadata, ) + + def get_secret_values( + self, + encryption_engine: Optional[AesGcmEngine] = None, + ) -> Dict[str, str]: + """Get the secret values for this secret. + + This method is used by the SQL secrets store to load the secret values + from the database. + + Args: + encryption_engine: The encryption engine to use to decrypt the + secret values. If None, the values will be base64 decoded. + + Returns: + The secret values + + Raises: + KeyError: if no secret values for the given ID are stored in the + secrets store. + """ + if not self.values: + raise KeyError( + f"Secret values for secret {self.id} have not been stored in " + f"the SQL secrets store." + ) + return self._load_secret_values(self.values, encryption_engine) + + def set_secret_values( + self, + secret_values: Dict[str, str], + encryption_engine: Optional[AesGcmEngine] = None, + ) -> None: + """Create a `SecretSchema` from a `SecretRequest`. + + This method is used by the SQL secrets store to store the secret values + in the database. + + Args: + secret_values: The new secret values. + encryption_engine: The encryption engine to use to encrypt the + secret values. If None, the values will be base64 encoded. + """ + self.values = self._dump_secret_values( + secret_values, encryption_engine + ) diff --git a/src/zenml/zen_stores/secrets_stores/aws_secrets_store.py b/src/zenml/zen_stores/secrets_stores/aws_secrets_store.py index cba349cee16..e2c8fa884f7 100644 --- a/src/zenml/zen_stores/secrets_stores/aws_secrets_store.py +++ b/src/zenml/zen_stores/secrets_stores/aws_secrets_store.py @@ -14,17 +14,11 @@ """AWS Secrets Store implementation.""" import json -import math -import re -import time -import uuid -from datetime import datetime from typing import ( Any, ClassVar, Dict, List, - Optional, Type, ) from uuid import UUID @@ -33,15 +27,9 @@ from botocore.exceptions import ClientError from pydantic import root_validator -from zenml.analytics.enums import AnalyticsEvent -from zenml.analytics.utils import track_decorator from zenml.enums import ( - GenericFilterOps, - LogicalOperators, - SecretScope, SecretsStoreType, ) -from zenml.exceptions import EntityExistsError from zenml.integrations.aws import ( AWS_CONNECTOR_TYPE, AWS_RESOURCE_TYPE, @@ -50,15 +38,6 @@ AWSAuthenticationMethods, ) from zenml.logger import get_logger -from zenml.models import ( - Page, - SecretFilter, - SecretRequest, - SecretResponse, - SecretResponseBody, - SecretResponseMetadata, - SecretUpdate, -) from zenml.zen_stores.secrets_stores.service_connector_secrets_store import ( ServiceConnectorSecretsStore, ServiceConnectorSecretsStoreConfiguration, @@ -75,23 +54,9 @@ class AWSSecretsStoreConfiguration(ServiceConnectorSecretsStoreConfiguration): Attributes: type: The type of the store. - list_page_size: The number of secrets to fetch per page when - listing secrets. - secret_list_refresh_timeout: The number of seconds to wait after - creating or updating an AWS secret until the changes are reflected - in the secrets returned by `list_secrets`. Set this to zero to - disable the wait. This may be necessary because it can take some - time for new secrets and updated secrets to be reflected in the - result returned by `list_secrets` on the client side. This value - should not be set to a large value, because it blocks ZenML server - threads while waiting and can cause performance issues. - Disable this if you don't need changes to be reflected immediately - on the client side. """ type: SecretsStoreType = SecretsStoreType.AWS - list_page_size: int = 100 - secret_list_refresh_timeout: int = 0 @property def region(self) -> str: @@ -144,7 +109,7 @@ def populate_config(cls, values: Dict[str, Any]) -> Dict[str, Any]: class Config: """Pydantic configuration class.""" - # Forbid extra attributes set in the class. + # Allow extra attributes set in the class. extra = "allow" @@ -162,36 +127,13 @@ class AWSSecretsStore(ServiceConnectorSecretsStore): `zenml` prefix in the form `zenml/{zenml_secret_uuid}`. This clearly identifies a secret as being managed by ZenML in the AWS console. - * the Secrets Store also makes heavy use of AWS secret tags to store all the - metadata associated with a ZenML secret (e.g. the secret name, scope, user - and workspace) and to filter secrets by these metadata. The `zenml` tag in - particular is used to identify and group all secrets that belong to the same - ZenML deployment. + * the Secrets Store also uses AWS secret tags to store additional + metadata associated with a ZenML secret. The `zenml` tag in particular is + used to identify and group all secrets that belong to the same ZenML + deployment. * all secret key-values configured in a ZenML secret are stored as a single JSON string value in the AWS secret value. - - * when a user or workspace is deleted, the secrets associated with it are - deleted automatically via registered event handlers. - - - Known challenges and limitations: - - * there is a known problem with the AWS Secrets Manager API that can cause - the `list_secrets` method to return stale data for a long time (seconds) - after a secret is created or updated. The AWS secrets store tries to - mitigate this problem by waiting for a maximum configurable number of - seconds after creating or updating a secret until the changes are reflected - in the `list_secrets` AWS content. However, this is not a perfect solution, - because it blocks ZenML server API threads while waiting. This can be - disabled by setting the `secret_list_refresh_timeout` configuration - parameter to zero. - - * only updating the secret values is reflected in the secret's `updated` - timestamp. Updating the secret metadata (e.g. name, scope, user or - workspace) does not update the secret's `updated` timestamp. This is a - limitation of the AWS Secrets Manager API (updating AWS tags does not update - the secret's `updated` timestamp). """ config: AWSSecretsStoreConfiguration @@ -230,35 +172,6 @@ def _initialize_client_from_connector(self, client: Any) -> Any: # Secrets # ------ - @staticmethod - def _validate_aws_secret_name(name: str) -> None: - """Validate a secret name. - - AWS secret names must contain only alphanumeric characters and the - characters /_+=.@-. The `/` character is only used internally to - implement the global namespace sharing scheme. - - Given that the ZenML secret name is stored as an AWS secret tag, the - maximum value length is also restricted to 255 characters. - - Args: - name: the secret name - - Raises: - ValueError: if the secret name is invalid - """ - if not re.fullmatch(r"[a-zA-Z0-9_+=\.@\-]*", name): - raise ValueError( - f"Invalid secret name '{name}'. Must contain only alphanumeric " - f"characters and the characters _+=.@-." - ) - - if len(name) > 255: - raise ValueError( - f"Invalid secret name '{name}'. The maximum length is 255 " - f"characters." - ) - @staticmethod def _get_aws_secret_id( secret_id: UUID, @@ -277,41 +190,6 @@ def _get_aws_secret_id( """ return f"{AWS_ZENML_SECRET_NAME_PREFIX}/{str(secret_id)}" - def _convert_aws_secret( - self, - tags: List[Dict[str, str]], - created: datetime, - updated: datetime, - values: Optional[str] = None, - hydrate: bool = False, - ) -> SecretResponse: - """Create a ZenML secret model from data stored in an AWS secret. - - If the AWS secret cannot be converted, the method acts as if the - secret does not exist and raises a KeyError. - - Args: - tags: The AWS secret tags. - created: The AWS secret creation time. - updated: The AWS secret last updated time. - values: The AWS secret values encoded as a JSON string (optional). - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - The ZenML secret. - """ - # Convert the AWS secret tags to a metadata dictionary. - metadata: Dict[str, str] = {tag["Key"]: tag["Value"] for tag in tags} - - return self._create_secret_from_metadata( - metadata=metadata, - created=created, - updated=updated, - values=json.loads(values) if values else None, - hydrate=hydrate, - ) - @staticmethod def _get_aws_secret_tags( metadata: Dict[str, str], @@ -335,145 +213,26 @@ def _get_aws_secret_tags( return aws_tags - @staticmethod - def _get_aws_secret_filters( - metadata: Dict[str, str], - ) -> List[Dict[str, str]]: - """Convert ZenML secret metadata to AWS secret filters. - - Args: - metadata: The ZenML secret metadata. - - Returns: - The AWS secret filters. - """ - aws_filters: List[Dict[str, Any]] = [] - for k, v in metadata.items(): - aws_filters.append( - { - "Key": "tag-key", - "Values": [ - k, - ], - } - ) - aws_filters.append( - { - "Key": "tag-value", - "Values": [ - str(v), - ], - } - ) - - return aws_filters - - def _wait_for_secret_to_propagate( - self, aws_secret_id: str, tags: List[Dict[str, str]] + def store_secret_values( + self, + secret_id: UUID, + secret_values: Dict[str, str], ) -> None: - """Wait for an AWS secret to be refreshed in the list of secrets. - - The AWS Secrets Manager does not immediately reflect newly created - and updated secrets in the `list_secrets` API. It is important that we - wait for the secret to be refreshed in the `list_secrets` API - before returning from create_secret/update_secret, otherwise the secret - will not be available to the user. We also rely on `list_secrets` - to enforce the scope rules, but given that the ZenML server runs - requests in separate threads, it is not entirely possible to - guarantee them. + """Store secret values for a new secret. Args: - aws_secret_id: The AWS secret ID. - tags: The AWS secret tags that are expected to be present in the - `list_secrets` response. - """ - if self.config.secret_list_refresh_timeout <= 0: - return - - # We wait for the secret to be available in the `list_secrets` API. - for _ in range(self.config.secret_list_refresh_timeout): - logger.debug(f"Waiting for secret {aws_secret_id} to be listed...") - secret_exists = False - try: - secrets = self.client.list_secrets( - Filters=[{"Key": "name", "Values": [aws_secret_id]}] - ) - if len(secrets["SecretList"]) > 0: - listed_secret = secrets["SecretList"][0] - # The supplied tags must exactly match those reported in the - # `list_secrets` response. - secret_exists = all( - tag in listed_secret["Tags"] for tag in tags - ) - except ClientError as e: - logger.warning( - f"Error checking if secret {aws_secret_id} is listed: " - f"{e}. Retrying..." - ) - - if not secret_exists: - logger.debug( - f"Secret {aws_secret_id} not yet listed. Retrying..." - ) - time.sleep(1) - else: - logger.debug(f"Secret {aws_secret_id} listed.") - break - else: - logger.warning( - f"Secret {aws_secret_id} not updated in `list_secrets` " - f"after {self.config.secret_list_refresh_timeout} seconds. " - ) - - @track_decorator(AnalyticsEvent.CREATED_SECRET) - def create_secret(self, secret: SecretRequest) -> SecretResponse: - """Creates a new secret. - - The new secret is also validated against the scoping rules enforced in - the secrets store: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. - - Args: - secret: The secret to create. - - Returns: - The newly created secret. + secret_id: ID of the secret. + secret_values: Values for the secret. Raises: - EntityExistsError: If a secret with the same name already exists - in the same scope. RuntimeError: If the AWS Secrets Manager API returns an unexpected error. """ - self._validate_aws_secret_name(secret.name) - user, workspace = self._validate_user_and_workspace( - secret.user, secret.workspace - ) - - # Check if a secret with the same name already exists in the same - # scope. - secret_exists, msg = self._check_secret_scope( - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace, - user=secret.user, - ) - if secret_exists: - raise EntityExistsError(msg) - - # Generate a new UUID for the secret - secret_id = uuid.uuid4() aws_secret_id = self._get_aws_secret_id(secret_id) - secret_value = json.dumps(secret.secret_values) + secret_value = json.dumps(secret_values) # Convert the ZenML secret metadata to AWS tags - metadata = self._get_secret_metadata_for_secret( - secret, secret_id=secret_id - ) + metadata = self._get_secret_metadata(secret_id=secret_id) tags = self._get_aws_secret_tags(metadata) try: @@ -482,50 +241,23 @@ def create_secret(self, secret: SecretRequest) -> SecretResponse: SecretString=secret_value, Tags=tags, ) - # We need a separate AWS API call to get the secret creation - # date, since the create_secret API does not return it. - describe_secret_response = self.client.describe_secret( - SecretId=aws_secret_id - ) except ClientError as e: raise RuntimeError(f"Error creating secret: {e}") - logger.debug("Created AWS secret: %s", aws_secret_id) - - self._wait_for_secret_to_propagate(aws_secret_id, tags=tags) - - secret_model = SecretResponse( - id=secret_id, - name=secret.name, - body=SecretResponseBody( - user=user, - created=describe_secret_response["CreatedDate"], - updated=describe_secret_response["LastChangedDate"], - scope=secret.scope, - values=secret.secret_values, - ), - metadata=SecretResponseMetadata( - workspace=workspace, - ), - ) - - return secret_model + logger.debug(f"Created AWS secret: {aws_secret_id}") - def get_secret( - self, secret_id: UUID, hydrate: bool = True - ) -> SecretResponse: - """Get a secret by ID. + def get_secret_values(self, secret_id: UUID) -> Dict[str, str]: + """Get the secret values for an existing secret. Args: - secret_id: The ID of the secret to fetch. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. + secret_id: ID of the secret. Returns: - The secret. + The secret values. Raises: - KeyError: If the secret does not exist. + KeyError: if no secret values for the given ID are stored in the + secrets store. RuntimeError: If the AWS Secrets Manager API returns an unexpected error. """ @@ -555,227 +287,57 @@ def get_secret( f"Error fetching secret with ID {secret_id} {e}" ) - # The _convert_aws_secret method raises a KeyError if the - # secret is tied to a workspace or user that no longer exists. Here we + # Convert the AWS secret tags to a metadata dictionary. + metadata: Dict[str, str] = { + tag["Key"]: tag["Value"] + for tag in describe_secret_response["Tags"] + } + + # The _verify_secret_metadata method raises a KeyError if the + # secret is not valid or does not belong to this server. Here we # simply pass the exception up the stack, as if the secret was not found - # in the first place, knowing that it will be cascade-deleted soon. - return self._convert_aws_secret( - tags=describe_secret_response["Tags"], - created=describe_secret_response["CreatedDate"], - updated=describe_secret_response["LastChangedDate"], - values=get_secret_value_response["SecretString"], - hydrate=hydrate, + # in the first place. + self._verify_secret_metadata( + secret_id=secret_id, + metadata=metadata, ) - def list_secrets( - self, secret_filter_model: SecretFilter, hydrate: bool = False - ) -> Page[SecretResponse]: - """List all secrets matching the given filter criteria. - - Note that returned secrets do not include any secret values. To fetch - the secret values, use `get_secret`. + values = get_secret_value_response["SecretString"] - Args: - secret_filter_model: All filter parameters including pagination - params. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - A list of all secrets matching the filter criteria, with pagination - information and sorted according to the filter criteria. The - returned secrets do not include any secret values, only metadata. To - fetch the secret values, use `get_secret` individually with each - secret. - - Raises: - ValueError: If the filter contains an out-of-bounds page number. - RuntimeError: If the AWS Secrets Manager API returns an unexpected - error. - """ - # The AWS Secrets Manager API does not natively support the entire - # range of filtering, sorting and pagination options that ZenML - # supports. The implementation of this method is therefore a bit - # involved. We try to make use of the AWS filtering API as much as - # possible to reduce the number of secrets that we need to fetch, then - # we apply the rest of filtering, sorting and pagination on - # the client side. - - metadata_args: Dict[str, Any] = {} - if secret_filter_model.logical_operator == LogicalOperators.AND: - # We can only filter on the AWS server side if we have an AND - # logical operator. Otherwise, we need to filter on the client - # side. - - for filter in secret_filter_model.list_of_filters: - # The AWS Secrets Manager API only supports prefix matching. We - # take advantage of this to filter as much as possible on the - # AWS server side, and we leave the rest to the client. - if filter.operation not in [ - GenericFilterOps.EQUALS, - GenericFilterOps.STARTSWITH, - ]: - continue - - if filter.column == "id": - metadata_args["secret_id"] = UUID(filter.value) - elif filter.column == "name": - metadata_args["secret_name"] = filter.value - elif filter.column == "scope": - metadata_args["scope"] = SecretScope(filter.value) - elif filter.column == "workspace_id": - metadata_args["workspace"] = UUID(filter.value) - elif filter.column == "user_id": - metadata_args["user"] = UUID(filter.value) - else: - # AWS doesn't support filtering on the created/updated - # timestamps, so we'll have to do that on the client side. - continue - - # The metadata will always contain at least the filter criteria - # required to exclude everything but AWS secrets that belong to the - # current ZenML deployment. - metadata = self._get_secret_metadata(**metadata_args) - aws_filters = self._get_aws_secret_filters(metadata) - - results: List[SecretResponse] = [] + logger.debug(f"Fetched AWS secret: {aws_secret_id}") - try: - # AWS Secrets Manager API pagination is wrapped around the - # `list_secrets` method call. We use it because we need to fetch all - # secrets matching the (partial) filter that we set up. Note that - # the pagination used here has nothing to do with the pagination - # that we do for the method caller. - paginator = self.client.get_paginator("list_secrets") - pages = paginator.paginate( - Filters=aws_filters, - PaginationConfig={ - "PageSize": self.config.list_page_size, - }, - ) + secret_values = json.loads(values) - for page in pages: - for secret in page["SecretList"]: - try: - # NOTE: we do not include the secret values in the - # response. We would need a separate API call to fetch - # them for each secret, which would be very inefficient - # anyway. - secret_model = self._convert_aws_secret( - tags=secret["Tags"], - created=secret["CreatedDate"], - updated=secret["LastChangedDate"], - hydrate=hydrate, - ) - except KeyError: - # The _convert_aws_secret method raises a KeyError - # if the secret is tied to a workspace or user that no - # longer exists. Here we pretend that the secret does - # not exist. - continue - - # Filter again on the client side to cover all filter - # operations. - if not secret_filter_model.secret_matches(secret_model): - continue - results.append(secret_model) - except ClientError as e: - raise RuntimeError(f"Error listing AWS secrets: {e}") - - # Sort the results - sorted_results = secret_filter_model.sort_secrets(results) - - # Paginate the results - total = len(sorted_results) - if total == 0: - total_pages = 1 - else: - total_pages = math.ceil(total / secret_filter_model.size) - - if secret_filter_model.page > total_pages: - raise ValueError( - f"Invalid page {secret_filter_model.page}. The requested page " - f"size is {secret_filter_model.size} and there are a total of " - f"{total} items for this query. The maximum page value " - f"therefore is {total_pages}." + if not isinstance(secret_values, dict): + raise RuntimeError( + f"AWS secret values for secret ID {aws_secret_id} could not be " + "decoded: expected a dictionary." ) - return Page[SecretResponse]( - total=total, - total_pages=total_pages, - items=sorted_results[ - (secret_filter_model.page - 1) - * secret_filter_model.size : secret_filter_model.page - * secret_filter_model.size - ], - index=secret_filter_model.page, - max_size=secret_filter_model.size, - ) - - def update_secret( - self, secret_id: UUID, secret_update: SecretUpdate - ) -> SecretResponse: - """Updates a secret. + return secret_values - Secret values that are specified as `None` in the update that are - present in the existing secret are removed from the existing secret. - Values that are present in both secrets are overwritten. All other - values in both the existing secret and the update are kept (merged). - - If the update includes a change of name or scope, the scoping rules - enforced in the secrets store are used to validate the update: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + def update_secret_values( + self, + secret_id: UUID, + secret_values: Dict[str, str], + ) -> None: + """Updates secret values for an existing secret. Args: secret_id: The ID of the secret to be updated. - secret_update: The update to be applied. - - Returns: - The updated secret. + secret_values: The new secret values. Raises: - EntityExistsError: If the update includes a change of name or - scope and a secret with the same name already exists in the - same scope. + KeyError: if no secret values for the given ID are stored in the + secrets store. RuntimeError: If the AWS Secrets Manager API returns an unexpected error. """ - secret = self.get_secret(secret_id) - - if secret_update.name is not None: - self._validate_aws_secret_name(secret_update.name) - secret.name = secret_update.name - if secret_update.scope is not None: - secret.get_body().scope = secret_update.scope - if secret_update.values is not None: - # Merge the existing values with the update values. - # The values that are set to `None` in the update are removed from - # the existing secret when we call `.secret_values` later. - secret.get_body().values.update(secret_update.values) - - if secret_update.name is not None or secret_update.scope is not None: - # Check if a secret with the same name already exists in the same - # scope. - assert secret.user is not None - secret_exists, msg = self._check_secret_scope( - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace.id, - user=secret.user.id, - exclude_secret_id=secret.id, - ) - if secret_exists: - raise EntityExistsError(msg) - aws_secret_id = self._get_aws_secret_id(secret_id) - secret_value = json.dumps(secret.secret_values) + secret_value = json.dumps(secret_values) # Convert the ZenML secret metadata to AWS tags - metadata = self._get_secret_metadata_for_secret(secret) + metadata = self._get_secret_metadata(secret_id) tags = self._get_aws_secret_tags(metadata) try: @@ -789,49 +351,30 @@ def update_secret( SecretId=aws_secret_id, Tags=tags, ) - # And another call to get the updated secret metadata which - # includes the created and updated timestamps. - describe_secret_response = self.client.describe_secret( - SecretId=aws_secret_id - ) except ClientError as e: + if e.response["Error"]["Code"] == "ResourceNotFoundException": + raise KeyError(f"Secret with ID {secret_id} not found") raise RuntimeError(f"Error updating secret: {e}") - logger.debug("Updated AWS secret: %s", aws_secret_id) - - self._wait_for_secret_to_propagate(aws_secret_id, tags=tags) - - secret_model = SecretResponse( - id=secret_id, - name=secret.name, - body=SecretResponseBody( - user=secret.user, - created=describe_secret_response["CreatedDate"], - updated=describe_secret_response["LastChangedDate"], - scope=secret.scope, - values=secret.secret_values, - ), - metadata=SecretResponseMetadata( - workspace=secret.workspace, - ), - ) - - return secret_model + logger.debug(f"Updated AWS secret: {aws_secret_id}") - def delete_secret(self, secret_id: UUID) -> None: - """Delete a secret. + def delete_secret_values(self, secret_id: UUID) -> None: + """Deletes secret values for an existing secret. Args: - secret_id: The id of the secret to delete. + secret_id: The ID of the secret. Raises: - KeyError: If the secret does not exist. + KeyError: if no secret values for the given ID are stored in the + secrets store. RuntimeError: If the AWS Secrets Manager API returns an unexpected error. """ + aws_secret_id = self._get_aws_secret_id(secret_id) + try: self.client.delete_secret( - SecretId=self._get_aws_secret_id(secret_id), + SecretId=aws_secret_id, # We set this to force immediate deletion of the AWS secret # instead of waiting for the recovery window to expire. ForceDeleteWithoutRecovery=True, @@ -849,3 +392,5 @@ def delete_secret(self, secret_id: UUID) -> None: raise RuntimeError( f"Error deleting secret with ID {secret_id}: {e}" ) + + logger.debug(f"Deleted AWS secret: {aws_secret_id}") diff --git a/src/zenml/zen_stores/secrets_stores/azure_secrets_store.py b/src/zenml/zen_stores/secrets_stores/azure_secrets_store.py index 6bebaf775ff..e63bd75a65a 100644 --- a/src/zenml/zen_stores/secrets_stores/azure_secrets_store.py +++ b/src/zenml/zen_stores/secrets_stores/azure_secrets_store.py @@ -15,16 +15,10 @@ import json import logging -import math -import re -import uuid -from datetime import datetime from typing import ( Any, ClassVar, Dict, - List, - Optional, Type, cast, ) @@ -35,12 +29,9 @@ from azure.keyvault.secrets import SecretClient from pydantic import root_validator -from zenml.analytics.enums import AnalyticsEvent -from zenml.analytics.utils import track_decorator from zenml.enums import ( SecretsStoreType, ) -from zenml.exceptions import EntityExistsError from zenml.integrations.azure import ( AZURE_CONNECTOR_TYPE, AZURE_RESOURCE_TYPE, @@ -49,15 +40,6 @@ AzureAuthenticationMethods, ) from zenml.logger import get_logger -from zenml.models import ( - Page, - SecretFilter, - SecretRequest, - SecretResponse, - SecretResponseBody, - SecretResponseMetadata, - SecretUpdate, -) from zenml.zen_stores.secrets_stores.service_connector_secrets_store import ( ServiceConnectorSecretsStore, ServiceConnectorSecretsStoreConfiguration, @@ -67,8 +49,6 @@ AZURE_ZENML_SECRET_NAME_PREFIX = "zenml" -ZENML_AZURE_SECRET_CREATED_KEY = "zenml_secret_created" -ZENML_AZURE_SECRET_UPDATED_KEY = "zenml_secret_updated" class AzureSecretsStoreConfiguration( @@ -139,29 +119,12 @@ class AzureSecretsStore(ServiceConnectorSecretsStore): `zenml` prefix in the form `zenml-{zenml_secret_uuid}`. This clearly identifies a secret as being managed by ZenML in the Azure console. - * the Secrets Store also makes heavy use of Azure Key Vault secret tags to - store all the metadata associated with a ZenML secret (e.g. the secret name, - scope, user and workspace) and to filter secrets by these metadata. The - `zenml` tag in particular is used to identify and group all secrets that - belong to the same ZenML deployment. + * the Secrets Store also uses Azure Key Vault secret tags to store metadata + associated with a ZenML secret. The `zenml` tag in particular is used to + identify and group all secrets that belong to the same ZenML deployment. * all secret key-values configured in a ZenML secret are stored as a single JSON string value in the Azure Key Vault secret value. - - * when a user or workspace is deleted, the secrets associated with it are - deleted automatically via registered event handlers. - - - Known challenges and limitations: - - * every Azure Key Vault secret has one or more versions. Every update to a - secret creates a new version. The created_on and updated_on timestamps - returned by the Secrets Store API are the timestamps of the latest version - of the secret. This means that we need to fetch the first version of the - secret to get the created_on timestamp. This is not ideal, as we'd need to - fetch all versions for every secret to get the created_on timestamp during - a list operation. So instead we manage the `created` and `updated` - timestamps ourselves and save them as tags in the Azure Key Vault secret. """ config: AzureSecretsStoreConfiguration @@ -216,35 +179,6 @@ def _initialize_client_from_connector(self, client: Any) -> Any: # Secrets # ------ - @staticmethod - def _validate_azure_secret_name(name: str) -> None: - """Validate a secret name. - - Azure secret names must contain only alphanumeric characters and the - character `-`. - - Given that the ZenML secret name is stored as an Azure Key Vault secret - label, we are also limited by the 256 maximum size limitation that Azure - imposes on label values. - - Args: - name: the secret name - - Raises: - ValueError: if the secret name is invalid - """ - if not re.fullmatch(r"[0-9a-zA-Z-]+", name): - raise ValueError( - f"Invalid secret name or namespace '{name}'. Must contain " - f"only alphanumeric characters and the character -." - ) - - if len(name) > 256: - raise ValueError( - f"Invalid secret name or namespace '{name}'. The length is " - f"limited to maximum 256 characters." - ) - @staticmethod def _get_azure_secret_id( secret_id: UUID, @@ -263,105 +197,26 @@ def _get_azure_secret_id( """ return f"{AZURE_ZENML_SECRET_NAME_PREFIX}-{str(secret_id)}" - def _convert_azure_secret( + def store_secret_values( self, - tags: Dict[str, str], - values: Optional[str] = None, - hydrate: bool = False, - ) -> SecretResponse: - """Create a ZenML secret model from data stored in an Azure secret. - - If the Azure secret cannot be converted, the method acts as if the - secret does not exist and raises a KeyError. - - Args: - tags: The Azure secret tags. - values: The Azure secret values encoded as a JSON string - (optional). - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - The ZenML secret. - - Raises: - KeyError: if the Azure secret cannot be converted. - """ - try: - created = datetime.fromisoformat( - tags[ZENML_AZURE_SECRET_CREATED_KEY], - ) - updated = datetime.fromisoformat( - tags[ZENML_AZURE_SECRET_UPDATED_KEY], - ) - except KeyError as e: - raise KeyError( - f"Secret could not be retrieved: missing required metadata: {e}" - ) - - return self._create_secret_from_metadata( - metadata=tags, - created=created, - updated=updated, - values=json.loads(values) if values else None, - hydrate=hydrate, - ) - - @track_decorator(AnalyticsEvent.CREATED_SECRET) - def create_secret(self, secret: SecretRequest) -> SecretResponse: - """Creates a new secret. - - The new secret is also validated against the scoping rules enforced in - the secrets store: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + secret_id: UUID, + secret_values: Dict[str, str], + ) -> None: + """Store secret values for a new secret. Args: - secret: The secret to create. - - Returns: - The newly created secret. + secret_id: ID of the secret. + secret_values: Values for the secret. Raises: - EntityExistsError: If a secret with the same name already exists - in the same scope. - RuntimeError: If the Azure Key Vault API returns an unexpected + RuntimeError: if the Azure Key Vault API returns an unexpected error. """ - self._validate_azure_secret_name(secret.name) - user, workspace = self._validate_user_and_workspace( - secret.user, secret.workspace - ) - - # Check if a secret with the same name already exists in the same - # scope. - secret_exists, msg = self._check_secret_scope( - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace, - user=secret.user, - ) - if secret_exists: - raise EntityExistsError(msg) - - # Generate a new UUID for the secret - secret_id = uuid.uuid4() azure_secret_id = self._get_azure_secret_id(secret_id) - secret_value = json.dumps(secret.secret_values) + secret_value = json.dumps(secret_values) # Use the ZenML secret metadata as Azure tags - metadata = self._get_secret_metadata_for_secret( - secret, secret_id=secret_id - ) - - # We manage the created and updated times ourselves, so we don't need to - # rely on the Azure Key Vault API to set them. - created = datetime.utcnow() - metadata[ZENML_AZURE_SECRET_CREATED_KEY] = created.isoformat() - metadata[ZENML_AZURE_SECRET_UPDATED_KEY] = created.isoformat() + metadata = self._get_secret_metadata(secret_id=secret_id) try: self.client.set_secret( @@ -373,41 +228,21 @@ def create_secret(self, secret: SecretRequest) -> SecretResponse: except HttpResponseError as e: raise RuntimeError(f"Error creating secret: {e}") - logger.debug("Created Azure secret: %s", azure_secret_id) - - secret_model = SecretResponse( - id=secret_id, - name=secret.name, - body=SecretResponseBody( - user=user, - created=created, - updated=created, - scope=secret.scope, - values=secret.secret_values, - ), - metadata=SecretResponseMetadata( - workspace=workspace, - ), - ) - - return secret_model + logger.debug(f"Created Azure secret: {azure_secret_id}") - def get_secret( - self, secret_id: UUID, hydrate: bool = True - ) -> SecretResponse: - """Get a secret by ID. + def get_secret_values(self, secret_id: UUID) -> Dict[str, str]: + """Get the secret values for an existing secret. Args: - secret_id: The ID of the secret to fetch. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. + secret_id: ID of the secret. Returns: - The secret. + The secret values. Raises: - KeyError: If the secret does not exist. - RuntimeError: If the Azure Key Vault API returns an unexpected + KeyError: if no secret values for the given ID are stored in the + secrets store. + RuntimeError: if the Azure Key Vault API returns an unexpected error. """ azure_secret_id = self._get_azure_secret_id(secret_id) @@ -423,184 +258,48 @@ def get_secret( f"Error fetching secret with ID {secret_id} {e}" ) - # The _convert_azure_secret method raises a KeyError if the - # secret is tied to a workspace or user that no longer exists. Here we + # The _verify_secret_metadata method raises a KeyError if the + # secret is not valid or does not belong to this server. Here we # simply pass the exception up the stack, as if the secret was not found - # in the first place, knowing that it will be cascade-deleted soon. + # in the first place. assert azure_secret.properties.tags is not None - return self._convert_azure_secret( - tags=azure_secret.properties.tags, - values=azure_secret.value, - hydrate=hydrate, + self._verify_secret_metadata( + secret_id=secret_id, + metadata=azure_secret.properties.tags, ) - def list_secrets( - self, secret_filter_model: SecretFilter, hydrate: bool = False - ) -> Page[SecretResponse]: - """List all secrets matching the given filter criteria. - - Note that returned secrets do not include any secret values. To fetch - the secret values, use `get_secret`. - - Args: - secret_filter_model: All filter parameters including pagination - params. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - A list of all secrets matching the filter criteria, with pagination - information and sorted according to the filter criteria. The - returned secrets do not include any secret values, only metadata. To - fetch the secret values, use `get_secret` individually with each - secret. - - Raises: - ValueError: If the filter contains an out-of-bounds page number. - RuntimeError: If the Azure Key Vault API returns an unexpected - error. - """ - # The Azure Key Vault API does not natively support any of the - # filtering, sorting or pagination options that ZenML supports. The - # implementation of this method therefore has to fetch all secrets from - # the Key Vault, then apply the filtering, sorting and pagination on - # the client side. - - # The metadata will always contain at least the filter criteria - # required to exclude everything but Azure secrets that belong to the - # current ZenML deployment. - results: List[SecretResponse] = [] - - try: - all_secrets = self.client.list_properties_of_secrets() - for secret_property in all_secrets: - try: - # NOTE: we do not include the secret values in the - # response. We would need a separate API call to fetch - # them for each secret, which would be very inefficient - # anyway. - assert secret_property.tags is not None - secret_model = self._convert_azure_secret( - tags=secret_property.tags, hydrate=hydrate - ) - except KeyError: - # The _convert_azure_secret method raises a KeyError - # if the secret is tied to a workspace or user that no - # longer exists or if it is otherwise not valid. Here we - # pretend that the secret does not exist. - continue - - # Filter the secret on the client side. - if not secret_filter_model.secret_matches(secret_model): - continue - results.append(secret_model) - except HttpResponseError as e: - raise RuntimeError(f"Error listing Azure Key Vault secrets: {e}") - - # Sort the results - sorted_results = secret_filter_model.sort_secrets(results) + values = json.loads(azure_secret.value) if azure_secret.value else {} - # Paginate the results - total = len(sorted_results) - if total == 0: - total_pages = 1 - else: - total_pages = math.ceil(total / secret_filter_model.size) - - if secret_filter_model.page > total_pages: - raise ValueError( - f"Invalid page {secret_filter_model.page}. The requested page " - f"size is {secret_filter_model.size} and there are a total of " - f"{total} items for this query. The maximum page value " - f"therefore is {total_pages}." + if not isinstance(values, dict): + raise RuntimeError( + f"Azure Key Vault secret values for secret {azure_secret_id} " + "could not be retrieved: invalid type for values" ) - return Page[SecretResponse]( - total=total, - total_pages=total_pages, - items=sorted_results[ - (secret_filter_model.page - 1) - * secret_filter_model.size : secret_filter_model.page - * secret_filter_model.size - ], - index=secret_filter_model.page, - max_size=secret_filter_model.size, - ) - - def update_secret( - self, secret_id: UUID, secret_update: SecretUpdate - ) -> SecretResponse: - """Updates a secret. - - Secret values that are specified as `None` in the update that are - present in the existing secret are removed from the existing secret. - Values that are present in both secrets are overwritten. All other - values in both the existing secret and the update are kept (merged). + logger.debug(f"Retrieved Azure secret: {azure_secret_id}") - If the update includes a change of name or scope, the scoping rules - enforced in the secrets store are used to validate the update: + return values - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + def update_secret_values( + self, + secret_id: UUID, + secret_values: Dict[str, str], + ) -> None: + """Updates secret values for an existing secret. Args: secret_id: The ID of the secret to be updated. - secret_update: The update to be applied. - - Returns: - The updated secret. + secret_values: The new secret values. Raises: - EntityExistsError: If the update includes a change of name or - scope and a secret with the same name already exists in the - same scope. - RuntimeError: If the Azure Key Vault API returns an unexpected + RuntimeError: if the Azure Key Vault API returns an unexpected error. """ - secret = self.get_secret(secret_id) - - if secret_update.name is not None: - self._validate_azure_secret_name(secret_update.name) - secret.name = secret_update.name - if secret_update.scope is not None: - secret.get_body().scope = secret_update.scope - if secret_update.values is not None: - # Merge the existing values with the update values. - # The values that are set to `None` in the update are removed from - # the existing secret when we call `.secret_values` later. - secret.get_body().values.update(secret_update.values) - - if secret_update.name is not None or secret_update.scope is not None: - # Check if a secret with the same name already exists in the same - # scope. - assert secret.user is not None - secret_exists, msg = self._check_secret_scope( - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace.id, - user=secret.user.id, - exclude_secret_id=secret.id, - ) - if secret_exists: - raise EntityExistsError(msg) - azure_secret_id = self._get_azure_secret_id(secret_id) - secret_value = json.dumps(secret.secret_values) + secret_value = json.dumps(secret_values) # Convert the ZenML secret metadata to Azure tags - metadata = self._get_secret_metadata_for_secret(secret) - - # We manage the created and updated times ourselves, so we don't need to - # rely on the Azure Key Vault API to set them. - updated = datetime.utcnow() - metadata[ZENML_AZURE_SECRET_UPDATED_KEY] = updated.isoformat() - metadata[ZENML_AZURE_SECRET_CREATED_KEY] = ( - secret.created.isoformat() - if secret.created - else metadata[ZENML_AZURE_SECRET_UPDATED_KEY] - ) + metadata = self._get_secret_metadata(secret_id=secret_id) try: self.client.set_secret( @@ -612,39 +311,25 @@ def update_secret( except HttpResponseError as e: raise RuntimeError(f"Error updating secret {secret_id}: {e}") - logger.debug("Updated Azure secret: %s", azure_secret_id) - - secret_model = SecretResponse( - id=secret_id, - name=secret.name, - body=SecretResponseBody( - user=secret.user, - created=secret.created, - updated=updated, - scope=secret.scope, - values=secret.secret_values, - ), - metadata=SecretResponseMetadata( - workspace=secret.workspace, - ), - ) - - return secret_model + logger.debug(f"Updated Azure secret: {azure_secret_id}") - def delete_secret(self, secret_id: UUID) -> None: - """Delete a secret. + def delete_secret_values(self, secret_id: UUID) -> None: + """Deletes secret values for an existing secret. Args: - secret_id: The id of the secret to delete. + secret_id: The ID of the secret. Raises: - KeyError: If the secret does not exist. - RuntimeError: If the Azure Key Vault API returns an unexpected + KeyError: if no secret values for the given ID are stored in the + secrets store. + RuntimeError: if the Azure Key Vault API returns an unexpected error. """ + azure_secret_id = self._get_azure_secret_id(secret_id) + try: self.client.begin_delete_secret( - self._get_azure_secret_id(secret_id), + azure_secret_id, ).wait() except ResourceNotFoundError: raise KeyError(f"Secret with ID {secret_id} not found") @@ -652,3 +337,5 @@ def delete_secret(self, secret_id: UUID) -> None: raise RuntimeError( f"Error deleting secret with ID {secret_id}: {e}" ) + + logger.debug(f"Deleted Azure secret: {azure_secret_id}") diff --git a/src/zenml/zen_stores/secrets_stores/base_secrets_store.py b/src/zenml/zen_stores/secrets_stores/base_secrets_store.py index ca5d0558e86..739d41b4542 100644 --- a/src/zenml/zen_stores/secrets_stores/base_secrets_store.py +++ b/src/zenml/zen_stores/secrets_stores/base_secrets_store.py @@ -13,37 +13,22 @@ # permissions and limitations under the License. """Base Secrets Store implementation.""" from abc import ABC -from datetime import datetime -from functools import partial from typing import ( TYPE_CHECKING, Any, ClassVar, Dict, Optional, - Tuple, Type, - Union, ) from uuid import UUID from pydantic import BaseModel from zenml.config.secrets_store_config import SecretsStoreConfiguration -from zenml.enums import SecretScope, SecretsStoreType +from zenml.enums import SecretsStoreType from zenml.logger import get_logger -from zenml.models import ( - SecretFilter, - SecretRequest, - SecretResponse, - SecretResponseBody, - SecretResponseMetadata, - UserResponse, - WorkspaceResponse, -) from zenml.utils import source_utils -from zenml.utils.pagination_utils import depaginate -from zenml.zen_stores.enums import StoreEvent from zenml.zen_stores.secrets_stores.secrets_store_interface import ( SecretsStoreInterface, ) @@ -56,13 +41,10 @@ ZENML_SECRET_LABEL = "zenml" ZENML_SECRET_ID_LABEL = "zenml_secret_id" ZENML_SECRET_NAME_LABEL = "zenml_secret_name" -ZENML_SECRET_SCOPE_LABEL = "zenml_secret_scope" -ZENML_SECRET_USER_LABEL = "zenml_secret_user" -ZENML_SECRET_WORKSPACE_LABEL = "zenml_secret_workspace" class BaseSecretsStore(BaseModel, SecretsStoreInterface, ABC): - """Base class for accessing and persisting ZenML secret objects. + """Base class for accessing and persisting ZenML secret values. Attributes: config: The configuration of the secret store. @@ -97,14 +79,6 @@ def __init__( super().__init__(**kwargs) self._zen_store = zen_store - self.zen_store.register_event_handler( - StoreEvent.WORKSPACE_DELETED, self._on_workspace_deleted - ) - - self.zen_store.register_event_handler( - StoreEvent.USER_DELETED, self._on_user_deleted - ) - try: self._initialize() except Exception as e: @@ -167,13 +141,6 @@ def get_store_class( return SqlSecretsStore - if store_config.type == SecretsStoreType.REST: - from zenml.zen_stores.secrets_stores.rest_secrets_store import ( - RestSecretsStore, - ) - - return RestSecretsStore - if store_config.type == SecretsStoreType.AWS: from zenml.zen_stores.secrets_stores.aws_secrets_store import ( AWSSecretsStore, @@ -253,160 +220,6 @@ def zen_store(self) -> "BaseZenStore": raise ValueError("Store not initialized") return self._zen_store - # -------------------- - # Store Event Handlers - # -------------------- - - def _on_workspace_deleted( - self, event: StoreEvent, workspace_id: UUID - ) -> None: - """Handle the deletion of a workspace. - - This method deletes all secrets associated with the given workspace. - - Args: - event: The store event. - workspace_id: The ID of the workspace that was deleted. - """ - logger.debug( - "Handling workspace deletion event for workspace %s", workspace_id - ) - - # Delete all secrets associated with the workspace. - secrets = depaginate( - partial( - self.list_secrets, - secret_filter_model=SecretFilter(workspace_id=workspace_id), - ) - ) - for secret in secrets: - try: - self.delete_secret(secret.id) - except KeyError: - pass - except Exception as e: - logger.warning("Failed to delete secret %s: %s", secret.id, e) - - def _on_user_deleted(self, event: StoreEvent, user_id: UUID) -> None: - """Handle the deletion of a user. - - This method deletes all secrets associated with the given user. - - Args: - event: The store event. - user_id: The ID of the user that was deleted. - """ - logger.debug("Handling user deletion event for user %s", user_id) - - # Delete all secrets associated with the user. - secrets = depaginate( - partial( - self.list_secrets, - secret_filter_model=SecretFilter(user_id=user_id), - ) - ) - for secret in secrets: - try: - self.delete_secret(secret.id) - except KeyError: - pass - except Exception as e: - logger.warning("Failed to delete secret %s: %s", secret.id, e) - - # ------------------------------------------ - # Common helpers for Secrets Store back-ends - # ------------------------------------------ - - def _validate_user_and_workspace( - self, user_id: UUID, workspace_id: UUID - ) -> Tuple[UserResponse, WorkspaceResponse]: - """Validates that the given user and workspace IDs are valid. - - This method calls the ZenML store to validate the user and workspace - IDs. It raises a KeyError exception if either the user or workspace - does not exist. - - Args: - user_id: The ID of the user to validate. - workspace_id: The ID of the workspace to validate. - - Returns: - The user and workspace. - """ - user = self.zen_store.get_user(user_id) - workspace = self.zen_store.get_workspace(workspace_id) - - return user, workspace - - def _check_secret_scope( - self, - secret_name: str, - scope: SecretScope, - workspace: UUID, - user: UUID, - exclude_secret_id: Optional[UUID] = None, - ) -> Tuple[bool, str]: - """Checks if a secret with the given name exists in the given scope. - - This method enforces the following scope rules: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. - - Args: - secret_name: The name of the secret. - scope: The scope of the secret. - workspace: The ID of the workspace to which the secret belongs. - user: The ID of the user to which the secret belongs. - exclude_secret_id: The ID of a secret to exclude from the check - (used e.g. during an update to exclude the existing secret). - - Returns: - True if a secret with the given name already exists in the given - scope, False otherwise, and an error message. - """ - filter = SecretFilter( - name=secret_name, - scope=scope, - page=1, - size=2, # We only need to know if there is more than one secret - ) - - if scope in [SecretScope.WORKSPACE, SecretScope.USER]: - filter.workspace_id = workspace - if scope == SecretScope.USER: - filter.user_id = user - - existing_secrets = self.list_secrets(secret_filter_model=filter).items - if exclude_secret_id is not None: - existing_secrets = [ - s for s in existing_secrets if s.id != exclude_secret_id - ] - - if existing_secrets: - existing_secret_model = existing_secrets[0] - - msg = ( - f"Found an existing {scope.value} scoped secret with the " - f"same '{secret_name}' name" - ) - if scope in [SecretScope.WORKSPACE, SecretScope.USER]: - msg += ( - f" in the same '{existing_secret_model.workspace.name}' " - f"workspace" - ) - if scope == SecretScope.USER: - assert existing_secret_model.user - msg += ( - f" for the same '{existing_secret_model.user.name}' user" - ) - - return True, msg - - return False, "" - # -------------------------------------------------------- # Helpers for Secrets Store back-ends that use tags/labels # -------------------------------------------------------- @@ -414,32 +227,21 @@ def _check_secret_scope( def _get_secret_metadata( self, secret_id: Optional[UUID] = None, - secret_name: Optional[str] = None, - scope: Optional[SecretScope] = None, - workspace: Optional[UUID] = None, - user: Optional[UUID] = None, ) -> Dict[str, str]: """Get a dictionary with metadata that can be used as tags/labels. This utility method can be used with Secrets Managers that can associate metadata (e.g. tags, labels) with a secret. The metadata can - be configured alongside each secret and then used as a filter criteria - when running queries against the backend e.g. to retrieve all the - secrets within a given scope or to retrieve all secrets with a given - name within a given scope. + be configured alongside each secret. NOTE: the ZENML_SECRET_LABEL is always included in the metadata to distinguish ZenML secrets from other secrets that might be stored in the same backend, as well as to distinguish between different ZenML deployments using the same backend. Its value is set to the ZenML - deployment ID, and it should be included in all queries to the backend. + deployment ID. Args: secret_id: Optional secret ID to include in the metadata. - secret_name: Optional secret name to include in the metadata. - scope: Optional scope to include in the metadata. - workspace: Optional workspace ID to include in the metadata. - user: Optional user ID to include in the scope metadata. Returns: Dictionary with secret metadata information. @@ -452,82 +254,27 @@ def _get_secret_metadata( ZENML_SECRET_LABEL: str(self.zen_store.get_store_info().id) } - if secret_id: + # Include the secret ID if provided. + if secret_id is not None: metadata[ZENML_SECRET_ID_LABEL] = str(secret_id) - if secret_name: - metadata[ZENML_SECRET_NAME_LABEL] = secret_name - if scope: - metadata[ZENML_SECRET_SCOPE_LABEL] = scope.value - if workspace: - metadata[ZENML_SECRET_WORKSPACE_LABEL] = str(workspace) - if user: - metadata[ZENML_SECRET_USER_LABEL] = str(user) return metadata - def _get_secret_metadata_for_secret( - self, - secret: Union[SecretRequest, SecretResponse], - secret_id: Optional[UUID] = None, - ) -> Dict[str, str]: - """Get a dictionary with the secrets metadata describing a secret. - - This utility method can be used with Secrets Managers that can - associate metadata (e.g. tags, labels) with a secret. The metadata can - be configured alongside each secret and then used as a filter criteria - when running queries against the backend. - - Args: - secret: The secret to get the metadata for. - secret_id: Optional secret ID to include in the metadata (if not - already included in the secret). - - Returns: - Dictionary with secret metadata information. - """ - if isinstance(secret, SecretRequest): - return self._get_secret_metadata( - secret_id=secret_id, - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace, - user=secret.user, - ) - - return self._get_secret_metadata( - secret_id=secret.id, - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace.id, - user=secret.user.id if secret.user else None, - ) - - def _create_secret_from_metadata( + def _verify_secret_metadata( self, + secret_id: UUID, metadata: Dict[str, str], - created: datetime, - updated: datetime, - values: Optional[Dict[str, str]] = None, - hydrate: bool = False, - ) -> SecretResponse: - """Create a ZenML secret model from metadata stored in the secrets store backend. + ) -> None: + """Verify that the given metadata corresponds to a valid ZenML secret. Args: + secret_id: The ID of the secret. metadata: ZenML secret metadata collected from the backend secret (e.g. from secret tags/labels). - created: The secret creation time. - updated: The secret last updated time. - values: The secret values (optional). - hydrate: Flag deciding whether to hydrate the output model - by including metadata fields in the response. - - Returns: - The ZenML secret. Raises: - KeyError: If the secret does not have the required metadata, if it - is not managed by this ZenML instance or if it is linked to a - user or workspace that no longer exists. + KeyError: If the secret does not have the required metadata or if it + is not managed by this ZenML instance. """ # Double-check that the secret is managed by this ZenML instance. if metadata.get(ZENML_SECRET_LABEL) != str( @@ -537,56 +284,18 @@ def _create_secret_from_metadata( # Recover the ZenML secret fields from the input secret metadata. try: - secret_id = UUID(metadata[ZENML_SECRET_ID_LABEL]) - name = metadata[ZENML_SECRET_NAME_LABEL] - scope = SecretScope(metadata[ZENML_SECRET_SCOPE_LABEL]) - workspace_id = UUID(metadata[ZENML_SECRET_WORKSPACE_LABEL]) - user_id = UUID(metadata[ZENML_SECRET_USER_LABEL]) + stored_secret_id = UUID(metadata[ZENML_SECRET_ID_LABEL]) except KeyError as e: raise KeyError( f"Secret could not be retrieved: missing required metadata: {e}" ) - try: - user, workspace = self._validate_user_and_workspace( - user_id, workspace_id - ) - except KeyError as e: - # The user or workspace associated with the secret no longer - # exists. This can happen if the user or workspace is being - # deleted nearly at the same time as this call. In this case, we - # raise a KeyError exception. The caller should handle this - # exception by assuming that the secret no longer exists. - logger.warning( - f"Secret with ID {secret_id} is associated with a " - f"non-existent user or workspace. Silently ignoring the " - f"secret: {e}" - ) + if secret_id != stored_secret_id: raise KeyError( - f"Secret with ID {secret_id} could not be retrieved: " - f"the secret is associated with a non-existent user or " - f"workspace: {e}" + f"Secret could not be retrieved: secret ID mismatch: " + f"expected {secret_id}, got {stored_secret_id}" ) - secret_model = SecretResponse( - id=secret_id, - name=name, - body=SecretResponseBody( - user=user, - created=created, - updated=updated, - scope=scope, - values=values if values else {}, - ), - metadata=SecretResponseMetadata( - workspace=workspace, - ) - if hydrate - else None, - ) - - return secret_model - class Config: """Pydantic configuration class.""" diff --git a/src/zenml/zen_stores/secrets_stores/gcp_secrets_store.py b/src/zenml/zen_stores/secrets_stores/gcp_secrets_store.py index eb0bca2d952..8c68f50203a 100644 --- a/src/zenml/zen_stores/secrets_stores/gcp_secrets_store.py +++ b/src/zenml/zen_stores/secrets_stores/gcp_secrets_store.py @@ -15,20 +15,13 @@ import json -import math import os -import re -import uuid -from datetime import datetime from typing import ( Any, ClassVar, Dict, - List, Optional, - Tuple, Type, - Union, cast, ) from uuid import UUID @@ -37,12 +30,9 @@ from google.cloud.secretmanager import SecretManagerServiceClient from pydantic import root_validator -from zenml.analytics.enums import AnalyticsEvent -from zenml.analytics.utils import track_decorator from zenml.enums import ( SecretsStoreType, ) -from zenml.exceptions import EntityExistsError from zenml.integrations.gcp import ( GCP_CONNECTOR_TYPE, GCP_RESOURCE_TYPE, @@ -51,15 +41,6 @@ GCPAuthenticationMethods, ) from zenml.logger import get_logger -from zenml.models import ( - Page, - SecretFilter, - SecretRequest, - SecretResponse, - SecretResponseBody, - SecretResponseMetadata, - SecretUpdate, -) from zenml.zen_stores.secrets_stores.service_connector_secrets_store import ( ServiceConnectorSecretsStore, ServiceConnectorSecretsStoreConfiguration, @@ -71,9 +52,6 @@ GCP_ZENML_SECRET_NAME_PREFIX = "zenml" ZENML_GROUP_KEY = "zenml-group-key" ZENML_GCP_SECRET_SCOPE_PATH_SEPARATOR = "-" -ZENML_GCP_DATE_FORMAT_STRING = "%Y-%m-%d-%H-%M-%S" -ZENML_GCP_SECRET_CREATED_KEY = "zenml-secret-created" -ZENML_GCP_SECRET_UPDATED_KEY = "zenml-secret-updated" class GCPSecretsStoreConfiguration(ServiceConnectorSecretsStoreConfiguration): @@ -195,47 +173,6 @@ def parent_name(self) -> str: """ return f"projects/{self.config.project_id}" - def _get_secret_labels( - self, secret: Union[SecretRequest, SecretResponse] - ) -> List[Tuple[str, str]]: - """Return a list of Google secret label values for a given secret. - - Args: - secret: the secret object - - Returns: - A list of Google secret label values - """ - metadata = self._get_secret_metadata_for_secret(secret) - return list(metadata.items()) - - def _validate_gcp_secret_name(self, name: str) -> None: - """Validate a secret name. - - Given that we save secret names as labels, we are also limited by the - limitation that Google imposes on label values: max 63 characters and - must only contain lowercase letters, numerals and the hyphen (-) and - underscore (_) characters. - - Args: - name: the secret name - - Raises: - ValueError: if the secret name is invalid - """ - if not re.fullmatch(r"[a-z0-9_\-]+", name): - raise ValueError( - f"Invalid secret name '{name}'. Must contain " - f"only lowercase alphanumeric characters and the hyphen (-) and " - f"underscore (_) characters." - ) - - if name and len(name) > 63: - raise ValueError( - f"Invalid secret name '{name}'. The length is " - f"limited to maximum 63 characters." - ) - def _get_gcp_secret_name( self, secret_id: UUID, @@ -254,133 +191,24 @@ def _get_gcp_secret_name( """ return f"{GCP_ZENML_SECRET_NAME_PREFIX}-{str(secret_id)}" - def _convert_gcp_secret( + def store_secret_values( self, - labels: Dict[str, str], - values: Optional[Dict[str, str]] = None, - hydrate: bool = False, - ) -> SecretResponse: - """Create a ZenML secret model from data stored in an GCP secret. - - If the GCP secret cannot be converted, the method acts as if the - secret does not exist and raises a KeyError. - - Args: - labels: The GCP secret labels. - values: The GCP secret values. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - The ZenML secret model. - - Raises: - KeyError: if the GCP secret cannot be converted. - """ - # Recover the ZenML secret metadata from the AWS secret tags. - - # The GCP secret labels do not really behave like a dictionary: when - # a key is not found, it does not raise a KeyError, but instead - # returns an empty string. That's why we make this conversion. - label_dict = dict(labels) - - try: - created = datetime.strptime( - label_dict[ZENML_GCP_SECRET_CREATED_KEY], - ZENML_GCP_DATE_FORMAT_STRING, - ) - updated = datetime.strptime( - label_dict[ZENML_GCP_SECRET_UPDATED_KEY], - ZENML_GCP_DATE_FORMAT_STRING, - ) - except KeyError as e: - raise KeyError( - f"Invalid GCP secret: missing required tag '{e}'" - ) from e - - return self._create_secret_from_metadata( - metadata=label_dict, - created=created, - updated=updated, - values=values, - hydrate=hydrate, - ) - - def _get_gcp_filter_string(self, secret_filter_model: SecretFilter) -> str: - """Convert a SecretFilter to a GCP filter string. - - Args: - secret_filter_model: The secret filter model. - - Returns: - The GCP filter string. - """ - operator_map = { - "equals": ":", - } - filter_terms = [] - for filter in secret_filter_model.list_of_filters: - filter_terms.append( - f"{filter.column}{operator_map[filter.operation.value]}{filter.value}" - ) - - return f" {secret_filter_model.logical_operator.name} ".join( - filter_terms - ) - - @track_decorator(AnalyticsEvent.CREATED_SECRET) - def create_secret(self, secret: SecretRequest) -> SecretResponse: - """Create a new secret. - - The new secret is also validated against the scoping rules enforced in - the secrets store: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + secret_id: UUID, + secret_values: Dict[str, str], + ) -> None: + """Store secret values for a new secret. Args: - secret: The secret to create. - - Returns: - The created secret. + secret_id: ID of the secret. + secret_values: Values for the secret. Raises: - RuntimeError: if the secret was unable to be created. - EntityExistsError: If a secret with the same name already exists - in the same scope. + RuntimeError: if the GCP Secrets Manager API returns an unexpected + error. """ - self._validate_gcp_secret_name(secret.name) - - user, workspace = self._validate_user_and_workspace( - secret.user, secret.workspace - ) - - # Check if a secret with the same name already exists in the same - # scope. - secret_exists, msg = self._check_secret_scope( - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace, - user=secret.user, - ) - if secret_exists: - raise EntityExistsError(msg) + secret_value = json.dumps(secret_values) - secret_id = uuid.uuid4() - secret_value = json.dumps(secret.secret_values) - - created = datetime.utcnow().replace(tzinfo=None, microsecond=0) - labels = self._get_secret_metadata_for_secret( - secret=secret, secret_id=secret_id - ) - labels[ZENML_GCP_SECRET_CREATED_KEY] = created.strftime( - ZENML_GCP_DATE_FORMAT_STRING - ) - labels[ZENML_GCP_SECRET_UPDATED_KEY] = created.strftime( - ZENML_GCP_DATE_FORMAT_STRING - ) + labels = self._get_secret_metadata(secret_id=secret_id) try: gcp_secret = self.client.create_secret( @@ -394,7 +222,7 @@ def create_secret(self, secret: SecretRequest) -> SecretResponse: } ) - logger.debug("Created empty parent secret: %s", gcp_secret.name) + logger.debug(f"Created empty GCP parent secret: {gcp_secret.name}") self.client.add_secret_version( request={ @@ -402,42 +230,26 @@ def create_secret(self, secret: SecretRequest) -> SecretResponse: "payload": {"data": secret_value.encode()}, } ) + + logger.debug(f"Added value to GCP secret {gcp_secret.name}") except Exception as e: raise RuntimeError(f"Failed to create secret.: {str(e)}") from e - logger.debug("Added value to secret.") - - return SecretResponse( - id=secret_id, - name=secret.name, - body=SecretResponseBody( - user=user, - created=created, - updated=created, - scope=secret.scope, - values=secret.secret_values, - ), - metadata=SecretResponseMetadata( - workspace=workspace, - ), - ) + logger.debug(f"Created GCP secret {gcp_secret.name}") - def get_secret( - self, secret_id: UUID, hydrate: bool = True - ) -> SecretResponse: - """Get a secret by ID. + def get_secret_values(self, secret_id: UUID) -> Dict[str, str]: + """Get the secret values for an existing secret. Args: - secret_id: The ID of the secret to fetch. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. + secret_id: ID of the secret. Returns: - The secret. + The secret values. Raises: - KeyError: If the secret does not exist. - RuntimeError: If the GCP Secrets Manager API returns an unexpected + KeyError: if no secret values for the given ID are stored in the + secrets store. + RuntimeError: if the GCP Secrets Manager API returns an unexpected error. """ gcp_secret_name = self.client.secret_path( @@ -452,189 +264,67 @@ def get_secret( ) except google_exceptions.NotFound as e: raise KeyError( - f"Can't find the specified secret for secret_id '{secret_id}': {str(e)}" + f"Can't find the specified secret for secret_id '{secret_id}': " + f"{str(e)}" ) from e except Exception as e: raise RuntimeError( f"Error fetching secret with ID {secret_id} {e}" ) - secret_values = json.loads( - secret_version_values.payload.data.decode("UTF-8") + # The GCP secret labels do not really behave like a dictionary: when + # a key is not found, it does not raise a KeyError, but instead + # returns an empty string. That's why we make this conversion. + metadata = dict(secret.labels) + + # The _verify_secret_metadata method raises a KeyError if the + # secret is not valid or does not belong to this server. Here we + # simply pass the exception up the stack, as if the secret was not found + # in the first place. + self._verify_secret_metadata( + secret_id=secret_id, + metadata=metadata, ) - return self._convert_gcp_secret( - labels=secret.labels, - values=secret_values, - hydrate=hydrate, + secret_values = json.loads( + secret_version_values.payload.data.decode("UTF-8") ) - def list_secrets( - self, secret_filter_model: SecretFilter, hydrate: bool = False - ) -> Page[SecretResponse]: - """List all secrets matching the given filter criteria. - - Note that returned secrets do not include any secret values. To fetch - the secret values, use `get_secret`. - - Args: - secret_filter_model: The filter criteria. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - A list of all secrets matching the filter criteria, with pagination - information and sorted according to the filter criteria. The - returned secrets do not include any secret values, only metadata. To - fetch the secret values, use `get_secret` individually with each - secret. - - Raises: - ValueError: If the filter contains an out-of-bounds page number. - RuntimeError: If the Azure Key Vault API returns an unexpected - error. - """ - # TODO: implement filter method for server-side filtering - # convert the secret_filter_model to a GCP filter string - gcp_filters = "" - # gcp_filters = self._get_gcp_filter_string( - # secret_filter_model=secret_filter_model - # ) - - try: - # get all the secrets and their labels (for their names) from GCP - # (use the filter string to limit what doesn't match the filter) - secrets = [] - for secret in self.client.list_secrets( - request={ - "parent": self.parent_name, - "filter": gcp_filters, - } - ): - try: - secrets.append( - self._convert_gcp_secret( - secret.labels, hydrate=hydrate - ) - ) - except KeyError: - # keep going / ignore if this secret version doesn't exist - # or isn't a ZenML secret - continue - except Exception as e: - raise RuntimeError(f"Error listing GCP secrets: {e}") from e - - # do client filtering for anything not covered by the filter string - filtered_secrets = [ - secret - for secret in secrets - if secret_filter_model.secret_matches(secret) - ] - - # sort the results - sorted_results = secret_filter_model.sort_secrets(filtered_secrets) - - # paginate the results - secret_count = len(sorted_results) - if secret_count == 0: - total_pages = 1 - else: - total_pages = math.ceil(secret_count / secret_filter_model.size) - if secret_filter_model.page > total_pages: - raise ValueError( - f"Invalid page {secret_filter_model.page}. The requested page " - f"size is {secret_filter_model.size} and there are a total of " - f"{secret_count} items for this query. The maximum page value " - f"therefore is {total_pages}." + if not isinstance(secret_values, dict): + raise RuntimeError( + f"Google secret values for secret ID {gcp_secret_name} could " + "not be decoded: expected a dictionary." ) - return Page[SecretResponse]( - total=secret_count, - total_pages=total_pages, - items=sorted_results[ - (secret_filter_model.page - 1) - * secret_filter_model.size : secret_filter_model.page - * secret_filter_model.size - ], - index=secret_filter_model.page, - max_size=secret_filter_model.size, - ) - - def update_secret( - self, secret_id: UUID, secret_update: SecretUpdate - ) -> SecretResponse: - """Update a secret. - Secret values that are specified as `None` in the update that are - present in the existing secret are removed from the existing secret. - Values that are present in both secrets are overwritten. All other - values in both the existing secret and the update are kept (merged). + logger.debug(f"Fetched GCP secret: {gcp_secret_name}") - If the update includes a change of name or scope, the scoping rules - enforced in the secrets store are used to validate the update: + return secret_values - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + def update_secret_values( + self, + secret_id: UUID, + secret_values: Dict[str, str], + ) -> None: + """Updates secret values for an existing secret. Args: - secret_id: The ID of the secret to update. - secret_update: The update to apply to the secret. - - Returns: - The updated secret. + secret_id: The ID of the secret to be updated. + secret_values: The new secret values. Raises: - RuntimeError: If the secret update is invalid. - EntityExistsError: If the update includes a change of name or - scope and a secret with the same name already exists in the - same scope. + RuntimeError: if the GCP Secrets Manager API returns an unexpected + error. """ - secret = self.get_secret(secret_id=secret_id) gcp_secret_name = self.client.secret_path( self.config.project_id, self._get_gcp_secret_name(secret_id=secret_id), ) - if secret_update.name is not None: - self._validate_gcp_secret_name(secret_update.name) - secret.name = secret_update.name - if secret_update.scope is not None: - secret.get_body().scope = secret_update.scope - if secret_update.values is not None: - # Merge the existing values with the update values. - # The values that are set to `None` in the update are removed from - # the existing secret when we call `.secret_values` later. - secret.get_body().values.update(secret_update.values) - - if secret_update.name is not None or secret_update.scope is not None: - # Check if a secret with the same name already exists in the same - # scope. - assert secret.user is not None - secret_exists, msg = self._check_secret_scope( - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace.id, - user=secret.user.id, - exclude_secret_id=secret.id, - ) - if secret_exists: - raise EntityExistsError(msg) - # Convert the ZenML secret metadata to GCP labels - updated = datetime.utcnow().replace(tzinfo=None, microsecond=0) - metadata = self._get_secret_metadata_for_secret(secret) - metadata[ZENML_GCP_SECRET_UPDATED_KEY] = updated.strftime( - ZENML_GCP_DATE_FORMAT_STRING - ) - metadata[ZENML_GCP_SECRET_CREATED_KEY] = ( - secret.created.strftime(ZENML_GCP_DATE_FORMAT_STRING) - if secret.created - else metadata[ZENML_GCP_SECRET_UPDATED_KEY] - ) + metadata = self._get_secret_metadata(secret_id) try: - # UPDATE THE SECRET METADATA + # Update the secret metadata update_secret = { "name": gcp_secret_name, "labels": metadata, @@ -646,8 +336,8 @@ def update_secret( "update_mask": update_mask, } ) - # ADD A NEW SECRET VERSION - secret_value = json.dumps(secret.secret_values) + # Add a new secret version + secret_value = json.dumps(secret_values) self.client.add_secret_version( request={ "parent": gcp_updated_secret.name, @@ -657,32 +347,19 @@ def update_secret( except Exception as e: raise RuntimeError(f"Error updating secret: {e}") from e - logger.debug("Updated GCP secret: %s", gcp_secret_name) - - return SecretResponse( - id=secret_id, - name=secret.name, - body=SecretResponseBody( - user=secret.user, - created=secret.created, - updated=updated, - scope=secret.scope, - values=secret.secret_values, - ), - metadata=SecretResponseMetadata( - workspace=secret.workspace, - ), - ) + logger.debug(f"Updated GCP secret: {gcp_secret_name}") - def delete_secret(self, secret_id: UUID) -> None: - """Delete a secret. + def delete_secret_values(self, secret_id: UUID) -> None: + """Deletes secret values for an existing secret. Args: - secret_id: The ID of the secret to delete. + secret_id: The ID of the secret. Raises: - KeyError: If the secret could not be found. - RuntimeError: If the secret could not be deleted. + KeyError: if no secret values for the given ID are stored in the + secrets store. + RuntimeError: if the GCP Secrets Manager API returns an unexpected + error. """ gcp_secret_name = self.client.secret_path( self.config.project_id, @@ -695,3 +372,5 @@ def delete_secret(self, secret_id: UUID) -> None: raise KeyError(f"Secret with ID {secret_id} not found") except Exception as e: raise RuntimeError(f"Failed to delete secret: {str(e)}") from e + + logger.debug(f"Deleted GCP secret: {gcp_secret_name}") diff --git a/src/zenml/zen_stores/secrets_stores/hashicorp_secrets_store.py b/src/zenml/zen_stores/secrets_stores/hashicorp_secrets_store.py index 67a770a6215..6eb5bf4121c 100644 --- a/src/zenml/zen_stores/secrets_stores/hashicorp_secrets_store.py +++ b/src/zenml/zen_stores/secrets_stores/hashicorp_secrets_store.py @@ -13,16 +13,9 @@ # permissions and limitations under the License. """HashiCorp Vault Secrets Store implementation.""" -import logging -import math -import re -import uuid -from datetime import datetime from typing import ( - Any, ClassVar, Dict, - List, Optional, Type, ) @@ -35,23 +28,11 @@ ) from pydantic import SecretStr -from zenml.analytics.enums import AnalyticsEvent -from zenml.analytics.utils import track_decorator from zenml.config.secrets_store_config import SecretsStoreConfiguration from zenml.enums import ( SecretsStoreType, ) -from zenml.exceptions import EntityExistsError from zenml.logger import get_logger -from zenml.models import ( - Page, - SecretFilter, - SecretRequest, - SecretResponse, - SecretResponseBody, - SecretResponseMetadata, - SecretUpdate, -) from zenml.zen_stores.secrets_stores.base_secrets_store import ( BaseSecretsStore, ) @@ -62,8 +43,6 @@ HVAC_ZENML_SECRET_NAME_PREFIX = "zenml" ZENML_VAULT_SECRET_VALUES_KEY = "zenml_secret_values" ZENML_VAULT_SECRET_METADATA_KEY = "zenml_secret_metadata" -ZENML_VAULT_SECRET_CREATED_KEY = "zenml_secret_created" -ZENML_VAULT_SECRET_UPDATED_KEY = "zenml_secret_updated" class HashiCorpVaultSecretsStoreConfiguration(SecretsStoreConfiguration): @@ -108,32 +87,11 @@ class HashiCorpVaultSecretsStore(BaseSecretsStore): * the name/ID of an HashiCorp Vault secret is derived from the ZenML secret UUID and a `zenml` prefix in the form `zenml/{zenml_secret_uuid}`. This clearly identifies a secret as being managed by ZenML in the HashiCorp Vault - server. This also allows use to reduce the scope of `list_secrets` to cover - only secrets managed by ZenML by using `zenml/` as the path prefix. + server. * given that HashiCorp Vault secrets do not support attaching arbitrary metadata in the form of label or tags, we store the entire ZenML secret - metadata (e.g. name, scope, etc.) alongside the secret values in the - HashiCorp Vault secret value. - - * when a user or workspace is deleted, the secrets associated with it are - deleted automatically via registered event handlers. - - Known challenges and limitations: - - * HashiCorp Vault secrets do not support filtering secrets by metadata - attached to secrets in the form of label or tags. This means that we cannot - filter secrets server-side based on their metadata (e.g. name, scope, etc.). - Instead, we have to retrieve all ZenML managed secrets and filter them - client-side. - - * HashiCorp Vault secrets are versioned. This means that when a secret is - updated, a new version is created which has its own creation timestamp. - Furthermore, older secret versions are deleted automatically after a certain - configurable number of versions is reached. To work around this, we also - manage `created` and `updated` timestamps here and store them in the secret - value itself. - + metadata alongside the secret values in the HashiCorp Vault secret value. Attributes: config: The configuration of the HashiCorp Vault secrets store. @@ -196,25 +154,6 @@ def _initialize(self) -> None: # Secrets # ------ - @staticmethod - def _validate_vault_secret_name(name: str) -> None: - """Validate a secret name. - - HashiCorp Vault secret names must contain only alphanumeric characters - and the characters _+=.@-/. - - Args: - name: the secret name - - Raises: - ValueError: if the secret name is invalid - """ - if not re.fullmatch(r"[a-zA-Z0-9_+=\.@\-/]*", name): - raise ValueError( - f"Invalid secret name or namespace '{name}'. Must contain " - f"only alphanumeric characters and the characters _+=.@-/." - ) - @staticmethod def _get_vault_secret_id( secret_id: UUID, @@ -233,107 +172,32 @@ def _get_vault_secret_id( """ return f"{HVAC_ZENML_SECRET_NAME_PREFIX}/{str(secret_id)}" - def _convert_vault_secret( + def store_secret_values( self, - vault_secret: Dict[str, Any], - hydrate: bool = False, - ) -> SecretResponse: - """Create a ZenML secret model from data stored in an HashiCorp Vault secret. - - If the HashiCorp Vault secret cannot be converted, the method acts as if - the secret does not exist and raises a KeyError. - - Args: - vault_secret: The HashiCorp Vault secret in JSON form. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - The ZenML secret. - - Raises: - KeyError: if the HashiCorp Vault secret cannot be converted. - """ - try: - metadata = vault_secret[ZENML_VAULT_SECRET_METADATA_KEY] - values = vault_secret[ZENML_VAULT_SECRET_VALUES_KEY] - created = datetime.fromisoformat( - vault_secret[ZENML_VAULT_SECRET_CREATED_KEY], - ) - updated = datetime.fromisoformat( - vault_secret[ZENML_VAULT_SECRET_UPDATED_KEY], - ) - except (KeyError, ValueError) as e: - raise KeyError( - f"Secret could not be retrieved: missing required metadata: {e}" - ) - - return self._create_secret_from_metadata( - metadata=metadata, - created=created, - updated=updated, - values=values, - hydrate=hydrate, - ) - - @track_decorator(AnalyticsEvent.CREATED_SECRET) - def create_secret(self, secret: SecretRequest) -> SecretResponse: - """Creates a new secret. - - The new secret is also validated against the scoping rules enforced in - the secrets store: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + secret_id: UUID, + secret_values: Dict[str, str], + ) -> None: + """Store secret values for a new secret. Args: - secret: The secret to create. - - Returns: - The newly created secret. + secret_id: ID of the secret. + secret_values: Values for the secret. Raises: - EntityExistsError: If a secret with the same name already exists - in the same scope. RuntimeError: If the HashiCorp Vault API returns an unexpected error. """ - self._validate_vault_secret_name(secret.name) - user, workspace = self._validate_user_and_workspace( - secret.user, secret.workspace - ) - - # Check if a secret with the same name already exists in the same - # scope. - secret_exists, msg = self._check_secret_scope( - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace, - user=secret.user, - ) - if secret_exists: - raise EntityExistsError(msg) - - # Generate a new UUID for the secret - secret_id = uuid.uuid4() vault_secret_id = self._get_vault_secret_id(secret_id) - metadata = self._get_secret_metadata_for_secret( - secret, secret_id=secret_id - ) + metadata = self._get_secret_metadata(secret_id=secret_id) - created = datetime.utcnow() try: self.client.secrets.kv.v2.create_or_update_secret( path=vault_secret_id, # Store the ZenML secret metadata alongside the secret values secret={ - ZENML_VAULT_SECRET_VALUES_KEY: secret.secret_values, + ZENML_VAULT_SECRET_VALUES_KEY: secret_values, ZENML_VAULT_SECRET_METADATA_KEY: metadata, - ZENML_VAULT_SECRET_CREATED_KEY: created.isoformat(), - ZENML_VAULT_SECRET_UPDATED_KEY: created.isoformat(), }, # Do not allow overwriting an existing secret cas=0, @@ -341,40 +205,20 @@ def create_secret(self, secret: SecretRequest) -> SecretResponse: except VaultError as e: raise RuntimeError(f"Error creating secret: {e}") - logger.debug("Created HashiCorp Vault secret: %s", vault_secret_id) - - secret_model = SecretResponse( - id=secret_id, - name=secret.name, - body=SecretResponseBody( - user=user, - created=created, - updated=created, - scope=secret.scope, - values=secret.secret_values, - ), - metadata=SecretResponseMetadata( - workspace=workspace, - ), - ) - - return secret_model + logger.debug(f"Created HashiCorp Vault secret: {vault_secret_id}") - def get_secret( - self, secret_id: UUID, hydrate: bool = True - ) -> SecretResponse: - """Get a secret by ID. + def get_secret_values(self, secret_id: UUID) -> Dict[str, str]: + """Get the secret values for an existing secret. Args: - secret_id: The ID of the secret to fetch. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. + secret_id: ID of the secret. Returns: - The secret. + The secret values. Raises: - KeyError: If the secret does not exist. + KeyError: if no secret values for the given ID are stored in the + secrets store. RuntimeError: If the HashiCorp Vault API returns an unexpected error. """ @@ -395,213 +239,62 @@ def get_secret( f"Error fetching secret with ID {secret_id} {e}" ) - # The _convert_vault_secret method raises a KeyError if the - # secret is tied to a workspace or user that no longer exists. Here we - # simply pass the exception up the stack, as if the secret was not found - # in the first place, knowing that it will be cascade-deleted soon. - return self._convert_vault_secret( - vault_secret, - hydrate=hydrate, - ) - - def list_secrets( - self, secret_filter_model: SecretFilter, hydrate: bool = False - ) -> Page[SecretResponse]: - """List all secrets matching the given filter criteria. - - Note that returned secrets do not include any secret values. To fetch - the secret values, use `get_secret`. - - Args: - secret_filter_model: All filter parameters including pagination - params. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - A list of all secrets matching the filter criteria, with pagination - information and sorted according to the filter criteria. The - returned secrets do not include any secret values, only metadata. To - fetch the secret values, use `get_secret` individually with each - secret. - - Raises: - ValueError: If the filter contains an out-of-bounds page number. - RuntimeError: If the HashiCorp Vault API returns an unexpected - error. - """ - # The HashiCorp Vault API does not natively support any of the - # filtering, sorting or pagination options that ZenML supports. The - # implementation of this method therefore has to fetch all secrets from - # the Key Vault, then apply the filtering, sorting and pagination on - # the client side. - - results: List[SecretResponse] = [] - try: - # List all ZenML secrets in the Vault - all_secrets = ( - self.client.secrets.kv.v2.list_secrets( - path=HVAC_ZENML_SECRET_NAME_PREFIX - ) - .get("data", {}) - .get("keys", []) + metadata = vault_secret[ZENML_VAULT_SECRET_METADATA_KEY] + values = vault_secret[ZENML_VAULT_SECRET_VALUES_KEY] + except (KeyError, ValueError) as e: + raise KeyError( + f"Secret could not be retrieved: missing required metadata: {e}" ) - except InvalidPath: - # no secrets created yet - pass - except VaultError as e: - raise RuntimeError(f"Error listing HashiCorp Vault secrets: {e}") - else: - # Convert the Vault secrets to ZenML secrets - for secret_uuid in all_secrets: - vault_secret_id = ( - f"{HVAC_ZENML_SECRET_NAME_PREFIX}/{secret_uuid}" - ) - try: - vault_secret = ( - self.client.secrets.kv.v2.read_secret( - path=vault_secret_id - ) - .get("data", {}) - .get("data", {}) - ) - except (InvalidPath, VaultError) as e: - logging.warning( - f"Error fetching secret with ID {vault_secret_id}: {e}", - ) - continue - - try: - secret_model = self._convert_vault_secret( - vault_secret, - hydrate=hydrate, - ) - except KeyError as e: - # The _convert_vault_secret method raises a KeyError - # if the secret is tied to a workspace or user that no - # longer exists or if it is otherwise not valid. Here we - # pretend that the secret does not exist. - logging.warning( - f"Error fetching secret with ID {vault_secret_id}: {e}", - ) - continue - - # Filter the secret on the client side. - if not secret_filter_model.secret_matches(secret_model): - continue - - # Remove the secret values from the response - secret_model.get_body().values = {} - results.append(secret_model) - - # Sort the results - sorted_results = secret_filter_model.sort_secrets(results) - - # Paginate the results - total = len(sorted_results) - if total == 0: - total_pages = 1 - else: - total_pages = math.ceil(total / secret_filter_model.size) - - if secret_filter_model.page > total_pages: - raise ValueError( - f"Invalid page {secret_filter_model.page}. The requested page " - f"size is {secret_filter_model.size} and there are a total of " - f"{total} items for this query. The maximum page value " - f"therefore is {total_pages}." + + if not isinstance(values, dict) or not isinstance(metadata, dict): + raise RuntimeError( + f"HashiCorp Vault secret values for secret {vault_secret_id} " + "could not be retrieved: invalid type for metadata or values" ) - return Page[SecretResponse]( - total=total, - total_pages=total_pages, - items=sorted_results[ - (secret_filter_model.page - 1) - * secret_filter_model.size : secret_filter_model.page - * secret_filter_model.size - ], - index=secret_filter_model.page, - max_size=secret_filter_model.size, + # The _verify_secret_metadata method raises a KeyError if the + # secret is not valid or does not belong to this server. Here we + # simply pass the exception up the stack, as if the secret was not found + # in the first place. + self._verify_secret_metadata( + secret_id=secret_id, + metadata=metadata, ) - def update_secret( - self, secret_id: UUID, secret_update: SecretUpdate - ) -> SecretResponse: - """Updates a secret. + logger.debug(f"Fetched HashiCorp Vault secret: {vault_secret_id}") - Secret values that are specified as `None` in the update that are - present in the existing secret are removed from the existing secret. - Values that are present in both secrets are overwritten. All other - values in both the existing secret and the update are kept (merged). + return values - If the update includes a change of name or scope, the scoping rules - enforced in the secrets store are used to validate the update: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + def update_secret_values( + self, + secret_id: UUID, + secret_values: Dict[str, str], + ) -> None: + """Updates secret values for an existing secret. Args: secret_id: The ID of the secret to be updated. - secret_update: The update to be applied. - - Returns: - The updated secret. + secret_values: The new secret values. Raises: - KeyError: If the secret does not exist. - EntityExistsError: If the update includes a change of name or - scope and a secret with the same name already exists in the - same scope. + KeyError: if no secret values for the given ID are stored in the + secrets store. RuntimeError: If the HashiCorp Vault API returns an unexpected error. """ - secret = self.get_secret(secret_id) - - if secret_update.name is not None: - self._validate_vault_secret_name(secret_update.name) - secret.name = secret_update.name - if secret_update.scope is not None: - secret.get_body().scope = secret_update.scope - if secret_update.values is not None: - # Merge the existing values with the update values. - # The values that are set to `None` in the update are removed from - # the existing secret when we call `.secret_values` later. - secret.get_body().values.update(secret_update.values) - - if secret_update.name is not None or secret_update.scope is not None: - # Check if a secret with the same name already exists in the same - # scope. - assert secret.user is not None - secret_exists, msg = self._check_secret_scope( - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace.id, - user=secret.user.id, - exclude_secret_id=secret.id, - ) - if secret_exists: - raise EntityExistsError(msg) - vault_secret_id = self._get_vault_secret_id(secret_id) # Convert the ZenML secret metadata to HashiCorp Vault tags - metadata = self._get_secret_metadata_for_secret(secret) + metadata = self._get_secret_metadata(secret_id=secret_id) - updated = datetime.utcnow() try: self.client.secrets.kv.v2.create_or_update_secret( path=vault_secret_id, # Store the ZenML secret metadata alongside the secret values secret={ - ZENML_VAULT_SECRET_VALUES_KEY: secret.secret_values, + ZENML_VAULT_SECRET_VALUES_KEY: secret_values, ZENML_VAULT_SECRET_METADATA_KEY: metadata, - ZENML_VAULT_SECRET_CREATED_KEY: secret.created.isoformat() - if secret.created - else updated.isoformat(), - ZENML_VAULT_SECRET_UPDATED_KEY: updated.isoformat(), }, ) except InvalidPath: @@ -609,39 +302,25 @@ def update_secret( except VaultError as e: raise RuntimeError(f"Error updating secret {secret_id}: {e}") - logger.debug("Updated HashiCorp Vault secret: %s", vault_secret_id) - - secret_model = SecretResponse( - id=secret_id, - name=secret.name, - body=SecretResponseBody( - user=secret.user, - created=secret.created, - updated=updated, - scope=secret.scope, - values=secret.secret_values, - ), - metadata=SecretResponseMetadata( - workspace=secret.workspace, - ), - ) + logger.debug(f"Updated HashiCorp Vault secret: {vault_secret_id}") - return secret_model - - def delete_secret(self, secret_id: UUID) -> None: - """Delete a secret. + def delete_secret_values(self, secret_id: UUID) -> None: + """Deletes secret values for an existing secret. Args: - secret_id: The id of the secret to delete. + secret_id: The ID of the secret. Raises: - KeyError: If the secret does not exist. + KeyError: if no secret values for the given ID are stored in the + secrets store. RuntimeError: If the HashiCorp Vault API returns an unexpected error. """ + vault_secret_id = self._get_vault_secret_id(secret_id) + try: self.client.secrets.kv.v2.delete_metadata_and_all_versions( - path=self._get_vault_secret_id(secret_id), + path=vault_secret_id, ) except InvalidPath: raise KeyError(f"Secret with ID {secret_id} does not exist.") @@ -649,3 +328,5 @@ def delete_secret(self, secret_id: UUID) -> None: raise RuntimeError( f"Error deleting secret with ID {secret_id}: {e}" ) + + logger.debug(f"Deleted HashiCorp Vault secret: {vault_secret_id}") diff --git a/src/zenml/zen_stores/secrets_stores/rest_secrets_store.py b/src/zenml/zen_stores/secrets_stores/rest_secrets_store.py deleted file mode 100644 index a34a1c2df9a..00000000000 --- a/src/zenml/zen_stores/secrets_stores/rest_secrets_store.py +++ /dev/null @@ -1,266 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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. -"""REST Secrets Store implementation.""" - -from typing import ( - TYPE_CHECKING, - Any, - ClassVar, - Type, -) -from uuid import UUID - -from zenml.config.secrets_store_config import SecretsStoreConfiguration -from zenml.constants import SECRETS -from zenml.enums import ( - SecretsStoreType, -) -from zenml.exceptions import ( - IllegalOperationError, -) -from zenml.logger import get_logger -from zenml.models import ( - Page, - SecretFilter, - SecretRequest, - SecretResponse, - SecretUpdate, -) -from zenml.zen_stores.secrets_stores.base_secrets_store import ( - BaseSecretsStore, -) - -logger = get_logger(__name__) - -if TYPE_CHECKING: - from zenml.zen_stores.base_zen_store import BaseZenStore - from zenml.zen_stores.rest_zen_store import RestZenStore - - -class RestSecretsStoreConfiguration(SecretsStoreConfiguration): - """REST secrets store configuration. - - Attributes: - type: The type of the store. - """ - - type: SecretsStoreType = SecretsStoreType.REST - - class Config: - """Pydantic configuration class.""" - - # Don't validate attributes when assigning them. This is necessary - # because the certificate attributes can be expanded to the contents - # of the certificate files. - validate_assignment = False - # Forbid extra attributes set in the class. - extra = "forbid" - - -class RestSecretsStore(BaseSecretsStore): - """Secrets store implementation that uses the REST ZenML store as a backend. - - This secrets store piggybacks on the REST ZenML store. It uses the same - REST client configuration as the REST ZenML store. - - Attributes: - config: The configuration of the REST secrets store. - TYPE: The type of the store. - CONFIG_TYPE: The type of the store configuration. - """ - - config: RestSecretsStoreConfiguration - TYPE: ClassVar[SecretsStoreType] = SecretsStoreType.REST - CONFIG_TYPE: ClassVar[ - Type[SecretsStoreConfiguration] - ] = RestSecretsStoreConfiguration - - def __init__( - self, - zen_store: "BaseZenStore", - **kwargs: Any, - ) -> None: - """Create and initialize the REST secrets store. - - Args: - zen_store: The ZenML store that owns this REST secrets store. - **kwargs: Additional keyword arguments to pass to the Pydantic - constructor. - - Raises: - IllegalOperationError: If the ZenML store to which this secrets - store belongs is not a REST ZenML store. - """ - from zenml.zen_stores.rest_zen_store import RestZenStore - - if not isinstance(zen_store, RestZenStore): - raise IllegalOperationError( - "The REST secrets store can only be used with the REST ZenML " - "store." - ) - super().__init__(zen_store, **kwargs) - - @property - def zen_store(self) -> "RestZenStore": - """The ZenML store that this REST secrets store is using as a back-end. - - Returns: - The ZenML store that this REST secrets store is using as a back-end. - - Raises: - ValueError: If the store is not initialized. - """ - from zenml.zen_stores.rest_zen_store import RestZenStore - - if not self._zen_store: - raise ValueError("Store not initialized") - assert isinstance(self._zen_store, RestZenStore) - return self._zen_store - - # ==================================== - # Secrets Store interface implementation - # ==================================== - - # -------------------------------- - # Initialization and configuration - # -------------------------------- - - def _initialize(self) -> None: - """Initialize the secrets REST store.""" - logger.debug("Initializing RestSecretsStore") - - # Nothing else to do here, the REST ZenML store back-end is already - # initialized - - # ------ - # Secrets - # ------ - - def create_secret(self, secret: SecretRequest) -> SecretResponse: - """Creates a new secret. - - The new secret is also validated against the scoping rules enforced in - the secrets store: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. - - Args: - secret: The secret to create. - - Returns: - The newly created secret. - """ - return self.zen_store._create_workspace_scoped_resource( - resource=secret, - route=SECRETS, - response_model=SecretResponse, - ) - - def get_secret( - self, secret_id: UUID, hydrate: bool = True - ) -> SecretResponse: - """Get a secret by ID. - - Args: - secret_id: The ID of the secret to fetch. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - The secret. - """ - return self.zen_store._get_resource( - resource_id=secret_id, - route=SECRETS, - response_model=SecretResponse, - params={"hydrate": hydrate}, - ) - - def list_secrets( - self, secret_filter_model: SecretFilter, hydrate: bool = False - ) -> Page[SecretResponse]: - """List all secrets matching the given filter criteria. - - Note that returned secrets do not include any secret values. To fetch - the secret values, use `get_secret`. - - Args: - secret_filter_model: All filter parameters including pagination - params. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - A list of all secrets matching the filter criteria, with pagination - information and sorted according to the filter criteria. The - returned secrets do not include any secret values, only metadata. To - fetch the secret values, use `get_secret` individually with each - secret. - """ - return self.zen_store._list_paginated_resources( - route=SECRETS, - response_model=SecretResponse, - filter_model=secret_filter_model, - params={"hydrate": hydrate}, - ) - - def update_secret( - self, secret_id: UUID, secret_update: SecretUpdate - ) -> SecretResponse: - """Updates a secret. - - Secret values that are specified as `None` in the update that are - present in the existing secret are removed from the existing secret. - Values that are present in both secrets are overwritten. All other - values in both the existing secret and the update are kept (merged). - - If the update includes a change of name or scope, the scoping rules - enforced in the secrets store are used to validate the update: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. - - Args: - secret_id: The ID of the secret to be updated. - secret_update: The update to be applied. - - Returns: - The updated secret. - """ - return self.zen_store._update_resource( - resource_id=secret_id, - resource_update=secret_update, - route=SECRETS, - response_model=SecretResponse, - # The default endpoint behavior is to replace all secret values - # with the values in the update. We want to merge the values - # instead. - params=dict(patch_values=True), - ) - - def delete_secret(self, secret_id: UUID) -> None: - """Delete a secret. - - Args: - secret_id: The id of the secret to delete. - """ - self.zen_store._delete_resource( - resource_id=secret_id, - route=SECRETS, - ) diff --git a/src/zenml/zen_stores/secrets_stores/secrets_store_interface.py b/src/zenml/zen_stores/secrets_stores/secrets_store_interface.py index 0736733635d..2601dac02a2 100644 --- a/src/zenml/zen_stores/secrets_stores/secrets_store_interface.py +++ b/src/zenml/zen_stores/secrets_stores/secrets_store_interface.py @@ -13,16 +13,9 @@ # permissions and limitations under the License. """ZenML secrets store interface.""" from abc import ABC, abstractmethod +from typing import Dict from uuid import UUID -from zenml.models import ( - Page, - SecretFilter, - SecretRequest, - SecretResponse, - SecretUpdate, -) - class SecretsStoreInterface(ABC): """ZenML secrets store interface. @@ -47,116 +40,58 @@ def _initialize(self) -> None: # --------- @abstractmethod - def create_secret( + def store_secret_values( self, - secret: SecretRequest, - ) -> SecretResponse: - """Creates a new secret. - - The new secret is also validated against the scoping rules enforced in - the secrets store: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + secret_id: UUID, + secret_values: Dict[str, str], + ) -> None: + """Store secret values for a new secret. Args: - secret: The secret to create. - - Returns: - The newly created secret. - - Raises: - KeyError: if the user or workspace does not exist. - EntityExistsError: If a secret with the same name already exists in - the same scope. - ValueError: if the secret is invalid. + secret_id: ID of the secret. + secret_values: Values for the secret. """ @abstractmethod - def get_secret( - self, secret_id: UUID, hydrate: bool = True - ) -> SecretResponse: - """Get a secret with a given name. + def get_secret_values(self, secret_id: UUID) -> Dict[str, str]: + """Get the secret values for an existing secret. Args: secret_id: ID of the secret. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. Returns: - The secret. + The secret values. Raises: - KeyError: if the secret does not exist. - """ - - @abstractmethod - def list_secrets( - self, secret_filter_model: SecretFilter, hydrate: bool = False - ) -> Page[SecretResponse]: - """List all secrets matching the given filter criteria. - - Note that returned secrets do not include any secret values. To fetch - the secret values, use `get_secret`. - - Args: - secret_filter_model: All filter parameters including pagination - params. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - A list of all secrets matching the filter criteria, with pagination - information and sorted according to the filter criteria. The - returned secrets do not include any secret values, only metadata. To - fetch the secret values, use `get_secret` individually with each - secret. + KeyError: if no secret values for the given ID are stored in the + secrets store. """ @abstractmethod - def update_secret( + def update_secret_values( self, secret_id: UUID, - secret_update: SecretUpdate, - ) -> SecretResponse: - """Updates a secret. - - Secret values that are specified as `None` in the update that are - present in the existing secret are removed from the existing secret. - Values that are present in both secrets are overwritten. All other - values in both the existing secret and the update are kept (merged). - - If the update includes a change of name or scope, the scoping rules - enforced in the secrets store are used to validate the update: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + secret_values: Dict[str, str], + ) -> None: + """Updates secret values for an existing secret. Args: secret_id: The ID of the secret to be updated. - secret_update: The update to be applied. - - Returns: - The updated secret. + secret_values: The new secret values. Raises: - KeyError: if the secret doesn't exist. - EntityExistsError: If a secret with the same name already exists in - the same scope. - ValueError: if the secret is invalid. + KeyError: if no secret values for the given ID are stored in the + secrets store. """ @abstractmethod - def delete_secret(self, secret_id: UUID) -> None: - """Deletes a secret. + def delete_secret_values(self, secret_id: UUID) -> None: + """Deletes secret values for an existing secret. Args: - secret_id: The ID of the secret to delete. + secret_id: The ID of the secret. Raises: - KeyError: if the secret doesn't exist. + KeyError: if no secret values for the given ID are stored in the + secrets store. """ diff --git a/src/zenml/zen_stores/secrets_stores/service_connector_secrets_store.py b/src/zenml/zen_stores/secrets_stores/service_connector_secrets_store.py index 250eafa1038..385e2f46a87 100644 --- a/src/zenml/zen_stores/secrets_stores/service_connector_secrets_store.py +++ b/src/zenml/zen_stores/secrets_stores/service_connector_secrets_store.py @@ -64,9 +64,19 @@ def validate_auth_config(cls, values: Dict[str, Any]) -> Dict[str, Any]: Returns: The validated configuration values. + + Raises: + ValueError: If the authentication configuration is not a valid + JSON object. """ if isinstance(values.get("auth_config"), str): - values["auth_config"] = json.loads(values["auth_config"]) + try: + values["auth_config"] = json.loads(values["auth_config"]) + except json.JSONDecodeError as e: + raise ValueError( + f"The authentication configuration is not a valid JSON " + f"object: {e}" + ) return values diff --git a/src/zenml/zen_stores/secrets_stores/sql_secrets_store.py b/src/zenml/zen_stores/secrets_stores/sql_secrets_store.py index 5dc5ff4376a..288e9aafaa7 100644 --- a/src/zenml/zen_stores/secrets_stores/sql_secrets_store.py +++ b/src/zenml/zen_stores/secrets_stores/sql_secrets_store.py @@ -17,8 +17,8 @@ TYPE_CHECKING, Any, ClassVar, + Dict, Optional, - Tuple, Type, ) from uuid import UUID @@ -28,25 +28,14 @@ from sqlalchemy_utils.types.encrypted.encrypted_type import AesGcmEngine from sqlmodel import Session, select -from zenml.analytics.enums import AnalyticsEvent -from zenml.analytics.utils import track_decorator from zenml.config.secrets_store_config import SecretsStoreConfiguration from zenml.enums import ( - SecretScope, SecretsStoreType, ) from zenml.exceptions import ( - EntityExistsError, IllegalOperationError, ) from zenml.logger import get_logger -from zenml.models import ( - Page, - SecretFilter, - SecretRequest, - SecretResponse, - SecretUpdate, -) from zenml.zen_stores.schemas import ( SecretSchema, ) @@ -179,140 +168,48 @@ def _initialize(self) -> None: # Secrets # ------ - def _check_sql_secret_scope( + def store_secret_values( self, - session: Session, - secret_name: str, - scope: SecretScope, - workspace: UUID, - user: UUID, - exclude_secret_id: Optional[UUID] = None, - ) -> Tuple[bool, str]: - """Checks if a secret with the given name already exists in the given scope. - - This method enforces the following scope rules: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. - - Args: - session: The SQLAlchemy session. - secret_name: The name of the secret. - scope: The scope of the secret. - workspace: The ID of the workspace to which the secret belongs. - user: The ID of the user to which the secret belongs. - exclude_secret_id: The ID of a secret to exclude from the check - (used e.g. during an update to exclude the existing secret). - - Returns: - True if a secret with the given name already exists in the given - scope, False otherwise, and an error message. - """ - scope_filter = ( - select(SecretSchema) - .where(SecretSchema.name == secret_name) - .where(SecretSchema.scope == scope.value) - ) - - if scope in [SecretScope.WORKSPACE, SecretScope.USER]: - scope_filter = scope_filter.where( - SecretSchema.workspace_id == workspace - ) - if scope == SecretScope.USER: - scope_filter = scope_filter.where(SecretSchema.user_id == user) - if exclude_secret_id is not None: - scope_filter = scope_filter.where( - SecretSchema.id != exclude_secret_id - ) - - existing_secret = session.exec(scope_filter).first() - - if existing_secret is not None: - existing_secret_model = existing_secret.to_model( - encryption_engine=self._encryption_engine - ) - - msg = ( - f"Found an existing {scope.value} scoped secret with the " - f"same '{secret_name}' name" - ) - if scope in [SecretScope.WORKSPACE, SecretScope.USER]: - msg += ( - f" in the same '{existing_secret_model.workspace.name}' " - f"workspace" - ) - if scope == SecretScope.USER: - assert existing_secret_model.user - msg += ( - f" for the same '{existing_secret_model.user.name}' user" - ) - - return True, msg - - return False, "" - - @track_decorator(AnalyticsEvent.CREATED_SECRET) - def create_secret(self, secret: SecretRequest) -> SecretResponse: - """Creates a new secret. - - The new secret is also validated against the scoping rules enforced in - the secrets store: + secret_id: UUID, + secret_values: Dict[str, str], + ) -> None: + """Store secret values for a new secret. - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + The secret is already created in the database by the SQL Zen store, this + method only stores the secret values. Args: - secret: The secret to create. - - Returns: - The newly created secret. + secret_id: ID of the secret. + secret_values: Values for the secret. Raises: - EntityExistsError: If a secret with the same name already exists in - the same scope. + KeyError: if a secret for the given ID is not found. """ with Session(self.engine) as session: - # Check if a secret with the same name already exists in the same - # scope. - secret_exists, msg = self._check_sql_secret_scope( - session=session, - secret_name=secret.name, - scope=secret.scope, - workspace=secret.workspace, - user=secret.user, - ) - if secret_exists: - raise EntityExistsError(msg) - - new_secret = SecretSchema.from_request( - secret, encryption_engine=self._encryption_engine + secret_in_db = session.exec( + select(SecretSchema).where(SecretSchema.id == secret_id) + ).first() + if secret_in_db is None: + raise KeyError(f"Secret with ID {secret_id} not found.") + secret_in_db.set_secret_values( + secret_values=secret_values, + encryption_engine=self._encryption_engine, ) - session.add(new_secret) + session.add(secret_in_db) session.commit() - return new_secret.to_model( - encryption_engine=self._encryption_engine, hydrate=True - ) - - def get_secret( - self, secret_id: UUID, hydrate: bool = True - ) -> SecretResponse: - """Get a secret by ID. + def get_secret_values(self, secret_id: UUID) -> Dict[str, str]: + """Get the secret values for an existing secret. Args: - secret_id: The ID of the secret to fetch. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. + secret_id: ID of the secret. Returns: - The secret. + The secret values. Raises: - KeyError: if the secret doesn't exist. + KeyError: if no secret values for the given ID are stored in the + secrets store. """ with Session(self.engine) as session: secret_in_db = session.exec( @@ -320,129 +217,39 @@ def get_secret( ).first() if secret_in_db is None: raise KeyError(f"Secret with ID {secret_id} not found.") - return secret_in_db.to_model( - encryption_engine=self._encryption_engine, hydrate=hydrate - ) - - def list_secrets( - self, secret_filter_model: SecretFilter, hydrate: bool = False - ) -> Page[SecretResponse]: - """List all secrets matching the given filter criteria. - - Note that returned secrets do not include any secret values. To fetch - the secret values, use `get_secret`. - - Args: - secret_filter_model: All filter parameters including pagination - params. - hydrate: Flag deciding whether to hydrate the output model(s) - by including metadata fields in the response. - - Returns: - A list of all secrets matching the filter criteria, with pagination - information and sorted according to the filter criteria. The - returned secrets do not include any secret values, only metadata. To - fetch the secret values, use `get_secret` individually with each - secret. - """ - with Session(self.engine) as session: - query = select(SecretSchema) - return self.zen_store.filter_and_paginate( - session=session, - query=query, - table=SecretSchema, - filter_model=secret_filter_model, - custom_schema_to_model_conversion=lambda secret: secret.to_model( - include_values=False, hydrate=hydrate - ), + return secret_in_db.get_secret_values( + encryption_engine=self._encryption_engine, ) - def update_secret( - self, secret_id: UUID, secret_update: SecretUpdate - ) -> SecretResponse: - """Updates a secret. - - Secret values that are specified as `None` in the update that are - present in the existing secret are removed from the existing secret. - Values that are present in both secrets are overwritten. All other - values in both the existing secret and the update are kept (merged). - - If the update includes a change of name or scope, the scoping rules - enforced in the secrets store are used to validate the update: - - - only one workspace-scoped secret with the given name can exist - in the target workspace. - - only one user-scoped secret with the given name can exist in the - target workspace for the target user. + def update_secret_values( + self, + secret_id: UUID, + secret_values: Dict[str, str], + ) -> None: + """Updates secret values for an existing secret. Args: secret_id: The ID of the secret to be updated. - secret_update: The update to be applied. - - Returns: - The updated secret. - - Raises: - KeyError: if the secret doesn't exist. - EntityExistsError: If a secret with the same name already exists in - the same scope. + secret_values: The new secret values. """ - with Session(self.engine) as session: - existing_secret = session.exec( - select(SecretSchema).where(SecretSchema.id == secret_id) - ).first() - - if not existing_secret: - raise KeyError(f"Secret with ID {secret_id} not found.") - - # A change in name or scope requires a check of the scoping rules. - if ( - secret_update.name is not None - and existing_secret.name != secret_update.name - or secret_update.scope is not None - and existing_secret.scope != secret_update.scope - ): - secret_exists, msg = self._check_sql_secret_scope( - session=session, - secret_name=secret_update.name or existing_secret.name, - scope=secret_update.scope - or SecretScope(existing_secret.scope), - workspace=existing_secret.workspace.id, - user=existing_secret.user.id, - exclude_secret_id=secret_id, - ) - - if secret_exists: - raise EntityExistsError(msg) - - existing_secret.update( - secret_update=secret_update, - encryption_engine=self._encryption_engine, - ) - session.add(existing_secret) - session.commit() - - # Refresh the Model that was just created - session.refresh(existing_secret) - return existing_secret.to_model( - encryption_engine=self._encryption_engine, hydrate=True - ) + self.store_secret_values(secret_id, secret_values) - def delete_secret(self, secret_id: UUID) -> None: - """Delete a secret. + def delete_secret_values(self, secret_id: UUID) -> None: + """Deletes secret values for an existing secret. Args: - secret_id: The id of the secret to delete. + secret_id: The ID of the secret. Raises: - KeyError: if the secret doesn't exist. + KeyError: if no secret values for the given ID are stored in the + secrets store. """ with Session(self.engine) as session: try: secret_in_db = session.exec( select(SecretSchema).where(SecretSchema.id == secret_id) ).one() - session.delete(secret_in_db) + secret_in_db.values = None session.commit() except NoResultFound: raise KeyError(f"Secret with ID {secret_id} not found.") diff --git a/src/zenml/zen_stores/sql_zen_store.py b/src/zenml/zen_stores/sql_zen_store.py index 10accb8d1fc..b3ecefad046 100644 --- a/src/zenml/zen_stores/sql_zen_store.py +++ b/src/zenml/zen_stores/sql_zen_store.py @@ -83,6 +83,7 @@ LoggingLevels, ModelStages, SecretScope, + SecretsStoreType, SorterOps, StackComponentType, StepRunInputArtifactType, @@ -177,6 +178,8 @@ ScheduleUpdate, SecretFilter, SecretRequest, + SecretResponse, + SecretUpdate, ServerDatabaseType, ServerModel, ServiceAccountFilter, @@ -228,7 +231,6 @@ from zenml.zen_stores.base_zen_store import ( BaseZenStore, ) -from zenml.zen_stores.enums import StoreEvent from zenml.zen_stores.migrations.alembic import ( ZENML_ALEMBIC_START_REVISION, Alembic, @@ -254,6 +256,7 @@ PipelineSchema, RunMetadataSchema, ScheduleSchema, + SecretSchema, ServiceConnectorSchema, StackComponentSchema, StackSchema, @@ -270,6 +273,7 @@ ArtifactVisualizationSchema, ) from zenml.zen_stores.schemas.logs_schemas import LogsSchema +from zenml.zen_stores.secrets_stores.base_secrets_store import BaseSecretsStore from zenml.zen_stores.secrets_stores.sql_secrets_store import ( SqlSecretsStoreConfiguration, ) @@ -712,6 +716,25 @@ class SqlZenStore(BaseZenStore): _engine: Optional[Engine] = None _alembic: Optional[Alembic] = None + _secrets_store: Optional[BaseSecretsStore] = None + + @property + def secrets_store(self) -> "BaseSecretsStore": + """The secrets store associated with this store. + + Returns: + The secrets store associated with this store. + + Raises: + NotImplementedError: If no secrets store is configured. + """ + if self._secrets_store is None: + raise NotImplementedError( + "No secrets store is configured. Please configure a secrets " + "store to create and manage ZenML secrets." + ) + + return self._secrets_store @property def engine(self) -> Engine: @@ -928,6 +951,24 @@ def _initialize(self) -> None: ): self.migrate_database() + secrets_store_config = self.config.secrets_store + + # Initialize the secrets store + if ( + secrets_store_config + and secrets_store_config.type != SecretsStoreType.NONE + ): + secrets_store_class = BaseSecretsStore.get_store_class( + secrets_store_config + ) + self._secrets_store = secrets_store_class( + zen_store=self, + config=secrets_store_config, + ) + # Update the config with the actual secrets store config + # to reflect the default values in the saved configuration + self.config.secrets_store = self._secrets_store.config + def _initialize_database(self) -> None: """Initialize the database on first use.""" self._get_or_create_default_workspace() @@ -3735,6 +3776,372 @@ def delete_schedule(self, schedule_id: UUID) -> None: session.delete(schedule) session.commit() + # ------------------------- Secrets ------------------------- + + def _check_sql_secret_scope( + self, + session: Session, + secret_name: str, + scope: SecretScope, + workspace: UUID, + user: UUID, + exclude_secret_id: Optional[UUID] = None, + ) -> Tuple[bool, str]: + """Checks if a secret with the given name already exists in the given scope. + + This method enforces the following scope rules: + + - only one workspace-scoped secret with the given name can exist + in the target workspace. + - only one user-scoped secret with the given name can exist in the + target workspace for the target user. + + Args: + session: The SQLAlchemy session. + secret_name: The name of the secret. + scope: The scope of the secret. + workspace: The ID of the workspace to which the secret belongs. + user: The ID of the user to which the secret belongs. + exclude_secret_id: The ID of a secret to exclude from the check + (used e.g. during an update to exclude the existing secret). + + Returns: + True if a secret with the given name already exists in the given + scope, False otherwise, and an error message. + """ + scope_filter = ( + select(SecretSchema) + .where(SecretSchema.name == secret_name) + .where(SecretSchema.scope == scope.value) + ) + + if scope in [SecretScope.WORKSPACE, SecretScope.USER]: + scope_filter = scope_filter.where( + SecretSchema.workspace_id == workspace + ) + if scope == SecretScope.USER: + scope_filter = scope_filter.where(SecretSchema.user_id == user) + if exclude_secret_id is not None: + scope_filter = scope_filter.where( + SecretSchema.id != exclude_secret_id + ) + + existing_secret = session.exec(scope_filter).first() + + if existing_secret is not None: + existing_secret_model = existing_secret.to_model(hydrate=True) + + msg = ( + f"Found an existing {scope.value} scoped secret with the " + f"same '{secret_name}' name" + ) + if scope in [SecretScope.WORKSPACE, SecretScope.USER]: + msg += ( + f" in the same '{existing_secret_model.workspace.name}' " + f"workspace" + ) + if scope == SecretScope.USER: + assert existing_secret_model.user + msg += ( + f" for the same '{existing_secret_model.user.name}' user" + ) + + return True, msg + + return False, "" + + def _set_secret_values( + self, secret_id: UUID, values: Dict[str, str] + ) -> None: + """Sets the values of a secret in the configured secrets store. + + Args: + secret_id: The ID of the secret to set the values of. + values: The values to set. + """ + self.secrets_store.store_secret_values( + secret_id=secret_id, secret_values=values + ) + + def _get_secret_values(self, secret_id: UUID) -> Dict[str, str]: + """Gets the values of a secret in the configured secrets store. + + Args: + secret_id: The ID of the secret to set the values of. + + Returns: + The values of the secret. + """ + return self.secrets_store.get_secret_values( + secret_id=secret_id, + ) + + def _update_secret_values( + self, secret_id: UUID, values: Dict[str, Optional[str]] + ) -> Dict[str, str]: + """Updates the values of a secret in the configured secrets store. + + This method will update the existing values with the new values + and drop `None` values. + + Args: + secret_id: The ID of the secret to set the values of. + values: The updated values to set. + + Returns: + The updated values. + """ + existing_values = self._get_secret_values(secret_id=secret_id) + + for k, v in values.items(): + if v is not None: + existing_values[k] = v + # Drop values removed in the update + if v is None and k in existing_values: + del existing_values[k] + + self.secrets_store.update_secret_values( + secret_id=secret_id, secret_values=existing_values + ) + + return existing_values + + def _delete_secret_values( + self, + secret_id: UUID, + ) -> None: + """Deletes the values of a secret in the configured secrets store. + + Args: + secret_id: The ID of the secret for which to delete the values. + """ + self.secrets_store.delete_secret_values(secret_id=secret_id) + + @track_decorator(AnalyticsEvent.CREATED_SECRET) + def create_secret(self, secret: SecretRequest) -> SecretResponse: + """Creates a new secret. + + The new secret is also validated against the scoping rules enforced in + the secrets store: + + - only one workspace-scoped secret with the given name can exist + in the target workspace. + - only one user-scoped secret with the given name can exist in the + target workspace for the target user. + + Args: + secret: The secret to create. + + Returns: + The newly created secret. + + Raises: + EntityExistsError: If a secret with the same name already exists in + the same scope. + """ + with Session(self.engine) as session: + # Check if a secret with the same name already exists in the same + # scope. + secret_exists, msg = self._check_sql_secret_scope( + session=session, + secret_name=secret.name, + scope=secret.scope, + workspace=secret.workspace, + user=secret.user, + ) + if secret_exists: + raise EntityExistsError(msg) + + new_secret = SecretSchema.from_request( + secret, + ) + session.add(new_secret) + session.commit() + + secret_model = new_secret.to_model(hydrate=True) + + try: + # Set the secret values in the configured secrets store + self._set_secret_values( + secret_id=new_secret.id, values=secret.secret_values + ) + except: + # If setting the secret values fails, delete the secret from the + # database. + with Session(self.engine) as session: + session.delete(new_secret) + session.commit() + raise + + secret_model.set_secrets(secret.secret_values) + return secret_model + + def get_secret( + self, secret_id: UUID, hydrate: bool = True + ) -> SecretResponse: + """Get a secret by ID. + + Args: + secret_id: The ID of the secret to fetch. + hydrate: Flag deciding whether to hydrate the output model(s) + by including metadata fields in the response. + + Returns: + The secret. + + Raises: + KeyError: if the secret doesn't exist. + """ + with Session(self.engine) as session: + secret_in_db = session.exec( + select(SecretSchema).where(SecretSchema.id == secret_id) + ).first() + if secret_in_db is None: + raise KeyError(f"Secret with ID {secret_id} not found.") + secret_model = secret_in_db.to_model(hydrate=hydrate) + + secret_model.set_secrets(self._get_secret_values(secret_id=secret_id)) + + return secret_model + + def list_secrets( + self, secret_filter_model: SecretFilter, hydrate: bool = False + ) -> Page[SecretResponse]: + """List all secrets matching the given filter criteria. + + Note that returned secrets do not include any secret values. To fetch + the secret values, use `get_secret`. + + Args: + secret_filter_model: All filter parameters including pagination + params. + hydrate: Flag deciding whether to hydrate the output model(s) + by including metadata fields in the response. + + Returns: + A list of all secrets matching the filter criteria, with pagination + information and sorted according to the filter criteria. The + returned secrets do not include any secret values, only metadata. To + fetch the secret values, use `get_secret` individually with each + secret. + """ + with Session(self.engine) as session: + query = select(SecretSchema) + return self.filter_and_paginate( + session=session, + query=query, + table=SecretSchema, + filter_model=secret_filter_model, + hydrate=hydrate, + ) + + def update_secret( + self, secret_id: UUID, secret_update: SecretUpdate + ) -> SecretResponse: + """Updates a secret. + + Secret values that are specified as `None` in the update that are + present in the existing secret are removed from the existing secret. + Values that are present in both secrets are overwritten. All other + values in both the existing secret and the update are kept (merged). + + If the update includes a change of name or scope, the scoping rules + enforced in the secrets store are used to validate the update: + + - only one workspace-scoped secret with the given name can exist + in the target workspace. + - only one user-scoped secret with the given name can exist in the + target workspace for the target user. + + Args: + secret_id: The ID of the secret to be updated. + secret_update: The update to be applied. + + Returns: + The updated secret. + + Raises: + KeyError: if the secret doesn't exist. + EntityExistsError: If a secret with the same name already exists in + the same scope. + """ + with Session(self.engine) as session: + existing_secret = session.exec( + select(SecretSchema).where(SecretSchema.id == secret_id) + ).first() + + if not existing_secret: + raise KeyError(f"Secret with ID {secret_id} not found.") + + # A change in name or scope requires a check of the scoping rules. + if ( + secret_update.name is not None + and existing_secret.name != secret_update.name + or secret_update.scope is not None + and existing_secret.scope != secret_update.scope + ): + secret_exists, msg = self._check_sql_secret_scope( + session=session, + secret_name=secret_update.name or existing_secret.name, + scope=secret_update.scope + or SecretScope(existing_secret.scope), + workspace=existing_secret.workspace.id, + user=existing_secret.user.id, + exclude_secret_id=secret_id, + ) + + if secret_exists: + raise EntityExistsError(msg) + + existing_secret.update( + secret_update=secret_update, + ) + session.add(existing_secret) + session.commit() + + # Refresh the Model that was just created + session.refresh(existing_secret) + secret_model = existing_secret.to_model(hydrate=True) + + if secret_update.values is not None: + # Update the secret values in the configured secrets store + updated_values = self._update_secret_values( + secret_id=secret_id, + values=secret_update.get_secret_values_update(), + ) + secret_model.set_secrets(updated_values) + else: + secret_model.set_secrets(self._get_secret_values(secret_id)) + + return secret_model + + def delete_secret(self, secret_id: UUID) -> None: + """Delete a secret. + + Args: + secret_id: The id of the secret to delete. + + Raises: + KeyError: if the secret doesn't exist. + """ + # Delete the secret values in the configured secrets store + try: + self._delete_secret_values(secret_id=secret_id) + except KeyError: + # If the secret values don't exist in the secrets store, we don't + # need to raise an error. + pass + + with Session(self.engine) as session: + try: + secret_in_db = session.exec( + select(SecretSchema).where(SecretSchema.id == secret_id) + ).one() + session.delete(secret_in_db) + session.commit() + except NoResultFound: + raise KeyError(f"Secret with ID {secret_id} not found.") + # ------------------------- Service Accounts ------------------------- @track_decorator(AnalyticsEvent.CREATED_SERVICE_ACCOUNT) @@ -3988,9 +4395,9 @@ def create_service_connector( session.refresh(new_service_connector) except Exception: # Delete the secret if it was created - if secret_id and self.secrets_store: + if secret_id: try: - self.secrets_store.delete_secret(secret_id) + self.delete_secret(secret_id) except Exception: # Ignore any errors that occur while deleting the # secret @@ -4286,11 +4693,9 @@ def delete_service_connector(self, service_connector_id: UUID) -> None: else: session.delete(service_connector) - if service_connector.secret_id and self.secrets_store: + if service_connector.secret_id: try: - self.secrets_store.delete_secret( - service_connector.secret_id - ) + self.delete_secret(service_connector.secret_id) except KeyError: # If the secret doesn't exist anymore, we can ignore # this error @@ -4351,19 +4756,10 @@ def _create_connector_secret( Returns: The ID of the newly created secret or None, if the service connector does not contain any secret credentials. - - Raises: - NotImplementedError: If a secrets store is not configured or - supported. """ if not secrets: return None - if not self.secrets_store: - raise NotImplementedError( - "A secrets store is not configured or supported." - ) - # Generate a unique name for the secret # Replace all non-alphanumeric characters with a dash because # the secret name must be a valid DNS subdomain name in some @@ -4373,14 +4769,14 @@ def _create_connector_secret( # that is not already in use while True: secret_name = f"connector-{connector_name}-{random_str(4)}".lower() - existing_secrets = self.secrets_store.list_secrets( + existing_secrets = self.list_secrets( SecretFilter( name=secret_name, ) ) if not existing_secrets.size: try: - return self.secrets_store.create_secret( + return self.create_secret( SecretRequest( name=secret_name, user=user, @@ -4476,16 +4872,7 @@ def _update_connector_secret( Returns: The ID of the updated secret or None, if the new service connector does not contain any secret credentials. - - Raises: - NotImplementedError: If a secrets store is not configured or - supported. """ - if not self.secrets_store: - raise NotImplementedError( - "A secrets store is not configured or supported." - ) - if updated_connector.secrets is None: # If the connector update does not contain a secrets update, keep # the existing secret (if any) @@ -4494,7 +4881,7 @@ def _update_connector_secret( # Delete the existing secret (if any), to be replaced by the new secret if existing_connector.secret_id: try: - self.secrets_store.delete_secret(existing_connector.secret_id) + self.delete_secret(existing_connector.secret_id) except KeyError: # Ignore if the secret no longer exists pass @@ -5530,10 +5917,8 @@ def _get_resource_references( and attr not in # These are not resources owned by the user or are resources that - # are deleted automatically when the user is deleted. Secrets in - # particular are left out because they are automatically deleted - # even when stored in an external secret store. - ["api_keys", "auth_devices", "secrets"] + # are deleted automatically when the user is deleted. + ["api_keys", "auth_devices"] ] # This next part is crucial in preserving scalability: we don't fetch @@ -5837,8 +6222,6 @@ def delete_user(self, user_name_or_id: Union[str, UUID]) -> None: "account or consider deactivating it instead." ) - self._trigger_event(StoreEvent.USER_DELETED, user_id=user.id) - session.delete(user) session.commit() @@ -6027,10 +6410,6 @@ def delete_workspace(self, workspace_name_or_id: Union[str, UUID]) -> None: "The default workspace cannot be deleted." ) - self._trigger_event( - StoreEvent.WORKSPACE_DELETED, workspace_id=workspace.id - ) - session.delete(workspace) session.commit() diff --git a/src/zenml/zen_stores/zen_store_interface.py b/src/zenml/zen_stores/zen_store_interface.py index 4a8bbb4e3c4..d308f4e96ad 100644 --- a/src/zenml/zen_stores/zen_store_interface.py +++ b/src/zenml/zen_stores/zen_store_interface.py @@ -84,6 +84,10 @@ ScheduleRequest, ScheduleResponse, ScheduleUpdate, + SecretFilter, + SecretRequest, + SecretResponse, + SecretUpdate, ServerModel, ServiceAccountFilter, ServiceAccountRequest, @@ -1337,6 +1341,121 @@ def delete_schedule(self, schedule_id: UUID) -> None: KeyError: if the schedule doesn't exist. """ + # -------------------- Secrets -------------------- + + @abstractmethod + def create_secret( + self, + secret: SecretRequest, + ) -> SecretResponse: + """Creates a new secret. + + The new secret is also validated against the scoping rules enforced in + the secrets store: + + - only one workspace-scoped secret with the given name can exist + in the target workspace. + - only one user-scoped secret with the given name can exist in the + target workspace for the target user. + + Args: + secret: The secret to create. + + Returns: + The newly created secret. + + Raises: + KeyError: if the user or workspace does not exist. + EntityExistsError: If a secret with the same name already exists in + the same scope. + """ + + @abstractmethod + def get_secret( + self, secret_id: UUID, hydrate: bool = True + ) -> SecretResponse: + """Get a secret with a given name. + + Args: + secret_id: ID of the secret. + hydrate: Flag deciding whether to hydrate the output model(s) + by including metadata fields in the response. + + Returns: + The secret. + + Raises: + KeyError: if the secret does not exist. + """ + + @abstractmethod + def list_secrets( + self, secret_filter_model: SecretFilter, hydrate: bool = False + ) -> Page[SecretResponse]: + """List all secrets matching the given filter criteria. + + Note that returned secrets do not include any secret values. To fetch + the secret values, use `get_secret`. + + Args: + secret_filter_model: All filter parameters including pagination + params. + hydrate: Flag deciding whether to hydrate the output model(s) + by including metadata fields in the response. + + Returns: + A list of all secrets matching the filter criteria, with pagination + information and sorted according to the filter criteria. The + returned secrets do not include any secret values, only metadata. To + fetch the secret values, use `get_secret` individually with each + secret. + """ + + @abstractmethod + def update_secret( + self, + secret_id: UUID, + secret_update: SecretUpdate, + ) -> SecretResponse: + """Updates a secret. + + Secret values that are specified as `None` in the update that are + present in the existing secret are removed from the existing secret. + Values that are present in both secrets are overwritten. All other + values in both the existing secret and the update are kept (merged). + + If the update includes a change of name or scope, the scoping rules + enforced in the secrets store are used to validate the update: + + - only one workspace-scoped secret with the given name can exist + in the target workspace. + - only one user-scoped secret with the given name can exist in the + target workspace for the target user. + + Args: + secret_id: The ID of the secret to be updated. + secret_update: The update to be applied. + + Returns: + The updated secret. + + Raises: + KeyError: if the secret doesn't exist. + EntityExistsError: If a secret with the same name already exists in + the same scope. + """ + + @abstractmethod + def delete_secret(self, secret_id: UUID) -> None: + """Deletes a secret. + + Args: + secret_id: The ID of the secret to delete. + + Raises: + KeyError: if the secret doesn't exist. + """ + # -------------------- Service Accounts -------------------- @abstractmethod diff --git a/tests/integration/functional/zen_stores/test_secrets_store.py b/tests/integration/functional/zen_stores/test_secrets_store.py index 6607aefb68b..bc3d79af393 100644 --- a/tests/integration/functional/zen_stores/test_secrets_store.py +++ b/tests/integration/functional/zen_stores/test_secrets_store.py @@ -26,15 +26,9 @@ ) from zenml.client import Client from zenml.enums import SecretScope, SecretsStoreType, StoreType -from zenml.exceptions import EntityExistsError +from zenml.exceptions import EntityExistsError, IllegalOperationError from zenml.models import SecretFilter, SecretUpdate -# The AWS secrets store takes some time to reflect new and updated secrets in -# the `list_secrets` API. This is the number of seconds to wait before making -# `list_secrets` calls after creating/updating a secret to ensure that the -# latest secret information is returned. -AWS_SECRET_REFRESH_SLEEP = 10 - def _get_secrets_store_type() -> SecretsStoreType: """Returns the secrets store back-end type that is used by the test @@ -623,12 +617,6 @@ def test_update_scope_succeeds(): ), ) - if _get_secrets_store_type() == SecretsStoreType.AWS: - # The AWS secrets store returns before the secret is actually - # updated in the backend, so we need to wait a bit before - # running `list_secrets`. - time.sleep(AWS_SECRET_REFRESH_SLEEP) - assert updated_secret.name == secret.name assert updated_secret.scope == SecretScope.USER @@ -670,12 +658,6 @@ def test_update_scope_succeeds(): ), ) - if _get_secrets_store_type() == SecretsStoreType.AWS: - # The AWS secrets store returns before the secret is actually - # updated in the backend, so we need to wait a bit before - # running `list_secrets`. - time.sleep(AWS_SECRET_REFRESH_SLEEP) - assert updated_secret.name == secret.name assert updated_secret.scope == SecretScope.WORKSPACE @@ -1466,14 +1448,8 @@ def test_list_secrets_pagination_and_sorting(): ), ) - if _get_secrets_store_type() == SecretsStoreType.AWS: - # The AWS secrets store returns before the secret is actually - # updated in the backend, so we need to wait a bit before - # running `list_secrets`. - time.sleep(AWS_SECRET_REFRESH_SLEEP) - else: - assert secret_one.updated > secret_one.created - assert secret_two.updated > secret_two.created + assert secret_one.updated > secret_one.created + assert secret_two.updated > secret_two.created secrets = store.list_secrets( SecretFilter( @@ -1618,8 +1594,8 @@ def test_secret_is_deleted_with_workspace(): assert len(all_workspace_secrets) == 0 -def test_secret_is_deleted_with_user(): - """Tests that deleting a user automatically deletes all its secrets.""" +def test_delete_user_with_secrets(): + """Tests that deleting a user is not possible while it owns secrets.""" client = Client() store = client.zen_store @@ -1679,9 +1655,34 @@ def test_secret_is_deleted_with_user(): assert len(user_secrets) == 1 assert other_secret.id == user_secrets[0].id - store.delete_user(user.id) + with pytest.raises(IllegalOperationError): + store.delete_user(user.id) + + with does_not_raise(): + store.get_secret(other_secret.id) + + all_secrets = store.list_secrets( + SecretFilter(name=secret.name), + ).items + assert len(all_secrets) == 2 + assert secret.id in [s.id for s in all_secrets] + assert other_secret.id in [s.id for s in all_secrets] + + user_secrets = store.list_secrets( + SecretFilter( + name=secret.name, + scope=SecretScope.USER, + user_id=user.id, + workspace_id=client.active_workspace.id, + ), + ).items + assert len(user_secrets) == 1 + + # Delete the secret + store.delete_secret(other_secret.id) - # New secret has been deleted at this point with the user + with does_not_raise(): + store.delete_user(user.id) with pytest.raises(KeyError): store.get_secret(other_secret.id) diff --git a/tests/integration/functional/zen_stores/test_zen_store.py b/tests/integration/functional/zen_stores/test_zen_store.py index 6d7e7813d18..811877e8d1a 100644 --- a/tests/integration/functional/zen_stores/test_zen_store.py +++ b/tests/integration/functional/zen_stores/test_zen_store.py @@ -478,10 +478,18 @@ def test_delete_user_with_resources_fails(): zen_store.delete_user(user.id) with UserContext(delete=False, login=login) as user: - with SecretContext(user_id=user.id, delete=False): + secret_context = SecretContext(user_id=user.id, delete=False) + with secret_context: + # We only use the context as a shortcut to create the resource pass - # Secrets are deleted when the user is deleted + # Can't delete because owned resources exist + with pytest.raises(IllegalOperationError): + zen_store.delete_user(user.id) + + secret_context.cleanup() + + # Can delete because owned resources have been removed with does_not_raise(): zen_store.delete_user(user.id) @@ -815,10 +823,20 @@ def test_delete_service_account_with_resources_fails(): zen_store.delete_service_account(service_account.id) with ServiceAccountContext(delete=False, login=login) as service_account: - with SecretContext(user_id=service_account.id, delete=False): + secret_context = SecretContext( + user_id=service_account.id, delete=False + ) + with secret_context: + # We only use the context as a shortcut to create the resource pass - # Secrets are deleted when the service_account is deleted + # Can't delete because owned resources exist + with pytest.raises(IllegalOperationError): + zen_store.delete_service_account(service_account.id) + + secret_context.cleanup() + + # Can delete because owned resources have been removed with does_not_raise(): zen_store.delete_service_account(service_account.id) diff --git a/tests/integration/functional/zen_stores/utils.py b/tests/integration/functional/zen_stores/utils.py index 40735b04ef2..c7fd2a2e87b 100644 --- a/tests/integration/functional/zen_stores/utils.py +++ b/tests/integration/functional/zen_stores/utils.py @@ -496,12 +496,15 @@ def __enter__(self): self.created_secret = self.store.create_secret(new_secret) return self.created_secret + def cleanup(self): + try: + self.store.delete_secret(self.created_secret.id) + except KeyError: + pass + def __exit__(self, exc_type, exc_value, exc_traceback): if self.delete: - try: - self.store.delete_secret(self.created_secret.id) - except KeyError: - pass + self.cleanup() class CodeRepositoryContext: From 3342af1a88df6b7e44747fec8a78303a44515690 Mon Sep 17 00:00:00 2001 From: Andrei Vishniakov <31008759+avishniakov@users.noreply.github.com> Date: Fri, 12 Jan 2024 09:10:28 +0100 Subject: [PATCH 12/16] Add `latest_version_id` to the `ModelResponse` (#2266) * add `latest_version_id` * Auto-update of NLP template * Update src/zenml/models/v2/core/model.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * update test case * Revert "update test case" This reverts commit eda0e6bd8345a2a52324812a9b220e6b0ef7c9fa. * update test case --------- Co-authored-by: GitHub Actions Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/zenml/cli/model.py | 2 +- src/zenml/models/v2/core/model.py | 18 ++++++++++++++---- src/zenml/zen_stores/schemas/model_schemas.py | 12 +++++++----- tests/integration/functional/test_client.py | 13 +++++++++++++ .../functional/zen_stores/test_zen_store.py | 11 +++++++++-- 5 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/zenml/cli/model.py b/src/zenml/cli/model.py index 2fe1d633c5d..da0f2410f29 100644 --- a/src/zenml/cli/model.py +++ b/src/zenml/cli/model.py @@ -38,7 +38,7 @@ def _model_to_print(model: ModelResponse) -> Dict[str, Any]: return { "id": model.id, "name": model.name, - "latest_version": model.latest_version, + "latest_version": model.latest_version_name, "description": model.description, "tags": [t.name for t in model.tags], "use_cases": model.use_cases, diff --git a/src/zenml/models/v2/core/model.py b/src/zenml/models/v2/core/model.py index cd88c4276a8..b27a1faecd0 100644 --- a/src/zenml/models/v2/core/model.py +++ b/src/zenml/models/v2/core/model.py @@ -116,7 +116,8 @@ class ModelResponseBody(WorkspaceScopedResponseBody): tags: List["TagResponse"] = Field( title="Tags associated with the model", ) - latest_version: Optional[str] + latest_version_name: Optional[str] + latest_version_id: Optional[UUID] created: datetime = Field( title="The timestamp when this component was created." ) @@ -200,13 +201,22 @@ def tags(self) -> List["TagResponse"]: return self.get_body().tags @property - def latest_version(self) -> Optional[str]: - """The `latest_version` property. + def latest_version_name(self) -> Optional[str]: + """The `latest_version_name` property. Returns: the value of the property. """ - return self.get_body().latest_version + return self.get_body().latest_version_name + + @property + def latest_version_id(self) -> Optional[UUID]: + """The `latest_version_id` property. + + Returns: + the value of the property. + """ + return self.get_body().latest_version_id @property def created(self) -> datetime: diff --git a/src/zenml/zen_stores/schemas/model_schemas.py b/src/zenml/zen_stores/schemas/model_schemas.py index 3190b60c4d1..843c8876253 100644 --- a/src/zenml/zen_stores/schemas/model_schemas.py +++ b/src/zenml/zen_stores/schemas/model_schemas.py @@ -145,11 +145,12 @@ def to_model( if self.model_versions: version_numbers = [mv.number for mv in self.model_versions] - latest_version = self.model_versions[ - version_numbers.index(max(version_numbers)) - ].name + latest_version_idx = version_numbers.index(max(version_numbers)) + latest_version_name = self.model_versions[latest_version_idx].name + latest_version_id = self.model_versions[latest_version_idx].id else: - latest_version = None + latest_version_name = None + latest_version_id = None metadata = None if hydrate: @@ -171,7 +172,8 @@ def to_model( created=self.created, updated=self.updated, tags=tags, - latest_version=latest_version, + latest_version_name=latest_version_name, + latest_version_id=latest_version_id, ) return ModelResponse( diff --git a/tests/integration/functional/test_client.py b/tests/integration/functional/test_client.py index 5398b6fd3df..3b5dd08ef1f 100644 --- a/tests/integration/functional/test_client.py +++ b/tests/integration/functional/test_client.py @@ -1310,6 +1310,19 @@ def test_name_is_mutable(self, clean_client: "Client"): model = clean_client.get_model(model.id) assert model.name == "bar" + def test_latest_version_retrieval(self, clean_client: "Client"): + """Test that model response has proper latest version in it.""" + model = clean_client.create_model(name=self.MODEL_NAME) + mv1 = clean_client.create_model_version(model.id, name="foo") + model_ = clean_client.get_model(model.id) + assert model_.latest_version_name == mv1.name + assert model_.latest_version_id == mv1.id + + mv2 = clean_client.create_model_version(model.id, name="bar") + model_ = clean_client.get_model(model.id) + assert model_.latest_version_name == mv2.name + assert model_.latest_version_id == mv2.id + class TestModelVersion: MODEL_NAME = "foo" diff --git a/tests/integration/functional/zen_stores/test_zen_store.py b/tests/integration/functional/zen_stores/test_zen_store.py index 811877e8d1a..ea26320be43 100644 --- a/tests/integration/functional/zen_stores/test_zen_store.py +++ b/tests/integration/functional/zen_stores/test_zen_store.py @@ -3610,7 +3610,8 @@ def test_latest_version_properly_fetched(self): """Test that latest version can be properly fetched.""" with ModelVersionContext() as created_model: zs = Client().zen_store - assert zs.get_model(created_model.id).latest_version is None + assert zs.get_model(created_model.id).latest_version_name is None + assert zs.get_model(created_model.id).latest_version_id is None for name in ["great one", "yet another one"]: mv = zs.create_model_version( ModelVersionRequest( @@ -3620,7 +3621,13 @@ def test_latest_version_properly_fetched(self): name=name, ) ) - assert zs.get_model(created_model.id).latest_version == mv.name + assert ( + zs.get_model(created_model.id).latest_version_name + == mv.name + ) + assert ( + zs.get_model(created_model.id).latest_version_id == mv.id + ) time.sleep(1) # thanks to MySQL again! def test_update_name(self, clean_client: "Client"): From 625c46c73906454c9a554688b914b37ee1ad425b Mon Sep 17 00:00:00 2001 From: Alex Strick van Linschoten Date: Fri, 12 Jan 2024 09:47:27 +0100 Subject: [PATCH 13/16] remove manual linkage from docs (#2272) --- .../data-management/model-management.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/docs/book/user-guide/advanced-guide/data-management/model-management.md b/docs/book/user-guide/advanced-guide/data-management/model-management.md index 7140685dde4..48d868c2aa4 100644 --- a/docs/book/user-guide/advanced-guide/data-management/model-management.md +++ b/docs/book/user-guide/advanced-guide/data-management/model-management.md @@ -323,17 +323,5 @@ artifact, and you specify whether it's for a model or deployment by using the `is_model_artifact` and `is_deployment_artifact` flags (as shown above) else it will be assumed to be a data artifact. -### Manual Linkage - -Finally, artifacts can be linked to an existing model version manually using the -SDK: - -```python -model_version = ModelVersion(name="my_model", version="1.0.0") -model_version.link_artifact(my_artifact, name="new_artifact") -``` - -The `link_artifact` method handles creating this connection. -
ZenML Scarf
From 9b2a3aa9b61068a6ca7af206059d5912f07564a0 Mon Sep 17 00:00:00 2001 From: Christian Versloot Date: Fri, 12 Jan 2024 09:53:03 +0100 Subject: [PATCH 14/16] Improve action by adding advice to KeyError when configured steps are not present in pipeline (#2265) * Improve action by adding advice to KeyError * Reformatting --- src/zenml/config/compiler.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/zenml/config/compiler.py b/src/zenml/config/compiler.py index c3f74c5c748..238ab7c29fa 100644 --- a/src/zenml/config/compiler.py +++ b/src/zenml/config/compiler.py @@ -210,7 +210,9 @@ def _apply_run_configuration( for invocation_id in config.steps: if invocation_id not in pipeline.invocations: - raise KeyError(f"No step invocation with id {invocation_id}.") + raise KeyError( + f"Configuration for step {invocation_id} cannot be applied to any pipeline step. Make sure that all configured steps are present in your pipeline." + ) # Override `enable_cache` of all steps if set at run level if config.enable_cache is not None: From a0fd100e247d1c1dd9a74bb2634fd139355ed159 Mon Sep 17 00:00:00 2001 From: Safoine El Khabich <34200873+safoinme@users.noreply.github.com> Date: Fri, 12 Jan 2024 12:12:36 +0100 Subject: [PATCH 15/16] Allow multi step configuration for skypilot (#2166) * allow multi step configuration for skypilot * fixes * Auto-update of Starter template * update skypilot to allow running using an orchestrating VM * add ability to create an aws config when configuring local client * Add advanced AWS configurations to config.yaml * Fix cluster name concatenation in skypilot orchestrator entrypoint * Fix AWS service connector and Skypilot orchestrator issues * Add APT packages to Skypilot integrations and sanitize cluster name * Remove advanced AWS configurations from config.yaml * Update Skypilot orchestrator code * Auto-update of Starter template * Refactor cluster name sanitization in SkypilotBaseOrchestrator * Refactor SkypilotBaseOrchestrator and SkypilotOrchestratorEntrypoint * Remove commented out code and update Skypilot orchestrator entrypoint * Fix GCP service connector support for local gcloud CLI login * Fix Skypilot orchestrator cluster name generation * Refactor cluster creation logic in SkypilotBaseOrchestrator * Allow custom docker run args when using the Skypilot orchestrator * Handle exception and log error message in SkypilotBaseOrchestrator * Refactor AWS service connector to improve file handling * Refactor Skypilot integrations for ZenML * Add encoding parameter to subprocess call * Update Skypilot integration for AWS, GCP, and Azure * Add note about configuring pipeline resources for specific orchestrator flavors * Update src/zenml/integrations/gcp/service_connectors/gcp_service_connector.py Co-authored-by: Alex Strick van Linschoten * Add error handling for running code in a notebook and update Skypilot orchestrator entrypoint --------- Co-authored-by: Alex Strick van Linschoten Co-authored-by: GitHub Actions Co-authored-by: Stefan Nica Co-authored-by: Michael Schuster --- .../orchestrators/skypilot-vm.md | 54 +++- .../aws_service_connector.py | 16 + .../gcp_service_connector.py | 108 +++++-- src/zenml/integrations/skypilot/__init__.py | 36 +-- .../skypilot_orchestrator_base_vm_config.py | 4 +- .../skypilot_base_vm_orchestrator.py | 95 ++++-- .../skypilot_orchestrator_entrypoint.py | 277 ++++++++++++++++++ ...t_orchestrator_entrypoint_configuration.py | 77 +++++ src/zenml/orchestrators/step_launcher.py | 4 +- 9 files changed, 595 insertions(+), 76 deletions(-) create mode 100644 src/zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py create mode 100644 src/zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint_configuration.py diff --git a/docs/book/stacks-and-components/component-guide/orchestrators/skypilot-vm.md b/docs/book/stacks-and-components/component-guide/orchestrators/skypilot-vm.md index ad7fd9d1ef8..3d250d5cdd9 100644 --- a/docs/book/stacks-and-components/component-guide/orchestrators/skypilot-vm.md +++ b/docs/book/stacks-and-components/component-guide/orchestrators/skypilot-vm.md @@ -65,16 +65,16 @@ To use the SkyPilot VM Orchestrator, you need: * One of the SkyPilot integrations installed. You can install the SkyPilot integration for your cloud provider of choice using the following command: ```shell # For AWS - pip install "zenml[connectors-gcp]" - zenml integration install aws vm_aws + pip install "zenml[connectors-aws]" + zenml integration install aws skypilot_aws # for GCP pip install "zenml[connectors-gcp]" - zenml integration install gcp vm_gcp # for GCP + zenml integration install gcp skypilot_gcp # for GCP # for Azure pip install "zenml[connectors-azure]" - zenml integration install azure vm_azure # for Azure + zenml integration install azure skypilot_azure # for Azure ``` * [Docker](https://www.docker.com) installed and running. * A [remote artifact store](../artifact-stores/artifact-stores.md) as part of your stack. @@ -91,7 +91,7 @@ We need first to install the SkyPilot integration for AWS and the AWS connectors ```shell pip install "zenml[connectors-aws]" - zenml integration install aws vm_aws + zenml integration install aws skypilot_aws ``` To provision VMs on AWS, your VM Orchestrator stack component needs to be configured to authenticate with [AWS Service Connector](../../../stacks-and-components/auth-management/aws-service-connector.md). @@ -141,7 +141,7 @@ We need first to install the SkyPilot integration for GCP and the GCP extra for ```shell pip install "zenml[connectors-gcp]" - zenml integration install gcp vm_gcp + zenml integration install gcp skypilot_gcp ``` To provision VMs on GCP, your VM Orchestrator stack component needs to be configured to authenticate with [GCP Service Connector](../../../stacks-and-components/auth-management/gcp-service-connector.md) @@ -199,7 +199,7 @@ We need first to install the SkyPilot integration for Azure and the Azure extra ```shell pip install "zenml[connectors-azure]" - zenml integration install azure vm_azure + zenml integration install azure skypilot_azure ``` To provision VMs on Azure, your VM Orchestrator stack component needs to be configured to authenticate with [Azure Service Connector](../../../stacks-and-components/auth-management/azure-service-connector.md) @@ -371,6 +371,46 @@ skypilot_settings = SkypilotAzureOrchestratorSettings( {% endtab %} {% endtabs %} + +One of the key features of the SkyPilot VM Orchestrator is the ability to run each step of a pipeline on a separate VM with its own specific settings. This allows for fine-grained control over the resources allocated to each step, ensuring that each part of your pipeline has the necessary compute power while optimizing for cost and efficiency. + +## Configuring Step-Specific Resources + +The SkyPilot VM Orchestrator allows you to configure resources for each step individually. This means you can specify different VM types, CPU and memory requirements, and even use spot instances for certain steps while using on-demand instances for others. + +To configure step-specific resources, you can pass a `SkypilotBaseOrchestratorSettings` object to the `settings` parameter of the `@step` decorator. This object allows you to define various attributes such as `instance_type`, `cpus`, `memory`, `use_spot`, `region`, and more. + +Here's an example of how to configure specific resources for a step for the AWS cloud: + +```python +from zenml.integrations.skypilot.flavors.skypilot_orchestrator_aws_vm_flavor import SkypilotAWSOrchestratorSettings + +# Settings for a specific step that requires more resources +high_resource_settings = SkypilotAWSOrchestratorSettings( + instance_type='t2.2xlarge', + cpus=8, + memory=32, + use_spot=False, + region='us-east-1', + # ... other settings +) + +@step(settings={"orchestrator.vm_aws": high_resource_settings}) +def my_resource_intensive_step(): + # Step implementation + pass +``` + +{% hint style="warning" %} +When configuring pipeline or step-specific resources, you can use the `settings` +parameter to specifically target the orchestrator flavor you want to use +`orchestrator.STACK_COMPONENT_FLAVOR` and not orchestrator component name +`orchestrator.STACK_COMPONENT_NAME`. For example, if you want to configure +resources for the `vm_gcp` flavor, you can use `settings={"orchestrator.vm_gcp": ...}`. +{% endhint %} + +By using the `settings` parameter, you can tailor the resources for each step according to its specific needs. This flexibility allows you to optimize your pipeline execution for both performance and cost. + Check out the [SDK docs](https://sdkdocs.zenml.io/latest/integration\_code\_docs/integrations-skypilot/#zenml.integrations.skypilot.flavors.skypilot\_orchestrator\_base\_vm\_flavor.SkypilotBaseOrchestratorSettings) for a full list of available attributes and [this docs page](/docs/book/user-guide/advanced-guide/pipelining-features/configure-steps-pipelines.md) for more diff --git a/src/zenml/integrations/aws/service_connectors/aws_service_connector.py b/src/zenml/integrations/aws/service_connectors/aws_service_connector.py index fd17fb3ec00..7ce03867fc6 100644 --- a/src/zenml/integrations/aws/service_connectors/aws_service_connector.py +++ b/src/zenml/integrations/aws/service_connectors/aws_service_connector.py @@ -27,6 +27,7 @@ import base64 import datetime import json +import os import re from typing import Any, Dict, List, Optional, Tuple, cast @@ -1371,6 +1372,21 @@ def _configure_local_client( "aws_session_token" ] = credentials.token + aws_credentials_path = os.path.join( + users_home, ".aws", "credentials" + ) + + # Create the file as well as the parent dir if needed. + dirname = os.path.split(aws_credentials_path)[0] + if not os.path.isdir(dirname): + os.makedirs(dirname) + with os.fdopen( + os.open(aws_credentials_path, os.O_WRONLY | os.O_CREAT, 0o600), + "w", + ): + pass + + # Write the credentials to the file common.rewrite_credentials_file(all_profiles, users_home) logger.info( diff --git a/src/zenml/integrations/gcp/service_connectors/gcp_service_connector.py b/src/zenml/integrations/gcp/service_connectors/gcp_service_connector.py index 577f935dbf0..94b37496575 100644 --- a/src/zenml/integrations/gcp/service_connectors/gcp_service_connector.py +++ b/src/zenml/integrations/gcp/service_connectors/gcp_service_connector.py @@ -23,6 +23,9 @@ import json import os import re +import shutil +import subprocess +import tempfile from typing import Any, Dict, List, Optional, Tuple import google.api_core.exceptions @@ -1062,6 +1065,7 @@ def _configure_local_client( NotImplementedError: If the connector instance does not support local configuration for the configured resource type or authentication method.registry + AuthorizationException: If the local client configuration fails. """ resource_type = self.resource_type @@ -1070,16 +1074,8 @@ def _configure_local_client( # There is no way to configure the local gcloud CLI to use # temporary OAuth 2.0 tokens. However, we can configure it to use - # the user account credentials or service account credentials - if self.auth_method == GCPAuthenticationMethods.USER_ACCOUNT: - assert isinstance(self.config, GCPUserAccountConfig) - # Use the user account credentials JSON to configure the - # local gcloud CLI - gcloud_config_json = ( - self.config.user_account_json.get_secret_value() - ) - - elif self.auth_method == GCPAuthenticationMethods.SERVICE_ACCOUNT: + # the service account credentials + if self.auth_method == GCPAuthenticationMethods.SERVICE_ACCOUNT: assert isinstance(self.config, GCPServiceAccountConfig) # Use the service account credentials JSON to configure the # local gcloud CLI @@ -1090,7 +1086,66 @@ def _configure_local_client( if gcloud_config_json: from google.auth import _cloud_sdk - # Dump the user account or service account credentials JSON to + if not shutil.which("gcloud"): + raise AuthorizationException( + "The local gcloud CLI is not installed. Please " + "install the gcloud CLI to use this feature." + ) + + # Write the credentials JSON to a temporary file + with tempfile.NamedTemporaryFile( + mode="w", suffix=".json", delete=True + ) as f: + f.write(gcloud_config_json) + f.flush() + adc_path = f.name + + try: + # Run the gcloud CLI command to configure the local + # gcloud CLI to use the credentials JSON + subprocess.run( + [ + "gcloud", + "auth", + "login", + "--cred-file", + adc_path, + ], + check=True, + stderr=subprocess.STDOUT, + encoding="utf-8", + stdout=subprocess.PIPE, + ) + except subprocess.CalledProcessError as e: + raise AuthorizationException( + f"Failed to configure the local gcloud CLI to use " + f"the credentials JSON: {e}\n" + f"{e.stdout.decode()}" + ) + + try: + # Run the gcloud CLI command to configure the local gcloud + # CLI to use the credentials project ID + subprocess.run( + [ + "gcloud", + "config", + "set", + "project", + self.config.project_id, + ], + check=True, + stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, + ) + except subprocess.CalledProcessError as e: + raise AuthorizationException( + f"Failed to configure the local gcloud CLI to use " + f"the project ID: {e}\n" + f"{e.stdout.decode()}" + ) + + # Dump the service account credentials JSON to # the local gcloud application default credentials file adc_path = ( _cloud_sdk.get_application_default_credentials_path() @@ -1099,8 +1154,8 @@ def _configure_local_client( f.write(gcloud_config_json) logger.info( - f"Updated the local gcloud default application " - f"credentials file at '{adc_path}'" + "Updated the local gcloud CLI and application default " + f"credentials file ({adc_path})." ) return @@ -1108,7 +1163,6 @@ def _configure_local_client( raise NotImplementedError( f"Local gcloud client configuration for resource type " f"{resource_type} is only supported if the " - f"'{GCPAuthenticationMethods.USER_ACCOUNT}' or " f"'{GCPAuthenticationMethods.SERVICE_ACCOUNT}' authentication " f"method is used and only if the generation of temporary OAuth " f"2.0 tokens is disabled by setting the " @@ -1257,13 +1311,27 @@ def _auto_configure( "GOOGLE_APPLICATION_CREDENTIALS" ) if service_account_json_file is None: - # Shouldn't happen since google.auth.default() should - # already have loaded the credentials from the environment + # No explicit service account JSON file was specified in the + # environment, meaning that the credentials were loaded from + # the GCP application default credentials (ADC) file. + from google.auth import _cloud_sdk + + # Use the location of the gcloud application default + # credentials file + service_account_json_file = ( + _cloud_sdk.get_application_default_credentials_path() + ) + + if not service_account_json_file or not os.path.isfile( + service_account_json_file + ): raise AuthorizationException( - "No GCP service account credentials found in the " - "environment. Please set the " - "GOOGLE_APPLICATION_CREDENTIALS environment variable " - "to the path of the service account JSON file." + "No GCP service account credentials were found in the " + "environment or the application default credentials " + "path. Please set the GOOGLE_APPLICATION_CREDENTIALS " + "environment variable to the path of the service " + "account JSON file or run 'gcloud auth application-" + "default login' to generate a new ADC file." ) with open(service_account_json_file, "r") as f: service_account_json = f.read() diff --git a/src/zenml/integrations/skypilot/__init__.py b/src/zenml/integrations/skypilot/__init__.py index 5c0330770a2..1b096c4e08c 100644 --- a/src/zenml/integrations/skypilot/__init__.py +++ b/src/zenml/integrations/skypilot/__init__.py @@ -30,52 +30,52 @@ SKYPILOT_GCP_ORCHESTRATOR_FLAVOR = "vm_gcp" SKYPILOT_AZURE_ORCHESTRATOR_FLAVOR = "vm_azure" +class SkypilotGCPIntegration(Integration): + """Definition of Skypilot Integration for ZenML.""" -class SkypilotAWSIntegration(Integration): - """Definition of Skypilot AWS Integration for ZenML.""" - - NAME = SKYPILOT_AWS - REQUIREMENTS = ["skypilot[aws]"] + NAME = SKYPILOT_GCP + REQUIREMENTS = ["skypilot[aws,gcp,azure]<=0.4.1"] + APT_PACKAGES = ["openssh-client","rsync"] @classmethod def flavors(cls) -> List[Type[Flavor]]: - """Declare the stack component flavors for the Skypilot AWS integration. + """Declare the stack component flavors for the Skypilot GCP integration. Returns: List of stack component flavors for this integration. """ from zenml.integrations.skypilot.flavors import ( - SkypilotAWSOrchestratorFlavor, + SkypilotGCPOrchestratorFlavor, ) - return [SkypilotAWSOrchestratorFlavor] - + return [SkypilotGCPOrchestratorFlavor] -class SkypilotGCPIntegration(Integration): - """Definition of Skypilot Integration for ZenML.""" +class SkypilotAWSIntegration(Integration): + """Definition of Skypilot AWS Integration for ZenML.""" - NAME = SKYPILOT_GCP - REQUIREMENTS = ["skypilot[gcp]"] + NAME = SKYPILOT_AWS + REQUIREMENTS = ["skypilot[aws,gcp,azure]<=0.4.1"] + APT_PACKAGES = ["openssh-client","rsync"] @classmethod def flavors(cls) -> List[Type[Flavor]]: - """Declare the stack component flavors for the Skypilot GCP integration. + """Declare the stack component flavors for the Skypilot AWS integration. Returns: List of stack component flavors for this integration. """ from zenml.integrations.skypilot.flavors import ( - SkypilotGCPOrchestratorFlavor, + SkypilotAWSOrchestratorFlavor, ) - return [SkypilotGCPOrchestratorFlavor] - + return [SkypilotAWSOrchestratorFlavor] class SkypilotAzureIntegration(Integration): """Definition of Skypilot Integration for ZenML.""" NAME = SKYPILOT_AZURE - REQUIREMENTS = ["skypilot[azure]"] + REQUIREMENTS = ["skypilot[aws,gcp,azure]<=0.4.1"] + APT_PACKAGES = ["openssh-client","rsync"] @classmethod def flavors(cls) -> List[Type[Flavor]]: diff --git a/src/zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py b/src/zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py index daca191d7fe..6f04b0445ec 100644 --- a/src/zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +++ b/src/zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py @@ -13,7 +13,7 @@ # permissions and limitations under the License. """Skypilot orchestrator base config and settings.""" -from typing import Dict, Literal, Optional, Union +from typing import Dict, List, Literal, Optional, Union from zenml.config.base_settings import BaseSettings from zenml.logger import get_logger @@ -107,6 +107,8 @@ class SkypilotBaseOrchestratorSettings(BaseSettings): down: bool = True stream_logs: bool = True + docker_run_args: List[str] = [] + class SkypilotBaseOrchestratorConfig( # type: ignore[misc] # https://github.com/pydantic/pydantic/issues/4173 BaseOrchestratorConfig, SkypilotBaseOrchestratorSettings diff --git a/src/zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py b/src/zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py index 48990bada12..f1ca4db56d9 100644 --- a/src/zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +++ b/src/zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py @@ -14,24 +14,26 @@ """Implementation of the Skypilot base VM orchestrator.""" import os -import time +import re from abc import abstractmethod from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, cast -from uuid import uuid4 import sky -from zenml.entrypoints import PipelineEntrypointConfiguration from zenml.enums import StackComponentType +from zenml.environment import Environment from zenml.integrations.skypilot.flavors.skypilot_orchestrator_base_vm_config import ( SkypilotBaseOrchestratorSettings, ) +from zenml.integrations.skypilot.orchestrators.skypilot_orchestrator_entrypoint_configuration import ( + SkypilotOrchestratorEntrypointConfiguration, +) from zenml.logger import get_logger from zenml.orchestrators import ( ContainerizedOrchestrator, ) +from zenml.orchestrators.utils import get_orchestrator_run_name from zenml.stack import StackValidator -from zenml.utils import string_utils if TYPE_CHECKING: from zenml.models import PipelineDeploymentResponse @@ -136,7 +138,7 @@ def prepare_or_run_pipeline( stack: "Stack", environment: Dict[str, str], ) -> Any: - """Runs all pipeline steps in Skypilot containers. + """Runs each pipeline step in a separate Skypilot container. Args: deployment: The pipeline deployment to prepare or run. @@ -146,7 +148,18 @@ def prepare_or_run_pipeline( Raises: Exception: If the pipeline run fails. + RuntimeError: If the code is running in a notebook. """ + # First check whether the code is running in a notebook. + if Environment.in_notebook(): + raise RuntimeError( + "The Skypilot orchestrator cannot run pipelines in a notebook " + "environment. The reason is that it is non-trivial to create " + "a Docker image of a notebook. Please consider refactoring " + "your notebook cells into separate scripts in a Python module " + "and run the code outside of a notebook when using this " + "orchestrator." + ) if deployment.schedule: logger.warning( "Skypilot Orchestrator currently does not support the" @@ -154,32 +167,42 @@ def prepare_or_run_pipeline( "and the pipeline will be run immediately." ) - # Set up some variables for configuration - orchestrator_run_id = str(uuid4()) - environment[ - ENV_ZENML_SKYPILOT_ORCHESTRATOR_RUN_ID - ] = orchestrator_run_id - settings = cast( SkypilotBaseOrchestratorSettings, self.get_settings(deployment), ) - entrypoint = PipelineEntrypointConfiguration.get_entrypoint_command() - entrypoint_str = " ".join(entrypoint) - arguments = PipelineEntrypointConfiguration.get_entrypoint_arguments( - deployment_id=deployment.id + pipeline_name = deployment.pipeline_configuration.name + orchestrator_run_name = get_orchestrator_run_name(pipeline_name) + + assert stack.container_registry + + # Get Docker image for the orchestrator pod + try: + image = self.get_image(deployment=deployment) + except KeyError: + # If no generic pipeline image exists (which means all steps have + # custom builds) we use a random step image as all of them include + # dependencies for the active stack + pipeline_step_name = next(iter(deployment.step_configurations)) + image = self.get_image( + deployment=deployment, step_name=pipeline_step_name + ) + + # Build entrypoint command and args for the orchestrator pod. + # This will internally also build the command/args for all step pods. + command = SkypilotOrchestratorEntrypointConfiguration.get_entrypoint_command() + entrypoint_str = " ".join(command) + args = SkypilotOrchestratorEntrypointConfiguration.get_entrypoint_arguments( + run_name=orchestrator_run_name, + deployment_id=deployment.id, ) - arguments_str = " ".join(arguments) + arguments_str = " ".join(args) - # Set up docker run command - image = self.get_image(deployment=deployment) docker_environment_str = " ".join( f"-e {k}={v}" for k, v in environment.items() ) - start_time = time.time() - instance_type = settings.instance_type or self.DEFAULT_INSTANCE_TYPE # Set up credentials @@ -188,8 +211,7 @@ def prepare_or_run_pipeline( # Guaranteed by stack validation assert stack is not None and stack.container_registry is not None - docker_creds = stack.container_registry.credentials - if docker_creds: + if docker_creds := stack.container_registry.credentials: docker_username, docker_password = docker_creds setup = ( f"docker login --username $DOCKER_USERNAME --password " @@ -232,6 +254,7 @@ def prepare_or_run_pipeline( ) ) + # Set the cluster name cluster_name = settings.cluster_name if cluster_name is None: # Find existing cluster @@ -243,6 +266,10 @@ def prepare_or_run_pipeline( logger.info( f"Found existing cluster {cluster_name}. Reusing..." ) + if cluster_name is None: + cluster_name = self.sanitize_cluster_name( + f"{orchestrator_run_name}" + ) # Launch the cluster sky.launch( @@ -252,17 +279,29 @@ def prepare_or_run_pipeline( idle_minutes_to_autostop=settings.idle_minutes_to_autostop, down=settings.down, stream_logs=settings.stream_logs, + detach_setup=True, ) except Exception as e: - raise e + logger.error(f"Pipeline run failed: {e}") + raise finally: # Unset the service connector AWS profile ENV variable self.prepare_environment_variable(set=False) - run_duration = time.time() - start_time - logger.info( - "Pipeline run has finished in `%s`.", - string_utils.get_human_readable_time(run_duration), - ) + def sanitize_cluster_name(self, name: str) -> str: + """Sanitize the value to be used in a cluster name. + + Args: + name: Arbitrary input cluster name. + + Returns: + Sanitized cluster name. + """ + name = re.sub( + r"[^a-z0-9-]", "-", name.lower() + ) # replaces any character that is not a lowercase letter, digit, or hyphen with a hyphen + name = re.sub(r"^[-]+", "", name) # trim leading hyphens + name = re.sub(r"[-]+$", "", name) # trim trailing hyphens + return name diff --git a/src/zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py b/src/zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py new file mode 100644 index 00000000000..ada74e63bb4 --- /dev/null +++ b/src/zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py @@ -0,0 +1,277 @@ +# Copyright (c) ZenML GmbH 2024. All Rights Reserved. +# +# 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: +# +# https://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. +"""Entrypoint of the Skypilot master/orchestrator VM.""" + +import argparse +import socket +import time +from typing import Dict, cast + +import sky + +from zenml.client import Client +from zenml.entrypoints.step_entrypoint_configuration import ( + StepEntrypointConfiguration, +) +from zenml.enums import ExecutionStatus +from zenml.integrations.skypilot.flavors.skypilot_orchestrator_base_vm_config import ( + SkypilotBaseOrchestratorSettings, +) +from zenml.integrations.skypilot.orchestrators.skypilot_base_vm_orchestrator import ( + ENV_ZENML_SKYPILOT_ORCHESTRATOR_RUN_ID, + SkypilotBaseOrchestrator, +) +from zenml.logger import get_logger +from zenml.orchestrators.dag_runner import ThreadedDagRunner +from zenml.orchestrators.utils import get_config_environment_vars + +logger = get_logger(__name__) + + +def parse_args() -> argparse.Namespace: + """Parse entrypoint arguments. + + Returns: + Parsed args. + """ + parser = argparse.ArgumentParser() + parser.add_argument("--run_name", type=str, required=True) + parser.add_argument("--deployment_id", type=str, required=True) + return parser.parse_args() + + +def main() -> None: + """Entrypoint of the Skypilot master/orchestrator VM. + + This is the entrypoint of the Skypilot master/orchestrator VM. It is + responsible for provisioning the VM and running the pipeline steps in + separate VMs. + + The VM is provisioned using the `sky` library. The pipeline steps are run + using the `sky` library as well. + + Raises: + TypeError: If the active stack's orchestrator is not an instance of + SkypilotBaseOrchestrator. + ValueError: If the active stack's container registry is None. + """ + # Log to the container's stdout so it can be streamed by the client. + logger.info("Skypilot orchestrator VM started.") + + # Parse / extract args. + args = parse_args() + + orchestrator_run_id = socket.gethostname() + + deployment = Client().get_deployment(args.deployment_id) + + pipeline_dag = { + step_name: step.spec.upstream_steps + for step_name, step in deployment.step_configurations.items() + } + step_command = StepEntrypointConfiguration.get_entrypoint_command() + entrypoint_str = " ".join(step_command) + + active_stack = Client().active_stack + + orchestrator = active_stack.orchestrator + if not isinstance(orchestrator, SkypilotBaseOrchestrator): + raise TypeError( + "The active stack's orchestrator is not an instance of SkypilotBaseOrchestrator." + ) + + # Set up credentials + orchestrator.setup_credentials() + + # Set the service connector AWS profile ENV variable + orchestrator.prepare_environment_variable(set=True) + + # get active container registry + container_registry = active_stack.container_registry + if container_registry is None: + raise ValueError("Container registry cannot be None.") + + if docker_creds := container_registry.credentials: + docker_username, docker_password = docker_creds + setup = ( + f"docker login --username $DOCKER_USERNAME --password " + f"$DOCKER_PASSWORD {container_registry.config.uri}" + ) + task_envs = { + "DOCKER_USERNAME": docker_username, + "DOCKER_PASSWORD": docker_password, + } + else: + setup = None + task_envs = None + + unique_resource_configs: Dict[str, str] = {} + for step_name, step in deployment.step_configurations.items(): + settings = cast( + SkypilotBaseOrchestratorSettings, + orchestrator.get_settings(step), + ) + # Handle both str and Dict[str, int] types for accelerators + if isinstance(settings.accelerators, dict): + accelerators_hashable = frozenset(settings.accelerators.items()) + elif isinstance(settings.accelerators, str): + accelerators_hashable = frozenset({(settings.accelerators, 1)}) + else: + accelerators_hashable = None + resource_config = ( + settings.instance_type, + settings.cpus, + settings.memory, + settings.disk_size, # Assuming disk_size is part of the settings + settings.disk_tier, # Assuming disk_tier is part of the settings + settings.use_spot, + settings.spot_recovery, + settings.region, + settings.zone, + accelerators_hashable, + ) + cluster_name_parts = [ + orchestrator.sanitize_cluster_name(str(part)) + for part in resource_config + if part is not None + ] + cluster_name = f"cluster-{orchestrator_run_id}" + "-".join( + cluster_name_parts + ) + unique_resource_configs[step_name] = cluster_name + + run = Client().list_pipeline_runs( + sort_by="asc:created", + size=1, + deployment_id=args.deployment_id, + status=ExecutionStatus.INITIALIZING, + )[0] + + logger.info("Fetching pipeline run: %s", run.id) + + def run_step_on_skypilot_vm(step_name: str) -> None: + """Run a pipeline step in a separate Skypilot VM. + + Args: + step_name: Name of the step. + """ + cluster_name = unique_resource_configs[step_name] + + image = SkypilotBaseOrchestrator.get_image( + deployment=deployment, step_name=step_name + ) + + step_args = StepEntrypointConfiguration.get_entrypoint_arguments( + step_name=step_name, deployment_id=deployment.id + ) + arguments_str = " ".join(step_args) + + step = deployment.step_configurations[step_name] + settings = cast( + SkypilotBaseOrchestratorSettings, + orchestrator.get_settings(step), + ) + env = get_config_environment_vars() + env[ENV_ZENML_SKYPILOT_ORCHESTRATOR_RUN_ID] = orchestrator_run_id + + docker_environment_str = " ".join( + f"-e {k}={v}" for k, v in env.items() + ) + custom_run_args = " ".join(settings.docker_run_args) + if custom_run_args: + custom_run_args += " " + + # Set up the task + run_command = f"docker run --rm {custom_run_args}{docker_environment_str} {image} {entrypoint_str} {arguments_str}" + task_name = f"{deployment.id}-{step_name}-{time.time()}" + task = sky.Task( + run=run_command, + setup=setup, + envs=task_envs, + name=task_name, + ) + task = task.set_resources( + sky.Resources( + cloud=orchestrator.cloud, + instance_type=settings.instance_type + or orchestrator.DEFAULT_INSTANCE_TYPE, + cpus=settings.cpus, + memory=settings.memory, + disk_size=settings.disk_size, + disk_tier=settings.disk_tier, + accelerators=settings.accelerators, + accelerator_args=settings.accelerator_args, + use_spot=settings.use_spot, + spot_recovery=settings.spot_recovery, + region=settings.region, + zone=settings.zone, + image_id=settings.image_id, + ) + ) + + sky.launch( + task, + cluster_name, + retry_until_up=settings.retry_until_up, + idle_minutes_to_autostop=settings.idle_minutes_to_autostop, + down=settings.down, + stream_logs=settings.stream_logs, + detach_setup=True, + detach_run=True, + ) + + # Wait for pod to finish. + logger.info(f"Waiting for pod of step `{step_name}` to start...") + + current_run = Client().get_pipeline_run(run.id) + + step_is_finished = False + while not step_is_finished: + time.sleep(10) + current_run = Client().get_pipeline_run(run.id) + try: + step_is_finished = current_run.steps[ + step_name + ].status.is_finished + except KeyError: + # Step is not yet in the run, so we wait for it to appear + continue + + # Pop the resource configuration for this step + unique_resource_configs.pop(step_name) + + if cluster_name in unique_resource_configs.values(): + # If there are more steps using this configuration, skip deprovisioning the cluster + logger.info( + f"Resource configuration for cluster '{cluster_name}' " + "is used by subsequent steps. Skipping the deprovisioning of " + "the cluster." + ) + else: + # If there are no more steps using this configuration, down the cluster + logger.info( + f"Resource configuration for cluster '{cluster_name}' " + "is not used by subsequent steps. deprovisioning the cluster." + ) + sky.down(cluster_name) + + logger.info(f"Running step `{step_name}` on a VM is completed.") + + ThreadedDagRunner(dag=pipeline_dag, run_fn=run_step_on_skypilot_vm).run() + + logger.info("Orchestration VM provisioned.") + + +if __name__ == "__main__": + main() diff --git a/src/zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint_configuration.py b/src/zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint_configuration.py new file mode 100644 index 00000000000..2df18d58d61 --- /dev/null +++ b/src/zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint_configuration.py @@ -0,0 +1,77 @@ +# Copyright (c) ZenML GmbH 2024. All Rights Reserved. +# +# 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: +# +# https://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. +"""Entrypoint configuration for the Skypilot master/orchestrator VM.""" + +from typing import TYPE_CHECKING, List, Set + +if TYPE_CHECKING: + from uuid import UUID + +RUN_NAME_OPTION = "run_name" +DEPLOYMENT_ID_OPTION = "deployment_id" + + +class SkypilotOrchestratorEntrypointConfiguration: + """Entrypoint configuration for the Skypilot master/orchestrator VM.""" + + @classmethod + def get_entrypoint_options(cls) -> Set[str]: + """Gets all the options required for running this entrypoint. + + Returns: + Entrypoint options. + """ + options = { + RUN_NAME_OPTION, + DEPLOYMENT_ID_OPTION, + } + return options + + @classmethod + def get_entrypoint_command(cls) -> List[str]: + """Returns a command that runs the entrypoint module. + + Returns: + Entrypoint command. + """ + command = [ + "python", + "-m", + "zenml.integrations.skypilot.orchestrators.skypilot_orchestrator_entrypoint", + ] + return command + + @classmethod + def get_entrypoint_arguments( + cls, + run_name: str, + deployment_id: "UUID", + ) -> List[str]: + """Gets all arguments that the entrypoint command should be called with. + + Args: + run_name: Name of the ZenML run. + deployment_id: ID of the deployment. + + Returns: + List of entrypoint arguments. + """ + args = [ + f"--{RUN_NAME_OPTION}", + run_name, + f"--{DEPLOYMENT_ID_OPTION}", + str(deployment_id), + ] + + return args diff --git a/src/zenml/orchestrators/step_launcher.py b/src/zenml/orchestrators/step_launcher.py index 6da14aa48d5..b3b9fd1d2cd 100644 --- a/src/zenml/orchestrators/step_launcher.py +++ b/src/zenml/orchestrators/step_launcher.py @@ -212,8 +212,8 @@ def launch(self) -> None: execution_needed, step_run = self._prepare( step_run=step_run ) - except: # noqa: E722 - logger.error( + except: + logger.exception( f"Failed preparing run step `{self._step_name}`." ) step_run.status = ExecutionStatus.FAILED From 542009544677739038b2ba4db3cb20bbf329ab6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Can=20Durak?= <36421093+bcdurak@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:11:23 +0100 Subject: [PATCH 16/16] Reworking the examples (#2259) * removed two examples * updated the README * reworking the toc for docs * removed the init file * fixing links after name changes * minor fix --- docs/book/learning/examples.md | 10 - docs/book/learning/projects.md | 57 --- docs/book/toc.md | 17 +- examples/README.md | 80 ++-- examples/__init__.py | 13 - examples/generative_chat/README.md | 137 ------- .../generative_chat/pipelines/__init__.py | 13 - .../pipelines/index_builder.py | 23 -- examples/generative_chat/requirements.txt | 15 - examples/generative_chat/run.py | 90 ----- examples/generative_chat/steps/__init__.py | 13 - examples/generative_chat/steps/docs_loader.py | 51 --- .../generative_chat/steps/index_generator.py | 91 ----- .../generative_chat/steps/slack_loader.py | 56 --- examples/generative_chat/steps/utils.py | 90 ----- examples/label_studio_annotation/README.md | 347 ------------------ examples/label_studio_annotation/__init__.py | 13 - .../cloud_config/aws/cors.json | 22 -- .../cloud_config/gcp/cors-config.json | 8 - .../2dc5fe08-152d-47d0-bdd4-f70ddbfb6486.jpeg | Bin 97123 -> 0 bytes .../7f5d8d61-c507-434f-9d4b-de28f93dad1e.jpeg | Bin 77478 -> 0 bytes ..._95ffaa51-3894-4773-a8c6-a4e7d09de050.jpeg | Bin 14751 -> 0 bytes .../data/batch_1/ARIA_IMG_0584.jpeg | Bin 20099 -> 0 bytes .../data/batch_1/ARIA_IMG_0688.jpeg | Bin 8980 -> 0 bytes .../data/batch_1/ARIA_IMG_0728.jpeg | Bin 13849 -> 0 bytes .../data/batch_1/ARIA_IMG_1481.jpeg | Bin 14526 -> 0 bytes .../data/batch_1/IMG_1892.jpeg | Bin 61347 -> 0 bytes .../data/batch_1/IMG_2262.jpeg | Bin 63734 -> 0 bytes .../data/batch_1/IMG_2640.jpeg | Bin 84672 -> 0 bytes .../11f096cb-4749-4a8b-ace0-f534bc7ed07d.jpeg | Bin 67598 -> 0 bytes .../24cbc5d8-ca52-4974-841c-f91a2dfb46a7.jpeg | Bin 82578 -> 0 bytes .../94f69181-2a52-43d3-9982-2cdbd018ff28.jpeg | Bin 91686 -> 0 bytes .../data/batch_2/ARIA_IMG_1507.jpeg | Bin 21500 -> 0 bytes .../data/batch_2/ARIA_IMG_5514.jpeg | Bin 16616 -> 0 bytes .../data/batch_2/ARIA_IMG_5515.jpeg | Bin 21067 -> 0 bytes .../data/batch_2/ARIA_IMG_5530.jpeg | Bin 13906 -> 0 bytes .../data/batch_2/ARIA_IMG_5587.jpeg | Bin 16924 -> 0 bytes .../data/batch_2/IMG_3154.jpeg | Bin 60213 -> 0 bytes .../data/batch_2/IMG_4813.jpeg | Bin 85063 -> 0 bytes .../pipelines/__init__.py | 15 - .../pipelines/inference_pipeline.py | 37 -- .../pipelines/training_pipeline.py | 33 -- examples/label_studio_annotation/run.py | 47 --- .../label_studio_annotation/steps/__init__.py | 13 - .../steps/convert_annotations_step.py | 37 -- .../steps/get_or_create_dataset.py | 30 -- .../steps/load_image_data_step.py | 53 --- .../steps/prediction_steps.py | 64 ---- .../steps/pytorch_trainer.py | 252 ------------- .../steps/sync_new_data_to_label_studio.py | 37 -- 50 files changed, 47 insertions(+), 1717 deletions(-) delete mode 100644 docs/book/learning/examples.md delete mode 100644 docs/book/learning/projects.md delete mode 100644 examples/__init__.py delete mode 100644 examples/generative_chat/README.md delete mode 100644 examples/generative_chat/pipelines/__init__.py delete mode 100644 examples/generative_chat/pipelines/index_builder.py delete mode 100644 examples/generative_chat/requirements.txt delete mode 100644 examples/generative_chat/run.py delete mode 100644 examples/generative_chat/steps/__init__.py delete mode 100644 examples/generative_chat/steps/docs_loader.py delete mode 100644 examples/generative_chat/steps/index_generator.py delete mode 100644 examples/generative_chat/steps/slack_loader.py delete mode 100644 examples/generative_chat/steps/utils.py delete mode 100644 examples/label_studio_annotation/README.md delete mode 100644 examples/label_studio_annotation/__init__.py delete mode 100644 examples/label_studio_annotation/cloud_config/aws/cors.json delete mode 100644 examples/label_studio_annotation/cloud_config/gcp/cors-config.json delete mode 100644 examples/label_studio_annotation/data/batch_1/2dc5fe08-152d-47d0-bdd4-f70ddbfb6486.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_1/7f5d8d61-c507-434f-9d4b-de28f93dad1e.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_1/ARIA_95ffaa51-3894-4773-a8c6-a4e7d09de050.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_1/ARIA_IMG_0584.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_1/ARIA_IMG_0688.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_1/ARIA_IMG_0728.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_1/ARIA_IMG_1481.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_1/IMG_1892.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_1/IMG_2262.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_1/IMG_2640.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_2/11f096cb-4749-4a8b-ace0-f534bc7ed07d.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_2/24cbc5d8-ca52-4974-841c-f91a2dfb46a7.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_2/94f69181-2a52-43d3-9982-2cdbd018ff28.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_2/ARIA_IMG_1507.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_2/ARIA_IMG_5514.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_2/ARIA_IMG_5515.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_2/ARIA_IMG_5530.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_2/ARIA_IMG_5587.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_2/IMG_3154.jpeg delete mode 100644 examples/label_studio_annotation/data/batch_2/IMG_4813.jpeg delete mode 100644 examples/label_studio_annotation/pipelines/__init__.py delete mode 100644 examples/label_studio_annotation/pipelines/inference_pipeline.py delete mode 100644 examples/label_studio_annotation/pipelines/training_pipeline.py delete mode 100644 examples/label_studio_annotation/run.py delete mode 100644 examples/label_studio_annotation/steps/__init__.py delete mode 100644 examples/label_studio_annotation/steps/convert_annotations_step.py delete mode 100644 examples/label_studio_annotation/steps/get_or_create_dataset.py delete mode 100644 examples/label_studio_annotation/steps/load_image_data_step.py delete mode 100644 examples/label_studio_annotation/steps/prediction_steps.py delete mode 100644 examples/label_studio_annotation/steps/pytorch_trainer.py delete mode 100644 examples/label_studio_annotation/steps/sync_new_data_to_label_studio.py diff --git a/docs/book/learning/examples.md b/docs/book/learning/examples.md deleted file mode 100644 index 6e1be0d7b13..00000000000 --- a/docs/book/learning/examples.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -description: Useful examples that utilize ZenML. ---- - -# 🔏 Examples - -ZenML examples are small examples that focus on particular aspects of ZenML, and can be found in the [examples directory of the open source repository](https://github.com/zenml-io/zenml/blob/main/examples/). - - -
ZenML Scarf
diff --git a/docs/book/learning/projects.md b/docs/book/learning/projects.md deleted file mode 100644 index 3a2b87aa845..00000000000 --- a/docs/book/learning/projects.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -description: Resources to learn how to use ZenML practically. ---- - -# 🧩 Projects - -ZenML Projects are small-scale production-grade ML use cases powered by ZenML. They are fully fleshed-out, end-to-end, projects that showcase ZenML's capabilities. They can also serve as a template from which to start similar projects. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Predicting customer satisfactionAnalyze customer feedback to predict satisfaction levels using ZenML.customer_satisfaction.pnghttps://github.com/zenml-io/zenml-projects/tree/main/customer-satisfaction
Build an LLM-powered community Slack botProductionalize LangChain and LlamaIndex with a ZenML MLOps Pipeline to support community Slack channels.llm.pnghttps://github.com/zenml-io/zenml-projects/tree/main/langchain-llamaindex-slackbot
Use ZenML seamlessly with GitHub ActionsAutomate machine-learning workflows with GitHub Actions and ZenML for continuous integration and deployment.Remote_with_git_ops.pnghttps://github.com/zenml-io/zenml-gitflow
Forecasting Time SeriesPredict future time-series events like power generation or stock prices with the help of ZenML's pipeline.pexels_pixabay_433308_0665b2fb5b.webphttps://github.com/zenml-io/zenml-projects/tree/main/time-series-forecast
Detect Sign Language alphabet in real-time images using Yolov5Utilize ZenML and Yolov5 to detect and recognize American Sign Language alphabets in real-time image streams.pexels_shvets_production_7516363_8bec88f86d.webphttps://github.com/zenml-io/zenml-projects/tree/main/sign-language-detection-yolov5
- -## Start working on your own projects with ZenML Templates - -If you like the projects listed above and you are interested in creating your own project, you can take a look at our [ZenML Project Templates](https://github.com/zenml-io/zenml-project-templates). The goal of these templates is to help you generate ready-to-use scaffolding for your own projects, with everything you need to get started: steps, pipelines, stack configurations, and other useful resources. - - -
ZenML Scarf
diff --git a/docs/book/toc.md b/docs/book/toc.md index cc541016a46..8a0a710d44b 100644 --- a/docs/book/toc.md +++ b/docs/book/toc.md @@ -158,19 +158,12 @@ * [Implement a custom stack component](stacks-and-components/custom-solutions/implement-a-custom-stack-component.md) * [Implement a custom integration](stacks-and-components/custom-solutions/implement-a-custom-integration.md) -## Learning +## Examples -* [🚀 Quickstart](https://github.com/zenml-io/zenml/blob/main/examples/quickstart/README.md) -* [🔏 Examples](learning/examples.md) - * [e2e Batch Inference using classical ML](https://github.com/zenml-io/zenml/tree/main/examples/e2e) - * [Generative Chat with LLMs](https://github.com/zenml-io/zenml/tree/main/examples/generative_chat) - * [Basic NLP with BERT](https://github.com/zenml-io/zenml/tree/main/examples/nlp-case) -* [🧩 Projects](learning/projects.md) - * [Predicting customer satisfaction](https://github.com/zenml-io/zenml-projects/tree/main/customer-satisfaction) - * [Build an LLM-powered community Slack bot](https://github.com/zenml-io/zenml-projects/tree/main/langchain-llamaindex-slackbot) - * [Use ZenML seamlessly with GitHub Actions](https://github.com/zenml-io/zenml-gitflow) - * [Forecasting Time Series](https://github.com/zenml-io/zenml-projects/tree/main/time-series-forecast) - * [Detect Sign Language alphabet in real-time images using Yolov5](https://github.com/zenml-io/zenml-projects/tree/main/sign-language-detection-yolov5) +* [🚀 Quickstart](https://github.com/zenml-io/zenml/blob/main/examples/quickstart) +* [🔏 End-to-End Batch Inference](https://github.com/zenml-io/zenml/tree/main/examples/e2e) +* [📚 Basic NLP with BERT](https://github.com/zenml-io/zenml/tree/main/examples/e2e_nlp) +* [🧩 More Projects...](https://github.com/zenml-io/zenml-projects) ## Reference diff --git a/examples/README.md b/examples/README.md index 82006bf5342..d174d48bb7d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,39 +1,43 @@ -# ZenML Use Cases - -This folder contains examples of ZenML pipelines. These are more involved use -cases with production-ready pipelines, with the exception of -some that will be indicated in the table below. - -These core demonstrations of ZenML showcase the power of the framework in real -scenarios that use cloud infrastructure or other cloud components. -Explanations for how to use and run the use cases can be found in the README -associated with each sub-folder. - -{% hint style="info" %} -This directory previously contained examples of ZenML integrations and how to -use them. These have been ingested into the core library as integration tests. -It is therefore still possible to view the code at -[`/tests/integration/examples`](https://github.com/zenml-io/zenml/tree/main/tests/integration/examples) -but for explanations on how to use them, please refer to our dedicated [Component -guide](https://docs.zenml.io/stacks-and-components/component-guide) in our -documentation which has been updated with all the latest information. -{% endhint %} - -Note that our full use cases are all implemented as templates so you can start -with our code and then adapt the specifics to your individual needs. To learn -more about how to do this, please [visit our dedicated documentation -page](https://docs.zenml.io/user-guide/starter-guide/using-project-templates) on -this. - -| Name | Description | Integrations | Core Project | -| ---- | ----------- | ------------ | ------------ | -| quickstart | This is our quickstart example showcasing basic functionality and a workflow to get you started with the ZenML framework | mlflow | ✅ | -| e2e | Trains one or more scikit-learn classification models to make predictions on tabular classification datasets | scikit-learn | ✅ | -| generative_chat | LEGACY: constructs a vector store to be used by a LLM-based chatbot based on documentation and data from a variety of sources | langchain, llama-index, slack | | -| label_studio_annotation | LEGACY: shows how to use the Label Studio integration for annotation in a computer-vision use case and series of pipelines | label_studio, pillow | | - -## ❓ Questions / Further Assistance - -If you have any questions about how to get going with these use cases, or if -you're wondering how you can adapt them to your particular needs, please do +# ZenML Examples + +Welcome to the `examples` folder of ZenML! This directory contains a collection +of examples that demonstrate the use of ZenML in various settings. Whether +you're a beginner looking to explore ZenML's capabilities or an experienced +user seeking inspiration, these examples cover a range of scenarios to help +you get started quickly. + +## Structure + +Each project in this folder is organized in a standardized structure to +showcase ZenML's best practices. Moreover, each example listed below is a +materialized form of one of our project templates. If you like any of the +examples here, and you want to set up something similar, just grab the template +and kickstart your own example. It's that simple! + +Here's a brief overview of the featured examples: + +| Name | Description | Template | +|-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------| +| **[Quickstart](quickstart)** | Our quickstart example showcasing the basic functionality and a workflow to get you started with the ZenML framework. | [starter](https://github.com/zenml-io/template-starter) | +| **[End-to-End Training with Batch Predictions](e2e)** | A comprehensive supervised ML project to train scikit-learn classification models and make predictions on tabular datasets. | [e2e-batch](https://github.com/zenml-io/template-e2e-batch) | +| **[NLP Training, Promotion and Deployment](e2e_nlp)** | An NLP pipeline that walks through tokenization, training, HP tuning, evaluation and deployment. | [nlp](https://github.com/zenml-io/template-nlp) | + +## More Projects & Practical Examples + +If you're eager to discover more projects leveraging ZenML, you can check out +our [zenml-projects](https://github.com/zenml-io/zenml-projects) repository. +It hosts a wide variety of projects that showcase the practical application +of ZenML pipelines in different real-world examples. + +Furthermore, if you are interested in targeted examples featuring a particular integration, +you can check out the [component guide](https://docs.zenml.io/stacks-and-components/component-guide) +in our docs or the [integration tests](https://github.com/zenml-io/zenml/tree/main/tests/integration/examples) +in our repository. + +## Support & Feedback + +If you have questions or need assistance with any of the examples, feel free to [reach out to us on Slack](https://zenml.io/slack-invite/)! + +Happy experimenting with ZenML! + diff --git a/examples/__init__.py b/examples/__init__.py deleted file mode 100644 index 5e058539166..00000000000 --- a/examples/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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. diff --git a/examples/generative_chat/README.md b/examples/generative_chat/README.md deleted file mode 100644 index aaba81a9d0c..00000000000 --- a/examples/generative_chat/README.md +++ /dev/null @@ -1,137 +0,0 @@ -# 💬 Generative Chat with Langchain and Llama Index: Enhancing Large Language Models with Custom Data - -Large language models (LLMs) have become a cornerstone of natural language -processing, offering unparalleled capabilities for knowledge generation and -reasoning. However, despite their immense potential, incorporating custom, -private data into these models remains a challenge. This is where tools like -[LangChain](https://github.com/hwchase17/langchain) and -[LlamaIndex](https://github.com/jerryjliu/llama_index) (formerly 'GPT Index') -come into play, offering innovative solutions for data ingestion and indexing, -enabling developers to augment LLMs with their unique datasets. - -LangChain and LlamaIndex facilitate in-context learning, an emerging paradigm -that allows developers to insert context into input prompts, leveraging LLM's -reasoning capabilities for generating more relevant and accurate responses. This -differs from finetuning, which requires retraining models using custom datasets, -often demanding significant computational resources and time. - -By addressing data ingestion and indexing, LangChain and LlamaIndex provide a -streamlined framework for integrating custom data into LLMs. Their flexible -design simplifies incorporating external data sources, enabling developers to -focus on creating powerful applications that harness LLMs' full potential. - -These tools bridge the gap between external data and LLMs, ensuring seamless -integration while maintaining performance. By utilizing LangChain and -LlamaIndex, developers can unlock LLMs' true potential and build cutting-edge -applications tailored to specific use cases and datasets. - -## 🗺 Overview - -This example showcases a simple way to use the core features of both frameworks, -ingesting data and building an index. There are lots of demos that you can plug -your index into, and we recommend you check out Langchain's [documentation on -use cases](https://langchain.readthedocs.io/en/latest/index.html#use-cases) for -more information on how to use your index. - -**COMING SOON:** We also recommend you check out our [more advanced project -implementation](https://github.com/zenml-io/zenml-projects) which showcases -additional benefits of integrating these tools with ZenML. - - -## 🧰 How the example is implemented - -This example is made up of the following steps: - -- a Langchain loader step to get documentation from a GitBook website -- a LlamaIndex loader step to download messages from a Slack workspace and - channel -- a Langchain index generator step that builds an index from the GitBook docs - and the Slack messages - -The index can then be accessed using ZenML's [post-execution workflow], for -example: - -```python -from zenml.post_execution import get_pipeline - -# Retrieve the pipeline for generating ZenML docs index -pipeline = get_pipeline("docs_to_index_pipeline") - -# Access the last pipeline run -pipeline_run = pipeline.runs[-1] - -# Retrieve the last step of the relevant run -last_step_of_relevant_run = pipeline_run.steps[-1] - -# Read the vector index from the last step's output -vector_index = last_step_of_relevant_run.outputs.read() -``` - -# 🖥 Run it locally - -## 👣 Step-by-Step - -### 📄 Prerequisites - -For this example you'll need the following: - -- A Slack API key / token which will allow you to download messages from a Slack - workspace and channel. You can get one by following the instructions - [here](https://api.slack.com/authentication/basics). -- [An OpenAI API - key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key) - to interface with their embeddings in the VectorIndex. (Alternatively, you - could use a different embedding provider as described [in the Langchain - documentation](https://langchain.readthedocs.io/en/latest/modules/indexes/examples/embeddings.html).) - -In addition to those requirements, in order to run this example, you need to -install and initialize ZenML: - -```shell -# install CLI -pip install zenml[server] - -# install ZenML integrations -zenml integration install langchain llama_index - -# install additional dependencies for this example -pip install -r requirements.txt - -# make your API key and token available in the environment -export SLACK_BOT_TOKEN= -export OPENAI_API_KEY= - -# clone the ZenML repository -git clone https://github.com/zenml-io/zenml.git -cd examples/generative_chat - -# Initialize ZenML repo -zenml init - -# Start the ZenServer to enable dashboard access -zenml up -``` - -### ▶️ Run the Code - -Now we're ready. Execute: - -```shell -python run.py -``` - -This will run it with default arguments which are to query the ZenML docs and -Slack channel. For your own use case you'll want to change the arguments passed -in via a CLI and you can see the arguments available to you by running: - -```shell -python run.py --help -``` - -### 🧽 Clean up - -In order to clean up, delete the remaining ZenML references. - -```shell -rm -rf zenml_examples -``` diff --git a/examples/generative_chat/pipelines/__init__.py b/examples/generative_chat/pipelines/__init__.py deleted file mode 100644 index 7d170426951..00000000000 --- a/examples/generative_chat/pipelines/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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. diff --git a/examples/generative_chat/pipelines/index_builder.py b/examples/generative_chat/pipelines/index_builder.py deleted file mode 100644 index 4b99ae3b148..00000000000 --- a/examples/generative_chat/pipelines/index_builder.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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. - - -from zenml.pipelines import pipeline - - -@pipeline() -def docs_to_index_pipeline(document_loader, slack_loader, index_generator): - documents = document_loader() - slack_docs = slack_loader() - index_generator(documents, slack_docs) diff --git a/examples/generative_chat/requirements.txt b/examples/generative_chat/requirements.txt deleted file mode 100644 index 7ae7452d8eb..00000000000 --- a/examples/generative_chat/requirements.txt +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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. - -faiss-cpu== "^1" diff --git a/examples/generative_chat/run.py b/examples/generative_chat/run.py deleted file mode 100644 index ed9cb168b63..00000000000 --- a/examples/generative_chat/run.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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 argparse -import logging - -from pipelines.index_builder import ( - docs_to_index_pipeline, -) -from steps.docs_loader import DocsLoaderParameters, docs_loader -from steps.index_generator import IndexGeneratorParameters, index_generator -from steps.slack_loader import SlackLoaderParameters, slack_loader -from steps.utils import get_channel_id_from_name, get_release_date, page_exists - -docs_version = "0.35.0" -base_url = "https://docs.zenml.io" -docs_url = f"https://docs.zenml.io/v/{docs_version}/" -channel_names = ["general"] -channel_ids = [ - get_channel_id_from_name(channel_name) for channel_name in channel_names -] - -if not page_exists(docs_url): - print(f"Couldn't find docs page for zenml version '{docs_version}'.") - -release_date, next_release_date = get_release_date("zenml", docs_version) - -parser = argparse.ArgumentParser( - description="Build ZenML documentation index." -) -parser.add_argument( - "--docs_version", - type=str, - default=docs_version, - help="Docs version number", -) -parser.add_argument( - "--base_url", - type=str, - default=base_url, - help="Base URL for documentation site", -) -parser.add_argument( - "--docs_url", - type=str, - default=docs_url, - help="URL for documentation site", -) -args = parser.parse_args() - -docs_version = args.docs_version -base_url = args.base_url -docs_url = args.docs_url - -docs_to_index_pipeline = docs_to_index_pipeline( - document_loader=docs_loader( - params=DocsLoaderParameters(docs_uri=docs_url, base_url=base_url) - ), - index_generator=index_generator(params=IndexGeneratorParameters()), - slack_loader=slack_loader( - params=SlackLoaderParameters( - channel_ids=channel_ids, - earliest_date=release_date, - latest_date=next_release_date, - ) - ), -) - - -def main(): - try: - docs_to_index_pipeline.run() - except Exception as e: - print(f"Failed to build index for docs version '{docs_version}'.") - print(e) - - -if __name__ == "__main__": - logging.basicConfig(level="INFO") - main() diff --git a/examples/generative_chat/steps/__init__.py b/examples/generative_chat/steps/__init__.py deleted file mode 100644 index 7d170426951..00000000000 --- a/examples/generative_chat/steps/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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. diff --git a/examples/generative_chat/steps/docs_loader.py b/examples/generative_chat/steps/docs_loader.py deleted file mode 100644 index 27c8e46fc7f..00000000000 --- a/examples/generative_chat/steps/docs_loader.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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. - - -from typing import List - -from langchain.docstore.document import Document -from langchain.document_loaders import GitbookLoader - -from zenml.steps import BaseParameters, step - - -class DocsLoaderParameters(BaseParameters): - """Params for Gitbook loader. - - Attributes: - docs_uri: URI of the docs. - docs_base_url: Base URL of the docs. - """ - - docs_uri: str = "https://docs.zenml.io" - docs_base_url: str = "https://docs.zenml.io" - - -@step(enable_cache=True) -def docs_loader(params: DocsLoaderParameters) -> List[Document]: - """Langchain loader for Gitbook docs. - - Args: - params: Parameters for the step. - - Returns: - List of langchain documents. - """ - loader = GitbookLoader( - web_page=params.docs_uri, - base_url=params.docs_base_url, - load_all_paths=True, - ) - return loader.load() diff --git a/examples/generative_chat/steps/index_generator.py b/examples/generative_chat/steps/index_generator.py deleted file mode 100644 index b130abf4c39..00000000000 --- a/examples/generative_chat/steps/index_generator.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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 random -from typing import List - -from langchain.docstore.document import Document -from langchain.embeddings import OpenAIEmbeddings -from langchain.text_splitter import ( - CharacterTextSplitter, - RecursiveCharacterTextSplitter, -) -from langchain.vectorstores import FAISS, VectorStore -from openai.error import InvalidRequestError - -from zenml.logger import get_logger -from zenml.steps import step -from zenml.steps.base_parameters import BaseParameters - -logger = get_logger(__name__) - - -class IndexGeneratorParameters(BaseParameters): - """Params for index generator. - - Attributes: - document_chunk_size: Size of the document chunks. - document_chunk_overlap: Overlap of the document chunks. - slack_chunk_size: Size of the slack chunks. - slack_chunk_overlap: Overlap of the slack chunks. - """ - - document_chunk_size: int = 1000 - document_chunk_overlap: int = 0 - slack_chunk_size: int = 1000 - slack_chunk_overlap: int = 200 - - -@step(enable_cache=True) -def index_generator( - documents: List[Document], - slack_documents: List[Document], - params: IndexGeneratorParameters, -) -> VectorStore: - """Generates a FAISS index from a list of documents. - - Args: - documents: List of langchain documents. - slack_documents: List of langchain documents. - - Returns: - FAISS index. - """ - embeddings = OpenAIEmbeddings() - - # chunk the documents into smaller chunks - docs_text_splitter = CharacterTextSplitter( - chunk_size=params.document_chunk_size, - chunk_overlap=params.document_chunk_overlap, - ) - split_documents = docs_text_splitter.split_documents(documents) - - # chunk the slack documents into smaller chunks - slack_text_splitter = RecursiveCharacterTextSplitter( - chunk_size=params.slack_chunk_size, - chunk_overlap=params.slack_chunk_overlap, - ) - slack_texts = slack_text_splitter.split_documents(slack_documents) - - split_documents.extend(slack_texts) # merges the two document lists - - try: - return FAISS.from_documents(documents, embeddings) - except InvalidRequestError: - random.shuffle(documents) - shorter_documents = documents[: len(documents) // 2] - logger.warning( - "Too many tokens passed to OpenAI. Trying with smaller set of documents" - ) - return FAISS.from_documents(shorter_documents, embeddings) diff --git a/examples/generative_chat/steps/slack_loader.py b/examples/generative_chat/steps/slack_loader.py deleted file mode 100644 index c87b3be0491..00000000000 --- a/examples/generative_chat/steps/slack_loader.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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 datetime -import os -from typing import List, Optional - -from langchain.docstore.document import Document -from llama_index.readers.slack import SlackReader - -from zenml.steps import BaseParameters, step - - -class SlackLoaderParameters(BaseParameters): - """Params for Slack loader. - - Attributes: - channel_ids: List of channel IDs to load. - earliest_date: Earliest date to load. - latest_date: Latest date to load. - """ - - channel_ids: List[str] = [] - earliest_date: Optional[datetime.datetime] = None - latest_date: Optional[datetime.datetime] = None - - -@step(enable_cache=True) -def slack_loader(params: SlackLoaderParameters) -> List[Document]: - """Langchain loader for Slack. - - Args: - params: Parameters for the step. - - Returns: - List of langchain documents. - """ - loader = SlackReader( - slack_token=os.environ["SLACK_BOT_TOKEN"], - earliest_date=params.earliest_date, - latest_date=params.latest_date, - ) - documents = loader.load_data(channel_ids=params.channel_ids) - return [d.to_langchain_format() for d in documents] diff --git a/examples/generative_chat/steps/utils.py b/examples/generative_chat/steps/utils.py deleted file mode 100644 index 39f4cfc0f56..00000000000 --- a/examples/generative_chat/steps/utils.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright (c) ZenML GmbH 2023. All Rights Reserved. -# -# 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: -# -# https://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 datetime -import os -from typing import Optional, Tuple - -import requests -from slack_sdk import WebClient - - -def get_channel_id_from_name(name: str) -> str: - """Gets a channel ID from a Slack channel name. - - Args: - name: Name of the channel. - - Returns: - Channel ID. - """ - client = WebClient(token=os.environ["SLACK_BOT_TOKEN"]) - response = client.conversations_list() - conversations = response["channels"] - if id := [c["id"] for c in conversations if c["name"] == name][0]: - return id - else: - raise ValueError(f"Channel {name} not found.") - - -SLACK_CHANNEL_IDS = [get_channel_id_from_name("general")] - - -def page_exists(url: str) -> bool: - import requests - - r = requests.get(url, timeout=5) - return r.status_code == 200 - - -def get_release_date( - package_name: str, version: str -) -> Tuple[datetime.datetime, Optional[datetime.datetime]]: - """Get the release date of a package version. - - Args: - package_name: Name of the package. - version: Version of the package. - - Returns: - The release date of the package version, and the date of the next - release if it exists (or None). - """ - # Get the package's release information from the PyPI API - response = requests.get( - f"https://pypi.org/pypi/{package_name}/json", timeout=5 - ) - - # Parse the JSON data - data = response.json() - - # Get a list of the package's release versions - release_info = data["releases"].get(version) - - if not release_info: - raise ValueError( - f"Version {version} not found for package {package_name}." - ) - release_upload_time = datetime.datetime.strptime( - data["releases"][version][0]["upload_time"], "%Y-%m-%dT%H:%M:%S" - ) - - two_weeks_later = release_upload_time + datetime.timedelta(weeks=2) - if two_weeks_later > datetime.datetime.now(): - two_weeks_later = datetime.datetime.now() - - return ( - release_upload_time, - two_weeks_later, - ) diff --git a/examples/label_studio_annotation/README.md b/examples/label_studio_annotation/README.md deleted file mode 100644 index e854e3432ab..00000000000 --- a/examples/label_studio_annotation/README.md +++ /dev/null @@ -1,347 +0,0 @@ -# 🏷 Continuous Annotation with Label Studio - -Data annotation / labeling is a core part of MLOps that is frequently left out -of the conversation. ZenML offers a way to build continuous annotation -(combining training and annotation into a loop) with Label Studio. This uses a -combination of user-defined steps as well as some built-in steps that ZenML -provides. - -## 🗺 Overview - -NOTE: This example currently only runs with a cloud artifact store. [This guide -by Label Studio](https://labelstud.io/guide/storage.html) contains more details -if you have trouble understanding the instructions below. - -For a full video walkthrough on how to run this example, please check out [our -community hour demo](https://www.youtube.com/watch?v=bLFGnoApWeU) in which we -show how to run the various pipelines, in what order, all using an AWS stack. - -# 🖥 Run the example - -In order to run this example, you need to install and initialize ZenML and Label -Studio. - -```shell -pip install "zenml[server]" torchvision - -# clone the ZenML repository -git clone https://github.com/zenml-io/zenml.git -cd examples/label_studio_annotation - -# Initialize ZenML repo -zenml init - -# Start the ZenServer to enable dashboard access -zenml up -``` - -You will need to install and start Label Studio locally: - -```shell -zenml integration install label_studio - -# start label-studio locally -label-studio start -p 8093 -``` - -To connect ZenML to your local Label Studio server, you also need an API key. -This will give you access to the web annotation interface. - -First order of business is to sign up if you haven't done so already, using an -email and a password. Then visit [http://localhost:8093/](http://localhost:8093/) to log in, and then -visit [http://localhost:8093/user/account](http://localhost:8093/user/account) and get your Label Studio API key (from -the upper right hand corner). You will need it for later. Keep the -Label Studio server running, because the ZenML Label Studio annotator will use -it as the backend. - -## 👣 Step-by-Step Infrastructure Setup - -Pick your preferred infrastructure provider from Azure, GCP and AWS. Then follow -the relevant guide below for how to set up the infrastructure required by this -example. - -### 🥞 Set up your stack for Microsoft Azure - -You should install the relevant integrations: - -```shell -zenml integration install pytorch azure pillow -``` - -Some setup for your stack is required. - -A resource group will allow you to clean up any associated resources easily, so -either create one with the following command, or reference an existing one in -what follows. The same applies to the storage account and container that we'll -create and use: - -```bash -az group create --name --location northeurope - -az storage account create --name --resource-group --location northeurope --sku Standard_ZRS --encryption-services blob - -az storage container create \ - --account-name \ - --name \ - --auth-mode login -``` - -At this point you'll want to get a storage account key with the following -command: - -```bash -az storage account keys list --account-name -``` - -You can pick either of the 'value' properties to use for the `--account-key` -value for the following command that adds CORS permissions to your storage -account: - -```bash -az storage cors add --origins '*' --methods GET --allowed-headers '*' --exposed-headers 'Access-Control-Allow-Origin' --max-age 3600 --services blob --account-key --account-name -``` - -Now we can set up all the necessary ZenML components: - -```shell -zenml stack copy default - -zenml stack set - -zenml secret create --account_name="" --account_key="" - -zenml artifact-store register -f azure --path="az://" --authentication_secret="" - -zenml stack update -a - -zenml secret create --api_key="" - -zenml annotator register --flavor label_studio --authentication_secret="" - -zenml stack update -an -``` - -At this point you should stop (`CTRL-C`) Label Studio, set the following two -environment variables (or do it wherever is appropriate if you have a deployed -Label Studio instance) before restarting Label Studio: - -```bash -export AZURE_BLOB_ACCOUNT_NAME="" -export AZURE_BLOB_ACCOUNT_KEY="" -``` - -### 🥞 Set up your stack for GCP - -You should install the relevant integrations: - -```shell -zenml integration install label_studio pytorch gcp pillow -``` - -This setup guide assumes that you have installed and are able to use the -`gcloud` CLI to run commands. - -Create your artifact store and set up the necessary permissions and service -accounts: - -```shell -gsutil mb -p -l -c standard "gs://" - -gcloud iam service-accounts create - -gcloud projects add-iam-policy-binding --member="serviceAccount:@.iam.gserviceaccount.com" --role="roles/storage.admin" - -gcloud projects add-iam-policy-binding --member="serviceAccount:@.iam.gserviceaccount.com" --role="roles/iam.serviceAccountTokenCreator" - -gcloud iam service-accounts keys create ls-annotation-credentials.json --iam-account=@.iam.gserviceaccount.com - -gsutil cors set cloud_config/gcp/cors-config.json gs:// -``` - -Now you have a credentials `json` file that you can use to authenticate with -Label Studio. Make sure to note down the path where this was created. - -Now you can set up the rest of your stack: - -```shell -zenml stack copy default - -zenml stack set - -zenml secret create --token="@PATH/TO/JSON/FILE/CREATED/ABOVE" - -zenml artifact-store register gcp_artifact_store -f gcp --path="gs://" --authentication_secret="" - -zenml stack update -a - -zenml secret create --api_key="" - -zenml annotator register --flavor label_studio --authentication_secret="" - -zenml stack update -an -``` - -Be sure also to set the environment variable for your GCP credentials and then -restart Label Studio: - -```shell -export GOOGLE_APPLICATION_CREDENTIALS="" -label-studio start -p 8093 -``` - -### 🥞 Set up your stack for AWS - -You should install the relevant integrations: - -```shell -# assuming label_studio was installed earlier -zenml integration install pytorch s3 pillow -``` - -Create your basic S3 bucket via CLI command: - -```shell -REGION= -S3_BUCKET_NAME= - -aws s3api create-bucket --bucket=$S3_BUCKET_NAME --region=$REGION --create-bucket-configuration=LocationConstraint=$REGION -``` - -Label Studio also needs you to set up cross-origin resource sharing (CORS) -access to your bucket, using a policy that allows `GET` access from the same -host name as your Label Studio deployment. You can use the CORS file we have -pre-populated for you inside the examples repo as follows: - -```shell -cd cloud_config/aws -aws s3api put-bucket-cors --bucket $S3_BUCKET_NAME --cors-configuration file://cors.json -cd ../.. -``` - -You will also need to assign a policy to your IAM user that allows it to access -the S3 bucket in the way that Label Studio needs. You can do this using [the -instructions described in the Label Studio -documentation](https://labelstud.io/guide/storage.html#Configure-access-to-your-S3-bucket) -(step two, specifically). - -Now you can get to the fun part of setting up Label Studio and working with -ZenML: - -```shell -YOUR_AWS_ZENML_STACK_NAME= -YOUR_ARTIFACT_STORE_NAME= - -zenml stack copy default $YOUR_AWS_ZENML_STACK_NAME - -zenml stack set $YOUR_AWS_ZENML_STACK_NAME - -# use your standard access key id and secret access key from ~/.aws/credentials here -zenml secret create --aws_access_key_id="" --aws_secret_access_key="" - -zenml artifact-store register $YOUR_ARTIFACT_STORE_NAME --flavor=s3 --path=s3://$S3_BUCKET_NAME --authentication_secret="" - -zenml stack update $YOUR_AWS_ZENML_STACK_NAME -a $YOUR_ARTIFACT_STORE_NAME - -zenml secret create --api_key="" - -zenml annotator register --flavor label_studio --authentication_secret="" - -zenml stack update $YOUR_AWS_ZENML_STACK_NAME -an -``` - -### ▶️ Run the Code - -There are several parts to running the pipeline. Start with: - -```shell -python run.py --train -``` - -On the first time you run this, this will fetch a pretrained model and amend the -head so that it is able to perform binary image classification. It does not get -finetuned at this point, however. - -You can use the CLI command to view our newly created dataset: - -``` -zenml annotator dataset list -``` - -It will show that we now have an `aria_detector` dataset. - -Then you can use this model to perform inference on some images (located in -`data/batch_1`). These 'pre-annotations' will then be synchronized with Label -Studio. - -```shell -python run.py --inference -``` - -At this point you should do some annotation using the Label Studio web -interface, making sure to annotate all the ten images. You can launch the -annotation interface with the CLI: - -```shell -zenml annotator dataset launch aria_detector -``` - -When you're done, you can get the stats on the annotation work you did by using -the ZenML CLI: - -```shell -zenml annotator dataset stats aria_detector -``` - -This will tell you how many labeled and unlabeled tasks you have for your Label -Studio dataset. - -With the annotations complete, you should rerun the training step. This time -instead of just pulling a pretrained model, the step will finetune our -previously-downloaded pretrained model using the ten annotations we just made. -This will improve our model's performance (a bit). - -```shell -python run.py --train --rerun -``` - -Now we can rerun the inference step, though using a different set of data -(`data/batch_2`). - -```shell -python run.py --inference --rerun -``` - -Once we've rerun this step, we can inspect the predictions our newly fine-tuned -model made within Label Studio. - -## CLI Commands for the Label Studio Integration - -Once you've run the pipeline for the first time, you'll be able to use some -ZenML CLI commands to interact with your Label Studio annotations and the -dataset: - -```shell -# the obvious ones to try -zenml annotator describe -zenml annotator dataset list -zenml annotator dataset stats -``` - -### 🧽 Clean up - -In order to clean up, delete any relevant cloud infrastructure that was created -above (the cloud storage bucket is the main one, along with any permissions and -whatever secrets or secrets vaults you created) and the remaining ZenML -references. If you created assets under a GCP project, or an Azure resource -group, then the newly created assets should be easy to find. With Amazon, -the IAM rules and the S3 bucket are what you need to delete. - -# 📜 Learn more - -If you want to learn more about annotation in general or about how to use your -own annotation tool in ZenML check out our -[docs](https://docs.zenml.io/stacks-and-components/component-guide/annotators/annotators). - -To explore other available CLI commands related to the annotator stack -components, check out the [CLI docs annotator -section](https://apidocs.zenml.io/latest/cli/#zenml.cli). diff --git a/examples/label_studio_annotation/__init__.py b/examples/label_studio_annotation/__init__.py deleted file mode 100644 index 5e058539166..00000000000 --- a/examples/label_studio_annotation/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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. diff --git a/examples/label_studio_annotation/cloud_config/aws/cors.json b/examples/label_studio_annotation/cloud_config/aws/cors.json deleted file mode 100644 index 4a334d320db..00000000000 --- a/examples/label_studio_annotation/cloud_config/aws/cors.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "CORSRules": - [ - { - "AllowedHeaders": [ - "*" - ], - "AllowedMethods": [ - "GET" - ], - "AllowedOrigins": [ - "*" - ], - "ExposeHeaders": [ - "x-amz-server-side-encryption", - "x-amz-request-id", - "x-amz-id-2" - ], - "MaxAgeSeconds": 3000 - } - ] -} diff --git a/examples/label_studio_annotation/cloud_config/gcp/cors-config.json b/examples/label_studio_annotation/cloud_config/gcp/cors-config.json deleted file mode 100644 index 4068af99215..00000000000 --- a/examples/label_studio_annotation/cloud_config/gcp/cors-config.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "origin": ["*"], - "method": ["GET"], - "responseHeader": ["Content-Type","Access-Control-Allow-Origin"], - "maxAgeSeconds": 3600 - } - ] diff --git a/examples/label_studio_annotation/data/batch_1/2dc5fe08-152d-47d0-bdd4-f70ddbfb6486.jpeg b/examples/label_studio_annotation/data/batch_1/2dc5fe08-152d-47d0-bdd4-f70ddbfb6486.jpeg deleted file mode 100644 index d28d5a655d24038b0fddc96174dde4c0a1691def..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97123 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%0ANIoIOUC&*%+`CnUy9rcN1ixMNmqMbpHUH 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ⅈ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 z zw${ay!-dn&ykm~0J>+lUBx-@pI!Z6&-N!~pdDtSUc^bMUyya4(!5d)(nQ~M!GfUog zXyv6+k|VcSOKY?=-HN9C4+g)@u=<}@PH|RGo#OGl&LWD)9(Btc2)qx`RP)kv_B<{Q zTLOKG7IvxQmS$jiUZ|3r0AjIVK{#6QsKHz%gYh@-?phAH@=Z}kMnRm_dFgYR>B_D; zsv2~=huP&)K+NOgWc_JesL1n1?C+5*n~0M@G7pI3y1`!CU&aeqhmv_Jk}UPoNW*$WGMEbl_DK9AtF`AitG zeV$r%vbF0U)DRy-&ubbQbrSL)E5{l72u!kagei`Em$#zFx`wjKgE*g47OKl7@0*mD zE0a()-z3=#OrNL?dP-nhp1okEV0jfWaetB`Gu<~3tAucU>^vJeue6)qzNL3{zXZQz zBCS%dnhaT|YtK5P1` zURn^KE&+05e`yBSYWA!}8^l*n$m*nId(f#3`Ih=547dzxXE>(Ju zx<+IG{`K6fiZm)t(h8y3mD|%(L)+MCP^qp?S}GSy0^8+ejo-FjQ%Ukv!$c&P0kbhX zc_d?V7>yA@IBw?MAB|N(=_kw6|7a12pXc3slTaD#@fenhV?#U$VEacG0aP|h%_z0l z6dQ2pZ_lrh(reA3W=h6_53Cf{9|7ahTr7GA&<0}z5Q7{LRT3WvHk*pbfMPW|6`0IY_a*qo3KB9aJl?VTB;U3JiNBJ>9R?x zC_xj18Ez}Nw}HLQXp_p_vc|qeGE~+Gl|f+cvwG`Yi>7TG=I;BqwGXtZIT=*#7^c!8 z;Vh`Kqh&i;=e^3r{ON2=*AzZ4QOA=59L$VaB_}oxnEB+bIg-|_U9tAnh>T}gj<>%F zMGwN;QuUz-$tC?Y^I(0e^d<=c?Y}*<$QHLcBGhPFu$|Y?+HHe_2sOp%!f)~W?U)ct zUY0^StyWuX?k;#jIxNE>ISX5b^Wmk!a27ge1*o;p$*t5B|F+hVi)%ERa{d~W7(KUP zi@+D0`Ruy{Ahp_|Db|>8y0!fIXZEoAx6h|WE|{P|%lygmuM*ST);nwW@e;1~+o*WS zoWJIRx+>b5X5vvpDSA!6XB%tnam>u;E?%Q79_w5m)ruW>is8q(Q5GTAZ0}U+W(C~m zy&)n7YxXsvOw;Ba^`gJQ51A8!4sPhLj@#S0$D?4hVXpet#?$fxAJPJ(zUv;EJ9vC& zbA1ukDy-IbwZ$Kw4ajNLr+2pyO_{c@Ro3!befS*vq||brMd#{o@rEzmNqFf8kA;Bp z!1(wcR(++{=aPIelikO1i`JB?F(Q|d=2HT!K8ERPD%p&WiCyQ0OSstpS*qmkT&5d$ z?!(}qSJ-Ed^SGnG8oU(?ZD@elp;^#u!XoboTjS^4t!(wQic9}yOrf^zmRJOP#B`DnPHA5E| zLrYbCs%;Q-IWR2X;qfZgKobHmOnPnhNRGCRCi?p`GTqBRjkbMC60+p7QJw#)ns{iQCC=&7bL{Rd1)u!bsT8%aP?lw)3pin2ydlj4~UyPzNy_~1H zIC=Va>mli(7kS)O+3A_5NMjk1ib|=B3@n?luq@-VKzQlxW+#DVyB7A4WO1?41DEuZ zU<13dCP8XHkz2hT4xTT*=YIF@wf}fl)=IMHnc2UYJ$p*_ zTPOl=!?ds0y9&2OFTNgAo#6XFQVBwjb%v5eV*WgiuzFkWWb)uAykrtgI|-0M`G%*TG3B1fgnZ<0%=TVvt-=Yu&Z~Wn^yMK*$H?fklfCpnf&)>=hjX+R;&X*~0UC3Io(9qJY6|}ngF6Bjy=b0}x6S~K6qp7XP zh2Nl&Gh&1G#y1ICzr+2wyXta;!7kgEk{v7`WM_2OF^DE)Hx4rPn>oc;6le;fEZO6K z+lV$xQD7YxBb`^CCaO8l=@b3#`b^12hFrXV{-$W1_GH0;h-gWvo@|-r*xjItdiRbS zX3yTeb#>FyQT^esuP3n}E>BH+@Et@1%Yi(qbC|1?EUn5SEv>~3BBjrDc}7E2hP=P?%l3$Vg;OyvmPwZ zaqF!cKi0)rHWn#lahrT0;&x>=kqj)P^?sK3wq1pzfA7bdmjfy@1+wi?D>pnWd+yvi zy;U_6hpD8ZN5rS6!P|q>YlZ{UK4clbz0mX<+B`~&b3bi~7-~XO>lL0MW3RF<`t}u- z!ScAwLjMojuVS_o3D`$US*)$AN6OG>1ZOQLO}}_9d{_OKY%*{79APU?}zHI9&1Tld2ZqtB}!_i*|0EsJpdzdh4iTJ{mY9ZAA^jbCO?=0=#E2LH9_Y(w``m5y_3Gk7#c6M{|V8NSw0@%0vG&i%_ z%K{hXo6RVh4F5&d-0806k*6XjTa-OT;$(dLt1VXZd%cV`zDs|GZdxCP4Aq?<&?g1Z zGf2AUG|GFZ{PSDD z-XEzobDe3I3{9`?eU?%|*l*hNO-jD? zr`t_Oo8x+P^mU@uc%3!69ShU&*;UJ!2+~T>NC6 z%O8n-(CsX3PWo%+KYoiQL7y|d@}JQ?Lwq~czZx>7avBZI*+C((A!KxXsxIn%%^ zCfnnOoXeL!KAXFF`<&&o1!my^r{ApKO}2UFC7RC}T+Kg5{APY>n`c3y;hf{u?(*M{ zUq*eLexl7Ak}$0|*?Qx>=Bg&iuZ~TK&*X z4kC)`{sBRIYV$<xlS>_Kzg9Z3=WJ zJ?m(OSzirbajgrI{wz{Nj|MpRs(3=H36eh6jSDk{uhlF_kP42UJ+*plHA%QSr8zC~ z(DF0&Z7*O&tHNRGD;Tnqzlp=GAKx%LJ%(+CkPtSPrD?(vX7#W|ES&4JnYbx8{$_c= z_cx<{0bY0AQ=!jaPM3&tUWjt|Rmv|YY2HE8lAlJ+U5Hk%NNbHz71$rVgx8yh&i{BW zJTmVM|D&?wCI_21tK%um@%mBy!IZ*>qpD|7#l%^wsIvFkAnO98&-9*oftn9RbbQ*j z`hzMh3bx~;*>0mgvq-cey8*F~=KF>966W*l=y67tVB@#T;#=RenP~wn-cq(BY~}w* zfI%*XuNScrP*59=#RZbtZI7(@)Hg#=q}+3| zhZ0H>|NMthMTN#$1$@!dd~M{%!WJ0D!iGf>;bnP(X!7pFjy^6|QF^X#KPRma0eir* zVG|p$=2(Tu8+N+{xWawoYHwDoo7w5*pZ?61@;OlF+kEnF;p=G4bJw2p++t?J6V<7S zGM3fnGlYH9z8BH*bB#Q&q)5Rrs8?uyVHM@@Ma?n1$PGdH@2xkJgrQ*VoswpI&RiNiHM06YicE1Z#6zgTm=OTF`jMN(^5VmWd4sPaFRF&Q2X}Z{=eycZk(Y3$}?!-1S(*LFNsu0RDi;^2u=!B}UvNeqh<9G9_PU~|YSIl71lI+NY;%J8Iyj(n4u4KKE{Z01ihA?7Ana`%lh zyV3!)5Z^|9hO#Ckj0l7u3Kb5Ljed{-*)0Qwt$wV->CKG`G@{Eyw$`>CRBM;qssq>jB8mY!Yn zTB*LtTjcVEUnUYAN?D<-WQAshQe5inkKqdicdV8KyI;GsDDM4(V!m9Ctm#p(y-(&t zGBaxt4;^saM^#uPU3v!#<1p^pWq&MKhmg{SD?wfvtq!_#qD@#E0Pz*46-W{L)X`E@ z@9kmStDkA_{Yo0M?A>=u2T%{DL!;o@?6X~uBXd1xpGM4T3(*KA7Gilmu}S$4_rW*U ztbBLVCU$dQc20ddV<&jVH@+eoQOk#Z;vY~6!?@6bt8xW89Oszprsn>24J$g*a5&QF6Q zll1$G$IzeVj!ZPf;ua^9_uEMWlw{#tGZN$p{e1F%vQZZis zjtnGo&!`M$K3Cv$TQJq9JQ|&KP>nRx_zLLlTPo6L*m7bOC)h2?3LGrP+5yHal?v7< z9xEv!TwpR>j-S&LL;s2$EpIpj*QJzaMD%ekR_FatvzP-wO#WeIxSiG)#J2J=O_qwo zaZ{Z$Y;MA0HgIDv9fa_Cr2E*)eay|ovFbA2E9~W597IuOFUwOWRcl#hljC^>?xY0K z4rDRjLrQ8GrMNw9)RPlX-SXhw*X8t z@WvHPDznulN~i62Tj(l4`Uis6CsPe(`4-dx3Sp(Xp|Y?7$xMI0_haj3C$DdplA{JZ z&ku-tVmo3H+m3ynTg~i(>;Hm^5-oFc$Z(2dXvkKh@BW-R1>!)Ta~ z)tS$#K#jRo8@RBr$j9iwMI4`tu#E<^tNXqjw}UO2LDnPp=CVPC>701pE@yDlr zp5Yh%YTp2L+|I-)cUERVAciIAtn>KGiRwJ8`eXaiJLX66fti_PH%{90K)wd`ID=TA zMz*#SPS03#{QVqd^JBl`w>~Q--%BhVb7SpZJza6kWA78MQoRhu7;kQ?TT#$T$NCp- zfP7#T6Z=Gs;pqqY$qH;;-dkNV`P3lqsEYSTTR(I%Vsv)Q5&xd3{n`1qlp(XgqFmo4 zj0Jr|_|#4y^Z+sb0Izkb_M3RtFY)PRaCung>dh-diaDVbAqSnkPq$FFc{*48=gE?J zQe(o?|D@m7T?=}+Ym&7R!`I_cRx(vX&TqET*$tDi!y zz$L;&y1rM+Ki4S6N4@L5NSx8cy|V&pMHI*JMY`rZXNWU3th0k$Ac`k?R0xRhebuuZ zC+gP+R&&M;^*8to5Mgyd$z+8(KtR<6C+oBM@neg5`f0S72SVb)SJx8QIt%GRmwYJS zKIi<3Yhk;;iPy)u|2dicC<<8JhbWq47Lnx5Ey^~t9N<=7TMPgCGqBl?3EzZ67>U-_ z`)O#A-q<1&XvivYJ%4N;1J6qxdD<GTF$p^=xD=yY zLU2*pB)u+t@o?!ru*{{)dz1-p&CO|BUItZCzr;AT6ey@y#4Sm0WGJyVhwi07O=ZvcE#2;#}ozyslAYglwcdZY&Lj2zKf_|LEO`4lnxzkFNQik z%>4FZW>Ixo?=~vuCuBL#UZL=_Q8&bv5VU^0wmE=E@d~?wgBfWtL5wQk%V6l)D?lDb>(75#!Lga68nN;t==?Nj75_5;RWK|b9Du%uOV zFEU%}kOq{)ch?MEFT0zdI%wY1Fs^j6wn5~t12xNWVBq9dh)^~m$D`rysWV8hH=P~n zr~Yh*M=vC&*83R_UwBs}gj%7Ahl1JP?&pSXca4TC)@PEDIXnz2*DAS3V2)NYwoV}5 z8Jipmd1KqDNE-hl72HW(DX2ehuRR=UPz9DRG^aKEaNg-AtO}Oh;Qo|0z+JkB2|dP* zhSmKoU2r4MNWc3GDFO0BrcP?7$dq`p?n;(4t-EutL9(x2!7^GK>1ZA(N*SpdF41yP z(l+)f81eD8Q{O%9V^>sww8bW6aMqh&m^M>(B`9nOlQMqzP5R)Q>$Y+AcIEUGbx~X0 z0Yo>%wfvFpO}b!rRUCFsqIt$sWt}mrLHb?#`m8#hd3tR9DoZ>)+r_=&{y6>|dTXLf z%WE{+%Q)PbF{gou*02y`6ocji2Qg63?1Tl&=0=8h0)i^C0K6=61aR)X=euyKt;@8h zYL;AS0v=$UPW8aZ#U_LzUAl38gvt%}x=-P9^y*qfX0eVxrZQeV?M2ylNTJ=?Q`edr zrS`FfLdmyt1g8U?nfMs4h-8}=QIlRGdcQ-y3-C_xnB%kB-eUT8%v~(j8$KVS?d<{#t89V7U$ep+y0RZMtEksZ^qsM zW|T}40y7!2`7`GmPSunU8!AQQ$U_1RTAvE}P3@Z?fTlO3@}SQxT|SGHNbb z)2o60zPS&~(|~%FYxo+Dfr1hT{g;FX#{)IN(cbjv70EA#Td6uYUO|?pNC*Wc;4f>Z z%feofs{^lzB1HS|>Ub``_q$RBXwGerueAZ%xf_Ci&KnJV@kx#MZ~^6U_n~Kr53|c5 zs<}Bx9T(WQ3z%v3KqE85YnP1rW_nfl(^3q-URD#NaF4S6fNPrxmwRqJPW8%E!J)@r zg-)v0L+duzmNElFC+IFkdsl|dXa~kS5RG?B4;eYLe-ez8fm@=d)U>ZyUNWG1#xEm2 zaXHn4Wfd~~EH@<05X3iQF*H_CojSOnDl0!XC1-{!&N1DoX+YtDK3L`Z_xoV4I=8Yn z;>lGv%4R&fnW`xn5iQR&H`v#qZ(V-)t*J+EH{P0Q3A{%c;{lv0D70u*LeBYQ_2+5>+C*X#c0skOJiy z3|zESR}S8A01JdUv)7VNla!@B6|Ote@?!OPr9tBxEAk@s>OXxX)T0?LU9g$JyhH1I z-%So312=_3fc+&opqkB z)$23G{A7uQngCXhSwA6u8oR+=E>(Xb57(UCu?dLQ63ML*krhnw`SoJD!uiG`y8m^P z7xON7q%(99S|aB!Vj(8H=O(qMKe0CMYB!H3FT=tI8`c@ag`w(-gT%!Y2+g>K>sw25r1`x6cDpE1wc|iw;?GD{UmEBk7?H1-?4kAv=q8rFVB-PD-Hudqop-;;@7Ch9 zMx6=a@=&U+4Bv8*G0X5bA8DUSANoTRO znP>Vxu7DV{k{;b7k!Be~XD~10eg+!7dar(d`SqSLg=t>JGsYMu9`i%PW-|NrgW)Z; z?P_-3=T{)XG2ZnOrWWZ9FO5m$=y*Q<0~_hcabZZ->l{#@^yLFv6RDACZ&FHS>A z!(K^z%xyaSi5Nxb^m&qIn#U4ttHcXHURX?0T!ajUxrnDKT|SdShmD1kLkv9&OD}GerI-mmKZszMF}NcuQz67qZtU=mVk<7GhEtz30c>#or0 zr~#2zO44)eomVPWR_JDa`DfIDFNCwCJz*HtGazBc%qTVC5~D22Xz)kZ?tohwA&@MP-cjD{I$UmgO z-xABa*!Vm0hGOyOyG|}WmPrz*V`PEsF~QAVml6%( zFQ_Fnq?exs)!1^S^lm@JD3Eqzqz%7pP^L)s9Dd0)D%+;IXw&&ODX{CkVid5!T+Ox&>x~KW6@=$~+UlD3C}#T7{U3`Di^Rks9$jLcshh;htf$l6}Qf{O}iH)1DIM3?j8+?+v))VD)5EcYe zfYb_oVpQD6oNf{G(Vngps(D}EE0#uITIyLzGgBSZP?-`;A0P9-QU$zKLN|%?u{27h z(!E_$QqVhiwRn!l-qHZfBz))<@JcRvEAnEACdcqZgK8^b3;@nmu%phH`-Id=r>-zB z4ubU5{`$%=H(~N7iCBLYVwKRzi>e9A^_}Y(ba+(msDq?t()Rv;DQXwi1YuKL5zO<{*bkSV(PwenL!2*30N zB1)m^5TH`g1;}N)-SQ3cmO_bn_N7(o1W7 zEAms#_k2iA9$727X&aM>vo`)vVsfBTWDw^sSgf;16bn}f3p$c}{Bwr5?UgLyoCmU{ zuNU_U+FzO56Ahb_D@RxoNZ9`DI!yjlqyk7?%9MJ+OR`MKZqd_NFkiDP9Ye=j78(Z5 zI&z!+BgEA8Oc6`llvP^KJ_0tp+Kq1SmaHml(>F(%&5ur*VrwQO{S%TLBv%C)zbgh< z{2p+Hwg{I5PAtYoKAPYoBXjtfp|u_uuG{ z8@CG(i`mp*(_~&lKFLhxruc8xac0d7G%nY{z)k}!GD8WR{{%*FujUB4Ga~2TrM*rl z2i;Dn9wzGw4i@qp17ry~YvuAqe~|k&N>gj7{d3XJ;HPaKm?fp zj<;zw70~HP=a6K8K#I?SAKtUNtk1s3xZW6~;P^_k2R809z}GZzEFyk>J3?y5?yn)4 zw)sAkv6}HEsu$Yx@=<>G?Se=^T77kL@RZLxBs*EsKc;|6*sG8rOt}bC;3Cn8WRPZ@ zpWFk=Jrs64U&~%l)`tl9=@(FWsZe>X0G5IAO#NRiYZ!U zQE^`UP(c&oEpWHplP$UAj$w(W2IB$JlgA9E*I@8z$0^+fy@T1q>w>us_*BN!WoY!K zt|=^^^jgyh);aRaB64iN|cv1 zYK3{(75>*xfKJAJUOyq#48fR1h^AE`(IAXKC2C(w%~%byDRQ^KFJ2gwRxaGxL7GN( zT~zkQsz?b7uGHN0_80IyUHHuMq$^_WR`dMTCW7mEJ^>m+b#1vK6L3vWz}Qx=jX z+MI+}tyC2VRem3C9!DC{{aA5|ESOkW!6}=$_Y~a)wL%k1{NB9@Aab{ODI*#T0!WXr z*c8fO@Ku~uo!*W!@R|-hmFR;y+w>S_i!*4*$S}W%Ny* zmm>qj*Y_1T@kkTgD=v79$$eFBh9&Mf(C;o5OJHu!-1H{-#5`jgZ^eB#U(8>+(l!iUGmU~RA`%`&kh%xCdZ^8(bHcAQopf@k_#Qh;r?;1;~d8L04g zCfnj?PLD>fN%MQR>rJ37eMp}+1(Z{QQj235GS6LU%{KV8K-W;AB6VyqKaZ@177ybEk&mU2xgq5Y8-UFAdPoyk@{09FB;QRVt#dn7wjO7+)~spOQ|Z* z$b`otD%)H|C8Ke)>Y4`q{x&9Rm?!?+^j^08yCwxE%`n4Da)hDqy{z!(8}b~ zebVlv5?3KJuf5i7fep4mWWFH)EW;Dy#db+=I=dNi-}ljk45!K=KMan(G24enK-|;l zJ({=`C;XYUWU6pXGgWdGGXA;trKif1Y@k23tRzyTvm-yfN-&{Bwz1r$q6*X~hme=G zs2fp^(4cPFa%=W??Im0fkRpnzrrkq^+VGl5@tVE(OPACP&moI!%G))?&M6?%{E`_M z`J5nNbh?*kf5 zrJpKpPxy$8aUH)7f=D34c`gPnL$&vP!^^}cTcAkwD!G>$Ewzh!zM=RgAg+}pUy~xn zOZnd2>VUXuVq%jCOb}(q7ghYimu_qH)BSPk}cMK`#?xC%9$>F@+9Wq$eRgrWCbL1+GllH>7L9+D-IOo27{ zZL2lQW7MSKie2!si{x{JKPTbj%Sr@xa)3q{VGMkj~&!mW5lTy*E>GiN@u6&pnYf_19RvxfsT zAZwATIm|OwJde5)>T?TF+Cx3-REaLZV_8!qf`AgC$`ut#zOXonO&d;$gOofR?Uqqx z+X_iYCmZddJ>QfqE&HyMxnwX*?(A^fx^H@NRxI_jS8+psP^TX{pND!n-^jpctT zOh=f|k3rGj9;WK0yrx8A0Xh7)D75AYS#q2g6?%;~6z+fDCb-*Hcy}wI{EF)5L32BQ zz9Lzpi6lsQr!IA@zE>gmY()rihlwi8nFrz-5J#_+G+VX4c_J>{tuk_}0f~I+{6fHV z3)Lf7N_-AXv;y&t^gJ{6_)zg7IV zmdui`SD(?Bx_?Thu%~B~g0ce9OJ{KcDpc`)Pi6K74w$&l1ITvHtkGp@!MiU)F=f4z zs@icsGj>h?B=A-FPjFa-JNmlfIQ`CW87F@f5U~3n`}i_Vl3DF>8GF)ylFx8w-|Mv; z?iIN;0r2{~Piq@;R3rMl*y%ET=D7I)*o|I%=J~#K!I4oZZJb_H{Y($e9=e<6;FKo( zy~2|VTcL&g$!q%pqXaAj@lqg;N=l+Ab9SB>pVI#O83l@1zl#@`?F+DY2x5ielE^K7 zcqHZGPTup|(LZED%m0xk<^wp1CZ3V%*7teM0^_Dv4uHtkYQY5gA>-C-=x{ZAj3nHl zpjkBk(5m3{F)Pg?k$YV-(;^g;Yb;HiCY_`2XB6DV@qv~WsgS$Lp236G`Nd3DGE(Hk zASQOASVD61d7kPUJ<=~ub&qAR^M5vK{4_D!1>)$$!fPzcR?y&VZ^2nWfF14WU@*l# zT4_{TZBHY#!vE<;Tv84z!O1)s`DT5<-zT&&GDtg z6lmOC#c(gVP&&mWH<9{8T$Ec>Lb<2-?4hGnBeInjipw&iVN$ zi_3@LC%7>-nsaH%)PO{W!K7Msyz-fH_Xk-j&_QuRHbSz37b~%0NYZfxNB7vT{ zr3WZWYpFTM8ZGqH2yn9&9tAJlgE^Lp7&_UGWR$qq;{-i|6`OC&bQx;oyvNQ9wzJ6I zq8!Kr5X{KHXp@SdrU=wRkj%=Y)f!n*N?WS1Ho67nUE3Hh>DyE^p4bR>49rflRp%{g z?M=?BMUMLSz$*pYwn#n5Y|wCdXQh<6B%wT#=&7LUyqn@5S5BCgQ|i+mlte+L*IY>) zO9Vm+04A9yCvGBj`HKD~{lP0+^Q9tJpGwx0emaU%%55F);MZ+%7UegQyb^0UI%H)?6qstg=K00{)9WE=8kniOVU6|kKRzpE5~ z4PSdOb5|I$Dbl}DV!TmkPRQbWKAytdKQ+vM!UCBBWb~KOm&dDe{_vkhGUi z-C8;$@8TrqL`oFsq*nua9$8~|ML3Pi<*i>be5DQA43|nzC7_J!FTZ#KCf{%erAj^s#Mi^;0*uuTZu7n2^vYPHfEU((L-*4YVdE9 zC0luI41vgkISHH(7@ilW=3kH_XtXSnyCk|@ltT=kNi9(YZ@TPRO8P1p6pJwq|A4-D z-XY?EiIl&-0}zmqqQktRW2Q2kD9ECQSr*KX*6l>UHR1x#)jW45n=KLg0*nZfOhAC3 z5D-MD5lH-d6rdLav+h_$d3RGo?$v_d($ktWaBC&(uUEQ3gpe(y2}>~U%C6sUfPj(R z1?J+uH$%#1u83mQCJ%&%eK@8IC@5=&kOPZv6{umh|MCEf z703`L&h-7zJ7WI*rNbM zHv=y@K{cE^T!YPTXl?m`>>n&kJMmVc9EbAqJ0@}1&~Zw4+We;>0dqD0S!%n$o`Scj z07@=SM#~tdwJxUnoKLHR6$EFi@lnt45Cv3~_dQ&PQ{X(VJXS12&qtK>Qi!V<6dZ*# z%%4X|GI>=1h@acs{mlqw#M-rSUfTF2ZnB8fS*jo9E|c=cCHjF3rRt^E|LP7K0F;0v zw?rqaCoAyF5-gXX7);7sB7uaW?cS=FUEpg7y&CDbe8@}b>R^jSbAap@A1{NLy1~W} zsb4A!R%vBdt> z^dEx$Tt^vSd3JNI8ETtKJ1to$(ATIqjcn^u1fvL@(fMK;9M`inrSlpLDszZ(xgu~u zuqGW%==N$`^wZlm6<-7Kl%f zdthS^YcEsk9MlorQZ?!z5};>B9MMpqaGrulXGAsZ5U@BZrd*-%>b$&$~ zF&UlZs2n|hx1m@oFM@6O>quifze$|nbe3rl)|vz{lyFL>PzJJJn*-_j^I1@4;>~jsUwLG5Ijr_xvR4<4 zc$wC=+wdLayq5wq>ldEBg`J;u{O(|x#ou77gUmua&?=Ga)exio12HII!2{*VbvomX zk-YO;r{}mbx2K!0eFJ@*X_AdZC=%KyuRHff?Z{3M#4;3)-zOjiLydZn-su7YHCj{A{bfX*r3^d zr%UWd0@rS^JuE}N^hzv=QeMqb4_HhiZV!h#V47D_EVD_fGopR3|5~oh{95Lv1%sp3 zvjyqCr6Sqx7>uW<*X99lMu>n+PL76;x5?8D#dYmsDc1}F)WMhik?Hk{g430UPNHR| z&b5MW%yd0}!@b;X6d?}GgOo`SzPsk~WK!^*7|SISm&5TmMi(i%WRcwY8^Lx>5QqA;h6-i8fYMacVJgCv%w(07zzLyq;S*| z2zSe6;+jcj{pmJdF!B7tm>49m0lLKvCb?T=a#3S`G)q22T8=L90Ii4U278FTW|>(B zC^DC|(}ky#uwm3B6+RxiVlrghQm5>E1dIP9Og%u~hTInv()fi3sci&**JzV#?%esZ zIOt|Ox?+A`qq*zoR+h;C>2E}F!(T39nZ^bbC&XnwghVDza@wNFACar4l$$9KMxGGz zH-SMb8WKGd=q$%IUU#v*F&pd1CZkUR6ZTb_6F@$?Dp|9%lIG6SMLKD<$X}kU15%tw zXD2mys|;hk?7ep)g?F}9AmwN^cihB&85H00k=@8KKPE}J<#}24?WFC{C&D*-8lVK2 zBvY&ZZ{VSL+S61wU7K92x*Bka7x*4agc#k|$V{7-4U`Vs)g|dZDKT>E^D*iFblWOo zt4lY0!^7*@OBv{CxJHxOMPjp2TDoFsluAisE33U9%L8p_&kEJXw**^CWZES-tFHZQ+66*cAf*2{ z_&5RHQ8`p7Lu>%*wQH>ruMH%3Txhty(EOdWOE859E(7-@o4MX$>o#B1d(nL!|3WU> z%P$>RW}+{;I}R%AP^BBKr~6Q{$$K7t=t&g?6pBokRy}~<{VDQlk$Kl#ma)61UIt$? zEM=*NUpp1oHS$g&@puQb(02{#;0j5V${VLWe}T1+`^uiK^a&}HKYnx!PW$i0F^yImJ34{sM+LL(dWE~P#Y7>W zvS&26`$*SF&)L2kd=aawS15gfX=gZMaG`ajur~kz`CZamlxc507*}=`e|Z#rNNc$mDqEY*?wuei9?~s z)7uSH&tU0yKyz#d0kTI!BRVp|XFn0^=o!Or%>C!)RQb7aCDn|V=zT97=d`AMbArKa zaHbmmw}2Tm%5^mEbOEA1M)F!JzEz>Mh6F*GP*_!OMN4_=*JJN0jV#-iBbWJo*1wXw z9$F8fyfzLbD4+!JYtnLk0E=UO-p@FEdLR-m;%~;blzXdSce2E-tX)$lchuFsbU=`E zQB&!wS>R|j{yx$f+~FcPF%uriC*IjuL#j8(9o2Zr7lMDhah3Qy`w&rzlgurLvf>(4 zTef$#CMt~gSnS-V@zi7Z@a%Q|>0uKusKl3${6N9-5_SpI&@L;( z$%fmW*)yWW8E1t~dE8)xzPA{ELb}+3yaJmoeUqY-FURLcUP>0Fy|84<*lMCrD*Fx! zGAl{MNT0Q~37o#YbRM}`V()mMT~k~jPZlU~eE;u>*)EokJbT39fv5pcQ%%W!*00y4 ztLe97PL%oZM`GOar6K-sC!RoyFWUtk!DbP4hF$MqUVhjnE~!`1>@ep`BZz6?y@#smSwFk-<=+!(3nG@Z0Nkzd z4j^4QZW*F^sz^F5rC3K;M|Dtafi-PGH~kk1vv^~%3wkK3j?Yl;U&^rf^5OjT{6yRP zsoNNg=`G4AXvfYUH;t0QNR`CGp1d+nPTHZHR7DC6=ccy@^Lb3-hPa|&cd#E&WIVvFElz=c! zxqxCAe^+qrj93-}W3ZRT2jk%}`>yEkU;Z8>?y7%VOW>!28EhSFrNnZFDdr5l(a+2>ESd@mn!MBXA&(pAZ#d zlEUZ#w7|frlY-L51K&9ilJ1zsmNio*_cRuD(BPRNovz(8Zw|(UWmXf<*;!i-I44)Z>!wJSMwVJT1c2zF#;^Zg@{<6S2AqA#kseyk9i_TH5 z^Sa0N?}^bhrk@EId_Xy>*mHUQ&bh&6_O%pOy3-nVRN|x+?)Pli+s_t5zG>*7(pFp5 zNaxBPZMHV_EBt+8WQy7D+9(nFL7F`5AN)Cw#bV&{w!2lm-m8jpYaW5U&wL}@#EpL* zIgZNQNG7R13Fa^i@fqTv84kWHMI6tygb9m1GIfxr!{+!PIFqH6`L=_rA%*tSg-=rx zQkw$UzF+cXbRHdF9vupRdmKT&OTDKZ4--A=85z!UxU35RXggnu&Y8fYtapldwT1U? zm+tsYH^6@DmJ2z!XCRf^yJSjVjQi!Wd|&zXXnylC=AAy?yID5Q-80*{Z@DQ)z+pfC zVZp0Vhf6==(tUS3h$Oe^`**UXfLSdlsmZw??{~iG3qBiKn6ZH5bUiR|B$#b0_P+a} zF+W4dc%^dj$Z23NlV9K;9I-jjx=-L8>t(Cl>Kh8vHOI)EI0zv{KR?y|+tWu@V}L(4 zON)4PfO6cmpYP^WYVYlH)h}E`hdOeY&D?G`RK6u!BK_|Pb3OciN5IMEn;eru0?9xZ z)J6#Xz38>Ei>rMKPmm(#3NU7-UtvF>Oam`T&F0sTn%_spr^Zs&$@ZTDTYZFgL)k-%4<|6kH3q|@SO+62C{6kznzBW1Nx6*e_+p{GaX4J)QLU52$pm-v82 zsC?^RqVzm(JJVb`C=AJ0GNv@`N1(-t8eYG4hM$>7F@Ey2uhSh zwkCotUowAx4FdzsRJHaV>$qn(O|Uh@W+Q->m<`tlO77@CxP3d#oI^k{CEPYX{obwk zE02A?T{Qnl9}Bym{^`kM8^IMWms{u9e%}Du=sEm3RiF}%BZd4g?7VwUnm@muO-ZQ|DIk#52t_T@>Ri0suDgR*Ynty&hCD%RP*OBw`*v%CJ z%ZW|RhafJgGa-PNmqs|tpnRe6sShDX6;K@A7kbuk%)}eJMsh4w{`RI6coi1<@zjsX zDXu6{*ruk;Tft5vy)j$WvF6qr)7|_TkG5KD8-sFWDe|aW=Nl6uRJZTodX9}DsWy=z zO_1jn2~u*p64;CHFGi70hW5SesDmKD1b+k=fB_(wCo;p2LgVkDE#b*o;VvqA?Tuw| z(kT7uoH?=)#h5YQEYiN&4!JHTI6736ySdCIecE9rOsy#-AjKrS8*R%iNNw#rNPF#B z27Yh*c;PHI);J8XUAA-H?-Ok8nfSu)y~c{OX3r}(GcPaX83GNfenU|)O$u_*hcSN*6KyUR3%X5)#{oJNVWjIB~{{SmEoet=*6Fc{}}JT zkq_*-u@Pw!^o^r_Za_0!1*L+!Y@Pcp`$Od7!E0D66(yJaroLSOy!J=r$I3u_sj|t} zMZf*1`n&AA(H`k{;_r_?0snhq_u9ORLQ$&<$*sifdW4TN)0+kc;*tOejX)sIkST}f z#6x_?OKtpp*|+OyW~z5pA8J7iHH&@jc#QSyJO&Xj6!q9YLybOpxRdiiV;~0OJ`2dn zX5}*F(k8#Yer(FwXgVwBYYqCU_iOfnY~x^(%HnrcV&u+t!J|69HC z-1wslGo?!JX3!(wFV@m2a0PZ<^K{*yNs^rtwK0(((fwq@)aJf(1kcj&oBvT}5Dm$w zfuz?0{rwX@p6?Oy5cU~O*PTj4HpG?kaR{ceG*xf%1*cofkQ0GblB2M6=fT`}rfObY zg52m+@5EoK*uk>cjE5{|!EY|GO!szosIa&Wgy_BP0t17e>WQq~wwb+R6@9imEb`6r z-lYM$Fq_5Yv2IkhCa-py*Z1PlBmBww!TtrW4_)G{4RM9wxsqg#US?C+Gb|S-J6T>8 zgVe;B$Mn5wrx?7VWo#Bt-UC*6l53da0y0@w^~@2t@%^=9S(dmhFlGFfsBVOiTx?cX zi)qT)(o@TyKn)qqerWG>Nmr6#J9m^s-${1+3dbisZy-Tr&fm= z6XCs-m$MoZ^zScndw&uqdqr3b*mp*r>hj}wLmy0&{Syu%OT@MoX@h^@bHzb7kly;Mby{0wU(C!dV`x`ijKJ4k1ET`W*~iS*tXy zD`4)oN|oJ;C<{{Ci|L=6hCCwmMGV=dSIhRU3gZGJj~^Z$PbK_&qV#z9;7I7-6YbYm z1;zkOQ}Nsn6^Fy~{~t~784cI_y$=rtqmSOZ5p72A5k?Op%ILj}5WPf==%d%DAvzgC z^xhc+BWe=86Y)_Z5rUBae1Fe+-kddS)_HNxx$nL2y|3%qdkdUhjNCJruN`?`Lqzgo z9ObpyAsH{uQmQ03+I8IQUe5N&{sRp7P2(mLUFFN%4J_k3y3DMU+<>@9$h&fEs}D9z z$#vp1L|%G`zw?J8eS^Yf*6%=ucXGmwVGjQQWT?3{fzdRfZ_4k|N3ILrVV0{oVtk)? zB7!(5MFy?nuY_4IpPPO=!z!;ve^zcz|9eVm`{+cL@c7$(zk^Rt@6(Ml8lJb0!FB`G zZp80r?$Syq?vH~wUA&4<4QwNdp57heX2XXD-Qng)*XDU%zPlfeXlwlkSkxIkUt|#=LxNruBTNyY$N9q6lF#fShF-TjOs*d9SS!+QZJI>d; z%o^l7T(0FHp{Ls;YC@9bES9qUy)Wn~?W-@pcPJhDt5GzcdwJGJQlCCJCG1$o8$XNm zh!EMo!*vnV#OqiaY`=YAw<$I@4OP8d^jl%^#GCyhkh|K(%Z?ep1H~y<0k@k4`2!^M zdVeDKc*zSRBcfo_oGw-{^#kW zq(PyBQef1(JuPa@$XxYiFi+PDQNPbVg4%|m=@N@BbDJbMj`gdLqh$JL_tw2s>plv( zSnm4oe%n?51%D6Ef#oyDm`k$#q;xYJLCUaafL~;>eI2WMc!Uw83S_i*vT)vwXaU=778J{{UV1 zOG??4k#B8HIyOpfUjG9;kN7@Zaypmu>_o$AU_X_f_8q!A^` zTh!1n^?VBn%mqLG963(E6&Ns;Cu%jnKb1Qbng_G)GSR21X8Fzj6pnL8PP((R=2PyN zZEN@PB`FpswnYhD`mU2dE*dcrByiahF7*V1%DAZ6<_hehMP-?~u12u02dlnR(fA$d z+9fSrJqHpTYqVQ^Q&b}90_Kbut(G#BA^)aEH1@~KuKf4voZm&eHP%}3$qe|d){Z2)A%krc)_gaR14?gMok%gpEe_NQ=fcS_zB3bS4b3m@J-40rfX zNuNJ@UUfoVhhubeRwX{NmIQ*L?bQ?CaFQ=oj8$+Kl41?#kWN+@!eRya)T^zF2s@2`0Gz9gbld&fAGd~8C!p!j zb6c$bSeu%2L!dDm%U`^B8-Pm*v~Zh71s6>G1K{tN^4Lmksx-Jg4_Qhr2Ww=3gapMcI?B)K3K^c5ThH_4XSBx7fiS?#F<;9V9 zJV;i+oIi*o3Mzga#^Ce#rBTP&4>{_WyRX;Q65kV3QC*Q%FtQMhstQ_Q$UL~RPJb{O z`eYdj?=`I;$*0Ppt;Slj@VtWH`Ew#`uAfpJ#ha_&cY^-`r2kqpjQgb3Z7Rf6;Q9Ee z6w}zZB`dql$tT28wuZhM!x@3tEG{E(T}R_=K`d4ovZz5gR$s~&2$8@l#EK1_Gk_gb zPhE}=0<`Ib>|4|cPXu-{(W+C~*>kU)7;y&ScLs|;!gp_7&J)#L9Pxc}HD5-*)k*vq z(eNet3zegwD2GjOc%z=(w!QzRU_7m1VQBP{%0#~9QpiuOV7FCa-g+pAi#e4&-UmAUm+xVK<4@Ep=|WyrsKu9)6T&ByAeueC}h6OOs&(q`cvuo-)w zFBoQadGQbMbo}W-m#^d0ml;iEVPVqu6t%yRN#&p4DIIfHl~quPMqp+aXJ=8-;8~Sf z+^a^!=>5zGD~%S6yAo3iLG{k7xeA=RV)U)jTTNQ6^WQVTpw_1$JSGel0yvKTKT!a=Bd5aBzxBMtpmz;W8@F2K!4`%+6K`h zr-Gi(-+r;HmRy}O^g}j(5y?_)-K0BOufuJ%jBWn7f}NDp^T9 zyX0BH4Q%``|AZG?WcClBhIx1Y^<3n?U${Ur`Fv>{89Y)TNp~^h;Q*_D6+)sbM+(JNs~w zSNuZ1EsU-z|96y8so-o54;Q$D)V_p17a7!)Cd4?bS6S01XmZ;+O`yh*&=~SVYe^zW zN(=sQS!^F&Uiq>|*;PdEjkggCXWWg(tlEW5Z8b-_x@h92NKm3>T8belm}|09<}3S3 zUR3oFb**P$ple;(gT~o};Ih(Sn!yjnLnJBM-#xl~atKtS%gTf4>s{o}4Lrx(w}mG-9Z zYNxKA#^1Q;{sUATKpf0d4c{GziO4$s0|e#$&0TW+Qp*{1>-E22>wo9ilZ{B+)fM-R zN-%C*7$Xe^afb2~`YAC-Rx5!ye_^m)yH&`F2tpPuwgMX5TcAFsfAXmC0%yPn#!dA% z>G1Egk>*KINi#R*K6NQt&p-zR;podTR=&m!ruE4q@5)!;?3W`yFSDz$0ql|nvK?uEXDk&RwJ{eF4bUTem4&pIVfVyy!rSn z`tWowSPyYxB-Pe>DvkRW(tX~lcR`0;5nD9hSgb-5jV{^=IWPbM`~T_VrMPjs5{IYY zu4UJzKY7pbUj*xBmCO2QQqK*SIuc;{DAd`>wmO@URz6rJA*TFCToloHr+BN( zJ_*^S%uC(*C<2s=V?aFxddi(rR_=LWsyqw&N*BVFRIK60NYVwi=N44*XpU^;vfwN- zZe&oB8GqkP7|w0n1tpftPF`m&{7T9QCWE zyV{EvPLlV~jFk2`S0S4lfMBQ4!$VbY6fPQ5~;~NLR!vEk^b7ygL|j4qBd=KvF%fkzw$zEuriW^?=LnW9AmP2^Xxv9|Hpqb ze=Ei!&NjGP!pb8Sou1uRhwn!V;gXsnJ8bH}sX9xm+kI#JP3hT16Od|zenId*xD13% zqPQw`La*8wN}Y|JOqiUn(wQ$Xs&X@Gt#?;^a|0U4R z!M_2E+%;uo-<9Mv-!t^h32bmViDyU(1il>u(Yp8sF`Rm#3&-k~quQop+fR9FAg2)1 z*W}yGeKt(v#>W=qVl&DyiC)nr8QyyHWa31n1cRC;1;#w)%j!cfg}C1H3^6|Cf-z7H zk;-&FJYtrEH>nBqBr8)J=8)T<8u+{W427|T$|a;WQuQ{2#pkTv`ZPTnz>rI?DHYkOML#|*GJ;|w7AB~ zc+aA?=m-WEj_*8{L0Xl(6Z{@p1A&RLr;gcgwgXdxF4ggDT^HE!bq9s+`*Y15^w8c8`YhI<&-ooMLD^hFo;J3aX6;y^H)I0 zW@Q5n8M1G@c-_gBfljkVaDrMC+)te3O}RG|WS()yw@}{2GhKIa|`d%40^@6V5-Mb5WMuq#`!`4p^(W>8ujOfe?yj*k!#p1OjeC)r~Qs9z5n^-LqpT0bwBG06GdU+ucWls z^wfz}u7~$PYCQHa8<7{y9;tf~E1m=^>gx7uf;k_|k7@dNH$>+wSu#+uT#Hg1k*Z)^ zR9q>gqfzN7F_5<&MHVW<8w@J)0pSsH_Aka;Of01K$u8+%aVfG z4%xmoI6lwHd)_0HLC`&O;oHF5ow9{q4jfXqNYh8z-2AgStFZ&@S;XlUF)76Kp%^!B zoxHgMI^~}JgIeZM`i)k2_-xF*p2PiqVMNnFPYFih9#7ey5;}BcYSQQ)RDU>?a`=9J zr&8)tS~gCBEB5xFWO{OBqb@u{`2$!A%6-Mvnc$@{I>v;~Di7V%j|dG>DnNX+U5B^| zEZuaLT#X$<5NOo#Puuf{QL{^) z``O!+*1+Y`jOt<1mb?6m@q{JU5Fpyih~BjdVx)n8n9 z0sp*+`5l3Ky?fpWpZs{gEsB`go3kH{v*C0W0%RHrfhiU1$*-!+BOsdVwz&57zN%Sj zzMM>*A1dgX&~Gf5nySrjV%mr3RNJ0$#63PNCgQBeQB)bRU{n+iw#P+;d5&KajaRkF zY?mIm{!ncGyg?j4W6 zwsyEib!xs5)S#NURgXoYPA>s#ttl${7ChtQ8}g`J?tNcE8#2C} z4q%AovaDPe*vZEm$e|;}*zyFS!hfsBrJpkOGmvS1tUws?v=lvwnkC9 z!7HNZ<@0p^{$P9?2ZU`$l$H!WIN9cX`%7S8)L(f=aYR3yQIOszyvo`)9(pdZ9&mwG zE@FvBE3u|k+9{tFmfO-34tQvCCZ~Ccmx~Xo$va8k;8Vl5xC@p%lSOsD?4C>+9t9Zh z6P%I~1HiFNIA%%a$>l}`Im{(<6KaGagws0mC- z$fJiBFCQ(}*)EsRqrMR0=2r$83EXC;U-YI~VbEYDOr-xKZa81%3J8qVO1+liw8!qt z12&!|AxhcGq4QylDUvA+_J`7WLQ1VgHM)DX#s^_1lA5P5SP@r2%o5f)Lv%k$9Pn`LWGFbZ z%ZIsGiLCRaFY5l(oA)>ZPu7_5$~#~xzmLT4BUX9bI+SWOmgBvu6bWpnbkTm&S!d|N z{I~Q=hbSKX+>*|2fwql=cSNTmgs9(?*2(P{=?8tPR%ehm#@&-d->kkY^^C`ua-=KV zryTwdOy#B^!jUP`AT_n~vel}v&Id88WvDa356Y!Dw`53MI7>?D1Z9c5Wb(O?oX=#~dx66#_t< zbxs~hit*I^E;NOfTQthBDSAN=1$_VH_g0aRUtunR2k=?f1>`U)Y73>LF-NC>9vxme zwNY)(^=BO-^eV+0>znZ{d+*w`Qp=FXb0*0PS;|Wt)r>AYweq#Dd#?1YleNu*Ftsy1 z^LyGslinwP8Mbnp4X6Jeh-=Jk{sY8MFj&6nF2dLFnT&Nv`bo1`+rmJ4E-LCT3?&u@ zRNhLnW}h=F2N&TTtAC&_EumQ6%M91_P+_Gd?_HD)RGke_V)VZKT!XV(Tp9;d0>t1l z(dVHQ+O3$Py0)YwbI20dK$q?*!5i+@y0yYmm_bdd>O&om!IzDT`*_vQB?I(CX_mn1 z6RoWlX1+XzlwPE^TfJKHj%bnLCRy&H<_sb#vEQVXwX2_XuP+%&hWDV4>h2xxqe}+I z@0b4pR3o@hPGlc4M|^_2Hrq*kqpPAx@InYfQt?SBR?R4jc4&~ccbJDK-o1u2tGu54 zW!*a|wS+E5piGla$2T9iOi0#UQ+EmFfZ_vHdJN>Rm-#<8VJ0`E6GZh7A zF+Kuv*FX=cT0l6eOBIZY`GSW_M9OOZkOZ|hZh?GyD!bWpT3r81+rgxag_#yv5#~ON zYseo0ylj-sI;kw>5{`%#HD}18qRK#x3uNb+L{>r_I;C7uS3nbF{>gv!6>mYPWU!R& zoQuha@{`k%n3!J}QJ`VzX^IS)$vX~^aL&$knBzBnOgIA(G<7t=Kuz@%v3u%Hrb`u} zyU!<`*e12;m=Ft}%=)*wycD0uTNzC+UCi<9w7^S9GUFXSZChihtm%Md&`QraWgQzb zdmSn*?9qtFbfoZAeB(OjUjAMwdL@cUZ5BgdkYi+k$6>7D=0LWCX>H^UB5XV?d=Mxn zq$vCVNLiKy6dXM*r zH<6adaQdG!0T}dT)Et8l{|1SH2+wA4rGdPYvr1i~qk>GgI2f`*CI@nS&CjtQI_FE# z-LEd>wKWu&bhqVR*qpzBBbbQ>oSbuYv!O8a%4DQ5RtVLh=!EdTNp}$Kv6{7$P5%dA zOpaC&v2%##oKD=mmWXOSr!D1oyYAzFdQGqf={8QqKXqD{60!pte@c?uWQ-BxFL2BnBIP3 zb8G%p3rPIDDerOfAmCEYp(LcwI|5q+M>QmaaOJibJLRBhjru4mYPe28wG3kDL{R~m z$iK8Q*(JZj*g%c;O1pt^8wJE4|9y#bc4~nXLzi6h3dB8x@8w{ejsp8RJtcu2Grx$3 zpaow_b#iL_my^t~6@Lo6A3G(!aWE6NEkq0W^c9#q8}-RVT&0GR^j0nTR#8v}Jyzx6 z-MY+Yed$lo*SoH_ScUSs68Nb%S(BfFX)*|GSm!F@t2JLfqu)yr6%P;AR@i#yKP4}D zz-YVcbewAzPI#xnb;-X?l)B#v1cAB!$Js+(*$H~jF(sm2{2u7FPJAo@*GkT*3_j=OLW{c*sT9hF5XEP*Q`w^?#0K68DYg2sJDpp-%NSKG1dWY3} zsPRmrF-<$QEV65JNGM-u@s~RyF+xpa4@W ztp5WTuvZd$*V=TCDx<1&kUEh%T=zzxy%DZLbA-5T(w+Yk@9j}m2C`;q)7P)&d4GSgObiIUn@ia2D9eufc28%MWruoE`Y;2m zzz2M1pk{f2sIkm2IA8fONBmmUH~yj4n>e}D~;1|1i{kcHSUp}<-waP^eRcL9Z-fX)MrwuDNF#ODRr>DZ<1iGT5Qdxf!y4y zB7xK_kjO6I;Q3{wxsMgwb3!YcXmgt3tsQ~a4)%@PFYfY(o~%t}_#5?pawPrqgDfk5 ztfw|z?QTlF5XZb&Z}BUrMrN+to@@Rr8C7vz-|NS>d)^E?b8|#|fC!%Hk;+(Mj^P7G zsh4U|67Q*kW9@mSd(_G~CH9|-J2F~H#G0)|2;exzCdz2v`wWw3D`gnFKqR0UZ|6@Q zu0dNwQk6osb-CRij~Q19OMOFj@f7pZpIr;7ZO*-4V`REIzmE8$)y*? zZl%UcWj~H8$kVj9RoBDhzRyD_;T;W|wjl=d2C0NbYvAP83 zh`Uw?T0H%`Yz>eLckOJxLli25PwJ=6tC2eV%2U3y#8DoTwFwlPb9t9=zqtf>h)x11 z?Q{SgMfFBpFl;nI4epTiV=}PK5z&aFix>!tW9{N!= z9?4FI7er5_nMkbtOhoD{9doXjY|7$WmZ6%m^2H!M0AS6*Y5kXK)u!vuS$ zDwlSPm@eq~FK(9m?{nJ0~5qaR)$ZZKx%P?G4%}>k6=8Q_(!S zjx#AOWou&&vUYcFjXL(>3>JPPbIl9Ze2J5t^24`z>(gl3$k2Ex!ZBb)tH!7}1eQ4n zX8S)4gL9v5p4cRsc%)#mrCRo51vz+<7iWGx--X=y%CcCYp3a`0@Fv3^;AX z{uHVM#)ZvzF>wAILBSAnWXnw-yU+OoJlqGSHaG^tJNsH_zLdzvI3BThpP+~%r|{n7 zGMmVQWDPe^#){A54HeKlRj*UA6TFYR2wlV^7@iD&7@KWstp6ZmaT{ZjVBA8k=#Ea5 z6N}z>wBUnuj5_GZ9af~@OC4(9E*;H6R48?N;o`;kQU@vn3R0F=$#nPp(hc_=+(I3B z5!F>stj}Lx0qWF`6O-~5Ym6!g`ycevqE*6wj@C^z_+IJ0T8^rs8FZD=)tt>rF@DVS zlks?n(OIRIYow?V@0rNN*txq$OTZRSHs6SVJM}9o{tKXD0f~8MhZWv_toHhNiqwf~PSXoCWcA{LN>QR@7fGH?^Y7ilt#tM1ssT;k9@@${)E#9Ruz9 z_?zWG)d^7sYGuX3D7oD4)!V_Jv#GGv@)fu2d~69-uzaL!CBNM`FA(DqQ}p3r-}_<&rPERV<>4tjZ^JDE!KYoY_}YN6ijB%#qdX{kx? zv);ikV#{Pt-$s*E;E-!IR&^-S)Lma~hVN|-;HM$WChImRVe&GR#Zzy3N_21DT?V?m z$~Y$!7W>-!Tv0rU$gS-rI%@YjU7Sx=RrI6M&g}4sB<@s9r+kWR5g6|o54T$W={3*a z`T6;6pmiT3k##$%EsJJpX!f^r1Yt~cc2u^`g2LDGR81-Z1A=^W+sDC_ft_e8AlGC! zM8MK((rCFZ68m+@!1jjEVSS2f{gXx z+9TKiH5`$?)cs&?<+uMNZZyRpm&FPE(l9T=QL5{uSU%~M)8|u%1Tlxh0c~YcJPKUh zMZ8ZmHc`0usr>QcE^nFQChmLtN#Z=K>n`cHTrWf= zWhAvQHo6eH^>4&sr(?i#gUdbu1ai!gzR6L?roddmMu%)c=P5+*HT+la5SYZN*K{F` z$34VJBD?uGo3B1AU0?G~8Pa1Sw!U>>6)?KfXFBY+AEI&K~UEZiF z*X~92W_2lFW-A+U&$Msg?^ie5mISeHzoz8&<`ikEqFExZQ>vI)1HXTWwI3Y>25A}! z<>Z$yA1x&ns1Z0@k zx1s~4)1n?dJW$~}zh(+3NwKb;VUc58l6M^ZT#Qbpm50>J=t=p{ye%M=Fu3PLkB#W? zBxWz>$Wm1(*Oj;lS$z9~V!^q-YEv3i^J&%1lElo-&5P$@|9Keyb+$Zh6z8K)R$b0b z4tmsSAHCz}9=FF>yPq9yOuTB{oO8X7zRWq4>hiJgkNN6rj-c(s2yhZ&vlcoeQa3)* zZ21V}Z&?lf&0k~h7KwUQA)XWw%1@gkx4WNL+ClT;zT6^*@O}OYSb)|we0hGyRHNpt zy<#%a!%cs})QM+3&e2cIWc|`VV!V5YnwoYHTHEpZbJEM=x)Zm&Ps(Gve`5&I*J79e z8J*k^O0MxeAiQZOMY9Ysp(iaZ#f?@oxER9GmaflTH^5W{zL=>42U!K2Dvr^l!5{F6 z^~~ZcUTiNogH*U(fv@SSKmAlYu>AG=R)p%2 z@l-K+5J5s@94*+ZG>}x;Iqu>T8_w$HLc=`e>nSi3V2z3MlO5WCo@j*p_mS^XtcToG z7C5bf8csel+vEL3s{fP6t;+ndvt^YXCB4C_lci3y{c~XH1nC$P*9TSzA=6=PT=^Kf3Cb^M;M9W$ns%}eutxH;~k%+Ig9)LAq~MjBn$SnK#O&6>_I-VLT#4L#Yga^#oT zz$?jRDyS6gO8a(2?rNFnN=MlD*xBf=`J~EjPL^WH@kKsLO z2)8P$Vpt>JPrYmbH5FeB>_7pD|9ZnF8vz4WF3WQH1ul)1S-i9&b542I$J&D5TKI?w z1!lRz=M@cTElgBuII?)jk(IB?5~~crsS9JdsWir78*c9}j+Upc5P9Lmr_;pxJQno6 z(feY2Od}LcCMe2j0oat=3z{sK@{j~d`}%61NhcZZW|Jr79w~0kVVY9dc5W{N=mBC@ z7^^OaSW32kiJ@N$W2*y+b?sEK$P}s|_SIJGMP3+6vHD2l^kOY6A(>oxbxkK9KZa4) zU?Lqn9!;pp!+)?QKJH>!_>nV`S|X;xrv8C9Yp2D~fL@=Ayorw2RZDa`rTAO2c~2A> zY(4=FSa?D&WSW+Ab7UxlXfXSQavaxdvI+ouzuMci_H(qP>D;GZBuP;9K?_5#X1Lid^a{w{tK##5ls7E<+9nKk;5*EA`gR33PtdV7CtO{81-11*OH5K%5dnx8=8J0(o z``bk3Fz!2;rznpun7p|zm(0+ax{5_!XeBI4vPIIQXYplG>$e%i#->oUjR!@C5eAFR1=PmF6>Q(3REgxEVkbMnutT2vO9=L`+R zjboA8T7l@Zos~=f@>w_Nv_Q>k8Eawv`KAtC!T^gFR=6?#n#v0^pSWDjd6-x|yWT}~ z;Man}j#g`K39=n4VlguIFWW}Au_3K4L5`wx_zZJD8-;}FCtlE>A}g>4z4`lkIR($F zkN647kZH1{_?Nl5AxCn|F#-S@2R= zVDOVIN|^xVEJi|-Wf~8O`;r$P#q*GS*&*4kyX`NRL`z#$zX4Ic6wSq&Ro2B}8tn57 z$7?OYYxq@7EwZaRqs><`9CHYGi+zq*^#>!t{kDYT$Oa=$_OVhnR;LyWgN-MX)F{y( zzV4e`E#IGUVw97QpExpmDO@8h4ZN?2C@HxetRG>zG`)xlP(mWjmIqFkgc)9M(4-&yRwM7ktpaN8S^w?irvL(IVwGvDl?zfrJP=)29FJPp?W{j zt#xd;BJ);qMaq{@x8CENa*nP;e-FK;J((!1p|dDGk{2CI1Lp%Xg#zBr&+&$EeFpsO z)d{s=$y-aBa-c`Wu2>r5{i4+Ew01l9$(}KENy*`4mj6ITh|Oyku%!Uo@$1rSh6rLY%Lx>V8j@$~nz%dLB=q?rj=@Bh>a^g~F%3x@Bj& ze=wyr9ek4>F2e`=KBskHamM3^^Z7vCyr3LBL0Szp6N6|F ze?rgcs)~+V|L9Fz_DZ>tJWf4$DAiN*_rg6`ZQmF)XrR0M#ESLUK+vncZk!xQ#Km4< zQ`NvnD@}`G^sN)mhj2|f3#U=zxeGW)sUrOs>4nP2JhH7-np(RP)!czK-OM6WL+?uu z6ya75c=_;;=HJ#G6@nm#`y#FKYZ<6cUBrG;gHX(BFzO8rK}N|3qSQp2VvfhK z{UK+6z~gROMw-K<9OIljxUP*!thV%mfWU2PL%y5UByB)4Oj)lIhCXs3V4FOt3LWj` zivAHz1$xYvA*Uk60t}PlNUEbh(emt9NHC;QyMuSeUWqmiU|OD?mfbIpq_46x-;3jW ziwfSG3HcftKg}*Dym0HurF*$1#&}m>MIWylVPNU=h+9t*NzeLA*z(%pjoHJo9JUr# zT_;QOk%@jiaM7v~5%S^NEX(2?k(0sYziI&==rAAs=q1mc3)Iq4q%UK39=OeHC~CO`e8xg$9jzVR)u5J`ho}Uu@2Y32hiV@6AZPtaTKV^8A#pp9-;^@;7Et=rV zY@fD_qFzYU4L3YtVp>44tQ3B#zK-H3#dNv*R9Qeh~$9z<=qrHa)>mMES&zKYDk2^6TYMIb1DGU?EOxc!RC19jYZbmXoBo$uqlN!{z-P^ zaA`A`?2&emP_PHbk90!p{?Ut|o&+dU>Y@gTMIy7nkboV@l_biVW^B!oUZ3^=AlvNn zLIHn^vd#nY2pFi?Y1#u`JE;4UpjbFVLV*(Q(=0~)Oyzy}Sa@DtRFXGn#U7mqyUl99 zT4ZcF4op0HocU>5j8$#Us7jRrZ&;fvMzxIj$=$dnf3R=(Nt|TPFE~&J>($iK zB7Fy+qFG4&2`5DJBuxfEjP&HyvBRZ9u48x!a2O4SmXdRg4kr%(NWd#usOCCua_}|gv{fppfS())5EE~E)?&jQ^j7C zX-r0X0#N64&rO!bpZ5?UnPucS8U0yJtIq*TNXIX}g^p{1CRmY*NUujQgporehW)ET zgQMS5=K;$-FnpJaf?z}?i-1JQbfszob?FtXJQ^V_cue(jzZ({gcuE@ z^7W1Qu}q~jky7BPdJn~@J1bhs|Lm9|0mBnfh%-(fnEocerj64Z^g3PjZm&#N)=f$N z4;byA2`{d&BDsyXC#*-5n>F{$|OwZ|_M) ze!^naWe8*0dC(=3kx=27j8;KvI;pF5#1tSDz8mH3nCl(-igXBCB&?MEKBm51VKDAb z%d;rZ(V?!ch&z+Dv|zfnN{$R6mr2SJf96x!KPzyaZ!b|G{w);`*LS;dpWJ|K#c9)B zq?g+0=PoGIv9Rhtn}*-CUbt!B46v$Dp7h|sU-V7>qC`B8{*-@-ij4^y^d>Dmjq6ll za1_jzxTxh|0iuWq;3kVb1~Zy2a(3RA=%S~6oP#rjCwDn9-_9C#%va1hM9&_7P^MDF zwD>~tSFy~w*52OB$+En#+~pDz`LKWvPVd#$@`KScf;?9hvZMrdQfqSbl3LG}r#LHh z{cg1Rr^~nGc)w)Q2yV?^p~1mJgj)93IWH32>BM;Qn#om0R&F~Rh|ER;?(M(W?^g#W zo&BLr2ol)iEw!OW_@l_zC<JloLM&RuTN#;fJV(pWnqxe5 zjYW;tGJ9E$$$n9=(lA-8V)R_;TEPbE0b}bBw|Ts?9wthA#atW%4vK89)_s#~j~I{@ z&gMZY67vdmNcG;NkGTomNf%|QD$9Z93FHp-uch!9CVcd<(#UYT)cAk+Vn z!derWvee&%M>CG;Y{yZ5SJ&MP9@1_=?<{gd)F8c{{wjB2=y?d2=wS%b>~G0lM>X(lFH&b&8_v{bzbLI zDeB}_ts))YR`VLJp^gxmhDiy}zeNk}r>uGCQ2Rb4-*ru?`#!|J8e^aH4ckiZfc9tk z5ZgA9yw;qWm}|datwT8zl(57E!Qb&_8|z~vBt1262sZlU1+-XWs9Vch@X4oL7pHum zM3pdmMa5T^oQg6s(-^g4y3`1w@gi4MvCr{U6dzYONj}-`j07~V;~o7Xi@UU2EsY-xYkp~=`7Y0#q|M%_<9~HWil40 z#{VWS6h<1KN_p@aiP3V3(8Vlj^_bC2rDc)@!J!QAPEF}nKm@|P?(GUMvntqz4D91} zN5s--AVee8LP@_!O+Ip2%Cwpk;Y~MVdXoX`+`(FMg*Cx}D$|z{!R6(2z9JN}6Jlvp zi_nna%a9}UZ^4l>2hR>znHe4!#NvacKou&HQ3NVdxMwV*|4xK^R;%t$Z9imI%;2+y zRcmOE#QZ7b+?F4Ut3nq?+0B~~{7#S#A^QhVXIC~N_%VA29;E8BXpC>Nd(q&fxZ2E4Qe@;sKZRqhyB3?5e_V26L!MntwHx5uLN{kgPLHhv>-OGkatdk`OXVl37Zr^t-;_ z@9)3QpU>yn@7MEwzn&cjo$q?zBm;XdGP21nj_jj~c+$Tz9k9Hju9X3^cc^ivt3}+- zWD!pNrXtZAh6i$^GNV$hj_AF}^{UwJuugYCW}lZ^P5E0JQFd|eQUxBvuL-sDq2<0~ z63a^^$ry3beUjhcXc_&_*eAjYo!XP52X1Yjve1RyH|i74shULmvi);`K(-Q^X&9i! z(KeYRJ;~X9iMdsJ`2YDmtM$~=jwgG_Y}(bO%jhILoZA*u1Ecg+gB+|&dI|}2=9ZWJ z+{E|y%)>@*O|eOp4d|PS_XxM@d4#AFG)?r@$3(vJ=WjF7lyO84FIyR~?Kb3em zl8UXEG#R$Zm0HQ4&`Zwx30-2C%*~5Z=*>#Ze-@RgP5*)b(J_Lc=N5r?^|H zI11T4&!GYI$vi?TQ1MdCyqwvtJd5fL2A&GAZ6esbTsu%^ie_z;AqZQaS28o}>W+OE z68K5yTb)OS?3`#GA{`HWvH&K@4YRKIw>JKlM*j0JdN@`fLfmv#p?l^|Bp0MB=6ejf zfnqlb%Ie;Mi`~-YJ*Vlon_216Ny7B#T$K4tYJU6yac>T(UDKY;NY{V6ug2fHi65T$ z#&jdq^FX!~8r3<`a>yaob4S_3KC$lMPiTvYR2ix>Q)VqJ;r6%C{-x zkL-V#35)~obNbEzI#q_%z5R%_f?4ZzlVVlAHUIAnB#n|nPRels=h|Uy1ewrbuwcHC zOI}KeCFl_{OUod^=Kv>dEc2c=zP=)qP2)!jcDWb*k%Oybh*4S35zle^kt#&h_BCCZ zwwt_h2)4wQO}y{AJqn}RHRzS1vQ>!4nrk&Rd*d=lMUyMc`jXcacj4h6;n9{8A$AqQ z-A>Dt9SauCh27Bq*Rhb?5{rbAJ~Y!`iFj3QXWQ5wSTTpmm%1WeE5?sdL~p&lHCnOG zC5L;$!yrfOK+em9D%6&Lo?I00_T1IOU+G!XhsmI( zeOSN9K^im}YTbDOAM^?i7u8YDs8kPDr(lnMF$#w4p<1Ci9%?iazsElHA4L)T92fsp z)KdDn=Fp>?&n6dDZ};g(9#-gjvsU?vTFNtkU6X=b)A>|ubQz`6Z$@QX3Gdnln=lgT zGG|X{u(&q*0_*CkfK(oGK&a=_YttTK-MSCV0qw;W6b!F&>8!c#xhG?^&;VoR2!RgP zE**F3Q0BMrY2;6$Wq=cF%Wb@3^y)zuj0|NYQIp@8CMGD}S|8JMwukwTg8nOG0^M1O zb&YE}ey>pnnaRTM_{-qor83I^7`5fz#cncgQJl$wmI=Mw60W9{un>o=9Lw6FJZ?3Y zs%_A3nMfrd?$z|I1|aI7dC#w6b4*2p&u3hA$rTkG<8wvm(p4@JM^y-ynE;Rw%o>VZ zsszI<{}+afHIA&kBF~NUx^lnI4lfehGkTSC9vgA#EtCh#&2(V6gpMhe2dk~>@@2ou z2=RXeA8Ve{$#^>O_Kh{&3$)#R?(RA)fHR8qi1sTUHU>x(!XLNz>2wuzX^$rLq6Xa! zE3KOx6;i}>LR1)}C^{*l?5jK8I(5P5>sSZhl3u7fytHGVTndo(ZBdTayKRP8mrGQl zZ$q%u!5UYb1X@?%9x&11wmzOu1lIpb{9k{L!>c_LbOriw|ybyt5Z>41uem2c)Ux z$)))ec1PmmHpf45F0SwMO;`2Rvw#Kg>~++NF|B4Adb15}uU5-uhGZ%Gh)k#b=AQrn zqCo8u&MncZKQj087ekX3iq)kCX3X`6%7GpXKrtZJW$-yATajKN2z~iEd?{|vdjn(!g+^#kj{x;`j5t2HbIw#T&?C|&StNwdkU^3G z+p4_i<{JvAD^*|ql1Zy=N9wu6t=^2GgtYM!jl{rDFFYivj5UX{l5UTu7}zFM{%Ss0*SBa2eVQ*UkQEXwY>QwbJ^nl z8E}}r-rInEu1?};ong$(x3$_%$veoo8MRH4geBTstT6Dt~ zTB_d=TF4S90JM%g|6G3_iu_&nmGZFkJ}s}h+d!z*y|op_9Hm_f3bt5JzILL^v>hRT zwM9ij1`qd;nr1zV0tLSqHK7f^Gb1j1$jzij)E1=>0J)e5iDny%r?%Q7zp;DNS4mGn z^#g-x1LdJ**m$4gYq8Do3bTP#F>B-&3_5vEF5{59`Vv@ISaC3iCh zxk!6M4%bH*ylAOph#WO=9zB=|_G0tdT%+c%jcb((q)H-Y$0p}$Q{$+fbnqmsWI6tX zYQ9lq>O(H_1rM#Z_q1#pcVp;Gy}AmzEsrI4b?An_l)@Am8Cd(~Q z{)j=*JXa>eZrj@4`zY6d3`LKKJq>R9oM;6JnA0t6bQx_=GK5gyJ6h+J5Gg_F51m94?rED7e14Cz71ZX z{tpN}{5fsZ35V;RYU)rgGg1;jsSV%}&lJ7ygHJ}jR(Ki~UWo8ocdv^1kTrWmqBL!+ zYHHP&2rLpxQcfCC8?yRKw*1b67cpk~zSKlkpH^DXIF#cDmP~ZD#nORnmDwWK2%^PL z3QAIH8=#6MS(D^ub2)vY8y?ddgHtK;C~5(8pE(*PBV;E%TPHFYbPLYmR_ni-Po+a) zaKZ?#z&O$suRbt7lqjROR8pa2-O+pcd_>VEa+FsnQ_8y_|KUs&181DZSJotjOvd3^ z=@-0r25mGa&Ach>6B-o8vYWn#6+_ZrQRI1iTE@%Nsx+eJVk zE6JyizuHw^;osfc5RtPhc2ew^+cIlX%{uHWWRP9=k=I^sx{lq6iTV`KMr$=NqKm%Q zDR5GX)u-OySl*j2wf^Mbt!8gk_mpAJMKLXimUYfs zRd^wx!otFkYoJl$IO8&bb$jsn&G(s(c{hD5Od zE+IKlmqkFAnH0}OWlsNKJbmei$`Z-UsaU6TAgoKyf6hndr*`$ z52npG!s?mr{!C1?Tn%!(R6xG67^j!eCTE0PB_M{)3s`=DP#=`9|0Ld1#4?yL`dgQfYv<_f7`q|bo(<|?a>>37sME0yfSc~Vi$11buxN~~iC#Tf284nvuCE=X=tfgp0~YYWDfru^n3uqpK0R3Xo{6k_R7 zz06UxeJAdJ5Xu_C1r*xuF3_C4#K$m?{iZ_y&C<4ba=6?fY+dahU>Vs$u3UKSF$sQ{ z=((d{u7|F9WadE*gd`%8vwaz1v0!K_otz#=Rkhz8$BuHHUGVMpw3{p|1jMosNBNO( zBtPlpif@e`tyRDGlW3{|t4|Tsm82m-@cgF2>@W>wAJ_YCGaKmkDxPXQDP+uTJLq$b z+g6kP6{{uJwRRcDE?jg_FI&~+5shK=7>ZG4kki5kg?==#xgwl zD$|otGVhofD~0cqgIyF?p3KVNX#$&XYWfI%Ssb>E)8zt<^t)xxI11RT07?@e%AIrF z!9?G!-3kU=G5BpC=wvmq(gMNH3x>c#nvkg}8(5A!e&8C*hpVA0Gi5vH`4TheD zx<%hFc8I8HOH2lVZg_$~31pPUN{xtB4i(s{CZs+0S~Fq&if!P~O0k7)h9#uW46EIW z;gqzooyXI(NiGnO-+~$FrTR6hcT(`J#dipM`d&5YRp)~cb-U&nQf&Bvt6#?GTYp(L zDZti)5zlodYc;@90_nfO^~m2gmyX&~E-s}yqW8rucZZ&dN34q7W|dBzu$tIHyIw4e z<*1-O$Dr7=9nkLk4q18laR@=JOYS|Fkn-+!;$v@7Rt(P`vc&IvMr{D44SwhLHBI|f z?ISTRAf~7xo{_g59#)*MbE6pHet-8pCUN{%fpKagCZC^w61lWMcQj6A?cTpfpXf=` zZT-pKB7b$DVp1)I34gM7dxLoc{fmH@BV`CG5=)wme(|8+jda6eg8m(lM&h=b)kxoP zSb)d0LTYiyV+JeMR632=rjuGmnQVh<7Ty`ZBXV7M+0A``!LjT4)5*8;d;d&g^fb0yL;Kh(i9B zt+SmrjjW>iCh=TX06e0+9S#q2r@3OO!#C2wV$)0Kfc2G^%Lj<$1Sk-~V0VJ}MMA)= zTsxGq0Wua}db6M$MO{Ji>K?IA8Nm$N!oprUT0Jh)Mq+9>_%-MmN`-V-S?sEx+qL2D4x^Zqnko$6b@9CrI+Y#3*;2e6^BKx@Ao}HDu%j!2?G121$zlE6Mfc@03Mw@Bj17X`GoL;+ojPOfhqseRU|d@b+^%GFKo4|e7^FKJx(Nn1JZH#J*J>Q@%0wh3q$aPtdPBPzyd@69G zo}c5xxiKJJ551GCwF?LH;`4uGSbuB<-6x8@DS|9zQELn`3&FHqWeOy_B6H6Dl>^`n zC?%hvpUy*#KOMT0Cn)}8+-pB=A6~hAE?NB~XsfVTw`Ly0?0JkYa(^dh;ym%Zfer{O z{w`*DUD(GsbPY&>q1mc&D;d!6bF^+8y_BjfHnN9RJlzlyiWs>($IQ$$E%S z6V6--%wH3b7+_hsyT$Ji=*N9Mrn&Ln#erod^%g$|7Hko;@HrkDcLxyKCg$}*qEiW# z#QN=8lNONqFIjqY`;Jw~6=MD5DKS!?SZwvM;!9P%nW%{8j6=5y!mKd-%C9WpDUAj( zCA+X7#kJ9pUKW?-rt)Kst)}kCFSw10a@~#nn=jiGUZ;N7I+BHc>Cp>0XR0Y{sAiF! zZQO?w-WhxMe0cBCi!uX=HlFO;eP|rKkh1&Df+Eap^U-u&Ti-zy-pNahS`|uw*}p0F zU)l+^yDd#x(AgTkea-BhqR$<9M-=&R%LHulvpqmyzT|qeyU&*o)7^;(tct)KIQK(G zLU9JNDyA!Ja3?IKW0QRV2r2VqkTh@DQNx)0mX3_{92-ZYLZc3MHHw3PS$fHqt;kGc zPu5n6np7ipdfna~C$H0-F=XPJXC3TB=(hsceCEC+D$7$JQrP{#Uos|0{kGwDZMS6Y z6d^N-8hrs|AD`w*zLWM!t4JuhKRXi1gd#ht5q4J|QVt*Gt_=JX*A8#k0I9&l(z^>F z&jTdwBI$2nB-G1JIaWuDt02p$^QCWSB87Z)U&|mcfEq=yLGif0liPeP0o~mNx{e?}*{fbrVkY@>`e@Im7{iglzmJW9qm0OE%?2On)NaVNXp~gPUdr zOkQ7`NEt3;8D?UFqQPmeWertYUBhGzYGMiKx*w4iLp)mhw%@0dCYQOB4VGCSk(syaC2f@a)~?G=}qO(v37#0 zu@Qv~j9FTqvbmY_Oa=o2?r#8`5Aq)mqZ|D~46KEW^zVmas_6>E{6Tjny6(T%C`Y#m z74Z-4s(v{a#+=G=s=ih)^gOzjfj;tt%`-HIiA$f_nvKd@RWnTC9oe-8t!p}f?$0Q< zNAr<*<-%#QY=(XkSXxar5pP2k?3Pq~52SvZk~EuIKEkDdH>kaULyQzK(my~EiJ$7P z4~lqD%LLy%91;9W#_NWIv$VKk#OS|SG;>GOo4^U*Qw_6<+yO#nNbo-YTjG#ua4!)t z*q|s6s+Jp$HWEFYd2G+l0tquJdxJ$c+r`{Wnb6Kr^@_I)b>#ZgOdF+(&L5SlLz|si z5JSRGdiOImRDK9*_v>i)0-j4cy9$?c7&wLEsf%gHQ-pC&;rwIPL+?EKtYg-HVI2}o zq@_K{DS;$p*3T84C}lwchPT9wFTU&CCQ&`y{edSuR@!5DCxF%u<%qc zw)&JsvZJqZ;%C;YNZ|J7m<>cgh$GZo5^f`UZGyUTRndm*2EF!PWVcU41`^LN36Qs7 z;l3X<1To=CuCr!0f%@>IwOCCR0KY68go42OCNM<{JxNv4#Q_rfLS*d+!vrdqG6ppE z-qMk_QvRenTda<^X+U+H8-7K86EL_e^c~YWzAm)N=%k)PKYj3*%(AORW70X}xFjpS z5RH4A#LuWrpVFk?NlSfTC#NyoS}9#F8AR4Qw&pd}3?eO_rKZ1EPR~YUDTT%8cPc)= zdNA}DJtv%-Vn`Up*k~^>0<QRmgF`F4xmPkNEKS9@6pyvYQcfK>8`TfZTFz8ZW;_3Y%v8f*WG z&EeOJ0!loB`37P*DP6)UEhTaWl3m#cykPnb{%zvS@|;|cr40ntC5;gfB;@Tc8DOa_ z;`^4!U$VKzueA=iFE#Ghni|_7)OW({HpG{Kf=&oJvOS42LTjxgm~}h%D$Y*j}rH;)eitmKIco}iu1twB2!o2)SO+lCNWp}%V^un zQ$(Tiq2U-gm%a#J7c(R!8@VJTndoN;@%0znPIne=^g4iEy!=Z>V^vlu3qW0n;Lh$Z zeJ$iq(LB!|x_iVSyH(G+LyZYjwvEFgQ87iEef@^KCTev?E zPBel`0D{%mJ+;ls%8a+6wU`;y&*YA5mbo9{c`HFjxWtZFUUZa2n<%PV*BGSbUUkS|w+fS!u8n`v=yNNBFCy!8nZFwZerLRi z91Rf*g35W8O%wT<5P^>yvZuH{j)aAqZ%bNpdWz?yx?D30{iX8&vC!T)6npimX8zKg zZ<2whXuov5G}pJv{I(DCZ%ZB7vq>c;asMN7X<)Rxd8N1#e?lUG98A~xMRkGo{rz&U z(5;haCP(12*3J^%HFeH5Bo*2d6dW-~58M6OcQ7F)vvCqdYfqjY0hh=Z>6SQ*J3^P5 z+~R(H`F#E)g>h5FU?FwxBAI&QDZ6B1MUVKRTmAe$g$>T5|;IXjW zVb<#6q*)(w#14d~oV#0?fGPZ~-C5Bec^P?WLvEY&#?&D5&|fg&B)&NmzF>Q-X@4P+ zX32yZn2xBp@$``O1CWnx*lDKnDjiOmqdCsGe))!^YW_ZSTW0hzIRVNeNg7pN7>!7i z-KS)G8QwRcQSxRh;x5?Na~C44CzaIIyL}a!=QaNj02IUw%<4qC^#cr+?tb?VD&Hw$ zT7QLc9*@=PpmIN${Z;Un>?B|*w+f0-BB5U>Umnurs=&l{=W?gWnqP)HZEYI@GN1Lg zs}lB|&|7G)hl!;X8@iL0F)399d0O+R-V^#aX;{Kva##K^jv#UUfqyEJR9@pe)K;7@ zthHCzIH6U!XhC$5#kd=m5Sd?+7@)O|x&*1lG}uPo zqObUH6vWyyT3tP^K@UP86aSKpSzhrG$Yp6mGT;15rWJDCsc8$|W0-OQ{^g}|Oi#K_ zbOHVWvwM$YK5`;QfsTUT zcu14js()**Fw2-`C9D4O+@QbQ5cBAFzknzS3=eRTHqzbQe)kh!5fDiuH2oXnfDT@g z{bK^sGrVbNtLTNCf0McMByib3F!dt)!Lx=dTMzd35;%(|>gO_d%$5E~UevsJAn?R| zfKAZplX6<+51uEda%bm^{4U%t9!EsI!e}PNyYOGP(=2?w_R*Gy?VbzwXr$6jwj?`J St~4}Pib~Bg+B??zyYhc6Dx??y diff --git a/examples/label_studio_annotation/data/batch_1/ARIA_95ffaa51-3894-4773-a8c6-a4e7d09de050.jpeg b/examples/label_studio_annotation/data/batch_1/ARIA_95ffaa51-3894-4773-a8c6-a4e7d09de050.jpeg deleted file mode 100644 index 46e40191edb0a7ece5bc0dba2253768f66f76f24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14751 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 Q5e$;hw;+}X?|&Qr2iMS^1poj5 diff --git a/examples/label_studio_annotation/data/batch_1/ARIA_IMG_0584.jpeg b/examples/label_studio_annotation/data/batch_1/ARIA_IMG_0584.jpeg deleted file mode 100644 index 01067f246d8891a9a89097ec711aa1162442f845..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20099 zcmb4pRaYELwCoTpL4!L(aCg_>E&~ki&R{`<>xa8ra2ed)-QAtwp5QJgXWeyvz^%vb zUcGzw!|txy^|A7?4iE<*z`-NH!yzERBOoFod`9|;g!JVL5;ht-%2zyWe0)4?TwFpD zDj*>d1u-rz86z15H4Pm-9RZMum5G*>ik6P{e>Z_aL_|dTjD&@Rghfk;OGx|wjgKAx z#%I7K%y(EAa=<4H7+4ILj{yKN0PqPG<{tq62Y3WnIK)pdp8@}7rN06`!F+;)g@^kL z3y%l~3j=`p1Pg}&fXDoXfW=16E($Wn7IO?hq);`9&#UdlnZ4w23QVZOrQ}r0-?{os zCEh1tI_LavBO;jp7v}$h{BKkM%)e_v{5Q#h0r>O}FtDHC;r0=c-{oG1DC{T1c=U(cTHk>0ErO<>DgU{uPWe1{0+aDSIfen3L!F#PDVpD- z^;6YG>8SWB@s{kC8+iKN^XxTD7d-;i77D>@9(eD|z0KVrjPp{2K>H$#Aidxxe%msr zeNHy_tF5ecEh-C?7 zQuKb`Fee zi_2>BqxqI9_gyJN-qv)SRwL_y=Hki@KQS7a-Zm7R>D`V`{RSf&DAowP@z7<3C-R#!N>$lb4VKrg1|hp~6asa@B-*u3!JnW;Bc*%(I$X_XVZ}f4 z4=VjVhVf>_(G9?uPBr22MH%XMkI2S z%25TS+$I34EZ~0;>CuwF+)#S6hH8VfwQ0EX(hLja7rS7eP=v2Yh@B3w4%vFEJhd6m zBe<-Dp}BaEJD8%3Ynk<*+)p+$catOu@5DOhJ@zAz}YNvLgGfO_{ z0dvm&Yd77KfvV;h{`Oqht|K37@wDm{Ool+FnT_0zO&UTGZM&J-|du!=o*)< zH>t@=#hC_WD*2^ieE>LsV&;ZdrLkEpmi1XPKswF4;aTnPolddh&%|ceh{ngz+f+{V zrzm#$!f(+54p*pM?go?8R=)$1SJ;XorXmD1HGs4I%UJXM;EW26o_fYsJ8i;+uNAd{ zXzvvL1SCG{*E8myxZ7pEEsf8ruy&tCvxYMMKu|52{s6!=xV_`4#Q#|is>hQOOe|aK z4@D~PF_T(-0SrvGEZ_(FC`GZ%4VMdK!(UXW0U`^d`AuwGNG)wy_w$R1`%0Dy+2#Wf zm&)M?7dPTNW5&+@dtzxYjMPgsz2jp*5^0~pdo-axHAbHL`!CNoIrR^~U5_m9Fl|Ah z6|^iys`GYm{S5(+Bet;Y3#kEEaNefbBM`OCrFDpahO%U)VP%!nns}bpT&0fYP~;*q zdDf6Vu#!Yh#+GQootUms;7v3-t!A(=p=7o}@;xu6_P{ard%h!aq`|^?(KD@3V{aM+ znL6PC)IE+&KL>ZnuFukLJ$TBel&!L$E%2jxO>O78SB0Cs5WZxq$UvlgT{(uLvxt+PscBhi7(+c?c2ZUX{MA{iB4~H7oIslHAE8p)FAJaSP6h(cuFfKN!^eh} z3yUGpsv?_)FbcODB&7r&$&3G33U%~~>iIP$mdf?wGC3K)*X0m-|LDzJlubRXZ_;>x zwzQpet*AfC|5^g=FV@(tr|=ktbzekj*DSPBXb7f~G7=;lqzg&P6W8U}$SYdXpL=_{ zp3M_Bsn7OBT({+~xMkX!5hK#Q3xF}?ZJ>yk4lg?|;W#nc-!+wP%5crQ;(8)?(7cIK zdp6uVHS(_6y0K?7o^@n!3XfzcmS-Fee5NqE(le~etpF*aaPiH?TET7ctw31+joYGK zPbSP8K36L)NOz~L@EfIhe)FSqayPRSkX+;<)Oh5YSrvAwr-lnZ?Iyj*z4-G;Sy1Zg zY8OyYJC%j;IKlq#&vVBVx;jWOW=-QX1wX;N4jiP$vef$5dYiCib^P#41QxaU00t2M z%Lky)kI^Fen`@!3#nErJ3iB&0eX}Rq<3IciQGL5*GHtD@CHrf}GFu8kqhA+Pt z{2IgjebjG7zPj}st{yyYBhckh9jN_{G}4!l5Qt?9r~1Q=5`!N&ZgIgz*iHOX`R%_C z0C1Zm=P@iM$7$t0-8B?^#jA-ijDyEoD(u(9mq-0m&i&mzJ+KcIvuf=;+ct zVW$Uif=1aH z7c-u>Hv@wRi)qgC7IwEYv544%s~>=?9;Qpv*UMx@Wi?&$VR>cB37?e$nyV(^#Az#c zXQ3&RY-RJRY*sP%3$NSW2!0)imdji(F~dFRdv7ac12IXC!0a2z6`E0nPvmM`yk&_| zPRbF=lfx{*Qgyn8P<1VeU+d5~jlw7I0q0iRB@-FoV_#8WSN`@=+JdB_9nJ*oS;*4P4#WaoLnZ zWHe0fR4AWi`Pz02z1K$WC+dgVu$s?p&-76oI!ca&BvM03Cj!1fVk>A7<*`BySY@ns zmPWm{kr&l(lWrU82$nN>m&auOfE61e|F(*xFrzjO^}oCZFmN!QR^A~M2bDZ$HHjb_ zNvzu5j8A0k$G^|p`(bsFM5%i%GXyY!!{-@I6+f+!cL@G+|oDP+P)iBJFpe6@bJa&PC%lMAxzdzT`P#& z^t*`I#UE0X2UW_;!7n3UPM-5s)Yki`Xa5a(yk!%7L2WJOqfo2U@$us39c3S-XCH-} zta>!48aD0H$qqGGLA47$}MA%7iBJo;%|c(FMUWC!KzK+ zClNA4l?^T32f=!WA%g8Ob;MKgnyY771)0j~nX+fc{eBV8I|UKW#9j6{C8GxwQDDsw zXfRFy{eT{(AfSnFik^>NpKu{Fdbl26>y*}6i?l$+{S?#EL3qZ*@%9KmiGY29$B{&@ zIdA=82!1#zpFhhHaxq`}w6?P89Inyse+TL2jwj|BA-3%Tsj{0jY=~lG%kmz=t5mQ= zYJ-WUsf#4(oRE2-DRkzIWl5go8VP;9>2^<9wa?A0AvjcbR`hWk%nmA*-f*cQvH3z^|GML^PZy;^I~wFO}=NC>NzNEM>B9nX)LN zhOG3xB|gPR&B|?N+1g#npCiioaD6$mMJS0_q!*^R=@*<~b%F6lJP1g>97ZX%lbrkj z5N*6`5l4dx@DW6dtum)E4^kmb@IF_u5DKc?7v3C(n8lPE3M75B&g8P+)Y0)?8&~g% z5l>R4X_uP{ci8-*$(+KC0{%Xqdoz;jxRwip9(qpOJjyNPJk^(uHs7X;v9phDOa??ZN6&3HQ^OVlrK&`@1Y-h$!^ZC#6=f22S{nBW&Oz7xi(`zLeW%_O}opB#@Mnw<%k`g z;qh0RYzsaq*VN^L4?x@CH~)e^cL3GeEtyDg91&TQ^Z0>%+N zsrkxQX49tVO6X~XRthX%;jiN6u43!v<`FRqR?m%s0oz=SgaBivpZ{%g*)<82hpvOn^ovM*d0SBgqZUgW z8P27u8*LReVW9T540}#p_*?CK1KKtObZgwJ^Cm6j$`eHs9*8b+7gxQ+A+%-n>ioBZ zWHYWj;s@b2b*s>yR$MmFZPjP@-M3ywDjxEp1ofFEJcBGpae*jQ_Ns}Nc4?i(MpnX* zi%i(-bv*Y}=6!*I_DyCsq49eV& zdm6|NBuqhYG2WdzWgxWE(CfjI6wiuQqmqm3d(@Miz;vwn@7EbsC!`O>2o@XQWb=mP zuc^_S)28wcVIygXf;(nY?rvRa>Q3vawWt>2e`bX+f`G?eA&xsSp37u|^`VMzy=RtlSmZe}nD+bvAALcCxlMbGFp{E{Lru zG74kA*R*A{G#6_1WeN;z#KfTnrr0A%gDP|k<92!=CXN)Xta1dHRq)>M_V?tU%-s{f(msU zqBxXlvt;ws}QE_!+g$%kz zcHM@IgjabQ`}DpVQfJ}mqM7rOqD)-h8&ww<$RtnIWh6fUw#ZZTrBBWS3yxjO7cxDi zk3mfs>mu25rKd!4)67j4$h%X94ooYrY~xF*uGSjTHSLL1VZx#JyxGZe{de}*IFpc1 zvyzx6p5erp5xHoSJ(Q?b4&m2w-e(*b_!$y1BO$mXzx$0%Pg=St$LVN~vOn)zNI4aD zl=~n~*vh;P@z{SEXHp2pOK;_OiJ5)+d)aq=ptTepOO#1(_KHEJR5l91A>|dNgSH(W zegF`zZ~7}mzL?F=Nz_)vFPtpI5Oo^y6BFbW(kJ%ZuHm};tzILFO+ipu@FKys2G{j$ zrZ}*AvrUfg@7viPn_lH9Ox-ACNLD0Y-$P2`$7B+!LOQ2ImYa`)m6+61Iwep>YW;r| zuUAKRI6UsD?8-z5D#P1xK9gk#&Hu~Hn~}@=2TepNt@E=~B6ENtTQS+l71Ld$VWV9W z{yM>i=EhjUf8Bx8D7~6E(%j9=u`)57f!10EBw;4`FLo!PC6H_Pl#9adNNYqOuVshn zz-?WFqsBGU2Y~r=hcNvQn3nnQ)AWF88_6bq%6~LlE{d7Aj%p1_?Y|u9*$r()#a~YF zq$P_Em8}w6Z%lSgeK(gKdLhzfC9#GYT0I{C(9qYXDjT-v*Lk*t4*;Z2`2$d)>TX_^ z#6X#h=1JF4dEGgM#+D;zc-&>p9KA*y6necDoL$we`>iV@W5pD47XkUe?|jKo$GUDU zs?IuW$uzKV)ObFBYrV1dW@hKt7Fa5lvU=_fy*7FAlo|eAYw>9B@)uptkzVSF#7BR?UMHN`#sJmi@OHj^qh zAwBA5Bq1g%bNiDiJE$E=vuo?`HSZZ{RG~;4yFt6KQf4iKqvgdQjY>MFlYeTa+ALD0 zqTPSfUc?)e%|}ymm<1L70HoakyBIXm^Xcg6!%a`h^GNA^&=11KMLD5ZGeQcgW&ByG zH-l}Aqvf1M;`$+*6)+(#;e7EB>}#*eMSNGa7mr)zR3-DTwk*?}5_6DSb3bm;^cfiv1n+F#PH9Nd zkQxt2VM}dSTO*4W&jm{Mz`=o$TGRdx=Z@?zLJ_peWaeSJF?O<^E%QxB2qrXs;pg^< zF~HGBeF3NmMzO;OROr^{2yx>M056DZ+6a%z(h=5lzVqLaxuYwXB~ji^(u4Gg26^zz z@8VvBbVefQRhzaMFk*Ch#!t+QdH9P&TNa_JL8l19o~6^fn%cBS8JxA}g2BtX@RPNa ztvg>lx2;@>C`-S|dsmu1?)Zg>3;mqErD-yciU!HE*mF2zj+&Y_i#HC52wCVY{7Gty z1Xj$|VS+oP)f|Rao|1Rawcg}&*Xl${XfN^&F}j^%Pny`cw?Wg0qcuwH87 z%^zYh2}a*xNm~Z54_D zDe3YoL44aPZ9WMOKmQ#3b;dkSRa7u>oG~R6@K8hGRgJa0fcB9{}^j#HE38ZCqWkB#93| zzo2(dnP*BXP&iF~cVp>`^Ov`f&nLU&YbJ4RwZ}3GN?YPzkG!=FGwQwMN0KhQB!3q? zJneY;*ndZ)@3WlX4(h{2BE_~Y&WxHA_-5yZI2r1PS1 z^#{iRx->kGd6}Zj90pCV2w8eWS7s!dJSnQnP_6*|&;`x;YSa$twXUaP_YDU-Hc9uZ z&h+bCH!@HvaeKI8b_=K3WJE-A=32A+(oU3^6UF)pFRO@U26kockkgxSo}rAAE!b-l zrHEt=QA5X1ax*1`yqzS1J^;zpP`~!4yTL)~i)8M(Lbl~)i(gd9QT>#=a>LcyIF^M8 zZl%EsOwmD~>~(*Lqc)v&5!bzQ747;G{j!LcO+Df~YF4_6(|Rd{{p}@!@@-n1*~kbQ zq2p1i0@TIWacc}e|AmGWe^_ZqURM*iH9di-rnR!QUn@-G5W>KW6K`#s=FBTp`@&Zu zHClQ~Q0SWqZa-0T?atf298?G{t#ghaRUA;2&s^+^D8tvFk~2dRYyJKOR2Ni|co5ZP zKwn;1vItV@OHrS}(b$sSyebX9s*Ai^o8am1@OFyWqof&0 zGF!->RPv6ADd0-xDC5^Y!gSkCu3!^p=&Zc%5h?VJrTPNfcl~`~CcBTGx?thLE@a)P zOR2HGuaP`InaXkfK3s-}7h`~!F5TihUOs!jMm3N*vzGjUEWwjB6gfpkN{NxT&q+>3 zoB#*(#giLFvd7~quDP|{-dasdQa#5d&p?C9H;+XQt}Oyo?dTsZAtlU zHMDPum*UnnY02E96q=BgS6CGOP3&SVL2T_;{IhAd=}vsTazgjRf#nC_B65S?siVu< zKyWv^Nd=)3)eBW37R&gzNPFaUeZ{z3_XxhDpxvK;oX#fP*(1f}zrk^{^*w)CEm=E5 z5-q+V$4*yeE|63{6LfkWsYKgQqO3P$(8qCAVP8duZX6k5xaz`(-98lO`b1JlRSsnK z-5%Vz6NthRffercp8%j>3XWd}m&L)VzLs*K;~o^VjQlE;$_UtrBKqlzAMMCV5CV zj}ZM5m)8bkk5Lkv-d&S^=u*$~8tbq7?Cy z;8B_|4tZvTr;80ExgW1Eqa6I=5l=t4_s~xHEg<0UFxM-!oei687gBKf1t;Cbm5I`7 ze$aluOcZt|Qg>Ggb!O2V>>`H>D>mt}{0Y%on9P;?wx5!KIGxdf^2c0Qn;VWR9})5$ z?$a*4`;AV6=bB6@2!6on+(YV~Qs-rR`l^QyI^(T_DE95^W?hLSpHMghxmNmg+SQ7C z{AJI?o?LQ-w3Z1_3rpD@DE>q&Fhlsvtp3!lnihup+@9{uL*eLv6-Mvmcc00Xl97;| zwZ_#EbuP}5qnq&k@)Eb_S|({FI%Upm1b1!Q@cX9Q?fOwbqf4Yl_aNPG%c8)M zH_71Fj>$Ho8A`q;@JOYOtcQh{Q2I|yj276dzDhfa`QlsxMqBB>A*&1t`S>WcQZc~O z)l|oY_#>Yy&qUh$6LTEJb-)+SnvF*PS2m`Bte_T+Duq!#Oc4{xx?G!oosBa3QID`j z6`jw```59e%Z+~7xR0^HHZ7|8NMi`rCX}5Wxcx($Qp}g#SZbOY5*)nPKKhO1=L0~J z=O<&#LB9+kLW+b`0#v?aGrnl-e7N*Q$#|^q>oZtg9E^P$&uN7x5%G7#yj@S%^=%vqsdj~Yw0?O?AkcZmbZq7Zun`|{Q1|qnx=lA2xV<@ z>&0FhT9=A$k$?J=-nIF*{7iNt#81#^w8H(mFVAR$R`;_roN)lvkmM@Eob3aEEEH-r zE7hd+>*=vu&2PGYAw(O^{MW?Q;vg|+T{qjoyfsnZK{)lh_+9VV7Xe$ib@jNOxXVLV zgMYMdjTw&C7Eg5Rtttm2(xI0?XlMwyF zh}^$TSswsX|71OMFg6o?noCUC3viz3js{~NDH0Ol^WCe>FXwK@e?$M5XyzaspAQ2h zD#2XaME>IKoMq{p8C6w!+9O60EVJ37uH_Ru4V!MRW{Q-f&%1mh44f>tx{#HqI5N7R zhbVV?y=#>#_TI%Gc&A?@4VC`vs3wk2_LC&;HI9sN)g?jETunG*7WmxN8Q;Y1@Wzko zY`LfT0l=oHe>-7wbOL*_DXaCPm?%y7&dU(Qd9q_Q;lD>;kLgvFbKZL*m+md`+t@gq1)pE@#|xsS^%NLo%nk68 z7MMQ&PFmfss6e=X(F)9Oq$;+DY;w2pT*O2P~qFOe%pQ#8r2e(Z3eSWad)fBA8ISLyyS(r`BV+ZH_ zm|7fle&4>uZ<$q8F0=P$g|4MmkD#@nYjY+pR8%s^On9Mk zg_L`+gziKUS7y4;j7_u6B|yt_Z^V}Wqvx{@5-2>#!wfjLztto$96Sb%d~|TDMQAX zdL7<%8(#eviUD+XyP%uHRkOIl@}vbpWT3<8Ej`((H~-_djord-Ffo_Mq5^tqp@*6N zaEb-|qSE0~SLSUEFknzhA(|YGZ2V@;yOGw+HK9bfehsGTXKi!X`8hY@!0&E!W}g&w znk!sr;i`eyOb0=>uZeXmF1HIh}#4>gzf}hS?B@3htpm+9c&95jt_mueI_p_s{OLmAl;%mS3x&1Y9lxFwLXZxhh` z_yUjKHU{qTlPmlg8|a~p`;le@E3m%l9q`NImxL)_L?>mLC7i%@(%SwV)568$@06Es zH8Yx$zswbt(-x!}LC|*Ng@05`WypBY8)Zh#%h&KO0)0t>e+4bq!`GdwpEC*UNuAv! zLmvQF+z+~JV!7htFhGthVGekA?*)L7>1r~~7=3(iF%w$7l zUqgEgQB}ZOz9gpT%a4b~j)j{R8?$NV( zi7Ar~TsMz)|7p^p9?lhF?+FV-tPQDl8cZ>so6{Yf50PE)hCt~{TvAGljK79Bcr1tQ zYOBmR8&;cVU4=9k`xX|h1==raS2kYJ*f;7!&8OKP3Ig+a*XYC1?e86Z+PobCrkSxj zL)>Q%3%5;xjiUJbi{`KU+v0ydcaP(gf$*X9ab@eJqOY~N%D1N341Vq7VrL(Km-r9B zGS0fcdj|ba@lWkvzyDKPmsW~0fZsY8F%o}(EgVHj%+MuK6n}6<|KZ<&iG&{i6^wl+ zEsOd9IBCY-4{lT?#<0^<6%~yx$zVh>7oxZF2!tY57c;ZqIZ6`wbzb&EfEIjyMp9o! zN8dGq=k)VL1jn2w!nrh-@P~uTi9Z00RwCaQ6O~#Q5+^xR_M=t#Y<|Y9h4+PcrKw+0 zR=+}$omNa>h8ln9-2x!6hjumnp|kLu>I)v#lszMVaW9o8ZW>=>i?I$w&TC%%o-nE` zT|NA28x|_vx<=P{Zd!!3l*%V3%0^f59ukLfjLSXN6=M3{T+V-Brkz%oX{;JkvmO69 zU{iw4mIX~ehwHZ4=MWP{M^(%&Fs-d~7_0q9EmOZ{XthN{1w7>L->c*@uo(+7<8G>O zVeJCdqnQt>vn-9ChmE;9%u7Aj#$8QWgD?1Pbj%}t^#sR##UF+ahQ`wM1%@fA`kt4K zW3z9@8nWB8!LE(d5HOFh*cL3(HED@uY_rLo-u$9snL(dB^L_K*XOk^iX+$Owx%X-x#0n(x@hlGY`fl*kq4Uo)RIbf~t2-j)j86tPUAyHo|PpQ}z`9#}1 zkpq9#%U76C6+TFQ>=7SRZ2F_net06m)90Ka_l5la^vgHxBYQ6iKuk7uD-Smq_wtHn zSn0DGxIvZDNwx2_#!M#J_KOWn*}M326ZZ8+N{0<+)od$b1OLjCcdh%9x@v)%rs&kK z&d7SL6Wx2|xNfzD+g{E9h1#@b`LqHiO*UiavRR({V5OlR7q|;&W19dk6Mkiz3ba=7 zYjqh3Pa^FVty-GW>q}DD;ZGcL7THx)F{S!Np=s*e$=RSY_W$6}{z8B51tydn7harmC0T+OlB^Ze)n$t*X*o-s9xksz_R!K^B+pWfqA7j; z$q9NS&Y-$3vL{%J6`d_o8eCc%Iu39NrWdc3%K8~#(NBcqzqL2@)pjrDl9Po{+9)Pt zBRmj^&OJ?!!HNR;w((@O(aRC`WM*x-j%Qk7<84(p>A|ym2?dFtm^P}-E$yMpV-$fDH)>|4l7Md)$_10gGrF)fofLO8rd|o=TB@8FzF%W_4 zyVDCqQnJXEm@Z$uZEW`#I@)@E{)x_Xa-b%8bILuU-|;&9bvSR;hhJG&;U{<|YXQOl4h$7XQK@XmD4 z5LG6F=W^|i!*9r4`K8WkGs9Nq6Kv7E-{dc*)`ozESDVi@sli$>Y=RD5S<8Ko&%ug~5q{0**a!Ru7 z$>vKu8n0K@;jG1J-IN7Ybsv4kkQ0WcdxIbtUTS^<5X6SSENRlJPv`8wHxq^5@laP; zGJ#EBOj~lS(5#jw7ZG~lZ)0rmpC^I!8LF9U6f`0Dx8+&g#Wk<&u6IIy3^>`uKvc3R z)&P3dd-^;YXx`^xy;D(yhZgzgrTNU8WQ2iiiriCg62JTtMhEGebTPqbWsoS#o4}PG z0f~l#q}CjyButRLwCcPts5^H)P*0cq&~=hBscRnR4^aw??vulRQ-nK5;~X9%uGZF; z>L{IZ@!d-K!>EmmjgaepNqB*6JH1KZ?9*;}Vxb739J7Mc?+o<`-bOwt4Uo-qYIZhN`|hTuC9Zi<<)_c zsw0(!uFh+^9`-U*j#5hFw5b0ynu_K*UM&46)iv=uQ}P!VB#)rCG)uh4wLLt#ayoM# z)&+~OrEd4`Vu#MrUObu;h6-W&)G%6}>cQ#@&5)`0|EHpjT2^nUH%hh5g8Z z;VVE`YgCX;YK4!>7)vYuk8^rr|5?GiO?ch}H2K>BaKgw%kAt%GYndAZP^syO zmK(nv5nZ*fiOr^4-=_IDBU=IldBfIWgFaDXEMm>-P`t(5{^8K^+(PT_1JEMIrE5qp zZ?GxI_Bl){B2S(6xV(v9W^@BGq>Un0`NZNF!``B(VWSlUQX}&b7AP6yPuI3=j_((l z-Bf4DKAcm36eqZB7Js^kX~>eAvIV!%J54fqqiJk3!yb7#c=L;c-mgmCjOUTOEjih5 zba3h-N&o)z30a|1)CviqX4?Ml<7t|=BR8+mdnj!kH^G2~En zVVs9OuU)~bQ~9k6f4*g|4S)|rhF|t|p*{@k--6`LRP*l61X3g)ni#jh{U>RlAcip8URGo!n>ZAC!aVPa z76)eJZ^GT_O(HhC!Hl~<8;(yH*FTPb27imx?F@Ga=vI!wKIMYJI;n&EC9?ZMx5`>wzA_myzAhfv(BI zI`)M>__pX3a78m+%G<7(GA|P`H`OULga|UV@9G4+tk9&1r-3Au8s=}3DcO3;TMm)+ z!(KXJ`krjfksGub@4`+fMytfQpkgkM7<)FiFDn)!);swX5xl=uYqrz=l8k>9>=Xp_ z5I2=`lvl{m9jG7R{!E>y-3U7MBjy2_t)?Yhj;$3^G?aICh@=nvI%`rl_CcAsl;CnX zHBm(A>z_#3_A|J+49GI`_>W-F2bG0&ervPZPqx`m?Volz!z<4^K|bNZrMjII{cUl^ zUonKps%}>0AxFl?{I+U;1(WA7g;zBP&y?5>6sy>~nn_@TbAB5ZA4^)OhnC+zjByaH zPUvs(c~DI~0MBT%{1eRC>eb^OC`3yqlnq+s%28ZUZOf>}3awve>&{SQ~P5F0q4L?`P5J3Ujd4{ZO-+EUSzyk7L`mq)(1E+U))J#D0YP zvbV7eq5sZ9pS@sMWn&;ohsVJ&IV2M(9`YJuZ^zDgUbEoDQsg^xD~w1$WmZ2o3Q8Tj zs3L64z_ZC((HS7kjrV%;-21+Zv{<;yuenUf03!RGRWpFejF?8~%d4>GiNL>zZcQ`na1iwnN}nGqU^adbH{Z%_Smz!6Dy+rCp=OCaKgwQXbsmVTZ)*34 zDcBcS7?LP(C^kXH@}pvC`L%}^zb}z#Y>oM9O5tW?Y;Gu=MOy#iy7|^I{7AE?++DwF zHi3)5&hMXIgW`iVG>#*sb3IgtKx}N`>X|1}gEeo;M_Ag=$P6i`0x97nYjkEx} zkR7QlDP6-B63@c4DLelJd&Y*H1yu$Lh{~qEpb9z{jtVYERcL%;X{=HloYq6mq$(M? ziSV=Y)l+SqEe&Hb@{Sqa3&2UPmse9J)i3^OL_Ch3lWNdz|6{ms7JT@l`O11l9r>Of zU+7|PndkMsr$OiQkA3IqK}Ya#u~}37>IOzlOShpO#PQ%(J6xk=%;||r_(p=u7&(Of zVf^fjP{ZiDg&$nO4b1BwB=e#7iW2&}P3Sm$9g(!=i8^~(!ReaR`k#kOd?#-myPR!q z=GrpZZ*{^ri-x3GWR-`rkEr zp@S1!z1qPl#`sanCuoi1jx(H`sbo50M|(bgFh z497zd%??K((gN^4k`uO#Eath(6w?xJsPfNlDlEfvy2U(?NBma?Ph8$(-+7u=XW?=u zD%FdcfASA8*4Pf03x;4aA+AtE*+$NRzn%i0BV&LU)dIvmmF9;pK3)G{UI;kT)#&q3 zl(34E;aF%0%nNOVU2}Km@}7er>C{f)eHIKSoluh@ z3o#;x8#IAaU6Y#>#yfPx!_1rA7*kW=yFKK7{%X9F0scOvxi{oH< zUP_N|Rird8yRy(s)$!#L_mUKd6?D5;cQA7e$-fw_n(Bfz5{p$^*c}3k-6oVHJa0P^ zZBgF6cIyF)ba-#@3ntRl;^AY>NNfQ@Lc0BbcF?J6$FPH=%6QEyjwDNjp6tWA#O~kQ zjPFCaGgz+~F|7pheZS{K*W}KkG_$AZ==1BXD`#@GdA_e$jNMogWJ-^Ku$SAd*X1JL zySotN?y>dZQrwddVq_XP9ao;SyNd-g1eX-CRHynSY=bqcPBmV<*)+o-RQIQ@;hH%# zoFf&Tn_;#8YzEifhsB@M{!_!K4Ni|$n*sLYeSQhz#@qP=EQqVmHtKxJXrdnX+Fr)P zqt4CNwhD<$+TYZiTFCRGi!4W%$S;(T(C147a6y)S+$JG3M-3_@xVBZ(1!47sU$4|=coGEw%lc&C=WFlCm8cTy2b8|gUy6&RWGU&=Qq}GaEY>vo`6YVyb zvAfj$R>`#*g@d#)W$_nUqp>O3G4xe9u5PU&M^L98+nCA?ZLBjz0Lu?~TXWnS|2MZ) zy-aI;gRSkJ#^JC-PW8wx?{Ny`shM1_tM0Wg{(h(k@en!>+eOY;Xu4va!(U~M%O zFOir1)OA$}r3Aai=B9UH3b zhe#EN26W0uJ)X4TwAn#A4MqTA(Mr&f9bIC_VxR_J05tDph&l-q-3`GUG8}PQE!L+I=5|gvG*38 zhUT>B^#gD@H{s%Pb>ge#&~Oi|q80WM6{|4G(vEG%yy5p)Cm63+W{|s>w7)Ojcy~WY zxz>{{ZQne%$jSKUz2blLE52gdPxKq=z8C4nRiHL$usyqv^7j>cEM>v7K)T0{&-ckT z{{RRW>kx(`B*iD!NM$W|bUn2H_s&2w+UkQmAb^6(Y_nKdy=D;9ql^7elhW|1 zf>kYA=x){we6{WMI)pG#QM-j_X7uxVyXwo*T;M2P95CQ4Fp0p$RW_eerO?-xyPr=L zHo8WTl8Su<6ji*>6V|PE)r5R7!{3jikO7i*Xm6eS0wy)v##}JlmDVwuz(%ifQ2Q+m z3s08sVWUqig^KBhl^bo>J-v)GiWNyy5xk@1Z9At-NRLkKB=|bYTSQr{nXX@?jY*@T z?a6lP$6@=E6N`%x;(GEiPifDdM3}dd}3^-bZ-+HZ4PY@)T|jnwaxO_yDA@BR9-SqgpbK%?WoYKq~E` zBeAXsYqyMv7xmM$11aqs{CQqG5Lo6V4u?8&*duwSH;)uCTQ)nt*ZYc0qu{t)MnL#D zrSnAjHSIgm$5tjyV{EflK2Yfv7=ZwXR_3LRG52zoSlEYRnyF?%jNC~R*px7{+VN{ni%XHT)+ zDKq%upEPmtehjZi-VxQM2fT#O0x?}&J`&+q@4l4SFSm}T_ zY2qCFFr&!=)~48MC2y|SYHIP=->o*asQRnuVSbX7_jBsJBw2*VFl z?B8zqLQ3EB-hu;4skmcRuN##cTDx7jJ+|e!9i$SaZEcgWim8I~C*-gM@ZCF6F0A`| zqnDh=A1$~?u^s>=uvG`A%2TYn>J67_nqCZg93ozMgt%o=3;#6|c-)d3kRNqT{Jcps z!|UnO(k12kg5DL3NZu5$e47Mqym)q=c@i^S<^QmnZvf*D*h=?RhwU>80Cs1A$T?=} zBQry_BRxM=1^!+Unet{>q`qh-D0iG2-VNJ)b8R+T^=!gn;d)0(~*_@u@m9>G)i*dH%0EOj?KPr!oG}t|e}F z?_wIk3dWYJb@sH~w(Q5~P?e@?I2n$1Z0;a>ZOPO{Wqx`3ZOa+PDD~XHI&i66wAh-V zW!m(I0eIcSunKG6_TwAe;!f6`n=9J&gQKIY3=3S2M{>K)4;-ZEJGan|mTVr^cmuA5 zt-t+W1KOfCh%<(hXHcaR;z(jY3}_jy znPygA?1-d%#to`;3fi+b&1f1Lg&}(*^To`EFpe6fmPG6#5Q@KRzziSFXhiD4c5l6b zRXItcpl6Rr*pSS_=Zk4Ft)SjdB@ZoYC1rM!LNxdiy?$5Q*RBVBU z=N`#3a#xotAw+MnsM`2+;LN%xslBGH?%b1QE%vNGTqkDhE@59$Qn6@WsoJmrTEuzX zh9{@aW)pHIMs?AnN_Ax*SO7QN^~3nKs81o9rKz(l)r_gGj7O~eK)1`?z&WydXzH1v z(mkRcWIDP9Q@av;!T$iK5cBg&*LbLD=G(AUdLMUiJvD9jy)bJk;JzZws}@Yf{gNX9 zfay^G09D~{4!uw1gN`-?rc4@^0$?CILsrCwq zsFm*@qOjZ_BYnJ%Gz^dE?=PZ7=OmI#We)RhNZ1>nD-0f*pNH~tf~nz!bN~^U0`|9n z^7vuP8e3&0JdcbKon~AUm~kwqN-Zo3G&-YR>Uv+oC&K$ab~tH~HZ&i0de-3dKX0+2iQ)u<7Mtilef1j`2E< zp11QpcUF-?M}~jrMf$co^}1lvhB+DDJ4ml^xr)zV<&TC9He6mL=@iuBATi z7TLNmql6u=wR}l%7Tp^hxK(YJvT@Q~*2BH_u|pC#xaP3ai9J2+M#xKV-W@T}>2Zn( z=n@fE{8*Q=TUM{`JAnB1+uZmE)jjkJ1XZp4-+;Y_RR|3mIZxa^n zcCEH6aD7yxB&v=kV9`!{E9wFLac78+WxGAB2;iEIUU6GQdy~Vgd{poFgZ}_dH6^3w z-r(%@qzx!<95&_BnvNaInCadHyL_#HTt!YbunNN6aLM#&DeCfi%4)~|0EBy@ZQWu> z`Cm}Q%c~@NqdUxm^juK0!q&LZbo90~OprZX5lJI=1+?N^$0DVuuIH8PgNsz=I&|ek zsuX*;zE+A#nOic{t9AJ*;3LpaRsFN}N4U5#QJBK7r0F;Ju_Q9xyE`T#bX!&gso|I> z?aaE^`>p4WUxZRgQdM>zd&}4V02pM3T~B{38lx~miuFy{Z@cTa_4329wEGn`T?mvM z9%HOYrFPR9?yBu;++ejcWZPE->}10O~G*TZ6hpfoAwt(oB6Ta z{Qm%4Jj0gdc`YN!D??2bTl1ZVWFG=grW3R7IuA20Lr%P;xD^!(VB2*Iu^@VphBq8) z} zex`RYc(`z?glLF)7vchwWknksPWEZHpa_$xip$#B1h!KdtfZ<(Q_+iVYp! z&A(}}Dehb@Aakvmw5s)OE3jXNJ6R5$J@2!K5+zhu)o$0>#|Sik{NhU#3QKCYXCJkW z(LLM{snuAHD7I84lh88JZTs)ii; ziaF_4rWV$YFWFxM(BIbpa%n0u%9nVS&tr9OeSDAYf}97Nt!7%;ZBw^Cm>mt~o*jPA zOcbfhgC*C!i@MV)uV|+?5K^@>9%`eGs@ohYX1qxrrV&cTkJ!On&mxL#SKY7>WJ)El zOfoG2D=E{O{2RN|c@nY&50uQ87@Ors?`^@DLZQDr1|`CBPUrqn)O)NV?yCvwi1kI(wm1my+1r&INPG9DppU! zd?_4GwUhHCmu+m`9}oI|YivoyJZnM2OYF3$wONr~#3So^O#GbqP;n_2&epq&G@P3%{ ze|IlmA0ceZH_Y>j$tp8ihMj@BMbaqx_Y+GectPI_>5DAP-ge^B4@msn@*M;tV>H!6RN9SZHQA&mb-uB9UUQe)BW!pOAQj#5!z%` z-w>huy_1j1=TCbQEsxI>5&3|2zrCya80zX9^~6^PQSSY$bh^2=9j#s5L4^9pUw7|f zXrtyUUrMjNi0qMXCu&c!y?%ey@#9GEw2G*{3ahp#mQNZ)9^tjH{4o=kX1i(C`D3WA zH4xo#`QF-&p2@`&cDLKYJ6#FVnm*AkoiN`1f%l9a@3Z*2hYh)DL$ZMR3+D zh*`=3&0BYIGLVn)zCUu_3WaX+``DY3B~?E2;)o?v$=a49?~lx2UTX1B2B zH^CRAT9{RW-AL}MZg#(p9-SXKYQ$vb(p4nzHi=_54Ts!^Jr&gYW>t=RZo0oQ>4j>V zNh6l!dnW{_ppHINimYr8XHXXN@acn-uu`F+g0f;5sMMR{g*|U3UR;|mhOf}zg4PWx zFf>`*gsNy=mmDZE1_xyy^<$@~j0>OhVyv|tts%U-zPPkNg#aAnQP^J{IIr}F$1_r8 zZAF&KvB@=}=B@6a?QnYEd_g@&v!<}j8s6`>thy6`71smEU$hpu=&x(kd`glCZ?3 zVbGEH6aYT$vHRK&HBY_!V0{#iEI(Phpx^HgKaMBnTcY*GXRRKm9IhdBo13J0{@Axn z2A4zLz?vD@Ge^}=*}*z#Y}&P5dLNz$d|7E?Lr%aqXzo`XMh1_(4n0LDWbWhhC|38i zb@^h4M6)iEiOccZv-;xHadtOm)#LX_#Umq)EE>u>dg8<~+vncZ`eMeSz)r$5_f4@_ zleu3!PA=-h-57v_;JvHwiVYTHAflZs(&HXGmwxK6mYhbm>8rJW*AfKX?r)sy3UnYyB7OBZ}G=E zb?IW=uJ>ymsR*_hfghr`Xcfhs3>QoHwDxgY;IlDqyW(^u*5|cu>v&>|L@GdaKIp}k zB1KX=P55nynlY;5$L(TxEQ+Vz#Sq~~WkE9eV z1#JEpv$0+M+i7px5IWgzd@*FR*nmdT`nSZ9C)WIb!-(VrCY*Hx7ms9w--%M(ExYvk(b_HaU$09ko! M+3BkmE>olb+1opwo&W#< diff --git a/examples/label_studio_annotation/data/batch_1/ARIA_IMG_0688.jpeg b/examples/label_studio_annotation/data/batch_1/ARIA_IMG_0688.jpeg deleted file mode 100644 index 4bfb7f4eaf9845f713c619871a055568f4855658..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8980 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 diff --git a/examples/label_studio_annotation/data/batch_1/ARIA_IMG_0728.jpeg b/examples/label_studio_annotation/data/batch_1/ARIA_IMG_0728.jpeg deleted file mode 100644 index d30c5c23c8e25521ba6044760ea1dc097f765982..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13849 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 diff --git a/examples/label_studio_annotation/data/batch_1/ARIA_IMG_1481.jpeg b/examples/label_studio_annotation/data/batch_1/ARIA_IMG_1481.jpeg deleted file mode 100644 index db33039eeacf27b31a0d5722b22626601dfdb201..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14526 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 BuSoy^ diff --git a/examples/label_studio_annotation/data/batch_1/IMG_1892.jpeg b/examples/label_studio_annotation/data/batch_1/IMG_1892.jpeg deleted file mode 100644 index a4dfbd9f1e78a30477407395e9d51e8884784fa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61347 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 hS42FS^~E{AN(M%0DSDdjlmLRBG1{6cKmni+|JfXo>^lGe diff --git a/examples/label_studio_annotation/data/batch_1/IMG_2262.jpeg b/examples/label_studio_annotation/data/batch_1/IMG_2262.jpeg deleted file mode 100644 index a911579c5dd10486f907161805502a33a9b9fc19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63734 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

w 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

}Cz|Vp6s8i@J>H}m5S%Q(de4~==o>i_$CkGj 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 diff --git a/examples/label_studio_annotation/data/batch_2/24cbc5d8-ca52-4974-841c-f91a2dfb46a7.jpeg b/examples/label_studio_annotation/data/batch_2/24cbc5d8-ca52-4974-841c-f91a2dfb46a7.jpeg deleted file mode 100644 index 46fbc56291481b9d69843d52eede466dce85ab90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82578 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\= 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 diff --git a/examples/label_studio_annotation/data/batch_2/ARIA_IMG_5530.jpeg b/examples/label_studio_annotation/data/batch_2/ARIA_IMG_5530.jpeg deleted file mode 100644 index 72883529e80f1969f7835a0f2d7126f6c970883d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13906 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 I`l5gT*|IyV00000 diff --git a/examples/label_studio_annotation/data/batch_2/IMG_3154.jpeg b/examples/label_studio_annotation/data/batch_2/IMG_3154.jpeg deleted file mode 100644 index 721ed4149a19c7198f5e21f54b270f5ccbb2158a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60213 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�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 GKmXb4H}~rR diff --git a/examples/label_studio_annotation/pipelines/__init__.py b/examples/label_studio_annotation/pipelines/__init__.py deleted file mode 100644 index 96091ab3586..00000000000 --- a/examples/label_studio_annotation/pipelines/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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. -from pipelines.inference_pipeline import inference_pipeline -from pipelines.training_pipeline import training_pipeline diff --git a/examples/label_studio_annotation/pipelines/inference_pipeline.py b/examples/label_studio_annotation/pipelines/inference_pipeline.py deleted file mode 100644 index 17948cfc28f..00000000000 --- a/examples/label_studio_annotation/pipelines/inference_pipeline.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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. - -from steps.get_or_create_dataset import get_or_create_the_dataset -from steps.load_image_data_step import load_image_data -from steps.prediction_steps import ( - prediction_service_loader, - predictor, -) -from steps.sync_new_data_to_label_studio import data_sync - -from zenml import pipeline -from zenml.logger import get_logger - -logger = get_logger(__name__) - - -@pipeline -def inference_pipeline(rerun: bool = False): - dataset_name = get_or_create_the_dataset() - new_images, new_images_uri = load_image_data( - dir_name="batch_2" if rerun else "batch_1" - ) - model_deployment_service = prediction_service_loader() - preds = predictor(model_deployment_service, new_images) - data_sync(uri=new_images_uri, dataset_name=dataset_name, predictions=preds) diff --git a/examples/label_studio_annotation/pipelines/training_pipeline.py b/examples/label_studio_annotation/pipelines/training_pipeline.py deleted file mode 100644 index a81d5808300..00000000000 --- a/examples/label_studio_annotation/pipelines/training_pipeline.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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. - - -from steps.convert_annotations_step import convert_annotations -from steps.get_or_create_dataset import get_or_create_the_dataset -from steps.pytorch_trainer import ( - pytorch_model_trainer, -) - -from zenml import pipeline -from zenml.integrations.label_studio.steps.label_studio_standard_steps import ( - get_labeled_data, -) - - -@pipeline(enable_cache=False) -def training_pipeline(): - dataset_name = get_or_create_the_dataset() - labeled_data = get_labeled_data(dataset_name) - training_images, training_annotations = convert_annotations(labeled_data) - pytorch_model_trainer(training_images, training_annotations) diff --git a/examples/label_studio_annotation/run.py b/examples/label_studio_annotation/run.py deleted file mode 100644 index 20a91e3b90d..00000000000 --- a/examples/label_studio_annotation/run.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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 click -from pipelines import inference_pipeline, training_pipeline - - -@click.command() -@click.option( - "--train", - "pipeline", - flag_value="train", - default=True, - help="Run the training pipeline.", -) -@click.option( - "--inference", - "pipeline", - flag_value="inference", - help="Run the inference pipeline.", -) -@click.option( - "--rerun", - is_flag=True, - default=False, -) -def main(pipeline, rerun): - """Simple CLI interface for annotation example.""" - if pipeline == "train": - training_pipeline() - elif pipeline == "inference": - inference_pipeline(rerun=rerun) - - -if __name__ == "__main__": - main() diff --git a/examples/label_studio_annotation/steps/__init__.py b/examples/label_studio_annotation/steps/__init__.py deleted file mode 100644 index 5e058539166..00000000000 --- a/examples/label_studio_annotation/steps/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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. diff --git a/examples/label_studio_annotation/steps/convert_annotations_step.py b/examples/label_studio_annotation/steps/convert_annotations_step.py deleted file mode 100644 index ea8bcd57ebf..00000000000 --- a/examples/label_studio_annotation/steps/convert_annotations_step.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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. -from typing import Any, Dict, List, Tuple - -from typing_extensions import Annotated - -from zenml import step -from zenml.logger import get_logger - -logger = get_logger(__name__) - - -@step -def convert_annotations( - label_studio_annotations: List[Dict[Any, Any]], -) -> Tuple[Annotated[List[str], "image_urls"], Annotated[List[str], "labels"]]: - """Converts the annotation from Label Studio to a dictionary.""" - image_urls, labels = [], [] - for annotation in label_studio_annotations: - image_url = annotation["storage_filename"] - label = annotation["annotations"][0]["result"][0]["value"]["choices"][ - 0 - ] - image_urls.append(image_url) - labels.append(label) - return image_urls, labels diff --git a/examples/label_studio_annotation/steps/get_or_create_dataset.py b/examples/label_studio_annotation/steps/get_or_create_dataset.py deleted file mode 100644 index 23b7138bd6a..00000000000 --- a/examples/label_studio_annotation/steps/get_or_create_dataset.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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. -from zenml.integrations.label_studio.label_config_generators import ( - generate_image_classification_label_config, -) -from zenml.integrations.label_studio.steps import ( - get_or_create_dataset, -) - -LABELS = ["aria", "not_aria"] - -label_config, _ = generate_image_classification_label_config(LABELS) - -get_or_create_the_dataset = get_or_create_dataset.with_options( - parameters=dict( - label_config=label_config, - dataset_name="aria_detector", - ) -) diff --git a/examples/label_studio_annotation/steps/load_image_data_step.py b/examples/label_studio_annotation/steps/load_image_data_step.py deleted file mode 100644 index a1fa0639853..00000000000 --- a/examples/label_studio_annotation/steps/load_image_data_step.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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 glob -import os -from pathlib import Path -from typing import Annotated, Dict, Optional, Tuple - -from PIL import Image - -from zenml import get_step_context, step -from zenml.integrations.pillow.materializers.pillow_image_materializer import ( - DEFAULT_IMAGE_FILENAME, -) - - -@step(enable_cache=False) -def load_image_data( - base_path: Optional[str] = None, - dir_name: str = "batch_1", -) -> Tuple[Annotated[Dict[str, Image.Image], "images"], Annotated[str, "uri"]]: - """Gets images from a cloud artifact store directory.""" - if base_path is None: - base_path = str( - Path(__file__).parent.absolute().parent.absolute() / "data" - ) - image_dir_path = os.path.join(base_path, dir_name) - image_files = glob.glob(f"{image_dir_path}/*.jpeg") - context = get_step_context() - uri = context.get_output_artifact_uri("images") - - images = {} - for i, image_file in enumerate(image_files): - image = Image.open(image_file) - image.load() - artifact_filepath = ( - f"{uri}/1/{i}/{DEFAULT_IMAGE_FILENAME}.{image.format}" - ) - - images[artifact_filepath] = image - - return images, uri diff --git a/examples/label_studio_annotation/steps/prediction_steps.py b/examples/label_studio_annotation/steps/prediction_steps.py deleted file mode 100644 index 6d7c9f136e5..00000000000 --- a/examples/label_studio_annotation/steps/prediction_steps.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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. -from typing import Dict, List - -import torch -from steps.pytorch_trainer import LABEL_MAPPING, load_mobilenetv3_transforms -from typing_extensions import Annotated - -from zenml import step -from zenml.client import Client - -REVERSE_LABEL_MAPPING = {value: key for key, value in LABEL_MAPPING.items()} -PIPELINE_NAME = "training_pipeline" -PIPELINE_STEP_NAME = "model_trainer" - - -@step -def prediction_service_loader( - training_pipeline_name: str = "training_pipeline", - training_pipeline_step_name: str = "pytorch_model_trainer", -) -> torch.nn.Module: - train_run = Client().get_pipeline(training_pipeline_name).last_run - return train_run.steps[training_pipeline_step_name].output.load() - - -@step(enable_cache=False) -def predictor( - model: torch.nn.Module, - images: Dict, -) -> Annotated[List[Dict[str, str]], "predictions"]: - preprocess = load_mobilenetv3_transforms() - preds = [] - for file_name, image in images.items(): - image = preprocess(image) - image = image.unsqueeze(0) - pred = model(image) - pred = pred.squeeze(0).softmax(0) - class_id = pred.argmax().item() - class_name = REVERSE_LABEL_MAPPING[class_id] - label_studio_output = { - "filename": file_name, - "result": [ - { - "value": {"choices": [class_name]}, - "from_name": "choice", - "to_name": "image", - "type": "choices", - "origin": "manual", - }, - ], - } - preds.append(label_studio_output) - return preds diff --git a/examples/label_studio_annotation/steps/pytorch_trainer.py b/examples/label_studio_annotation/steps/pytorch_trainer.py deleted file mode 100644 index 8e9b6921e28..00000000000 --- a/examples/label_studio_annotation/steps/pytorch_trainer.py +++ /dev/null @@ -1,252 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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 os -import tempfile -from typing import List, Optional -from urllib.parse import urlparse - -import numpy as np -import torch -import torch.nn as nn -import torch.optim as optim -from PIL import Image -from steps.get_or_create_dataset import LABELS -from torchvision import models, transforms - -from zenml import get_step_context, step -from zenml.client import Client -from zenml.integrations.label_studio.label_studio_utils import ( - get_file_extension, - is_azure_url, - is_s3_url, -) -from zenml.io import fileio -from zenml.utils import io_utils - -LABEL_MAPPING = {label: idx for idx, label in enumerate(LABELS)} - -PIPELINE_NAME = "training_pipeline" -PIPELINE_STEP_NAME = "pytorch_model_trainer" - - -def train_model( - model, - dataloaders, - criterion, - optimizer, - num_epochs=25, - device="cpu", -): - """Simplified version of https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html.""" - for epoch in range(num_epochs): - print(f"Epoch {epoch}/{num_epochs - 1}") - print("-" * 10) - - # Each epoch has a training and validation phase - for phase in ["train", "val"]: - if phase == "train": - model.train() # Set model to training mode - else: - model.eval() # Set model to evaluate mode - - running_loss = 0.0 - running_corrects = 0 - - # Iterate over data. - for inputs, labels in dataloaders[phase]: - inputs = inputs.to(device) - labels = labels.to(device) - - # zero the parameter gradients - optimizer.zero_grad() - - # forward; track history only if in train - with torch.set_grad_enabled(phase == "train"): - outputs = model(inputs) - loss = criterion(outputs, labels) - _, preds = torch.max(outputs, 1) - - # backward; optimize only if in training phase - if phase == "train": - loss.backward() - optimizer.step() - - # statistics - running_loss += loss.item() * inputs.size(0) - running_corrects += torch.sum(preds == labels.data) - - epoch_loss = running_loss / len(dataloaders[phase].dataset) - epoch_acc = running_corrects.double() / len( - dataloaders[phase].dataset - ) - print(f"{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}") - - return model - - -class CustomDataset: - """Creates a dataset to be used in the PyTorch model training.""" - - def __init__( - self, image_urls, labels, transforms, artifact_store_path: str - ) -> None: - assert len(image_urls) == len(labels) - self.transforms = transforms - - # Download all images from the artifact store as np.ndarray - self.images = [] - temp_dir = tempfile.TemporaryDirectory() - for i, image_url in enumerate(image_urls): - parts = image_url.split("/") - if is_s3_url(image_url): - file_url = f"{artifact_store_path}{urlparse(image_url).path}" - elif is_azure_url(image_url): - file_url = "az://" + "/".join(parts[3:]) - else: - url_path = urlparse(image_url).path - file_url = f"{artifact_store_path}/{url_path}" - file_extension = get_file_extension(urlparse(image_url).path) - path = os.path.join(temp_dir.name, f"{i}{file_extension}") - - io_utils.copy(file_url, path) - with fileio.open(path, "rb") as f: - image = np.asarray(Image.open(f)) - self.images.append(image) - fileio.rmtree(temp_dir.name) - - # Define class-label mapping and map labels - self.class_label_mapping = LABEL_MAPPING - self.labels = [self.class_label_mapping[label] for label in labels] - - def __getitem__(self, idx): - image = self.transforms(self.images[idx]) - label = self.labels[idx] - return (image, label) - - def __len__(self): - return len(self.images) - - -def _load_last_model() -> Optional[nn.Module]: - """Return the most recently trained model from this pipeline, or None.""" - last_run = Client().get_pipeline(PIPELINE_NAME).last_successful_run - return last_run.steps[PIPELINE_STEP_NAME].output.load() - - -def _is_new_data_available(image_urls: List[str]) -> bool: - """Find whether new data is available since the last run.""" - # If there are no samples, nothing can be new. - num_samples = len(image_urls) - if num_samples == 0: - return False - - # Else, we check whether we had the same number of samples before. - last_run = Client().get_pipeline(PIPELINE_NAME).last_successful_run - last_inputs = last_run.steps[PIPELINE_STEP_NAME].inputs - last_image_urls = last_inputs["image_urls"].load() - return len(last_image_urls) != len(image_urls) - - -def load_pretrained_mobilenetv3(num_classes: int = 2): - """Load a pretrained mobilenetv3 with fresh classification head.""" - model = models.mobilenet_v3_small(pretrained=True) - for param in model.parameters(): - param.requires_grad = False - model.classifier[-1] = nn.Linear(1024, num_classes) - model.num_classes = num_classes - return model - - -def load_mobilenetv3_transforms(): - """Load the transforms required before running mobilenetv3 on data.""" - weights = models.MobileNet_V3_Small_Weights.DEFAULT - return transforms.Compose([transforms.ToTensor(), weights.transforms()]) - - -@step(enable_cache=False) -def pytorch_model_trainer( - image_urls: List[str], - labels: List[str], - batch_size=1, - num_epochs=2, - learning_rate=5e-3, - device="cpu", - shuffle=True, - num_workers=1, - seed=42, # don't change: this seed ensures a good train/val split -) -> nn.Module: - """ZenML step which finetunes or loads a pretrained mobilenetv3 model.""" - # Try to load a model from a previous run, otherwise use a pretrained net - model = _load_last_model() - if model is None: - model = load_pretrained_mobilenetv3() - - # If there is no new data, just return the model - if not _is_new_data_available(image_urls): - return model - - context = get_step_context() - artifact_store_path = context.stack.artifact_store.path - - # Otherwise finetune the model on the current data - # Write images and labels to torch dataset - dataset = CustomDataset( - image_urls=image_urls, - labels=labels, - transforms=load_mobilenetv3_transforms(), - artifact_store_path=artifact_store_path, - ) - - # Split dataset into train and val - train_size = int(0.8 * len(dataset)) - val_size = len(dataset) - train_size - train_dataset, val_dataset = torch.utils.data.random_split( - dataset=dataset, - lengths=[train_size, val_size], - generator=torch.Generator().manual_seed(seed), - ) - dataset_dict = { - "train": train_dataset, - "val": val_dataset, - } - - # Create training and validation dataloaders - dataloaders_dict = { - dataset_type: torch.utils.data.DataLoader( - dataset, - batch_size=batch_size, - shuffle=shuffle, - num_workers=num_workers, - ) - for dataset_type, dataset in dataset_dict.items() - } - - # Define optimizer - optimizer_ft = optim.Adam( - params=model.classifier[-1].parameters(), lr=learning_rate - ) - - # Define loss - criterion = nn.CrossEntropyLoss() - - # Train and evaluate - model = train_model( - model, - dataloaders_dict, - criterion, - optimizer_ft, - num_epochs=num_epochs, - device=device, - ) - return model diff --git a/examples/label_studio_annotation/steps/sync_new_data_to_label_studio.py b/examples/label_studio_annotation/steps/sync_new_data_to_label_studio.py deleted file mode 100644 index 75df78ebce6..00000000000 --- a/examples/label_studio_annotation/steps/sync_new_data_to_label_studio.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) ZenML GmbH 2022. All Rights Reserved. -# -# 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: -# -# https://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. -from zenml.integrations.label_studio.label_config_generators import ( - generate_image_classification_label_config, -) -from zenml.integrations.label_studio.steps import ( - LabelStudioDatasetSyncParameters, - sync_new_data_to_label_studio, -) - -IMAGE_REGEX_FILTER = ".*(jpe?g|png|JPE?G|PNG)" - - -_, label_config_type = generate_image_classification_label_config( - ["aria", "not_aria"] -) - - -zenml_sync_params = LabelStudioDatasetSyncParameters( - label_config_type=label_config_type, - regex_filter=IMAGE_REGEX_FILTER, -) - -data_sync = sync_new_data_to_label_studio.with_options( - parameters={"params": zenml_sync_params}, -)