diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..20d51bc8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,96 @@ +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +* @remyleone + +/scaleway/scaleway/account/ @scaleway/devtools-core +/scaleway-async/scaleway_async/account/ @scaleway/devtools-core + +/scaleway/scaleway/applesilicon/ @scaleway/devtools-compute-foundation +/scaleway-async/scaleway_async/applesilicon/ @scaleway/devtools-compute-foundation + +/scaleway/scaleway/baremetal/ @scaleway/devtools-compute-foundation +/scaleway-async/scaleway_async/baremetal/ @scaleway/devtools-compute-foundation + +/scaleway/scaleway/billing/ @scaleway/devtools-core +/scaleway-async/scaleway_async/billing/ @scaleway/devtools-core + +/scaleway/scaleway/block/ @scaleway/devtools-storage +/scaleway-async/scaleway_async/block/ @scaleway/devtools-storage + +/scaleway/scaleway/cockpit/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/cockpit/ @scaleway/devtools-dms + +/scaleway/scaleway/container/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/container/ @scaleway/devtools-compute + +/scaleway/scaleway/dedibox/ @scaleway/devtools-compute-foundation +/scaleway-async/scaleway_async/dedibox/ @scaleway/devtools-compute-foundation + +/scaleway/scaleway/domain/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/domain/ @scaleway/devtools-dms + +/scaleway/scaleway/edge_services/ @scaleway/devtools-network +/scaleway-async/scaleway_async/edge_services/ @scaleway/devtools-network + +/scaleway/scaleway/flexibleip/ @scaleway/devtools-network +/scaleway-async/scaleway_async/flexibleip/ @scaleway/devtools-network + +/scaleway/scaleway/function/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/function/ @scaleway/devtools-compute + +/scaleway/scaleway/iam/ @scaleway/devtools-core +/scaleway-async/scaleway_async/iam/ @scaleway/devtools-core + +/scaleway/scaleway/instance/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/instance/ @scaleway/devtools-compute + +/scaleway/scaleway/iot/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/iot/ @scaleway/devtools-dms + +/scaleway/scaleway/ipam/ @scaleway/devtools-network +/scaleway-async/scaleway_async/ipam/ @scaleway/devtools-network + +/scaleway/scaleway/jobs/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/jobs/ @scaleway/devtools-compute + +/scaleway/scaleway/k8s/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/k8s/ @scaleway/devtools-compute + +/scaleway/scaleway/key_manager/ @scaleway/devtools-core +/scaleway-async/scaleway_async/key_manager/ @scaleway/devtools-core + +/scaleway/scaleway/lb/ @scaleway/devtools-network +/scaleway-async/scaleway_async/lb/ @scaleway/devtools-network + +/scaleway/scaleway/marketplace/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/marketplace/ @scaleway/devtools-compute + +/scaleway/scaleway/mnq/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/mnq/ @scaleway/devtools-dms + +/scaleway/scaleway/rdb/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/rdb/ @scaleway/devtools-dms + +/scaleway/scaleway/redis/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/redis/ @scaleway/devtools-dms + +/scaleway/scaleway/registry/ @scaleway/devtools-compute +/scaleway-async/scaleway_async/registry/ @scaleway/devtools-compute + +/scaleway/scaleway/secret/ @scaleway/devtools-core +/scaleway-async/scaleway_async/secret/ @scaleway/devtools-core + +/scaleway/scaleway/serverless_sqldb/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/serverless_sqldb/ @scaleway/devtools-dms + +/scaleway/scaleway/tem/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/tem/ @scaleway/devtools-dms + +/scaleway/scaleway/vpc/ @scaleway/devtools-network +/scaleway-async/scaleway_async/vpc/ @scaleway/devtools-network + +/scaleway/scaleway/vpcgw/ @scaleway/devtools-network +/scaleway-async/scaleway_async/vpcgw/ @scaleway/devtools-network + +/scaleway/scaleway/webhosting/ @scaleway/devtools-dms +/scaleway-async/scaleway_async/webhosting/ @scaleway/devtools-dms diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..437932a6 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,21 @@ +version: 2 +updates: + - package-ecosystem: pip + directory: /scaleway + schedule: + interval: monthly + + - package-ecosystem: pip + directory: /scaleway-async + schedule: + interval: monthly + + - package-ecosystem: pip + directory: /scaleway-core + schedule: + interval: monthly + + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000..a59d3c89 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,186 @@ +account: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/account/** + - scaleway-async/scaleway_async/account/** + + +apple-silicon: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/applesilicon/** + - scaleway-async/scaleway_async/applesilicon/** + +baremetal: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/baremetal/** + - scaleway-async/scaleway_async/baremetal/** + +billing: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/billing/** + - scaleway-async/scaleway_async/billing/** + +cockpit: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/cockpit/** + - scaleway-async/scaleway_async/cockpit/** + +container: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/container/** + - scaleway-async/scaleway_async/container/** + +dedibox: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/dedibox/** + - scaleway-async/scaleway_async/dedibox/** + +domain: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/domain/** + - scaleway-async/scaleway_async/domain/** + +edge_services: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/edge_services/** + - scaleway-async/scaleway_async/edge_services/** + +flexible-ip: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/flexibleip/** + - scaleway-async/scaleway_async/flexibleip/** + +function: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/function/** + - scaleway-async/scaleway_async/function/** + +iam: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/iam/** + - scaleway-async/scaleway_async/iam/** + +instance: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/instance/** + - scaleway-async/scaleway_async/instance/** + +iot: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/iot/** + - scaleway-async/scaleway_async/iot/** + +ipam: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/ipam/** + - scaleway-async/scaleway_async/ipam/** + +jobs: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/jobs/** + - scaleway-async/scaleway_async/jobs/** + +k8s: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/k8s/** + - scaleway-async/scaleway_async/k8s/** + +key_manager: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/key_manager/** + - scaleway-async/scaleway_async/key_manager/** + +load-balancer: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/lb/** + - scaleway-async/scaleway_async/lb/** + +marketplace: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/marketplace/** + - scaleway-async/scaleway_async/marketplace/** + +mnq: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/mnq/** + - scaleway-async/scaleway_async/mnq/** + +rdb: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/rdb/** + - scaleway-async/scaleway_async/rdb/** + +redis: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/redis/** + - scaleway-async/scaleway_async/redis/** + +registry: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/registry/** + - scaleway-async/scaleway_async/registry/** + +sbs: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/block/** + - scaleway-async/scaleway_async/block/** + +sdb: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/serverless_sqldb/** + - scaleway-async/scaleway_async/serverless_sqldb/** + +secret: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/secret/** + - scaleway-async/scaleway_async/secret/** + +tem: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/tem/** + - scaleway-async/scaleway_async/tem/** + +vpc: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/vpc/** + - scaleway-async/scaleway_async/vpc/** + +vpcgw: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/vpcgw/** + - scaleway-async/scaleway_async/vpcgw/** + +webhosting: + - changed-files: + - any-glob-to-any-file: + - scaleway/scaleway/webhosting/** + - scaleway-async/scaleway_async/webhosting/** diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index f86a481c..21218dbc 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -19,11 +19,11 @@ jobs: run: working-directory: ${{ matrix.lib }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: "3.10" - name: Install poetry run: | pip install poetry @@ -31,7 +31,7 @@ jobs: - name: Install dependencies and library run: poetry install - name: Check format - run: poetry run ruff format -q + run: poetry run ruff format --check typing: runs-on: ubuntu-latest @@ -45,11 +45,11 @@ jobs: run: working-directory: ${{ matrix.lib }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: "3.10" - name: Install poetry run: | pip install poetry @@ -71,11 +71,11 @@ jobs: run: working-directory: ${{ matrix.lib }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: "3.10" - name: Install poetry run: | pip install poetry @@ -100,11 +100,11 @@ jobs: # run: # working-directory: ${{ matrix.lib }} # steps: - # - uses: actions/checkout@v3 + # - uses: actions/checkout@v4 # - name: Set up Python - # uses: actions/setup-python@v4 + # uses: actions/setup-python@v5 # with: - # python-version: 3.8 + # python-version: "3.10" # - name: Install poetry # run: | # pip install poetry diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a7bfe318..42b0940f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -15,11 +15,11 @@ jobs: run: working-directory: ./docs steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: "3.10" - name: Install poetry run: | pip install poetry @@ -34,7 +34,7 @@ jobs: - name: Generate documentation run: poetry run sphinx-build -b html ./ ./_build - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} with: publish_branch: docs diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 00000000..bfeaac16 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,17 @@ +name: "Pull Request Labeler" +on: + - pull_request_target + +jobs: + triage: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Labeler + uses: actions/labeler@v5 + with: + sync-labels: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0617bb88..84f3620e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,11 +11,11 @@ jobs: run: working-directory: scaleway-core steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: "3.10" - name: Install poetry run: | pip install poetry @@ -48,11 +48,11 @@ jobs: run: working-directory: ${{ matrix.lib }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: "3.10" - name: Install poetry run: | pip install poetry diff --git a/docs/poetry.lock b/docs/poetry.lock index fdd9002e..2beed55b 100644 --- a/docs/poetry.lock +++ b/docs/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "alabaster" version = "0.7.13" description = "A configurable sidebar-enabled Sphinx theme" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -16,7 +15,6 @@ files = [ name = "babel" version = "2.13.1" description = "Internationalization utilities" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -35,7 +33,6 @@ dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] name = "certifi" version = "2023.11.17" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -47,7 +44,6 @@ files = [ name = "charset-normalizer" version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -147,7 +143,6 @@ files = [ name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -159,7 +154,6 @@ files = [ name = "docutils" version = "0.18.1" description = "Docutils -- Python Documentation Utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -171,7 +165,6 @@ files = [ name = "idna" version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -183,7 +176,6 @@ files = [ name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -195,7 +187,6 @@ files = [ name = "importlib-metadata" version = "6.8.0" description = "Read metadata from Python packages" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -213,14 +204,13 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs [[package]] name = "jinja2" -version = "3.1.2" +version = "3.1.3" description = "A very fast and expressive template engine." -category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, ] [package.dependencies] @@ -233,7 +223,6 @@ i18n = ["Babel (>=2.7)"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -303,7 +292,6 @@ files = [ name = "packaging" version = "23.2" description = "Core utilities for Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -315,7 +303,6 @@ files = [ name = "pygments" version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -331,7 +318,6 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -346,7 +332,6 @@ six = ">=1.5" name = "pytz" version = "2023.3.post1" description = "World timezone definitions, modern and historical" -category = "main" optional = false python-versions = "*" files = [ @@ -358,7 +343,6 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -380,6 +364,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -418,7 +403,6 @@ files = [ name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -440,7 +424,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "scaleway" version = "2.0.0" description = "Scaleway SDK for Python" -category = "main" optional = false python-versions = "^3.8" files = [] @@ -457,7 +440,6 @@ url = "../scaleway" name = "scaleway-async" version = "2.0.0" description = "Scaleway SDK for Python" -category = "main" optional = false python-versions = "^3.8" files = [] @@ -474,7 +456,6 @@ url = "../scaleway-async" name = "scaleway-core" version = "2.0.0" description = "Scaleway SDK for Python" -category = "main" optional = false python-versions = "^3.8" files = [] @@ -493,7 +474,6 @@ url = "../scaleway-core" name = "setuptools" version = "69.0.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -510,7 +490,6 @@ testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jar name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -522,7 +501,6 @@ files = [ name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "main" optional = false python-versions = "*" files = [ @@ -534,7 +512,6 @@ files = [ name = "sphinx" version = "5.3.0" description = "Python documentation generator" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -570,7 +547,6 @@ test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] name = "sphinx-rtd-theme" version = "1.3.0" description = "Read the Docs theme for Sphinx" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -590,7 +566,6 @@ dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] name = "sphinxcontrib-applehelp" version = "1.0.4" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -606,7 +581,6 @@ test = ["pytest"] name = "sphinxcontrib-devhelp" version = "1.0.2" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -622,7 +596,6 @@ test = ["pytest"] name = "sphinxcontrib-htmlhelp" version = "2.0.1" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -638,7 +611,6 @@ test = ["html5lib", "pytest"] name = "sphinxcontrib-jquery" version = "4.1" description = "Extension to include jQuery on newer Sphinx releases" -category = "main" optional = false python-versions = ">=2.7" files = [ @@ -653,7 +625,6 @@ Sphinx = ">=1.8" name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -668,7 +639,6 @@ test = ["flake8", "mypy", "pytest"] name = "sphinxcontrib-qthelp" version = "1.0.3" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -684,7 +654,6 @@ test = ["pytest"] name = "sphinxcontrib-serializinghtml" version = "1.1.5" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -700,7 +669,6 @@ test = ["pytest"] name = "urllib3" version = "2.1.0" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -717,7 +685,6 @@ zstd = ["zstandard (>=0.18.0)"] name = "zipp" version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" optional = false python-versions = ">=3.8" files = [ diff --git a/scaleway-async/poetry.lock b/scaleway-async/poetry.lock index ac19aa15..b2fa0006 100644 --- a/scaleway-async/poetry.lock +++ b/scaleway-async/poetry.lock @@ -1,173 +1,184 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, + {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] [[package]] name = "charset-normalizer" -version = "3.3.2" +version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.7" +groups = ["main", "dev"] files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, + {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, + {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, ] [[package]] name = "idna" -version = "3.6" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" +groups = ["main", "dev"] files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "mypy" -version = "1.9.0" +version = "1.15.0" description = "Optional static typing for Python" -category = "dev" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"}, - {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"}, - {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"}, - {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"}, - {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"}, - {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"}, - {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"}, - {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"}, - {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"}, - {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"}, - {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"}, - {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"}, - {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"}, - {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"}, - {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"}, - {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"}, - {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"}, - {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"}, - {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, + {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, + {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, + {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, + {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, + {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, + {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, + {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, + {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, + {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, + {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, + {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, + {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, ] [package.dependencies] -mypy-extensions = ">=1.0.0" +mypy_extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.1.0" +typing_extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] +faster-cache = ["orjson"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] reports = ["lxml"] @@ -176,9 +187,9 @@ reports = ["lxml"] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, @@ -188,9 +199,9 @@ files = [ name = "python-dateutil" version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -201,75 +212,77 @@ six = ">=1.5" [[package]] name = "pyyaml" -version = "6.0.1" +version = "6.0.2" description = "YAML parser and emitter for Python" -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -284,38 +297,39 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.0.286" -description = "An extremely fast Python linter, written in Rust." -category = "dev" +version = "0.11.7" +description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "ruff-0.0.286-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:8e22cb557e7395893490e7f9cfea1073d19a5b1dd337f44fd81359b2767da4e9"}, - {file = "ruff-0.0.286-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:68ed8c99c883ae79a9133cb1a86d7130feee0397fdf5ba385abf2d53e178d3fa"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8301f0bb4ec1a5b29cfaf15b83565136c47abefb771603241af9d6038f8981e8"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:acc4598f810bbc465ce0ed84417ac687e392c993a84c7eaf3abf97638701c1ec"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88c8e358b445eb66d47164fa38541cfcc267847d1e7a92dd186dddb1a0a9a17f"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0433683d0c5dbcf6162a4beb2356e820a593243f1fa714072fec15e2e4f4c939"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddb61a0c4454cbe4623f4a07fef03c5ae921fe04fede8d15c6e36703c0a73b07"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:47549c7c0be24c8ae9f2bce6f1c49fbafea83bca80142d118306f08ec7414041"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:559aa793149ac23dc4310f94f2c83209eedb16908a0343663be19bec42233d25"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d73cfb1c3352e7aa0ce6fb2321f36fa1d4a2c48d2ceac694cb03611ddf0e4db6"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:3dad93b1f973c6d1db4b6a5da8690c5625a3fa32bdf38e543a6936e634b83dc3"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26afc0851f4fc3738afcf30f5f8b8612a31ac3455cb76e611deea80f5c0bf3ce"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9b6b116d1c4000de1b9bf027131dbc3b8a70507788f794c6b09509d28952c512"}, - {file = "ruff-0.0.286-py3-none-win32.whl", hash = "sha256:556e965ac07c1e8c1c2d759ac512e526ecff62c00fde1a046acb088d3cbc1a6c"}, - {file = "ruff-0.0.286-py3-none-win_amd64.whl", hash = "sha256:5d295c758961376c84aaa92d16e643d110be32add7465e197bfdaec5a431a107"}, - {file = "ruff-0.0.286-py3-none-win_arm64.whl", hash = "sha256:1d6142d53ab7f164204b3133d053c4958d4d11ec3a39abf23a40b13b0784e3f0"}, - {file = "ruff-0.0.286.tar.gz", hash = "sha256:f1e9d169cce81a384a26ee5bb8c919fe9ae88255f39a1a69fd1ebab233a85ed2"}, + {file = "ruff-0.11.7-py3-none-linux_armv6l.whl", hash = "sha256:d29e909d9a8d02f928d72ab7837b5cbc450a5bdf578ab9ebee3263d0a525091c"}, + {file = "ruff-0.11.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dd1fb86b168ae349fb01dd497d83537b2c5541fe0626e70c786427dd8363aaee"}, + {file = "ruff-0.11.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3d7d2e140a6fbbc09033bce65bd7ea29d6a0adeb90b8430262fbacd58c38ada"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4809df77de390a1c2077d9b7945d82f44b95d19ceccf0c287c56e4dc9b91ca64"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3a0c2e169e6b545f8e2dba185eabbd9db4f08880032e75aa0e285a6d3f48201"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49b888200a320dd96a68e86736cf531d6afba03e4f6cf098401406a257fcf3d6"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2b19cdb9cf7dae00d5ee2e7c013540cdc3b31c4f281f1dacb5a799d610e90db4"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64e0ee994c9e326b43539d133a36a455dbaab477bc84fe7bfbd528abe2f05c1e"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bad82052311479a5865f52c76ecee5d468a58ba44fb23ee15079f17dd4c8fd63"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7940665e74e7b65d427b82bffc1e46710ec7f30d58b4b2d5016e3f0321436502"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:169027e31c52c0e36c44ae9a9c7db35e505fee0b39f8d9fca7274a6305295a92"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:305b93f9798aee582e91e34437810439acb28b5fc1fee6b8205c78c806845a94"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a681db041ef55550c371f9cd52a3cf17a0da4c75d6bd691092dfc38170ebc4b6"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:07f1496ad00a4a139f4de220b0c97da6d4c85e0e4aa9b2624167b7d4d44fd6b6"}, + {file = "ruff-0.11.7-py3-none-win32.whl", hash = "sha256:f25dfb853ad217e6e5f1924ae8a5b3f6709051a13e9dad18690de6c8ff299e26"}, + {file = "ruff-0.11.7-py3-none-win_amd64.whl", hash = "sha256:0a931d85959ceb77e92aea4bbedfded0a31534ce191252721128f77e5ae1f98a"}, + {file = "ruff-0.11.7-py3-none-win_arm64.whl", hash = "sha256:778c1e5d6f9e91034142dfd06110534ca13220bfaad5c3735f6cb844654f6177"}, + {file = "ruff-0.11.7.tar.gz", hash = "sha256:655089ad3224070736dc32844fde783454f8558e71f501cb207485fe4eee23d4"}, ] [[package]] name = "scaleway-core" version = "2.0.0" description = "Scaleway SDK for Python" -category = "main" optional = false -python-versions = "^3.8" +python-versions = ">=3.10" +groups = ["main", "dev"] files = [] develop = true @@ -330,59 +344,90 @@ url = "../scaleway-core" [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] name = "tomli" -version = "2.0.1" +version = "2.2.1" description = "A lil' TOML parser" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version < \"3.11\"" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] name = "typing-extensions" -version = "4.10.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, - {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] name = "urllib3" -version = "2.2.1" +version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main", "dev"] files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, + {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [metadata] -lock-version = "2.0" -python-versions = "^3.8" -content-hash = "441285c99087ba7e2715e85918cefdd80615528d46711cb9c85dc8d28e1f308c" +lock-version = "2.1" +python-versions = ">=3.10" +content-hash = "68ef82872418760889cf9cc20b83ca32fe57cd6a0fe8df937f4907f5f0809b98" diff --git a/scaleway-async/pyproject.toml b/scaleway-async/pyproject.toml index 56a0a0aa..27f31d34 100644 --- a/scaleway-async/pyproject.toml +++ b/scaleway-async/pyproject.toml @@ -23,17 +23,17 @@ classifiers = [ ] [tool.poetry.dependencies] -python = "^3.8" +python = ">=3.10" scaleway-core = "*" [tool.poetry.group.dev.dependencies] scaleway-core = { path = "../scaleway-core", develop = true } -ruff = "^0.0.286" +ruff = ">=0.5.0,<0.11.8" mypy = "^1.5.1" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" -[tool.ruff] +[tool.ruff.lint] ignore = ["E501"] diff --git a/scaleway-async/scaleway_async/__init__.py b/scaleway-async/scaleway_async/__init__.py index eb108d1f..c22dc86a 100644 --- a/scaleway-async/scaleway_async/__init__.py +++ b/scaleway-async/scaleway_async/__init__.py @@ -1,8 +1,8 @@ """Scaleway SDK for Python - Async""" -import pkg_resources +import importlib.metadata -__version__: str = pkg_resources.get_distribution(__name__).version +__version__: str = importlib.metadata.version(__name__) from scaleway_core.api import ( API, diff --git a/scaleway-async/scaleway_async/account/v2/api.py b/scaleway-async/scaleway_async/account/v2/api.py index 20855ebe..2c912cd4 100644 --- a/scaleway-async/scaleway_async/account/v2/api.py +++ b/scaleway-async/scaleway_async/account/v2/api.py @@ -26,7 +26,7 @@ class AccountV2API(API): """ - This API allows you to manage projects. + This API allows you to manage your Scaleway Projects. """ async def create_project( diff --git a/scaleway-async/scaleway_async/account/v2/marshalling.py b/scaleway-async/scaleway_async/account/v2/marshalling.py index 869668e9..c577c2d2 100644 --- a/scaleway-async/scaleway_async/account/v2/marshalling.py +++ b/scaleway-async/scaleway_async/account/v2/marshalling.py @@ -40,10 +40,14 @@ def unmarshal_Project(data: Any) -> Project: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Project(**args) diff --git a/scaleway-async/scaleway_async/account/v3/__init__.py b/scaleway-async/scaleway_async/account/v3/__init__.py index 262de9a5..db42391c 100644 --- a/scaleway-async/scaleway_async/account/v3/__init__.py +++ b/scaleway-async/scaleway_async/account/v3/__init__.py @@ -1,23 +1,91 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import ContractType +from .types import ListContractSignaturesRequestOrderBy from .types import ListProjectsRequestOrderBy +from .types import QualificationAiMachineSubUseCase +from .types import QualificationArchitectureType +from .types import QualificationArchiveDataSubUseCase +from .types import QualificationContainerSubUseCase +from .types import QualificationDeploySoftwareSubUseCase +from .types import QualificationHostApplicationSubUseCase +from .types import QualificationHostWebsiteSubUseCase +from .types import QualificationOtherUseCaseSubUseCase +from .types import QualificationSetScalewayEnvironmentSubUseCase +from .types import QualificationShareDataSubUseCase +from .types import QualificationAiMachine +from .types import QualificationArchiveData +from .types import QualificationContainer +from .types import QualificationDeploySoftware +from .types import QualificationHostApplication +from .types import QualificationHostWebsite +from .types import QualificationOtherUseCase +from .types import QualificationSetScalewayEnvironment +from .types import QualificationShareData +from .types import Contract +from .types import Qualification +from .types import ContractSignature from .types import Project +from .types import CheckContractSignatureResponse +from .types import ContractApiCheckContractSignatureRequest +from .types import ContractApiCreateContractSignatureRequest +from .types import ContractApiDownloadContractSignatureRequest +from .types import ContractApiListContractSignaturesRequest +from .types import ContractApiValidateContractSignatureRequest +from .types import ListContractSignaturesResponse from .types import ListProjectsResponse from .types import ProjectApiCreateProjectRequest from .types import ProjectApiDeleteProjectRequest from .types import ProjectApiGetProjectRequest from .types import ProjectApiListProjectsRequest +from .types import ProjectApiSetProjectQualificationRequest from .types import ProjectApiUpdateProjectRequest +from .types import ProjectQualification +from .api import AccountV3ContractAPI from .api import AccountV3ProjectAPI __all__ = [ + "ContractType", + "ListContractSignaturesRequestOrderBy", "ListProjectsRequestOrderBy", + "QualificationAiMachineSubUseCase", + "QualificationArchitectureType", + "QualificationArchiveDataSubUseCase", + "QualificationContainerSubUseCase", + "QualificationDeploySoftwareSubUseCase", + "QualificationHostApplicationSubUseCase", + "QualificationHostWebsiteSubUseCase", + "QualificationOtherUseCaseSubUseCase", + "QualificationSetScalewayEnvironmentSubUseCase", + "QualificationShareDataSubUseCase", + "QualificationAiMachine", + "QualificationArchiveData", + "QualificationContainer", + "QualificationDeploySoftware", + "QualificationHostApplication", + "QualificationHostWebsite", + "QualificationOtherUseCase", + "QualificationSetScalewayEnvironment", + "QualificationShareData", + "Contract", + "Qualification", + "ContractSignature", "Project", + "CheckContractSignatureResponse", + "ContractApiCheckContractSignatureRequest", + "ContractApiCreateContractSignatureRequest", + "ContractApiDownloadContractSignatureRequest", + "ContractApiListContractSignaturesRequest", + "ContractApiValidateContractSignatureRequest", + "ListContractSignaturesResponse", "ListProjectsResponse", "ProjectApiCreateProjectRequest", "ProjectApiDeleteProjectRequest", "ProjectApiGetProjectRequest", "ProjectApiListProjectsRequest", + "ProjectApiSetProjectQualificationRequest", "ProjectApiUpdateProjectRequest", + "ProjectQualification", + "AccountV3ContractAPI", "AccountV3ProjectAPI", ] diff --git a/scaleway-async/scaleway_async/account/v3/api.py b/scaleway-async/scaleway_async/account/v3/api.py index f5791f04..98d728b3 100644 --- a/scaleway-async/scaleway_async/account/v3/api.py +++ b/scaleway-async/scaleway_async/account/v3/api.py @@ -4,29 +4,276 @@ from typing import List, Optional from scaleway_core.api import API +from scaleway_core.bridge import ( + ScwFile, + unmarshal_ScwFile, +) from scaleway_core.utils import ( random_name, validate_path_param, fetch_all_pages_async, ) from .types import ( + ContractType, + ListContractSignaturesRequestOrderBy, ListProjectsRequestOrderBy, + CheckContractSignatureResponse, + ContractApiCheckContractSignatureRequest, + ContractApiCreateContractSignatureRequest, + ContractSignature, + ListContractSignaturesResponse, ListProjectsResponse, Project, ProjectApiCreateProjectRequest, + ProjectApiSetProjectQualificationRequest, ProjectApiUpdateProjectRequest, + ProjectQualification, + Qualification, ) from .marshalling import ( + unmarshal_ContractSignature, unmarshal_Project, + unmarshal_CheckContractSignatureResponse, + unmarshal_ListContractSignaturesResponse, unmarshal_ListProjectsResponse, + unmarshal_ProjectQualification, + marshal_ContractApiCheckContractSignatureRequest, + marshal_ContractApiCreateContractSignatureRequest, marshal_ProjectApiCreateProjectRequest, + marshal_ProjectApiSetProjectQualificationRequest, marshal_ProjectApiUpdateProjectRequest, ) +from ...std.types import ( + LanguageCode as StdLanguageCode, +) + + +class AccountV3ContractAPI(API): + """ + The Contract API allows you to manage contracts. + """ + + async def download_contract_signature( + self, + *, + contract_signature_id: str, + locale: Optional[StdLanguageCode] = None, + ) -> ScwFile: + """ + Download a contract content. + :param contract_signature_id: The contract signature ID. + :param locale: The locale requested for the content of the contract. + :return: :class:`ScwFile ` + + Usage: + :: + + result = await api.download_contract_signature( + contract_signature_id="example", + ) + """ + + param_contract_signature_id = validate_path_param( + "contract_signature_id", contract_signature_id + ) + + res = self._request( + "GET", + f"/account/v3/contract-signatures/{param_contract_signature_id}/download", + params={ + "locale": locale, + }, + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + async def create_contract_signature( + self, + *, + contract_name: str, + validated: bool, + contract_type: Optional[ContractType] = None, + organization_id: Optional[str] = None, + ) -> ContractSignature: + """ + Create a signature for your Organization for the latest version of the requested contract. + :param contract_name: The name of the contract. + :param validated: Whether the contract is validated at creation. + :param contract_type: The type of the contract. + :param organization_id: ID of the Organization. + :return: :class:`ContractSignature ` + + Usage: + :: + + result = await api.create_contract_signature( + contract_name="example", + validated=False, + ) + """ + + res = self._request( + "POST", + "/account/v3/contract-signatures", + body=marshal_ContractApiCreateContractSignatureRequest( + ContractApiCreateContractSignatureRequest( + contract_name=contract_name, + validated=validated, + contract_type=contract_type, + organization_id=organization_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ContractSignature(res.json()) + + async def validate_contract_signature( + self, + *, + contract_signature_id: str, + ) -> ContractSignature: + """ + Sign a contract for your Organization. + :param contract_signature_id: The contract linked to your Organization you want to sign. + :return: :class:`ContractSignature ` + + Usage: + :: + + result = await api.validate_contract_signature( + contract_signature_id="example", + ) + """ + + param_contract_signature_id = validate_path_param( + "contract_signature_id", contract_signature_id + ) + + res = self._request( + "POST", + f"/account/v3/contract-signatures/{param_contract_signature_id}/validate", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_ContractSignature(res.json()) + + async def check_contract_signature( + self, + *, + contract_name: str, + organization_id: Optional[str] = None, + contract_type: Optional[ContractType] = None, + ) -> CheckContractSignatureResponse: + """ + Check if a contract is signed for your Organization. + :param contract_name: Filter on contract name. + :param organization_id: ID of the Organization to check the contract signature for. + :param contract_type: Filter on contract type. + :return: :class:`CheckContractSignatureResponse ` + + Usage: + :: + + result = await api.check_contract_signature( + contract_name="example", + ) + """ + + res = self._request( + "POST", + "/account/v3/contract-signatures/check", + body=marshal_ContractApiCheckContractSignatureRequest( + ContractApiCheckContractSignatureRequest( + contract_name=contract_name, + organization_id=organization_id, + contract_type=contract_type, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckContractSignatureResponse(res.json()) + + async def list_contract_signatures( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListContractSignaturesRequestOrderBy] = None, + organization_id: Optional[str] = None, + ) -> ListContractSignaturesResponse: + """ + List contract signatures for an Organization. + :param page: The page number for the returned contracts. + :param page_size: The maximum number of contracts per page. + :param order_by: How the contracts are ordered in the response. + :param organization_id: Filter on Organization ID. + :return: :class:`ListContractSignaturesResponse ` + + Usage: + :: + + result = await api.list_contract_signatures() + """ + + res = self._request( + "GET", + "/account/v3/contract-signatures", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListContractSignaturesResponse(res.json()) + + async def list_contract_signatures_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListContractSignaturesRequestOrderBy] = None, + organization_id: Optional[str] = None, + ) -> List[ContractSignature]: + """ + List contract signatures for an Organization. + :param page: The page number for the returned contracts. + :param page_size: The maximum number of contracts per page. + :param order_by: How the contracts are ordered in the response. + :param organization_id: Filter on Organization ID. + :return: :class:`List[ContractSignature] ` + + Usage: + :: + + result = await api.list_contract_signatures_all() + """ + + return await fetch_all_pages_async( + type=ListContractSignaturesResponse, + key="contract_signatures", + fetcher=self.list_contract_signatures, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "organization_id": organization_id, + }, + ) class AccountV3ProjectAPI(API): """ - This API allows you to manage projects. + This API allows you to manage your Scaleway Projects. """ async def create_project( @@ -249,3 +496,41 @@ async def update_project( self._throw_on_error(res) return unmarshal_Project(res.json()) + + async def set_project_qualification( + self, + *, + project_id: Optional[str] = None, + qualification: Optional[Qualification] = None, + ) -> ProjectQualification: + """ + Set project use case. + Set the project use case for a new or existing Project, specified by its Project ID. You can customize the use case, sub use case, and architecture type you want to use in the Project. + :param project_id: Project ID. + :param qualification: Use case chosen for the Project. + :return: :class:`ProjectQualification ` + + Usage: + :: + + result = await api.set_project_qualification() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "POST", + f"/account/v3/projects/{param_project_id}/project-qualification", + body=marshal_ProjectApiSetProjectQualificationRequest( + ProjectApiSetProjectQualificationRequest( + project_id=project_id, + qualification=qualification, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ProjectQualification(res.json()) diff --git a/scaleway-async/scaleway_async/account/v3/marshalling.py b/scaleway-async/scaleway_async/account/v3/marshalling.py index 2725094d..2875dfa3 100644 --- a/scaleway-async/scaleway_async/account/v3/marshalling.py +++ b/scaleway-async/scaleway_async/account/v3/marshalling.py @@ -5,14 +5,326 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) from .types import ( + Contract, + ContractSignature, + QualificationAiMachine, + QualificationArchiveData, + QualificationContainer, + QualificationDeploySoftware, + QualificationHostApplication, + QualificationHostWebsite, + QualificationOtherUseCase, + QualificationSetScalewayEnvironment, + QualificationShareData, + Qualification, Project, + CheckContractSignatureResponse, + ListContractSignaturesResponse, ListProjectsResponse, + ProjectQualification, + ContractApiCheckContractSignatureRequest, + ContractApiCreateContractSignatureRequest, ProjectApiCreateProjectRequest, + ProjectApiSetProjectQualificationRequest, ProjectApiUpdateProjectRequest, ) +def unmarshal_Contract(data: Any) -> Contract: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Contract' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Contract(**args) + + +def unmarshal_ContractSignature(data: Any) -> ContractSignature: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContractSignature' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("signed_at", None) + if field is not None: + args["signed_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["signed_at"] = None + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + field = data.get("contract", None) + if field is not None: + args["contract"] = unmarshal_Contract(field) + else: + args["contract"] = None + + return ContractSignature(**args) + + +def unmarshal_QualificationAiMachine(data: Any) -> QualificationAiMachine: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationAiMachine' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationAiMachine(**args) + + +def unmarshal_QualificationArchiveData(data: Any) -> QualificationArchiveData: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationArchiveData' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationArchiveData(**args) + + +def unmarshal_QualificationContainer(data: Any) -> QualificationContainer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationContainer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationContainer(**args) + + +def unmarshal_QualificationDeploySoftware(data: Any) -> QualificationDeploySoftware: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationDeploySoftware' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationDeploySoftware(**args) + + +def unmarshal_QualificationHostApplication(data: Any) -> QualificationHostApplication: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationHostApplication' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationHostApplication(**args) + + +def unmarshal_QualificationHostWebsite(data: Any) -> QualificationHostWebsite: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationHostWebsite' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationHostWebsite(**args) + + +def unmarshal_QualificationOtherUseCase(data: Any) -> QualificationOtherUseCase: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationOtherUseCase' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationOtherUseCase(**args) + + +def unmarshal_QualificationSetScalewayEnvironment( + data: Any, +) -> QualificationSetScalewayEnvironment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationSetScalewayEnvironment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationSetScalewayEnvironment(**args) + + +def unmarshal_QualificationShareData(data: Any) -> QualificationShareData: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationShareData' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationShareData(**args) + + +def unmarshal_Qualification(data: Any) -> Qualification: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Qualification' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("architecture_type", None) + if field is not None: + args["architecture_type"] = field + + field = data.get("host_website", None) + if field is not None: + args["host_website"] = unmarshal_QualificationHostWebsite(field) + else: + args["host_website"] = None + + field = data.get("host_application", None) + if field is not None: + args["host_application"] = unmarshal_QualificationHostApplication(field) + else: + args["host_application"] = None + + field = data.get("deploy_software", None) + if field is not None: + args["deploy_software"] = unmarshal_QualificationDeploySoftware(field) + else: + args["deploy_software"] = None + + field = data.get("set_scaleway_environment", None) + if field is not None: + args["set_scaleway_environment"] = ( + unmarshal_QualificationSetScalewayEnvironment(field) + ) + else: + args["set_scaleway_environment"] = None + + field = data.get("ai_machine", None) + if field is not None: + args["ai_machine"] = unmarshal_QualificationAiMachine(field) + else: + args["ai_machine"] = None + + field = data.get("container", None) + if field is not None: + args["container"] = unmarshal_QualificationContainer(field) + else: + args["container"] = None + + field = data.get("archive_data", None) + if field is not None: + args["archive_data"] = unmarshal_QualificationArchiveData(field) + else: + args["archive_data"] = None + + field = data.get("share_data", None) + if field is not None: + args["share_data"] = unmarshal_QualificationShareData(field) + else: + args["share_data"] = None + + field = data.get("other_use_case", None) + if field is not None: + args["other_use_case"] = unmarshal_QualificationOtherUseCase(field) + else: + args["other_use_case"] = None + + return Qualification(**args) + + def unmarshal_Project(data: Any) -> Project: if not isinstance(data, dict): raise TypeError( @@ -40,14 +352,70 @@ def unmarshal_Project(data: Any) -> Project: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("qualification", None) + if field is not None: + args["qualification"] = unmarshal_Qualification(field) + else: + args["qualification"] = None return Project(**args) +def unmarshal_CheckContractSignatureResponse( + data: Any, +) -> CheckContractSignatureResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckContractSignatureResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("created", None) + if field is not None: + args["created"] = field + + field = data.get("validated", None) + if field is not None: + args["validated"] = field + + return CheckContractSignatureResponse(**args) + + +def unmarshal_ListContractSignaturesResponse( + data: Any, +) -> ListContractSignaturesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListContractSignaturesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("contract_signatures", None) + if field is not None: + args["contract_signatures"] = ( + [unmarshal_ContractSignature(v) for v in field] + if field is not None + else None + ) + + return ListContractSignaturesResponse(**args) + + def unmarshal_ListProjectsResponse(data: Any) -> ListProjectsResponse: if not isinstance(data, dict): raise TypeError( @@ -69,6 +437,70 @@ def unmarshal_ListProjectsResponse(data: Any) -> ListProjectsResponse: return ListProjectsResponse(**args) +def unmarshal_ProjectQualification(data: Any) -> ProjectQualification: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectQualification' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("qualification", None) + if field is not None: + args["qualification"] = unmarshal_Qualification(field) + else: + args["qualification"] = None + + return ProjectQualification(**args) + + +def marshal_ContractApiCheckContractSignatureRequest( + request: ContractApiCheckContractSignatureRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.contract_name is not None: + output["contract_name"] = request.contract_name + + if request.organization_id is not None: + output["organization_id"] = ( + request.organization_id or defaults.default_organization_id + ) + + if request.contract_type is not None: + output["contract_type"] = str(request.contract_type) + + return output + + +def marshal_ContractApiCreateContractSignatureRequest( + request: ContractApiCreateContractSignatureRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.contract_name is not None: + output["contract_name"] = request.contract_name + + if request.validated is not None: + output["validated"] = request.validated + + if request.contract_type is not None: + output["contract_type"] = str(request.contract_type) + + if request.organization_id is not None: + output["organization_id"] = ( + request.organization_id or defaults.default_organization_id + ) + + return output + + def marshal_ProjectApiCreateProjectRequest( request: ProjectApiCreateProjectRequest, defaults: ProfileDefaults, @@ -89,6 +521,155 @@ def marshal_ProjectApiCreateProjectRequest( return output +def marshal_QualificationAiMachine( + request: QualificationAiMachine, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationArchiveData( + request: QualificationArchiveData, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationContainer( + request: QualificationContainer, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationDeploySoftware( + request: QualificationDeploySoftware, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationHostApplication( + request: QualificationHostApplication, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationHostWebsite( + request: QualificationHostWebsite, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationOtherUseCase( + request: QualificationOtherUseCase, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationSetScalewayEnvironment( + request: QualificationSetScalewayEnvironment, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationShareData( + request: QualificationShareData, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_Qualification( + request: Qualification, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("host_website", request.host_website), + OneOfPossibility("host_application", request.host_application), + OneOfPossibility("deploy_software", request.deploy_software), + OneOfPossibility( + "set_scaleway_environment", request.set_scaleway_environment + ), + OneOfPossibility("ai_machine", request.ai_machine), + OneOfPossibility("container", request.container), + OneOfPossibility("archive_data", request.archive_data), + OneOfPossibility("share_data", request.share_data), + OneOfPossibility("other_use_case", request.other_use_case), + ] + ), + ) + + if request.architecture_type is not None: + output["architecture_type"] = str(request.architecture_type) + + return output + + +def marshal_ProjectApiSetProjectQualificationRequest( + request: ProjectApiSetProjectQualificationRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.qualification is not None: + output["qualification"] = marshal_Qualification(request.qualification, defaults) + + return output + + def marshal_ProjectApiUpdateProjectRequest( request: ProjectApiUpdateProjectRequest, defaults: ProfileDefaults, diff --git a/scaleway-async/scaleway_async/account/v3/types.py b/scaleway-async/scaleway_async/account/v3/types.py index 915bdd22..d8c33ddd 100644 --- a/scaleway-async/scaleway_async/account/v3/types.py +++ b/scaleway-async/scaleway_async/account/v3/types.py @@ -11,6 +11,34 @@ StrEnumMeta, ) +from ...std.types import ( + LanguageCode as StdLanguageCode, +) + + +class ContractType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + GLOBAL = "global" + K8S = "k8s" + INSTANCE = "instance" + CONTAINER = "container" + BAREMETAL = "baremetal" + + def __str__(self) -> str: + return str(self.value) + + +class ListContractSignaturesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + SIGNED_AT_ASC = "signed_at_asc" + SIGNED_AT_DESC = "signed_at_desc" + EXPIRES_AT_ASC = "expires_at_asc" + EXPIRES_AT_DESC = "expires_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + class ListProjectsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" @@ -22,6 +50,227 @@ def __str__(self) -> str: return str(self.value) +class QualificationAiMachineSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationArchitectureType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ARCHITECTURE_TYPE = "unknown_architecture_type" + OBJECT_STORAGE = "object_storage" + WEB_HOSTING = "web_hosting" + INSTANCE = "instance" + ELASTIC = "elastic" + KUBERNETES = "kubernetes" + SERVERLESS = "serverless" + DEDICATED_SERVER = "dedicated_server" + OTHER_ARCHITECTURE_TYPE = "other_architecture_type" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationArchiveDataSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationContainerSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationDeploySoftwareSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationHostApplicationSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + SAAS_APP = "saas_app" + GOVERNMENT_APP = "government_app" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationHostWebsiteSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + INFORMATION_WEBSITE = "information_website" + ECOMMERCE_WEBSITE = "ecommerce_website" + HIGH_WEBSITE = "high_website" + OTHER_SUB_USE_CASE = "other_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationOtherUseCaseSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationSetScalewayEnvironmentSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationShareDataSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class QualificationAiMachine: + sub_use_case: QualificationAiMachineSubUseCase + + +@dataclass +class QualificationArchiveData: + sub_use_case: QualificationArchiveDataSubUseCase + + +@dataclass +class QualificationContainer: + sub_use_case: QualificationContainerSubUseCase + + +@dataclass +class QualificationDeploySoftware: + sub_use_case: QualificationDeploySoftwareSubUseCase + + +@dataclass +class QualificationHostApplication: + sub_use_case: QualificationHostApplicationSubUseCase + + +@dataclass +class QualificationHostWebsite: + sub_use_case: QualificationHostWebsiteSubUseCase + + +@dataclass +class QualificationOtherUseCase: + sub_use_case: QualificationOtherUseCaseSubUseCase + + +@dataclass +class QualificationSetScalewayEnvironment: + sub_use_case: QualificationSetScalewayEnvironmentSubUseCase + + +@dataclass +class QualificationShareData: + sub_use_case: QualificationShareDataSubUseCase + + +@dataclass +class Contract: + id: str + """ + ID of the contract. + """ + + type_: ContractType + """ + The type of the contract. + """ + + name: str + """ + The name of the contract. + """ + + version: int + """ + The version of the contract. + """ + + created_at: Optional[datetime] + """ + The creation date of the contract. + """ + + updated_at: Optional[datetime] + """ + The last modification date of the contract. + """ + + +@dataclass +class Qualification: + architecture_type: QualificationArchitectureType + """ + Architecture type of the qualification. + """ + + host_website: Optional[QualificationHostWebsite] + + host_application: Optional[QualificationHostApplication] + + deploy_software: Optional[QualificationDeploySoftware] + + set_scaleway_environment: Optional[QualificationSetScalewayEnvironment] + + ai_machine: Optional[QualificationAiMachine] + + container: Optional[QualificationContainer] + + archive_data: Optional[QualificationArchiveData] + + share_data: Optional[QualificationShareData] + + other_use_case: Optional[QualificationOtherUseCase] + + +@dataclass +class ContractSignature: + id: str + """ + ID of the contract signature. + """ + + organization_id: str + """ + The Organization ID which signed the contract. + """ + + created_at: Optional[datetime] + """ + The creation date of the contract signature. + """ + + signed_at: Optional[datetime] + """ + The signing date of the contract signature. + """ + + expires_at: Optional[datetime] + """ + The expiration date of the contract signature. + """ + + contract: Optional[Contract] + """ + The contract signed. + """ + + @dataclass class Project: id: str @@ -54,6 +303,122 @@ class Project: Update date of the Project. """ + qualification: Optional[Qualification] + """ + Qualification of the Project. + """ + + +@dataclass +class CheckContractSignatureResponse: + created: bool + """ + Whether a signature has been requested for this contract. + """ + + validated: bool + """ + Whether the signature for this contract has been validated. + """ + + +@dataclass +class ContractApiCheckContractSignatureRequest: + contract_name: str + """ + Filter on contract name. + """ + + organization_id: Optional[str] + """ + ID of the Organization to check the contract signature for. + """ + + contract_type: Optional[ContractType] + """ + Filter on contract type. + """ + + +@dataclass +class ContractApiCreateContractSignatureRequest: + contract_name: str + """ + The name of the contract. + """ + + validated: bool + """ + Whether the contract is validated at creation. + """ + + contract_type: Optional[ContractType] + """ + The type of the contract. + """ + + organization_id: Optional[str] + """ + ID of the Organization. + """ + + +@dataclass +class ContractApiDownloadContractSignatureRequest: + contract_signature_id: str + """ + The contract signature ID. + """ + + locale: Optional[StdLanguageCode] + """ + The locale requested for the content of the contract. + """ + + +@dataclass +class ContractApiListContractSignaturesRequest: + page: Optional[int] + """ + The page number for the returned contracts. + """ + + page_size: Optional[int] + """ + The maximum number of contracts per page. + """ + + order_by: Optional[ListContractSignaturesRequestOrderBy] + """ + How the contracts are ordered in the response. + """ + + organization_id: Optional[str] + """ + Filter on Organization ID. + """ + + +@dataclass +class ContractApiValidateContractSignatureRequest: + contract_signature_id: str + """ + The contract linked to your Organization you want to sign. + """ + + +@dataclass +class ListContractSignaturesResponse: + total_count: int + """ + The total number of contract signatures. + """ + + contract_signatures: List[ContractSignature] + """ + The paginated returned contract signatures. + """ + @dataclass class ListProjectsResponse: @@ -135,6 +500,19 @@ class ProjectApiListProjectsRequest: """ +@dataclass +class ProjectApiSetProjectQualificationRequest: + project_id: Optional[str] + """ + Project ID. + """ + + qualification: Optional[Qualification] + """ + Use case chosen for the Project. + """ + + @dataclass class ProjectApiUpdateProjectRequest: project_id: Optional[str] @@ -151,3 +529,16 @@ class ProjectApiUpdateProjectRequest: """ Description of the Project. """ + + +@dataclass +class ProjectQualification: + project_id: str + """ + Project ID. + """ + + qualification: Optional[Qualification] + """ + Qualification of the Project. + """ diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/__init__.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/__init__.py index fed91efc..e50c753f 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/__init__.py @@ -1,55 +1,107 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import CommitmentType +from .types import ConnectivityDiagnosticActionType +from .types import ConnectivityDiagnosticDiagnosticStatus +from .types import ListServerPrivateNetworksRequestOrderBy from .types import ListServersRequestOrderBy +from .types import ServerPrivateNetworkServerStatus +from .content import SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES +from .types import ServerPrivateNetworkStatus +from .content import SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES from .types import ServerStatus from .content import SERVER_TRANSIENT_STATUSES from .types import ServerTypeStock +from .types import OS from .types import ServerTypeCPU from .types import ServerTypeDisk +from .types import ServerTypeGPU from .types import ServerTypeMemory -from .types import OS +from .types import ServerTypeNetwork +from .types import Commitment +from .types import ConnectivityDiagnosticServerHealth +from .types import ServerPrivateNetwork from .types import ServerType from .types import Server +from .types import CommitmentTypeValue +from .types import ConnectivityDiagnostic from .types import CreateServerRequest from .types import DeleteServerRequest +from .types import GetConnectivityDiagnosticRequest from .types import GetOSRequest from .types import GetServerRequest from .types import GetServerTypeRequest from .types import ListOSRequest from .types import ListOSResponse +from .types import ListServerPrivateNetworksResponse from .types import ListServerTypesRequest from .types import ListServerTypesResponse from .types import ListServersRequest from .types import ListServersResponse +from .types import PrivateNetworkApiAddServerPrivateNetworkRequest +from .types import PrivateNetworkApiDeleteServerPrivateNetworkRequest +from .types import PrivateNetworkApiGetServerPrivateNetworkRequest +from .types import PrivateNetworkApiListServerPrivateNetworksRequest +from .types import PrivateNetworkApiSetServerPrivateNetworksRequest from .types import RebootServerRequest from .types import ReinstallServerRequest +from .types import SetServerPrivateNetworksResponse +from .types import StartConnectivityDiagnosticRequest +from .types import StartConnectivityDiagnosticResponse from .types import UpdateServerRequest from .api import ApplesiliconV1Alpha1API +from .api import ApplesiliconV1Alpha1PrivateNetworkAPI __all__ = [ + "CommitmentType", + "ConnectivityDiagnosticActionType", + "ConnectivityDiagnosticDiagnosticStatus", + "ListServerPrivateNetworksRequestOrderBy", "ListServersRequestOrderBy", + "ServerPrivateNetworkServerStatus", + "SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES", + "ServerPrivateNetworkStatus", + "SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES", "ServerStatus", "SERVER_TRANSIENT_STATUSES", "ServerTypeStock", + "OS", "ServerTypeCPU", "ServerTypeDisk", + "ServerTypeGPU", "ServerTypeMemory", - "OS", + "ServerTypeNetwork", + "Commitment", + "ConnectivityDiagnosticServerHealth", + "ServerPrivateNetwork", "ServerType", "Server", + "CommitmentTypeValue", + "ConnectivityDiagnostic", "CreateServerRequest", "DeleteServerRequest", + "GetConnectivityDiagnosticRequest", "GetOSRequest", "GetServerRequest", "GetServerTypeRequest", "ListOSRequest", "ListOSResponse", + "ListServerPrivateNetworksResponse", "ListServerTypesRequest", "ListServerTypesResponse", "ListServersRequest", "ListServersResponse", + "PrivateNetworkApiAddServerPrivateNetworkRequest", + "PrivateNetworkApiDeleteServerPrivateNetworkRequest", + "PrivateNetworkApiGetServerPrivateNetworkRequest", + "PrivateNetworkApiListServerPrivateNetworksRequest", + "PrivateNetworkApiSetServerPrivateNetworksRequest", "RebootServerRequest", "ReinstallServerRequest", + "SetServerPrivateNetworksResponse", + "StartConnectivityDiagnosticRequest", + "StartConnectivityDiagnosticResponse", "UpdateServerRequest", "ApplesiliconV1Alpha1API", + "ApplesiliconV1Alpha1PrivateNetworkAPI", ] diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py index c358fbb2..15711479 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/api.py @@ -1,11 +1,11 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. -from typing import Awaitable, List, Optional, Union +from typing import Awaitable, Dict, List, Optional, Union from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, @@ -15,38 +15,62 @@ wait_for_resource_async, ) from .types import ( + CommitmentType, + ListServerPrivateNetworksRequestOrderBy, ListServersRequestOrderBy, + CommitmentTypeValue, + ConnectivityDiagnostic, CreateServerRequest, ListOSResponse, + ListServerPrivateNetworksResponse, ListServerTypesResponse, ListServersResponse, OS, + PrivateNetworkApiAddServerPrivateNetworkRequest, + PrivateNetworkApiSetServerPrivateNetworksRequest, + ReinstallServerRequest, Server, + ServerPrivateNetwork, ServerType, + SetServerPrivateNetworksResponse, + StartConnectivityDiagnosticRequest, + StartConnectivityDiagnosticResponse, UpdateServerRequest, ) from .content import ( + SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES, SERVER_TRANSIENT_STATUSES, ) from .marshalling import ( unmarshal_OS, + unmarshal_ServerPrivateNetwork, unmarshal_ServerType, unmarshal_Server, + unmarshal_ConnectivityDiagnostic, unmarshal_ListOSResponse, + unmarshal_ListServerPrivateNetworksResponse, unmarshal_ListServerTypesResponse, unmarshal_ListServersResponse, + unmarshal_SetServerPrivateNetworksResponse, + unmarshal_StartConnectivityDiagnosticResponse, marshal_CreateServerRequest, + marshal_PrivateNetworkApiAddServerPrivateNetworkRequest, + marshal_PrivateNetworkApiSetServerPrivateNetworksRequest, + marshal_ReinstallServerRequest, + marshal_StartConnectivityDiagnosticRequest, marshal_UpdateServerRequest, ) class ApplesiliconV1Alpha1API(API): - """ """ + """ + This API allows you to manage your Apple silicon machines. + """ async def list_server_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ListServerTypesResponse: """ List server types. @@ -74,7 +98,7 @@ async def get_server_type( self, *, server_type: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ServerType: """ Get a server type. @@ -106,17 +130,23 @@ async def create_server( self, *, type_: str, - zone: Optional[Zone] = None, + enable_vpc: bool, + zone: Optional[ScwZone] = None, name: Optional[str] = None, project_id: Optional[str] = None, + os_id: Optional[str] = None, + commitment_type: Optional[CommitmentType] = None, ) -> Server: """ Create a server. Create a new server in the targeted zone, specifying its configuration including name and type. :param type_: Create a server of the given type. + :param enable_vpc: Activate the Private Network feature for this server. This feature is configured through the Apple Silicon - Private Networks API. :param zone: Zone to target. If none is passed will use default zone from the config. :param name: Create a server with this given name. :param project_id: Create a server in the given project ID. + :param os_id: Create a server & install the given os_id, when no os_id provided the default OS for this server type is chosen. Requesting a non-default OS will induce an extended delivery time. + :param commitment_type: Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing (commitment_type `duration_24h`). It can be updated with the Update Server request. Available commitment depends on server type. :return: :class:`Server ` Usage: @@ -124,6 +154,7 @@ async def create_server( result = await api.create_server( type="example", + enable_vpc=False, ) """ @@ -135,9 +166,12 @@ async def create_server( body=marshal_CreateServerRequest( CreateServerRequest( type_=type_, + enable_vpc=enable_vpc, zone=zone, name=name or random_name(prefix="as"), project_id=project_id, + os_id=os_id, + commitment_type=commitment_type, ), self.client, ), @@ -149,7 +183,7 @@ async def create_server( async def list_servers( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListServersRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -194,7 +228,7 @@ async def list_servers( async def list_servers_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListServersRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -235,7 +269,7 @@ async def list_servers_all( async def list_os( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, server_type: Optional[str] = None, @@ -276,7 +310,7 @@ async def list_os( async def list_os_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, server_type: Optional[str] = None, @@ -315,7 +349,7 @@ async def get_os( self, *, os_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> OS: """ Get an Operating System (OS). @@ -347,7 +381,7 @@ async def get_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Get a server. @@ -379,7 +413,7 @@ async def wait_for_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Server, Union[bool, Awaitable[bool]]]] = None, ) -> Server: """ @@ -416,8 +450,11 @@ async def update_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, + schedule_deletion: Optional[bool] = None, + enable_vpc: Optional[bool] = None, + commitment_type: Optional[CommitmentTypeValue] = None, ) -> Server: """ Update a server. @@ -425,6 +462,9 @@ async def update_server( :param server_id: UUID of the server you want to update. :param zone: Zone to target. If none is passed will use default zone from the config. :param name: Updated name for your server. + :param schedule_deletion: Specify whether the server should be flagged for automatic deletion. + :param enable_vpc: Activate or deactivate Private Network support for this server. + :param commitment_type: Change commitment. Use 'none' to automatically cancel a renewing commitment. :return: :class:`Server ` Usage: @@ -446,6 +486,9 @@ async def update_server( server_id=server_id, zone=zone, name=name, + schedule_deletion=schedule_deletion, + enable_vpc=enable_vpc, + commitment_type=commitment_type, ), self.client, ), @@ -458,7 +501,7 @@ async def delete_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a server. @@ -488,7 +531,7 @@ async def reboot_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Reboot a server. @@ -521,13 +564,15 @@ async def reinstall_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, + os_id: Optional[str] = None, ) -> Server: """ Reinstall a server. Reinstall an existing Apple silicon server (specified by its server ID) from a new image (OS). All the data on the disk is deleted and all configuration is reset to the defailt configuration values of the image (OS). :param server_id: UUID of the server you want to reinstall. :param zone: Zone to target. If none is passed will use default zone from the config. + :param os_id: Reinstall the server with the target OS, when no os_id provided the default OS for the server type is used. :return: :class:`Server ` Usage: @@ -544,8 +589,395 @@ async def reinstall_server( res = self._request( "POST", f"/apple-silicon/v1alpha1/zones/{param_zone}/servers/{param_server_id}/reinstall", - body={}, + body=marshal_ReinstallServerRequest( + ReinstallServerRequest( + server_id=server_id, + zone=zone, + os_id=os_id, + ), + self.client, + ), ) self._throw_on_error(res) return unmarshal_Server(res.json()) + + async def start_connectivity_diagnostic( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> StartConnectivityDiagnosticResponse: + """ + :param server_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`StartConnectivityDiagnosticResponse ` + + Usage: + :: + + result = await api.start_connectivity_diagnostic( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/apple-silicon/v1alpha1/zones/{param_zone}/connectivity-diagnostics", + body=marshal_StartConnectivityDiagnosticRequest( + StartConnectivityDiagnosticRequest( + server_id=server_id, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_StartConnectivityDiagnosticResponse(res.json()) + + async def get_connectivity_diagnostic( + self, + *, + diagnostic_id: str, + zone: Optional[ScwZone] = None, + ) -> ConnectivityDiagnostic: + """ + :param diagnostic_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ConnectivityDiagnostic ` + + Usage: + :: + + result = await api.get_connectivity_diagnostic( + diagnostic_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_diagnostic_id = validate_path_param("diagnostic_id", diagnostic_id) + + res = self._request( + "GET", + f"/apple-silicon/v1alpha1/zones/{param_zone}/connectivity-diagnostics/{param_diagnostic_id}", + ) + + self._throw_on_error(res) + return unmarshal_ConnectivityDiagnostic(res.json()) + + +class ApplesiliconV1Alpha1PrivateNetworkAPI(API): + """ + Apple silicon - Private Networks API. + """ + + async def get_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + ) -> ServerPrivateNetwork: + """ + :param server_id: + :param private_network_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerPrivateNetwork ` + + Usage: + :: + + result = await api.get_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + param_private_network_id = validate_path_param( + "private_network_id", private_network_id + ) + + res = self._request( + "GET", + f"/apple-silicon/v1alpha1/zones/{param_zone}/servers/{param_server_id}/private-networks/{param_private_network_id}", + ) + + self._throw_on_error(res) + return unmarshal_ServerPrivateNetwork(res.json()) + + async def wait_for_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + options: Optional[ + WaitForOptions[ServerPrivateNetwork, Union[bool, Awaitable[bool]]] + ] = None, + ) -> ServerPrivateNetwork: + """ + :param server_id: + :param private_network_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerPrivateNetwork ` + + Usage: + :: + + result = await api.get_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status + not in SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES + ) + + return await wait_for_resource_async( + fetcher=self.get_server_private_network, + options=options, + args={ + "server_id": server_id, + "private_network_id": private_network_id, + "zone": zone, + }, + ) + + async def add_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> ServerPrivateNetwork: + """ + Add a server to a Private Network. + Add an Apple silicon server to a Private Network. + :param server_id: ID of the server. + :param private_network_id: ID of the Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param ipam_ip_ids: IPAM IDs of IPs to attach to the server. + :return: :class:`ServerPrivateNetwork ` + + Usage: + :: + + result = await api.add_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/apple-silicon/v1alpha1/zones/{param_zone}/servers/{param_server_id}/private-networks", + body=marshal_PrivateNetworkApiAddServerPrivateNetworkRequest( + PrivateNetworkApiAddServerPrivateNetworkRequest( + server_id=server_id, + private_network_id=private_network_id, + zone=zone, + ipam_ip_ids=ipam_ip_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ServerPrivateNetwork(res.json()) + + async def set_server_private_networks( + self, + *, + server_id: str, + per_private_network_ipam_ip_ids: Dict[str, List[str]], + zone: Optional[ScwZone] = None, + ) -> SetServerPrivateNetworksResponse: + """ + Set multiple Private Networks on a server. + Configure multiple Private Networks on an Apple silicon server. + :param server_id: ID of the server. + :param per_private_network_ipam_ip_ids: Object where the keys are the IDs of Private Networks and the values are arrays of IPAM IDs representing the IPs to assign to this Apple silicon server on the Private Network. If the array supplied for a Private Network is empty, the next available IP from the Private Network's CIDR block will automatically be used for attachment. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`SetServerPrivateNetworksResponse ` + + Usage: + :: + + result = await api.set_server_private_networks( + server_id="example", + per_private_network_ipam_ip_ids={}, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "PUT", + f"/apple-silicon/v1alpha1/zones/{param_zone}/servers/{param_server_id}/private-networks", + body=marshal_PrivateNetworkApiSetServerPrivateNetworksRequest( + PrivateNetworkApiSetServerPrivateNetworksRequest( + server_id=server_id, + per_private_network_ipam_ip_ids=per_private_network_ipam_ip_ids, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetServerPrivateNetworksResponse(res.json()) + + async def list_server_private_networks( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + server_id: Optional[str] = None, + private_network_id: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> ListServerPrivateNetworksResponse: + """ + List the Private Networks of a server. + List the Private Networks of an Apple silicon server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order for the returned Private Networks. + :param page: Page number for the returned Private Networks. + :param page_size: Maximum number of Private Networks per page. + :param server_id: Filter Private Networks by server ID. + :param private_network_id: Filter Private Networks by Private Network ID. + :param organization_id: Filter Private Networks by Organization ID. + :param project_id: Filter Private Networks by Project ID. + :param ipam_ip_ids: Filter Private Networks by IPAM IP IDs. + :return: :class:`ListServerPrivateNetworksResponse ` + + Usage: + :: + + result = await api.list_server_private_networks() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/apple-silicon/v1alpha1/zones/{param_zone}/server-private-networks", + params={ + "ipam_ip_ids": ipam_ip_ids, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "private_network_id": private_network_id, + "project_id": project_id or self.client.default_project_id, + "server_id": server_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServerPrivateNetworksResponse(res.json()) + + async def list_server_private_networks_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + server_id: Optional[str] = None, + private_network_id: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> List[ServerPrivateNetwork]: + """ + List the Private Networks of a server. + List the Private Networks of an Apple silicon server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order for the returned Private Networks. + :param page: Page number for the returned Private Networks. + :param page_size: Maximum number of Private Networks per page. + :param server_id: Filter Private Networks by server ID. + :param private_network_id: Filter Private Networks by Private Network ID. + :param organization_id: Filter Private Networks by Organization ID. + :param project_id: Filter Private Networks by Project ID. + :param ipam_ip_ids: Filter Private Networks by IPAM IP IDs. + :return: :class:`List[ServerPrivateNetwork] ` + + Usage: + :: + + result = await api.list_server_private_networks_all() + """ + + return await fetch_all_pages_async( + type=ListServerPrivateNetworksResponse, + key="server_private_networks", + fetcher=self.list_server_private_networks, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "server_id": server_id, + "private_network_id": private_network_id, + "organization_id": organization_id, + "project_id": project_id, + "ipam_ip_ids": ipam_ip_ids, + }, + ) + + async def delete_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a Private Network. + :param server_id: ID of the server. + :param private_network_id: ID of the Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + param_private_network_id = validate_path_param( + "private_network_id", private_network_id + ) + + res = self._request( + "DELETE", + f"/apple-silicon/v1alpha1/zones/{param_zone}/servers/{param_server_id}/private-networks/{param_private_network_id}", + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/content.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/content.py index bac38d1e..d8118f9f 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/content.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/content.py @@ -3,9 +3,26 @@ from typing import List from .types import ( + ServerPrivateNetworkServerStatus, + ServerPrivateNetworkStatus, ServerStatus, ) +SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES: List[ + ServerPrivateNetworkServerStatus +] = [ + ServerPrivateNetworkServerStatus.ATTACHING, + ServerPrivateNetworkServerStatus.DETACHING, +] +""" +Lists transient statutes of the enum :class:`ServerPrivateNetworkServerStatus `. +""" +SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES: List[ServerPrivateNetworkStatus] = [ + ServerPrivateNetworkStatus.VPC_UPDATING, +] +""" +Lists transient statutes of the enum :class:`ServerPrivateNetworkStatus `. +""" SERVER_TRANSIENT_STATUSES: List[ServerStatus] = [ ServerStatus.STARTING, ServerStatus.REBOOTING, @@ -13,6 +30,7 @@ ServerStatus.LOCKING, ServerStatus.UNLOCKING, ServerStatus.REINSTALLING, + ServerStatus.BUSY, ] """ Lists transient statutes of the enum :class:`ServerStatus `. diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/marshalling.py index 4524d1c5..be75811b 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/marshalling.py @@ -6,16 +6,31 @@ from scaleway_core.profile import ProfileDefaults from .types import ( + ConnectivityDiagnosticActionType, OS, + ServerPrivateNetwork, ServerTypeCPU, ServerTypeDisk, + ServerTypeGPU, ServerTypeMemory, + ServerTypeNetwork, ServerType, + Commitment, Server, + ConnectivityDiagnosticServerHealth, + ConnectivityDiagnostic, ListOSResponse, + ListServerPrivateNetworksResponse, ListServerTypesResponse, ListServersResponse, + SetServerPrivateNetworksResponse, + StartConnectivityDiagnosticResponse, CreateServerRequest, + PrivateNetworkApiAddServerPrivateNetworkRequest, + PrivateNetworkApiSetServerPrivateNetworksRequest, + ReinstallServerRequest, + StartConnectivityDiagnosticRequest, + CommitmentTypeValue, UpdateServerRequest, ) @@ -44,6 +59,22 @@ def unmarshal_OS(data: Any) -> OS: if field is not None: args["image_url"] = field + field = data.get("family", None) + if field is not None: + args["family"] = field + + field = data.get("is_beta", None) + if field is not None: + args["is_beta"] = field + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("xcode_version", None) + if field is not None: + args["xcode_version"] = field + field = data.get("compatible_server_types", None) if field is not None: args["compatible_server_types"] = field @@ -51,6 +82,59 @@ def unmarshal_OS(data: Any) -> OS: return OS(**args) +def unmarshal_ServerPrivateNetwork(data: Any) -> ServerPrivateNetwork: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerPrivateNetwork' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("server_id", None) + if field is not None: + args["server_id"] = field + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("ipam_ip_ids", None) + if field is not None: + args["ipam_ip_ids"] = field + + field = data.get("vlan", None) + if field is not None: + args["vlan"] = field + else: + args["vlan"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return ServerPrivateNetwork(**args) + + def unmarshal_ServerTypeCPU(data: Any) -> ServerTypeCPU: if not isinstance(data, dict): raise TypeError( @@ -67,6 +151,10 @@ def unmarshal_ServerTypeCPU(data: Any) -> ServerTypeCPU: if field is not None: args["core_count"] = field + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + return ServerTypeCPU(**args) @@ -82,13 +170,28 @@ def unmarshal_ServerTypeDisk(data: Any) -> ServerTypeDisk: if field is not None: args["capacity"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field return ServerTypeDisk(**args) +def unmarshal_ServerTypeGPU(data: Any) -> ServerTypeGPU: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerTypeGPU' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("count", None) + if field is not None: + args["count"] = field + + return ServerTypeGPU(**args) + + def unmarshal_ServerTypeMemory(data: Any) -> ServerTypeMemory: if not isinstance(data, dict): raise TypeError( @@ -101,13 +204,28 @@ def unmarshal_ServerTypeMemory(data: Any) -> ServerTypeMemory: if field is not None: args["capacity"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field return ServerTypeMemory(**args) +def unmarshal_ServerTypeNetwork(data: Any) -> ServerTypeNetwork: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerTypeNetwork' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("public_bandwidth_bps", None) + if field is not None: + args["public_bandwidth_bps"] = field + + return ServerTypeNetwork(**args) + + def unmarshal_ServerType(data: Any) -> ServerType: if not isinstance(data, dict): raise TypeError( @@ -127,22 +245,67 @@ def unmarshal_ServerType(data: Any) -> ServerType: field = data.get("cpu", None) if field is not None: args["cpu"] = unmarshal_ServerTypeCPU(field) + else: + args["cpu"] = None field = data.get("disk", None) if field is not None: args["disk"] = unmarshal_ServerTypeDisk(field) + else: + args["disk"] = None field = data.get("memory", None) if field is not None: args["memory"] = unmarshal_ServerTypeMemory(field) + else: + args["memory"] = None field = data.get("minimum_lease_duration", None) if field is not None: args["minimum_lease_duration"] = field + else: + args["minimum_lease_duration"] = None + + field = data.get("gpu", None) + if field is not None: + args["gpu"] = unmarshal_ServerTypeGPU(field) + else: + args["gpu"] = None + + field = data.get("network", None) + if field is not None: + args["network"] = unmarshal_ServerTypeNetwork(field) + else: + args["network"] = None + + field = data.get("default_os", None) + if field is not None: + args["default_os"] = unmarshal_OS(field) + else: + args["default_os"] = None return ServerType(**args) +def unmarshal_Commitment(data: Any) -> Commitment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Commitment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("cancelled", None) + if field is not None: + args["cancelled"] = field + + return Commitment(**args) + + def unmarshal_Server(data: Any) -> Server: if not isinstance(data, dict): raise TypeError( @@ -155,7 +318,7 @@ def unmarshal_Server(data: Any) -> Server: if field is not None: args["id"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -179,31 +342,155 @@ def unmarshal_Server(data: Any) -> Server: if field is not None: args["vnc_url"] = field + field = data.get("ssh_username", None) + if field is not None: + args["ssh_username"] = field + + field = data.get("sudo_password", None) + if field is not None: + args["sudo_password"] = field + + field = data.get("vnc_port", None) + if field is not None: + args["vnc_port"] = field + field = data.get("status", None) if field is not None: args["status"] = field - field = data.get("zone", None) + field = data.get("os", None) if field is not None: - args["zone"] = field + args["os"] = unmarshal_OS(field) + else: + args["os"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("deletable_at", None) if field is not None: args["deletable_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["deletable_at"] = None + + field = data.get("deletion_scheduled", None) + if field is not None: + args["deletion_scheduled"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("delivered", None) + if field is not None: + args["delivered"] = field + + field = data.get("vpc_status", None) + if field is not None: + args["vpc_status"] = field + + field = data.get("commitment", None) + if field is not None: + args["commitment"] = unmarshal_Commitment(field) + else: + args["commitment"] = None return Server(**args) +def unmarshal_ConnectivityDiagnosticServerHealth( + data: Any, +) -> ConnectivityDiagnosticServerHealth: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ConnectivityDiagnosticServerHealth' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_server_alive", None) + if field is not None: + args["is_server_alive"] = field + + field = data.get("is_agent_alive", None) + if field is not None: + args["is_agent_alive"] = field + + field = data.get("is_mdm_alive", None) + if field is not None: + args["is_mdm_alive"] = field + + field = data.get("is_ssh_port_up", None) + if field is not None: + args["is_ssh_port_up"] = field + + field = data.get("is_vnc_port_up", None) + if field is not None: + args["is_vnc_port_up"] = field + + field = data.get("last_checkin_date", None) + if field is not None: + args["last_checkin_date"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["last_checkin_date"] = None + + return ConnectivityDiagnosticServerHealth(**args) + + +def unmarshal_ConnectivityDiagnostic(data: Any) -> ConnectivityDiagnostic: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ConnectivityDiagnostic' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("is_healthy", None) + if field is not None: + args["is_healthy"] = field + + field = data.get("supported_actions", None) + if field is not None: + args["supported_actions"] = ( + [ConnectivityDiagnosticActionType(v) for v in field] + if field is not None + else None + ) + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + + field = data.get("health_details", None) + if field is not None: + args["health_details"] = unmarshal_ConnectivityDiagnosticServerHealth(field) + else: + args["health_details"] = None + + return ConnectivityDiagnostic(**args) + + def unmarshal_ListOSResponse(data: Any) -> ListOSResponse: if not isinstance(data, dict): raise TypeError( @@ -223,6 +510,31 @@ def unmarshal_ListOSResponse(data: Any) -> ListOSResponse: return ListOSResponse(**args) +def unmarshal_ListServerPrivateNetworksResponse( + data: Any, +) -> ListServerPrivateNetworksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServerPrivateNetworksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("server_private_networks", None) + if field is not None: + args["server_private_networks"] = ( + [unmarshal_ServerPrivateNetwork(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListServerPrivateNetworksResponse(**args) + + def unmarshal_ListServerTypesResponse(data: Any) -> ListServerTypesResponse: if not isinstance(data, dict): raise TypeError( @@ -261,6 +573,44 @@ def unmarshal_ListServersResponse(data: Any) -> ListServersResponse: return ListServersResponse(**args) +def unmarshal_SetServerPrivateNetworksResponse( + data: Any, +) -> SetServerPrivateNetworksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetServerPrivateNetworksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("server_private_networks", None) + if field is not None: + args["server_private_networks"] = ( + [unmarshal_ServerPrivateNetwork(v) for v in field] + if field is not None + else None + ) + + return SetServerPrivateNetworksResponse(**args) + + +def unmarshal_StartConnectivityDiagnosticResponse( + data: Any, +) -> StartConnectivityDiagnosticResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'StartConnectivityDiagnosticResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("diagnostic_id", None) + if field is not None: + args["diagnostic_id"] = field + + return StartConnectivityDiagnosticResponse(**args) + + def marshal_CreateServerRequest( request: CreateServerRequest, defaults: ProfileDefaults, @@ -270,12 +620,86 @@ def marshal_CreateServerRequest( if request.type_ is not None: output["type"] = request.type_ + if request.enable_vpc is not None: + output["enable_vpc"] = request.enable_vpc + if request.name is not None: output["name"] = request.name if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id + if request.os_id is not None: + output["os_id"] = request.os_id + + if request.commitment_type is not None: + output["commitment_type"] = str(request.commitment_type) + + return output + + +def marshal_PrivateNetworkApiAddServerPrivateNetworkRequest( + request: PrivateNetworkApiAddServerPrivateNetworkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + if request.ipam_ip_ids is not None: + output["ipam_ip_ids"] = request.ipam_ip_ids + + return output + + +def marshal_PrivateNetworkApiSetServerPrivateNetworksRequest( + request: PrivateNetworkApiSetServerPrivateNetworksRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.per_private_network_ipam_ip_ids is not None: + output["per_private_network_ipam_ip_ids"] = { + key: value for key, value in request.per_private_network_ipam_ip_ids.items() + } + + return output + + +def marshal_ReinstallServerRequest( + request: ReinstallServerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.os_id is not None: + output["os_id"] = request.os_id + + return output + + +def marshal_StartConnectivityDiagnosticRequest( + request: StartConnectivityDiagnosticRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.server_id is not None: + output["server_id"] = request.server_id + + return output + + +def marshal_CommitmentTypeValue( + request: CommitmentTypeValue, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.commitment_type is not None: + output["commitment_type"] = str(request.commitment_type) + return output @@ -288,4 +712,15 @@ def marshal_UpdateServerRequest( if request.name is not None: output["name"] = request.name + if request.schedule_deletion is not None: + output["schedule_deletion"] = request.schedule_deletion + + if request.enable_vpc is not None: + output["enable_vpc"] = request.enable_vpc + + if request.commitment_type is not None: + output["commitment_type"] = marshal_CommitmentTypeValue( + request.commitment_type, defaults + ) + return output diff --git a/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py b/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py index 79291bad..692f3e59 100644 --- a/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/applesilicon/v1alpha1/types.py @@ -5,16 +5,53 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import List, Optional +from typing import Dict, List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, ) +class CommitmentType(str, Enum, metaclass=StrEnumMeta): + DURATION_24H = "duration_24h" + RENEWED_MONTHLY = "renewed_monthly" + NONE = "none" + + def __str__(self) -> str: + return str(self.value) + + +class ConnectivityDiagnosticActionType(str, Enum, metaclass=StrEnumMeta): + REBOOT_SERVER = "reboot_server" + REINSTALL_SERVER = "reinstall_server" + + def __str__(self) -> str: + return str(self.value) + + +class ConnectivityDiagnosticDiagnosticStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + PROCESSING = "processing" + ERROR = "error" + COMPLETED = "completed" + + def __str__(self) -> str: + return str(self.value) + + +class ListServerPrivateNetworksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + UPDATED_AT_ASC = "updated_at_asc" + UPDATED_AT_DESC = "updated_at_desc" + + def __str__(self) -> str: + return str(self.value) + + class ListServersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -23,6 +60,28 @@ def __str__(self) -> str: return str(self.value) +class ServerPrivateNetworkServerStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + ATTACHING = "attaching" + ATTACHED = "attached" + ERROR = "error" + DETACHING = "detaching" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class ServerPrivateNetworkStatus(str, Enum, metaclass=StrEnumMeta): + VPC_UNKNOWN_STATUS = "vpc_unknown_status" + VPC_ENABLED = "vpc_enabled" + VPC_UPDATING = "vpc_updating" + VPC_DISABLED = "vpc_disabled" + + def __str__(self) -> str: + return str(self.value) + + class ServerStatus(str, Enum, metaclass=StrEnumMeta): UNKNOWN_STATUS = "unknown_status" STARTING = "starting" @@ -34,6 +93,7 @@ class ServerStatus(str, Enum, metaclass=StrEnumMeta): LOCKED = "locked" UNLOCKING = "unlocking" REINSTALLING = "reinstalling" + BUSY = "busy" def __str__(self) -> str: return str(self.value) @@ -49,12 +109,62 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class OS: + id: str + """ + Unique ID of the OS. + """ + + name: str + """ + OS name. + """ + + label: str + """ + OS name as it should be displayed. + """ + + image_url: str + """ + URL of the image. + """ + + family: str + """ + The OS family to which this OS belongs, eg. 13 or 14. + """ + + is_beta: bool + """ + Describes if the OS is in beta. + """ + + version: str + """ + The OS version number, eg. Sonoma has version number 14.3. + """ + + xcode_version: str + """ + The current xcode version for this OS. + """ + + compatible_server_types: List[str] + """ + List of compatible server types. + """ + + @dataclass class ServerTypeCPU: name: str core_count: int + frequency: int + @dataclass class ServerTypeDisk: @@ -63,6 +173,11 @@ class ServerTypeDisk: type_: str +@dataclass +class ServerTypeGPU: + count: int + + @dataclass class ServerTypeMemory: capacity: int @@ -71,30 +186,77 @@ class ServerTypeMemory: @dataclass -class OS: +class ServerTypeNetwork: + public_bandwidth_bps: int + + +@dataclass +class Commitment: + type_: CommitmentType + + cancelled: bool + + +@dataclass +class ConnectivityDiagnosticServerHealth: + is_server_alive: bool + + is_agent_alive: bool + + is_mdm_alive: bool + + is_ssh_port_up: bool + + is_vnc_port_up: bool + + last_checkin_date: Optional[datetime] + + +@dataclass +class ServerPrivateNetwork: id: str """ - Unique ID of the OS. + ID of the Server-to-Private Network mapping. """ - name: str + project_id: str """ - OS name. + Private Network Project ID. """ - label: str + server_id: str """ - OS name as it should be displayed. + Apple silicon server ID. """ - image_url: str + private_network_id: str """ - URL of the image. + Private Network ID. """ - compatible_server_types: List[str] + status: ServerPrivateNetworkServerStatus """ - List of compatible server types. + Configuration status of the Private Network. + """ + + ipam_ip_ids: List[str] + """ + IPAM IP IDs of the server, if it has any. + """ + + vlan: Optional[int] + """ + ID of the VLAN associated with the Private Network. + """ + + created_at: Optional[datetime] + """ + Private Network creation date. + """ + + updated_at: Optional[datetime] + """ + Date the Private Network was last modified. """ @@ -130,6 +292,21 @@ class ServerType: Minimum duration of the lease in seconds (example. 3.4s). """ + gpu: Optional[ServerTypeGPU] + """ + GPU description. + """ + + network: Optional[ServerTypeNetwork] + """ + Network description. + """ + + default_os: Optional[OS] + """ + The default OS for this server type. + """ + @dataclass class Server: @@ -165,7 +342,22 @@ class Server: vnc_url: str """ - URL of the VNC. + Vnc:// URL to access Apple Remote Desktop. + """ + + ssh_username: str + """ + SSH Username for remote shell. + """ + + sudo_password: str + """ + Admin password required to execute commands. + """ + + vnc_port: int + """ + VNC port to use for remote desktop connection. """ status: ServerStatus @@ -173,9 +365,9 @@ class Server: Current status of the server. """ - zone: Zone + os: Optional[OS] """ - Zone of the server. + Initially installed OS, this does not necessarily reflect the current OS version. """ created_at: Optional[datetime] @@ -190,10 +382,55 @@ class Server: deletable_at: Optional[datetime] """ - Date on which the server was last deleted. + Date from which the server can be deleted. + """ + + deletion_scheduled: bool + """ + Set to true to mark the server for automatic deletion depending on `deletable_at` date. Set to false to cancel an existing deletion schedule. Leave unset otherwise. + """ + + zone: ScwZone + """ + Zone of the server. + """ + + delivered: bool + """ + Set to true once the server has completed its provisioning steps and is ready to use. Some OS configurations might require a reinstallation of the server before delivery depending on the available stock. A reinstallation after the initial delivery will not change this flag and can be tracked using the server status. + """ + + vpc_status: ServerPrivateNetworkStatus + """ + Activation status of optional Private Network feature support for this server. + """ + + commitment: Optional[Commitment] + """ + Commitment scheme applied to this server. """ +@dataclass +class CommitmentTypeValue: + commitment_type: CommitmentType + + +@dataclass +class ConnectivityDiagnostic: + id: str + + status: ConnectivityDiagnosticDiagnosticStatus + + is_healthy: bool + + supported_actions: List[ConnectivityDiagnosticActionType] + + error_message: str + + health_details: Optional[ConnectivityDiagnosticServerHealth] + + @dataclass class CreateServerRequest: type_: str @@ -201,7 +438,12 @@ class CreateServerRequest: Create a server of the given type. """ - zone: Optional[Zone] + enable_vpc: bool + """ + Activate the Private Network feature for this server. This feature is configured through the Apple Silicon - Private Networks API. + """ + + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -216,6 +458,16 @@ class CreateServerRequest: Create a server in the given project ID. """ + os_id: Optional[str] + """ + Create a server & install the given os_id, when no os_id provided the default OS for this server type is chosen. Requesting a non-default OS will induce an extended delivery time. + """ + + commitment_type: Optional[CommitmentType] + """ + Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing (commitment_type `duration_24h`). It can be updated with the Update Server request. Available commitment depends on server type. + """ + @dataclass class DeleteServerRequest: @@ -224,7 +476,17 @@ class DeleteServerRequest: UUID of the server you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetConnectivityDiagnosticRequest: + diagnostic_id: str + + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -237,7 +499,7 @@ class GetOSRequest: UUID of the OS you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -250,7 +512,7 @@ class GetServerRequest: UUID of the server you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -263,7 +525,7 @@ class GetServerTypeRequest: Server type identifier. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -271,7 +533,7 @@ class GetServerTypeRequest: @dataclass class ListOSRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -310,9 +572,16 @@ class ListOSResponse: """ +@dataclass +class ListServerPrivateNetworksResponse: + server_private_networks: List[ServerPrivateNetwork] + + total_count: int + + @dataclass class ListServerTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -328,7 +597,7 @@ class ListServerTypesResponse: @dataclass class ListServersRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -372,6 +641,125 @@ class ListServersResponse: """ +@dataclass +class PrivateNetworkApiAddServerPrivateNetworkRequest: + server_id: str + """ + ID of the server. + """ + + private_network_id: str + """ + ID of the Private Network. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + ipam_ip_ids: Optional[List[str]] + """ + IPAM IDs of IPs to attach to the server. + """ + + +@dataclass +class PrivateNetworkApiDeleteServerPrivateNetworkRequest: + server_id: str + """ + ID of the server. + """ + + private_network_id: str + """ + ID of the Private Network. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class PrivateNetworkApiGetServerPrivateNetworkRequest: + server_id: str + + private_network_id: str + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class PrivateNetworkApiListServerPrivateNetworksRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] + """ + Sort order for the returned Private Networks. + """ + + page: Optional[int] + """ + Page number for the returned Private Networks. + """ + + page_size: Optional[int] + """ + Maximum number of Private Networks per page. + """ + + server_id: Optional[str] + """ + Filter Private Networks by server ID. + """ + + private_network_id: Optional[str] + """ + Filter Private Networks by Private Network ID. + """ + + organization_id: Optional[str] + """ + Filter Private Networks by Organization ID. + """ + + project_id: Optional[str] + """ + Filter Private Networks by Project ID. + """ + + ipam_ip_ids: Optional[List[str]] + """ + Filter Private Networks by IPAM IP IDs. + """ + + +@dataclass +class PrivateNetworkApiSetServerPrivateNetworksRequest: + server_id: str + """ + ID of the server. + """ + + per_private_network_ipam_ip_ids: Dict[str, List[str]] + """ + Object where the keys are the IDs of Private Networks and the values are arrays of IPAM IDs representing the IPs to assign to this Apple silicon server on the Private Network. If the array supplied for a Private Network is empty, the next available IP from the Private Network's CIDR block will automatically be used for attachment. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class RebootServerRequest: server_id: str @@ -379,7 +767,7 @@ class RebootServerRequest: UUID of the server you want to reboot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -392,11 +780,36 @@ class ReinstallServerRequest: UUID of the server you want to reinstall. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ + os_id: Optional[str] + """ + Reinstall the server with the target OS, when no os_id provided the default OS for the server type is used. + """ + + +@dataclass +class SetServerPrivateNetworksResponse: + server_private_networks: List[ServerPrivateNetwork] + + +@dataclass +class StartConnectivityDiagnosticRequest: + server_id: str + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StartConnectivityDiagnosticResponse: + diagnostic_id: str + @dataclass class UpdateServerRequest: @@ -405,7 +818,7 @@ class UpdateServerRequest: UUID of the server you want to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -414,3 +827,18 @@ class UpdateServerRequest: """ Updated name for your server. """ + + schedule_deletion: Optional[bool] + """ + Specify whether the server should be flagged for automatic deletion. + """ + + enable_vpc: Optional[bool] + """ + Activate or deactivate Private Network support for this server. + """ + + commitment_type: Optional[CommitmentTypeValue] + """ + Change commitment. Use 'none' to automatically cancel a renewing commitment. + """ diff --git a/scaleway-async/scaleway_async/llm_inference/__init__.py b/scaleway-async/scaleway_async/audit_trail/__init__.py similarity index 100% rename from scaleway-async/scaleway_async/llm_inference/__init__.py rename to scaleway-async/scaleway_async/audit_trail/__init__.py diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/__init__.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/__init__.py new file mode 100644 index 00000000..519c5190 --- /dev/null +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/__init__.py @@ -0,0 +1,47 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import ListEventsRequestOrderBy +from .types import ResourceType +from .types import AccountOrganizationInfo +from .types import AccountUserInfo +from .types import KeyManagerKeyInfo +from .types import KubernetesACLInfo +from .types import KubernetesClusterInfo +from .types import KubernetesNodeInfo +from .types import KubernetesPoolInfo +from .types import SecretManagerSecretInfo +from .types import SecretManagerSecretVersionInfo +from .types import EventPrincipal +from .types import Resource +from .types import ProductService +from .types import Event +from .types import Product +from .types import ListEventsRequest +from .types import ListEventsResponse +from .types import ListProductsRequest +from .types import ListProductsResponse +from .api import AuditTrailV1Alpha1API + +__all__ = [ + "ListEventsRequestOrderBy", + "ResourceType", + "AccountOrganizationInfo", + "AccountUserInfo", + "KeyManagerKeyInfo", + "KubernetesACLInfo", + "KubernetesClusterInfo", + "KubernetesNodeInfo", + "KubernetesPoolInfo", + "SecretManagerSecretInfo", + "SecretManagerSecretVersionInfo", + "EventPrincipal", + "Resource", + "ProductService", + "Event", + "Product", + "ListEventsRequest", + "ListEventsResponse", + "ListProductsRequest", + "ListProductsResponse", + "AuditTrailV1Alpha1API", +] diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py new file mode 100644 index 00000000..143a8da7 --- /dev/null +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/api.py @@ -0,0 +1,131 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from datetime import datetime +from typing import Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + validate_path_param, +) +from .types import ( + ListEventsRequestOrderBy, + ResourceType, + ListEventsResponse, + ListProductsResponse, +) +from .marshalling import ( + unmarshal_ListEventsResponse, + unmarshal_ListProductsResponse, +) + + +class AuditTrailV1Alpha1API(API): + """ + This API allows you to ensure accountability and security by recording events and changes performed within your Scaleway Organization. + """ + + async def list_events( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + resource_type: Optional[ResourceType] = None, + method_name: Optional[str] = None, + status: Optional[int] = None, + recorded_after: Optional[datetime] = None, + recorded_before: Optional[datetime] = None, + order_by: Optional[ListEventsRequestOrderBy] = None, + page_size: Optional[int] = None, + page_token: Optional[str] = None, + product_name: Optional[str] = None, + service_name: Optional[str] = None, + ) -> ListEventsResponse: + """ + List events. + Retrieve the list of Audit Trail events for a Scaleway Organization and/or Project. You must specify the `organization_id` and optionally, the `project_id`. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: (Optional) ID of the Project containing the Audit Trail events. + :param organization_id: ID of the Organization containing the Audit Trail events. + :param resource_type: (Optional) Returns a paginated list of Scaleway resources' features. + :param method_name: (Optional) Name of the method of the API call performed. + :param status: (Optional) HTTP status code of the request. Returns either `200` if the request was successful or `403` if the permission was denied. + :param recorded_after: (Optional) The `recorded_after` parameter defines the earliest timestamp from which Audit Trail events are retrieved. Returns `one hour ago` by default. + :param recorded_before: (Optional) The `recorded_before` parameter defines the latest timestamp up to which Audit Trail events are retrieved. Returns `now` by default. + :param order_by: + :param page_size: + :param page_token: + :param product_name: (Optional) Name of the Scaleway resource in a hyphenated format. + :param service_name: (Optional) Name of the service of the API call performed. + :return: :class:`ListEventsResponse ` + + Usage: + :: + + result = await api.list_events() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/audit-trail/v1alpha1/regions/{param_region}/events", + params={ + "method_name": method_name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page_size": page_size or self.client.default_page_size, + "page_token": page_token, + "product_name": product_name, + "project_id": project_id or self.client.default_project_id, + "recorded_after": recorded_after, + "recorded_before": recorded_before, + "resource_type": resource_type, + "service_name": service_name, + "status": status, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListEventsResponse(res.json()) + + async def list_products( + self, + *, + region: Optional[ScwRegion] = None, + organization_id: Optional[str] = None, + ) -> ListProductsResponse: + """ + Retrieve the list of Scaleway resources for which you have Audit Trail events. + :param region: Region to target. If none is passed will use default region from the config. + :param organization_id: ID of the Organization containing the Audit Trail events. + :return: :class:`ListProductsResponse ` + + Usage: + :: + + result = await api.list_products() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/audit-trail/v1alpha1/regions/{param_region}/products", + params={ + "organization_id": organization_id + or self.client.default_organization_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListProductsResponse(res.json()) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py new file mode 100644 index 00000000..f1d0b7f2 --- /dev/null +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/marshalling.py @@ -0,0 +1,466 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from .types import ( + AccountOrganizationInfo, + AccountUserInfo, + KeyManagerKeyInfo, + KubernetesACLInfo, + KubernetesClusterInfo, + KubernetesNodeInfo, + KubernetesPoolInfo, + SecretManagerSecretInfo, + SecretManagerSecretVersionInfo, + EventPrincipal, + Resource, + Event, + ListEventsResponse, + ProductService, + Product, + ListProductsResponse, +) + + +def unmarshal_AccountOrganizationInfo(data: Any) -> AccountOrganizationInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AccountOrganizationInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return AccountOrganizationInfo(**args) + + +def unmarshal_AccountUserInfo(data: Any) -> AccountUserInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AccountUserInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("email", None) + if field is not None: + args["email"] = field + + return AccountUserInfo(**args) + + +def unmarshal_KeyManagerKeyInfo(data: Any) -> KeyManagerKeyInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KeyManagerKeyInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return KeyManagerKeyInfo(**args) + + +def unmarshal_KubernetesACLInfo(data: Any) -> KubernetesACLInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KubernetesACLInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return KubernetesACLInfo(**args) + + +def unmarshal_KubernetesClusterInfo(data: Any) -> KubernetesClusterInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KubernetesClusterInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return KubernetesClusterInfo(**args) + + +def unmarshal_KubernetesNodeInfo(data: Any) -> KubernetesNodeInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KubernetesNodeInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + return KubernetesNodeInfo(**args) + + +def unmarshal_KubernetesPoolInfo(data: Any) -> KubernetesPoolInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KubernetesPoolInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + return KubernetesPoolInfo(**args) + + +def unmarshal_SecretManagerSecretInfo(data: Any) -> SecretManagerSecretInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SecretManagerSecretInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("path", None) + if field is not None: + args["path"] = field + + return SecretManagerSecretInfo(**args) + + +def unmarshal_SecretManagerSecretVersionInfo( + data: Any, +) -> SecretManagerSecretVersionInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SecretManagerSecretVersionInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("revision", None) + if field is not None: + args["revision"] = field + + return SecretManagerSecretVersionInfo(**args) + + +def unmarshal_EventPrincipal(data: Any) -> EventPrincipal: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EventPrincipal' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + return EventPrincipal(**args) + + +def unmarshal_Resource(data: Any) -> Resource: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Resource' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("deleted_at", None) + if field is not None: + args["deleted_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["deleted_at"] = None + + field = data.get("name", None) + if field is not None: + args["name"] = field + else: + args["name"] = None + + field = data.get("secm_secret_info", None) + if field is not None: + args["secm_secret_info"] = unmarshal_SecretManagerSecretInfo(field) + else: + args["secm_secret_info"] = None + + field = data.get("secm_secret_version_info", None) + if field is not None: + args["secm_secret_version_info"] = unmarshal_SecretManagerSecretVersionInfo( + field + ) + else: + args["secm_secret_version_info"] = None + + field = data.get("kube_cluster_info", None) + if field is not None: + args["kube_cluster_info"] = unmarshal_KubernetesClusterInfo(field) + else: + args["kube_cluster_info"] = None + + field = data.get("kube_pool_info", None) + if field is not None: + args["kube_pool_info"] = unmarshal_KubernetesPoolInfo(field) + else: + args["kube_pool_info"] = None + + field = data.get("kube_node_info", None) + if field is not None: + args["kube_node_info"] = unmarshal_KubernetesNodeInfo(field) + else: + args["kube_node_info"] = None + + field = data.get("kube_acl_info", None) + if field is not None: + args["kube_acl_info"] = unmarshal_KubernetesACLInfo(field) + else: + args["kube_acl_info"] = None + + field = data.get("keym_key_info", None) + if field is not None: + args["keym_key_info"] = unmarshal_KeyManagerKeyInfo(field) + else: + args["keym_key_info"] = None + + field = data.get("secret_manager_secret_info", None) + if field is not None: + args["secret_manager_secret_info"] = unmarshal_SecretManagerSecretInfo(field) + else: + args["secret_manager_secret_info"] = None + + field = data.get("secret_manager_version_info", None) + if field is not None: + args["secret_manager_version_info"] = unmarshal_SecretManagerSecretVersionInfo( + field + ) + else: + args["secret_manager_version_info"] = None + + field = data.get("key_manager_key_info", None) + if field is not None: + args["key_manager_key_info"] = unmarshal_KeyManagerKeyInfo(field) + else: + args["key_manager_key_info"] = None + + field = data.get("account_user_info", None) + if field is not None: + args["account_user_info"] = unmarshal_AccountUserInfo(field) + else: + args["account_user_info"] = None + + field = data.get("account_organization_info", None) + if field is not None: + args["account_organization_info"] = unmarshal_AccountOrganizationInfo(field) + else: + args["account_organization_info"] = None + + return Resource(**args) + + +def unmarshal_Event(data: Any) -> Event: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Event' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("locality", None) + if field is not None: + args["locality"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("source_ip", None) + if field is not None: + args["source_ip"] = field + + field = data.get("recorded_at", None) + if field is not None: + args["recorded_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["recorded_at"] = None + + field = data.get("principal", None) + if field is not None: + args["principal"] = unmarshal_EventPrincipal(field) + else: + args["principal"] = None + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + else: + args["project_id"] = None + + field = data.get("user_agent", None) + if field is not None: + args["user_agent"] = field + else: + args["user_agent"] = None + + field = data.get("product_name", None) + if field is not None: + args["product_name"] = field + + field = data.get("service_name", None) + if field is not None: + args["service_name"] = field + + field = data.get("method_name", None) + if field is not None: + args["method_name"] = field + + field = data.get("resources", None) + if field is not None: + args["resources"] = ( + [unmarshal_Resource(v) for v in field] if field is not None else None + ) + + field = data.get("request_id", None) + if field is not None: + args["request_id"] = field + + field = data.get("status_code", None) + if field is not None: + args["status_code"] = field + + field = data.get("resource", None) + if field is not None: + args["resource"] = unmarshal_Resource(field) + else: + args["resource"] = None + + field = data.get("request_body", None) + if field is not None: + args["request_body"] = field + else: + args["request_body"] = None + + return Event(**args) + + +def unmarshal_ListEventsResponse(data: Any) -> ListEventsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListEventsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("events", None) + if field is not None: + args["events"] = ( + [unmarshal_Event(v) for v in field] if field is not None else None + ) + + field = data.get("next_page_token", None) + if field is not None: + args["next_page_token"] = field + else: + args["next_page_token"] = None + + return ListEventsResponse(**args) + + +def unmarshal_ProductService(data: Any) -> ProductService: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProductService' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("methods", None) + if field is not None: + args["methods"] = field + + return ProductService(**args) + + +def unmarshal_Product(data: Any) -> Product: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Product' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("title", None) + if field is not None: + args["title"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("services", None) + if field is not None: + args["services"] = ( + [unmarshal_ProductService(v) for v in field] if field is not None else None + ) + + return Product(**args) + + +def unmarshal_ListProductsResponse(data: Any) -> ListProductsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListProductsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("products", None) + if field is not None: + args["products"] = ( + [unmarshal_Product(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListProductsResponse(**args) diff --git a/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py new file mode 100644 index 00000000..ea9c8cf2 --- /dev/null +++ b/scaleway-async/scaleway_async/audit_trail/v1alpha1/types.py @@ -0,0 +1,348 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Any, Dict, List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class ListEventsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + RECORDED_AT_DESC = "recorded_at_desc" + RECORDED_AT_ASC = "recorded_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ResourceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + SECM_SECRET = "secm_secret" + SECM_SECRET_VERSION = "secm_secret_version" + KUBE_CLUSTER = "kube_cluster" + KUBE_POOL = "kube_pool" + KUBE_NODE = "kube_node" + KUBE_ACL = "kube_acl" + KEYM_KEY = "keym_key" + IAM_USER = "iam_user" + IAM_APPLICATION = "iam_application" + IAM_GROUP = "iam_group" + IAM_POLICY = "iam_policy" + IAM_API_KEY = "iam_api_key" + IAM_SSH_KEY = "iam_ssh_key" + IAM_RULE = "iam_rule" + SECRET_MANAGER_SECRET = "secret_manager_secret" + SECRET_MANAGER_VERSION = "secret_manager_version" + KEY_MANAGER_KEY = "key_manager_key" + ACCOUNT_USER = "account_user" + ACCOUNT_ORGANIZATION = "account_organization" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class AccountOrganizationInfo: + pass + + +@dataclass +class AccountUserInfo: + email: str + + +@dataclass +class KeyManagerKeyInfo: + pass + + +@dataclass +class KubernetesACLInfo: + pass + + +@dataclass +class KubernetesClusterInfo: + pass + + +@dataclass +class KubernetesNodeInfo: + id: str + + name: str + + +@dataclass +class KubernetesPoolInfo: + id: str + + name: str + + +@dataclass +class SecretManagerSecretInfo: + path: str + + +@dataclass +class SecretManagerSecretVersionInfo: + revision: int + + +@dataclass +class EventPrincipal: + id: str + + +@dataclass +class Resource: + id: str + + type_: ResourceType + + created_at: Optional[datetime] + + updated_at: Optional[datetime] + + deleted_at: Optional[datetime] + + name: Optional[str] + + secm_secret_info: Optional[SecretManagerSecretInfo] + + secm_secret_version_info: Optional[SecretManagerSecretVersionInfo] + + kube_cluster_info: Optional[KubernetesClusterInfo] + + kube_pool_info: Optional[KubernetesPoolInfo] + + kube_node_info: Optional[KubernetesNodeInfo] + + kube_acl_info: Optional[KubernetesACLInfo] + + keym_key_info: Optional[KeyManagerKeyInfo] + + secret_manager_secret_info: Optional[SecretManagerSecretInfo] + + secret_manager_version_info: Optional[SecretManagerSecretVersionInfo] + + key_manager_key_info: Optional[KeyManagerKeyInfo] + + account_user_info: Optional[AccountUserInfo] + + account_organization_info: Optional[AccountOrganizationInfo] + + +@dataclass +class ProductService: + name: str + + methods: List[str] + + +@dataclass +class Event: + id: str + """ + ID of the event. + """ + + locality: str + """ + Locality of the resource attached to the event. + """ + + organization_id: str + """ + Organization ID containing the event. + """ + + source_ip: str + """ + IP address at the origin of the event. + """ + + recorded_at: Optional[datetime] + """ + Timestamp of the event. + """ + + principal: Optional[EventPrincipal] + """ + User or IAM application at the origin of the event. + """ + + project_id: Optional[str] + """ + (Optional) Project of the resource attached to the event. + """ + + user_agent: Optional[str] + """ + User Agent at the origin of the event. + """ + + product_name: str + """ + Product name of the resource attached to the event. + """ + + service_name: str + """ + API name called to trigger the event. + """ + + method_name: str + """ + API method called to trigger the event. + """ + + resources: List[Resource] + """ + Resources attached to the event. + """ + + request_id: str + """ + Unique identifier of the request at the origin of the event. + """ + + status_code: int + """ + HTTP status code resulting of the API call. + """ + + resource: Optional[Resource] + """ + Resource attached to the event. + """ + + request_body: Optional[Dict[str, Any]] + """ + Request at the origin of the event. + """ + + +@dataclass +class Product: + title: str + """ + Product title. + """ + + name: str + """ + Product name. + """ + + services: List[ProductService] + """ + Specifies the API versions of the products integrated with Audit Trail. Each version defines the methods logged by Audit Trail. + """ + + +@dataclass +class ListEventsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + (Optional) ID of the Project containing the Audit Trail events. + """ + + organization_id: Optional[str] + """ + ID of the Organization containing the Audit Trail events. + """ + + resource_type: Optional[ResourceType] + """ + (Optional) Returns a paginated list of Scaleway resources' features. + """ + + method_name: Optional[str] + """ + (Optional) Name of the method of the API call performed. + """ + + status: Optional[int] + """ + (Optional) HTTP status code of the request. Returns either `200` if the request was successful or `403` if the permission was denied. + """ + + recorded_after: Optional[datetime] + """ + (Optional) The `recorded_after` parameter defines the earliest timestamp from which Audit Trail events are retrieved. Returns `one hour ago` by default. + """ + + recorded_before: Optional[datetime] + """ + (Optional) The `recorded_before` parameter defines the latest timestamp up to which Audit Trail events are retrieved. Returns `now` by default. + """ + + order_by: Optional[ListEventsRequestOrderBy] + + page_size: Optional[int] + + page_token: Optional[str] + + product_name: Optional[str] + """ + (Optional) Name of the Scaleway resource in a hyphenated format. + """ + + service_name: Optional[str] + """ + (Optional) Name of the service of the API call performed. + """ + + +@dataclass +class ListEventsResponse: + events: List[Event] + """ + Single page of events matching the requested criteria. + """ + + next_page_token: Optional[str] + """ + Page token to use in following calls to keep listing. + """ + + +@dataclass +class ListProductsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + organization_id: Optional[str] + """ + ID of the Organization containing the Audit Trail events. + """ + + +@dataclass +class ListProductsResponse: + products: List[Product] + """ + List of all products integrated with Audit Trail. + """ + + total_count: int + """ + Number of integrated products. + """ diff --git a/scaleway/scaleway/llm_inference/__init__.py b/scaleway-async/scaleway_async/autoscaling/__init__.py similarity index 100% rename from scaleway/scaleway/llm_inference/__init__.py rename to scaleway-async/scaleway_async/autoscaling/__init__.py diff --git a/scaleway-async/scaleway_async/autoscaling/v1alpha1/__init__.py b/scaleway-async/scaleway_async/autoscaling/v1alpha1/__init__.py new file mode 100644 index 00000000..67bcfcbe --- /dev/null +++ b/scaleway-async/scaleway_async/autoscaling/v1alpha1/__init__.py @@ -0,0 +1,105 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import InstanceGroupEventLevel +from .types import InstanceGroupEventSource +from .types import InstancePolicyAction +from .types import InstancePolicyType +from .types import InstanceTemplateStatus +from .types import ListInstanceGroupEventsRequestOrderBy +from .types import ListInstanceGroupsRequestOrderBy +from .types import ListInstancePoliciesRequestOrderBy +from .types import ListInstanceTemplatesRequestOrderBy +from .types import MetricAggregate +from .types import MetricManagedMetric +from .types import MetricOperator +from .types import UpdateInstancePolicyRequestMetricAggregate +from .types import UpdateInstancePolicyRequestMetricManagedMetric +from .types import UpdateInstancePolicyRequestMetricOperator +from .types import VolumeInstanceTemplateVolumeType +from .types import VolumeInstanceTemplateFromEmpty +from .types import VolumeInstanceTemplateFromSnapshot +from .types import Capacity +from .types import Loadbalancer +from .types import Metric +from .types import VolumeInstanceTemplate +from .types import InstanceGroupEvent +from .types import InstanceGroup +from .types import InstancePolicy +from .types import InstanceTemplate +from .types import UpdateInstanceGroupRequestCapacity +from .types import UpdateInstanceGroupRequestLoadbalancer +from .types import UpdateInstancePolicyRequestMetric +from .types import CreateInstanceGroupRequest +from .types import CreateInstancePolicyRequest +from .types import CreateInstanceTemplateRequest +from .types import DeleteInstanceGroupRequest +from .types import DeleteInstancePolicyRequest +from .types import DeleteInstanceTemplateRequest +from .types import GetInstanceGroupRequest +from .types import GetInstancePolicyRequest +from .types import GetInstanceTemplateRequest +from .types import ListInstanceGroupEventsRequest +from .types import ListInstanceGroupEventsResponse +from .types import ListInstanceGroupsRequest +from .types import ListInstanceGroupsResponse +from .types import ListInstancePoliciesRequest +from .types import ListInstancePoliciesResponse +from .types import ListInstanceTemplatesRequest +from .types import ListInstanceTemplatesResponse +from .types import UpdateInstanceGroupRequest +from .types import UpdateInstancePolicyRequest +from .types import UpdateInstanceTemplateRequest +from .api import AutoscalingV1Alpha1API + +__all__ = [ + "InstanceGroupEventLevel", + "InstanceGroupEventSource", + "InstancePolicyAction", + "InstancePolicyType", + "InstanceTemplateStatus", + "ListInstanceGroupEventsRequestOrderBy", + "ListInstanceGroupsRequestOrderBy", + "ListInstancePoliciesRequestOrderBy", + "ListInstanceTemplatesRequestOrderBy", + "MetricAggregate", + "MetricManagedMetric", + "MetricOperator", + "UpdateInstancePolicyRequestMetricAggregate", + "UpdateInstancePolicyRequestMetricManagedMetric", + "UpdateInstancePolicyRequestMetricOperator", + "VolumeInstanceTemplateVolumeType", + "VolumeInstanceTemplateFromEmpty", + "VolumeInstanceTemplateFromSnapshot", + "Capacity", + "Loadbalancer", + "Metric", + "VolumeInstanceTemplate", + "InstanceGroupEvent", + "InstanceGroup", + "InstancePolicy", + "InstanceTemplate", + "UpdateInstanceGroupRequestCapacity", + "UpdateInstanceGroupRequestLoadbalancer", + "UpdateInstancePolicyRequestMetric", + "CreateInstanceGroupRequest", + "CreateInstancePolicyRequest", + "CreateInstanceTemplateRequest", + "DeleteInstanceGroupRequest", + "DeleteInstancePolicyRequest", + "DeleteInstanceTemplateRequest", + "GetInstanceGroupRequest", + "GetInstancePolicyRequest", + "GetInstanceTemplateRequest", + "ListInstanceGroupEventsRequest", + "ListInstanceGroupEventsResponse", + "ListInstanceGroupsRequest", + "ListInstanceGroupsResponse", + "ListInstancePoliciesRequest", + "ListInstancePoliciesResponse", + "ListInstanceTemplatesRequest", + "ListInstanceTemplatesResponse", + "UpdateInstanceGroupRequest", + "UpdateInstancePolicyRequest", + "UpdateInstanceTemplateRequest", + "AutoscalingV1Alpha1API", +] diff --git a/scaleway-async/scaleway_async/autoscaling/v1alpha1/api.py b/scaleway-async/scaleway_async/autoscaling/v1alpha1/api.py new file mode 100644 index 00000000..9a957627 --- /dev/null +++ b/scaleway-async/scaleway_async/autoscaling/v1alpha1/api.py @@ -0,0 +1,939 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Dict, List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + validate_path_param, + fetch_all_pages_async, +) +from .types import ( + InstancePolicyAction, + InstancePolicyType, + ListInstanceGroupEventsRequestOrderBy, + ListInstanceGroupsRequestOrderBy, + ListInstancePoliciesRequestOrderBy, + ListInstanceTemplatesRequestOrderBy, + Capacity, + CreateInstanceGroupRequest, + CreateInstancePolicyRequest, + CreateInstanceTemplateRequest, + InstanceGroup, + InstanceGroupEvent, + InstancePolicy, + InstanceTemplate, + ListInstanceGroupEventsResponse, + ListInstanceGroupsResponse, + ListInstancePoliciesResponse, + ListInstanceTemplatesResponse, + Loadbalancer, + Metric, + UpdateInstanceGroupRequest, + UpdateInstanceGroupRequestCapacity, + UpdateInstanceGroupRequestLoadbalancer, + UpdateInstancePolicyRequest, + UpdateInstancePolicyRequestMetric, + UpdateInstanceTemplateRequest, + VolumeInstanceTemplate, +) +from .marshalling import ( + unmarshal_InstanceGroup, + unmarshal_InstancePolicy, + unmarshal_InstanceTemplate, + unmarshal_ListInstanceGroupEventsResponse, + unmarshal_ListInstanceGroupsResponse, + unmarshal_ListInstancePoliciesResponse, + unmarshal_ListInstanceTemplatesResponse, + marshal_CreateInstanceGroupRequest, + marshal_CreateInstancePolicyRequest, + marshal_CreateInstanceTemplateRequest, + marshal_UpdateInstanceGroupRequest, + marshal_UpdateInstancePolicyRequest, + marshal_UpdateInstanceTemplateRequest, +) + + +class AutoscalingV1Alpha1API(API): + """ """ + + async def get_instance_group( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + ) -> InstanceGroup: + """ + Get Instance group. + Retrieve information about an existing Instance group, specified by its `instance_group_id`. Its full details, including errors, are returned in the response object. + :param instance_group_id: ID of the requested Instance group. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`InstanceGroup ` + + Usage: + :: + + result = await api.get_instance_group( + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_instance_group_id = validate_path_param( + "instance_group_id", instance_group_id + ) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups/{param_instance_group_id}", + ) + + self._throw_on_error(res) + return unmarshal_InstanceGroup(res.json()) + + async def create_instance_group( + self, + *, + name: str, + template_id: str, + capacity: Capacity, + loadbalancer: Loadbalancer, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> InstanceGroup: + """ + Create Instance group. + Create a new Instance group. You must specify a `template_id`, capacity and Load Balancer object. + :param name: Name of Instance group. + :param template_id: Template ID (ID of the Instance template to attach to the Instance group). + :param capacity: Specification of the minimum and maximum replicas for the Instance group, and the cooldown interval between two scaling events. + :param loadbalancer: Specification of the Load Balancer to link to the Instance group. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID to filter for, only Instance groups from this Project will be returned. + :param tags: List of tags for the Instance group. + :return: :class:`InstanceGroup ` + + Usage: + :: + + result = await api.create_instance_group( + name="example", + template_id="example", + capacity=Capacity(), + loadbalancer=Loadbalancer(), + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups", + body=marshal_CreateInstanceGroupRequest( + CreateInstanceGroupRequest( + name=name, + template_id=template_id, + capacity=capacity, + loadbalancer=loadbalancer, + zone=zone, + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstanceGroup(res.json()) + + async def list_instance_groups( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceGroupsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListInstanceGroupsResponse: + """ + List Instance groups. + List all Instance groups, for a Scaleway Organization or Scaleway Project. By default, the Instance groups returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`ListInstanceGroupsResponse ` + + Usage: + :: + + result = await api.list_instance_groups() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInstanceGroupsResponse(res.json()) + + async def list_instance_groups_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceGroupsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[InstanceGroup]: + """ + List Instance groups. + List all Instance groups, for a Scaleway Organization or Scaleway Project. By default, the Instance groups returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`List[InstanceGroup] ` + + Usage: + :: + + result = await api.list_instance_groups_all() + """ + + return await fetch_all_pages_async( + type=ListInstanceGroupsResponse, + key="instance_groups", + fetcher=self.list_instance_groups, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + }, + ) + + async def update_instance_group( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + capacity: Optional[UpdateInstanceGroupRequestCapacity] = None, + loadbalancer: Optional[UpdateInstanceGroupRequestLoadbalancer] = None, + ) -> InstanceGroup: + """ + Update Instance group. + Update the parameters of an existing Instance group, specified by its `instance_group_id`. + :param instance_group_id: Instance group ID to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of Instance group. + :param tags: List of tags for the Load Balancer. + :param capacity: Specification of the minimum and maximum replicas for the Instance group, and the cooldown interval between two scaling events. + :param loadbalancer: Specification of the Load Balancer to link to the Instance group. + :return: :class:`InstanceGroup ` + + Usage: + :: + + result = await api.update_instance_group( + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_instance_group_id = validate_path_param( + "instance_group_id", instance_group_id + ) + + res = self._request( + "PATCH", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups/{param_instance_group_id}", + body=marshal_UpdateInstanceGroupRequest( + UpdateInstanceGroupRequest( + instance_group_id=instance_group_id, + zone=zone, + name=name, + tags=tags, + capacity=capacity, + loadbalancer=loadbalancer, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstanceGroup(res.json()) + + async def delete_instance_group( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete Instance group. + Delete an existing Instance group, specified by its `instance_group_id`. Deleting an Instance group is permanent, and cannot be undone. + :param instance_group_id: ID of the Instance group to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_instance_group( + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_instance_group_id = validate_path_param( + "instance_group_id", instance_group_id + ) + + res = self._request( + "DELETE", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups/{param_instance_group_id}", + ) + + self._throw_on_error(res) + + async def create_instance_template( + self, + *, + zone: Optional[ScwZone] = None, + commercial_type: str, + volumes: Dict[str, VolumeInstanceTemplate], + image_id: Optional[str] = None, + tags: Optional[List[str]] = None, + security_group_id: Optional[str] = None, + name: str, + placement_group_id: Optional[str] = None, + public_ips_v4_count: Optional[int] = None, + public_ips_v6_count: Optional[int] = None, + project_id: Optional[str] = None, + private_network_ids: Optional[List[str]] = None, + cloud_init: Optional[str] = None, + ) -> InstanceTemplate: + """ + Create Instance template. + Create a new Instance template. This specifies the details of the Instance (commercial type, zone, image, volumes etc.) that will be in the Instance group. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param commercial_type: Name of Instance commercial type. + :param volumes: Template of Instance volume. + :param image_id: Instance image ID. Can be an ID of a marketplace or personal image. This image must be compatible with `volume` and `commercial_type` template. + :param tags: List of tags for the Instance template. + :param security_group_id: Instance security group ID (optional). + :param name: Name of Instance template. + :param placement_group_id: Instance placement group ID. This is optional, but it is highly recommended to set a preference for Instance location within Availability Zone. + :param public_ips_v4_count: Number of flexible IPv4 addresses to attach to the new Instance. + :param public_ips_v6_count: Number of flexible IPv6 addresses to attach to the new Instance. + :param project_id: ID of the Project containing the Instance template resource. + :param private_network_ids: Private Network IDs to attach to the new Instance. + :param cloud_init: Cloud-config file must be passed in Base64 format. Cloud-config files are special scripts designed to be run by the cloud-init process. These are generally used for initial configuration on the very first boot of a server. + :return: :class:`InstanceTemplate ` + + Usage: + :: + + result = await api.create_instance_template( + commercial_type="example", + volumes={}, + name="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-templates", + body=marshal_CreateInstanceTemplateRequest( + CreateInstanceTemplateRequest( + zone=zone, + commercial_type=commercial_type, + volumes=volumes, + image_id=image_id, + tags=tags, + security_group_id=security_group_id, + name=name, + placement_group_id=placement_group_id, + public_ips_v4_count=public_ips_v4_count, + public_ips_v6_count=public_ips_v6_count, + project_id=project_id, + private_network_ids=private_network_ids, + cloud_init=cloud_init, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstanceTemplate(res.json()) + + async def update_instance_template( + self, + *, + template_id: str, + zone: Optional[ScwZone] = None, + commercial_type: Optional[str] = None, + image_id: Optional[str] = None, + volumes: Optional[Dict[str, VolumeInstanceTemplate]] = None, + tags: Optional[List[str]] = None, + security_group_id: Optional[str] = None, + placement_group_id: Optional[str] = None, + public_ips_v4_count: Optional[int] = None, + public_ips_v6_count: Optional[int] = None, + name: Optional[str] = None, + private_network_ids: Optional[List[str]] = None, + cloud_init: Optional[str] = None, + ) -> InstanceTemplate: + """ + Update Instance template. + Update an Instance template, such as its commercial offer type, image or volume template. + :param template_id: Template ID of the resource. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param commercial_type: Name of Instance commercial type. + :param image_id: Instance image ID. Can be an ID of a marketplace or personal image. This image must be compatible with `volume` and `commercial_type` template. + :param volumes: Template of Instance volume. + :param tags: List of tags for the Instance template. + :param security_group_id: Instance security group ID (optional). + :param placement_group_id: Instance placement group ID. This is optional, but it is highly recommended to set a preference for Instance location within Availability Zone. + :param public_ips_v4_count: Number of flexible IPv4 addresses to attach to the new Instance. + :param public_ips_v6_count: Number of flexible IPv6 addresses to attach to the new Instance. + :param name: Name of Instance template. + :param private_network_ids: Private Network IDs to attach to the new Instance. + :param cloud_init: Cloud-config file must be passed in Base64 format. Cloud-config files are special scripts designed to be run by the cloud-init process. These are generally used for initial configuration on the very first boot of a server. + :return: :class:`InstanceTemplate ` + + Usage: + :: + + result = await api.update_instance_template( + template_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_template_id = validate_path_param("template_id", template_id) + + res = self._request( + "PATCH", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-templates/{param_template_id}", + body=marshal_UpdateInstanceTemplateRequest( + UpdateInstanceTemplateRequest( + template_id=template_id, + zone=zone, + commercial_type=commercial_type, + image_id=image_id, + volumes=volumes, + tags=tags, + security_group_id=security_group_id, + placement_group_id=placement_group_id, + public_ips_v4_count=public_ips_v4_count, + public_ips_v6_count=public_ips_v6_count, + name=name, + private_network_ids=private_network_ids, + cloud_init=cloud_init, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstanceTemplate(res.json()) + + async def get_instance_template( + self, + *, + template_id: str, + zone: Optional[ScwZone] = None, + ) -> InstanceTemplate: + """ + Get Instance template. + Get an existing Instance template from its `template_id`. + :param template_id: Template ID of the resource. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`InstanceTemplate ` + + Usage: + :: + + result = await api.get_instance_template( + template_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_template_id = validate_path_param("template_id", template_id) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-templates/{param_template_id}", + ) + + self._throw_on_error(res) + return unmarshal_InstanceTemplate(res.json()) + + async def delete_instance_template( + self, + *, + template_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete Instance template. + Delete an existing Instance template. This action is permanent and cannot be undone. + :param template_id: ID of the template to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_instance_template( + template_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_template_id = validate_path_param("template_id", template_id) + + res = self._request( + "DELETE", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-templates/{param_template_id}", + ) + + self._throw_on_error(res) + + async def list_instance_templates( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceTemplatesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListInstanceTemplatesResponse: + """ + List Instance templates. + List all Instance templates, for a Scaleway Organization or Scaleway Project. By default, the Instance templates returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`ListInstanceTemplatesResponse ` + + Usage: + :: + + result = await api.list_instance_templates() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-templates", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInstanceTemplatesResponse(res.json()) + + async def list_instance_templates_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceTemplatesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[InstanceTemplate]: + """ + List Instance templates. + List all Instance templates, for a Scaleway Organization or Scaleway Project. By default, the Instance templates returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`List[InstanceTemplate] ` + + Usage: + :: + + result = await api.list_instance_templates_all() + """ + + return await fetch_all_pages_async( + type=ListInstanceTemplatesResponse, + key="instance_templates", + fetcher=self.list_instance_templates, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + }, + ) + + async def create_instance_policy( + self, + *, + name: str, + action: InstancePolicyAction, + type_: InstancePolicyType, + value: int, + priority: int, + instance_group_id: str, + zone: Optional[ScwZone] = None, + metric: Optional[Metric] = None, + ) -> InstancePolicy: + """ + Create scaling policy. + Create a new scaling policy. You must specify a `policy_id`, capacity and Load Balancer object. + :param name: Name of the policy. + :param action: Action to execute when the metric-based condition is met. + :param type_: How to use the number defined in `value` when determining by how many Instances to scale up/down. + :param value: Value representing the magnitude of the scaling action to take for the Instance group. Depending on the `type` parameter, this number could represent a total number of Instances in the group, a number of Instances to add, or a percentage to scale the group by. + :param priority: Priority of this policy compared to all other scaling policies. This determines the processing order. The lower the number, the higher the priority. + :param instance_group_id: Instance group ID related to this policy. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param metric: Cockpit metric to use when determining whether to trigger a scale up/down action. + One-Of ('trigger'): at most one of 'metric' could be set. + :return: :class:`InstancePolicy ` + + Usage: + :: + + result = await api.create_instance_policy( + name="example", + action=InstancePolicyAction.unknown_action, + type=InstancePolicyType.unknown_type, + value=1, + priority=1, + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-policies", + body=marshal_CreateInstancePolicyRequest( + CreateInstancePolicyRequest( + name=name, + action=action, + type_=type_, + value=value, + priority=priority, + instance_group_id=instance_group_id, + zone=zone, + metric=metric, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstancePolicy(res.json()) + + async def update_instance_policy( + self, + *, + policy_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + metric: Optional[UpdateInstancePolicyRequestMetric] = None, + action: Optional[InstancePolicyAction] = None, + type_: Optional[InstancePolicyType] = None, + value: Optional[int] = None, + priority: Optional[int] = None, + ) -> InstancePolicy: + """ + Update scaling policy. + Update the parameters of an existing scaling policy, specified by its `policy_id`. + :param policy_id: Policy ID to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Policy name to update. + :param metric: Metric specification to update (Cockpit metric to use when determining whether to trigger a scale up/down action). + One-Of ('trigger'): at most one of 'metric' could be set. + :param action: Action to update (action to execute when the metric-based condition is met). + :param type_: Type to update (how to use the number defined in `value` when determining by how many Instances to scale up/down). + :param value: Value to update (number representing the magnitude of the scaling action to take for the Instance group). + :param priority: Priority to update (priority of this policy compared to all other scaling policies. The lower the number, the higher the priority). + :return: :class:`InstancePolicy ` + + Usage: + :: + + result = await api.update_instance_policy( + policy_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_policy_id = validate_path_param("policy_id", policy_id) + + res = self._request( + "PATCH", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-policies/{param_policy_id}", + body=marshal_UpdateInstancePolicyRequest( + UpdateInstancePolicyRequest( + policy_id=policy_id, + zone=zone, + name=name, + action=action, + type_=type_, + value=value, + priority=priority, + metric=metric, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstancePolicy(res.json()) + + async def list_instance_policies( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstancePoliciesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListInstancePoliciesResponse: + """ + List scaling policies. + List all scaling policies, for a Scaleway Organization or Scaleway Project. By default, the policies returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param instance_group_id: Instance group ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of scaling policies to return per page. + :return: :class:`ListInstancePoliciesResponse ` + + Usage: + :: + + result = await api.list_instance_policies( + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-policies", + params={ + "instance_group_id": instance_group_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInstancePoliciesResponse(res.json()) + + async def list_instance_policies_all( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstancePoliciesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[InstancePolicy]: + """ + List scaling policies. + List all scaling policies, for a Scaleway Organization or Scaleway Project. By default, the policies returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param instance_group_id: Instance group ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of scaling policies to return per page. + :return: :class:`List[InstancePolicy] ` + + Usage: + :: + + result = await api.list_instance_policies_all( + instance_group_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListInstancePoliciesResponse, + key="policies", + fetcher=self.list_instance_policies, + args={ + "instance_group_id": instance_group_id, + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + }, + ) + + async def get_instance_policy( + self, + *, + policy_id: str, + zone: Optional[ScwZone] = None, + ) -> InstancePolicy: + """ + Get scaling policy. + Retrieve information about an existing scaling policy, specified by its `policy_id`. Its full details are returned in the response object. + :param policy_id: Policy ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`InstancePolicy ` + + Usage: + :: + + result = await api.get_instance_policy( + policy_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_policy_id = validate_path_param("policy_id", policy_id) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-policies/{param_policy_id}", + ) + + self._throw_on_error(res) + return unmarshal_InstancePolicy(res.json()) + + async def delete_instance_policy( + self, + *, + policy_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete scaling policy. + Delete an existing scaling policy, specified by its `policy_id`. Deleting a scaling policy is permanent, and cannot be undone. + :param policy_id: ID of the policy to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_instance_policy( + policy_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_policy_id = validate_path_param("policy_id", policy_id) + + res = self._request( + "DELETE", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-policies/{param_policy_id}", + ) + + self._throw_on_error(res) + + async def list_instance_group_events( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceGroupEventsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListInstanceGroupEventsResponse: + """ + List events. + List all events for a given Instance group. By default, the events are ordered by creation date in descending order, though this can be modified via the `order_by` field. + :param instance_group_id: List all event logs for the Instance group ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`ListInstanceGroupEventsResponse ` + + Usage: + :: + + result = await api.list_instance_group_events( + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_instance_group_id = validate_path_param( + "instance_group_id", instance_group_id + ) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups/{param_instance_group_id}/events", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInstanceGroupEventsResponse(res.json()) + + async def list_instance_group_events_all( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceGroupEventsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[InstanceGroupEvent]: + """ + List events. + List all events for a given Instance group. By default, the events are ordered by creation date in descending order, though this can be modified via the `order_by` field. + :param instance_group_id: List all event logs for the Instance group ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`List[InstanceGroupEvent] ` + + Usage: + :: + + result = await api.list_instance_group_events_all( + instance_group_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListInstanceGroupEventsResponse, + key="instance_events", + fetcher=self.list_instance_group_events, + args={ + "instance_group_id": instance_group_id, + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + }, + ) diff --git a/scaleway-async/scaleway_async/autoscaling/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/autoscaling/v1alpha1/marshalling.py new file mode 100644 index 00000000..0558608f --- /dev/null +++ b/scaleway-async/scaleway_async/autoscaling/v1alpha1/marshalling.py @@ -0,0 +1,942 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + Capacity, + Loadbalancer, + InstanceGroup, + Metric, + InstancePolicy, + VolumeInstanceTemplateFromEmpty, + VolumeInstanceTemplateFromSnapshot, + VolumeInstanceTemplate, + InstanceTemplate, + InstanceGroupEvent, + ListInstanceGroupEventsResponse, + ListInstanceGroupsResponse, + ListInstancePoliciesResponse, + ListInstanceTemplatesResponse, + CreateInstanceGroupRequest, + CreateInstancePolicyRequest, + CreateInstanceTemplateRequest, + UpdateInstanceGroupRequestCapacity, + UpdateInstanceGroupRequestLoadbalancer, + UpdateInstanceGroupRequest, + UpdateInstancePolicyRequestMetric, + UpdateInstancePolicyRequest, + UpdateInstanceTemplateRequest, +) + + +def unmarshal_Capacity(data: Any) -> Capacity: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Capacity' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("max_replicas", None) + if field is not None: + args["max_replicas"] = field + + field = data.get("min_replicas", None) + if field is not None: + args["min_replicas"] = field + + field = data.get("cooldown_delay", None) + if field is not None: + args["cooldown_delay"] = field + else: + args["cooldown_delay"] = None + + return Capacity(**args) + + +def unmarshal_Loadbalancer(data: Any) -> Loadbalancer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Loadbalancer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("backend_ids", None) + if field is not None: + args["backend_ids"] = field + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + return Loadbalancer(**args) + + +def unmarshal_InstanceGroup(data: Any) -> InstanceGroup: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InstanceGroup' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("instance_template_id", None) + if field is not None: + args["instance_template_id"] = field + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = unmarshal_Capacity(field) + + field = data.get("loadbalancer", None) + if field is not None: + args["loadbalancer"] = unmarshal_Loadbalancer(field) + + field = data.get("error_messages", None) + if field is not None: + args["error_messages"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return InstanceGroup(**args) + + +def unmarshal_Metric(data: Any) -> Metric: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Metric' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("operator", None) + if field is not None: + args["operator"] = field + + field = data.get("aggregate", None) + if field is not None: + args["aggregate"] = field + + field = data.get("sampling_range_min", None) + if field is not None: + args["sampling_range_min"] = field + + field = data.get("threshold", None) + if field is not None: + args["threshold"] = field + + field = data.get("managed_metric", None) + if field is not None: + args["managed_metric"] = field + else: + args["managed_metric"] = None + + field = data.get("cockpit_metric_name", None) + if field is not None: + args["cockpit_metric_name"] = field + else: + args["cockpit_metric_name"] = None + + return Metric(**args) + + +def unmarshal_InstancePolicy(data: Any) -> InstancePolicy: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InstancePolicy' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("action", None) + if field is not None: + args["action"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + field = data.get("priority", None) + if field is not None: + args["priority"] = field + + field = data.get("instance_group_id", None) + if field is not None: + args["instance_group_id"] = field + + field = data.get("metric", None) + if field is not None: + args["metric"] = unmarshal_Metric(field) + else: + args["metric"] = None + + return InstancePolicy(**args) + + +def unmarshal_VolumeInstanceTemplateFromEmpty( + data: Any, +) -> VolumeInstanceTemplateFromEmpty: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeInstanceTemplateFromEmpty' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("size", None) + if field is not None: + args["size"] = field + + return VolumeInstanceTemplateFromEmpty(**args) + + +def unmarshal_VolumeInstanceTemplateFromSnapshot( + data: Any, +) -> VolumeInstanceTemplateFromSnapshot: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeInstanceTemplateFromSnapshot' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("snapshot_id", None) + if field is not None: + args["snapshot_id"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + else: + args["size"] = None + + return VolumeInstanceTemplateFromSnapshot(**args) + + +def unmarshal_VolumeInstanceTemplate(data: Any) -> VolumeInstanceTemplate: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeInstanceTemplate' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("boot", None) + if field is not None: + args["boot"] = field + + field = data.get("volume_type", None) + if field is not None: + args["volume_type"] = field + + field = data.get("perf_iops", None) + if field is not None: + args["perf_iops"] = field + else: + args["perf_iops"] = None + + field = data.get("from_empty", None) + if field is not None: + args["from_empty"] = unmarshal_VolumeInstanceTemplateFromEmpty(field) + else: + args["from_empty"] = None + + field = data.get("from_snapshot", None) + if field is not None: + args["from_snapshot"] = unmarshal_VolumeInstanceTemplateFromSnapshot(field) + else: + args["from_snapshot"] = None + + return VolumeInstanceTemplate(**args) + + +def unmarshal_InstanceTemplate(data: Any) -> InstanceTemplate: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InstanceTemplate' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("commercial_type", None) + if field is not None: + args["commercial_type"] = field + + field = data.get("volumes", None) + if field is not None: + args["volumes"] = ( + { + key: unmarshal_VolumeInstanceTemplate(value) + for key, value in field.items() + } + if field is not None + else None + ) + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("private_network_ids", None) + if field is not None: + args["private_network_ids"] = field + + field = data.get("image_id", None) + if field is not None: + args["image_id"] = field + else: + args["image_id"] = None + + field = data.get("security_group_id", None) + if field is not None: + args["security_group_id"] = field + else: + args["security_group_id"] = None + + field = data.get("placement_group_id", None) + if field is not None: + args["placement_group_id"] = field + else: + args["placement_group_id"] = None + + field = data.get("public_ips_v4_count", None) + if field is not None: + args["public_ips_v4_count"] = field + else: + args["public_ips_v4_count"] = None + + field = data.get("public_ips_v6_count", None) + if field is not None: + args["public_ips_v6_count"] = field + else: + args["public_ips_v6_count"] = None + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("cloud_init", None) + if field is not None: + args["cloud_init"] = field + else: + args["cloud_init"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return InstanceTemplate(**args) + + +def unmarshal_InstanceGroupEvent(data: Any) -> InstanceGroupEvent: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InstanceGroupEvent' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("source", None) + if field is not None: + args["source"] = field + + field = data.get("level", None) + if field is not None: + args["level"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("details", None) + if field is not None: + args["details"] = field + else: + args["details"] = None + + return InstanceGroupEvent(**args) + + +def unmarshal_ListInstanceGroupEventsResponse( + data: Any, +) -> ListInstanceGroupEventsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInstanceGroupEventsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("instance_events", None) + if field is not None: + args["instance_events"] = ( + [unmarshal_InstanceGroupEvent(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListInstanceGroupEventsResponse(**args) + + +def unmarshal_ListInstanceGroupsResponse(data: Any) -> ListInstanceGroupsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInstanceGroupsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("instance_groups", None) + if field is not None: + args["instance_groups"] = ( + [unmarshal_InstanceGroup(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListInstanceGroupsResponse(**args) + + +def unmarshal_ListInstancePoliciesResponse(data: Any) -> ListInstancePoliciesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInstancePoliciesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("policies", None) + if field is not None: + args["policies"] = ( + [unmarshal_InstancePolicy(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListInstancePoliciesResponse(**args) + + +def unmarshal_ListInstanceTemplatesResponse(data: Any) -> ListInstanceTemplatesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInstanceTemplatesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("instance_templates", None) + if field is not None: + args["instance_templates"] = ( + [unmarshal_InstanceTemplate(v) for v in field] + if field is not None + else None + ) + + return ListInstanceTemplatesResponse(**args) + + +def marshal_Capacity( + request: Capacity, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.max_replicas is not None: + output["max_replicas"] = request.max_replicas + + if request.min_replicas is not None: + output["min_replicas"] = request.min_replicas + + if request.cooldown_delay is not None: + output["cooldown_delay"] = request.cooldown_delay + + return output + + +def marshal_Loadbalancer( + request: Loadbalancer, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.id is not None: + output["id"] = request.id + + if request.backend_ids is not None: + output["backend_ids"] = request.backend_ids + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + return output + + +def marshal_CreateInstanceGroupRequest( + request: CreateInstanceGroupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.template_id is not None: + output["template_id"] = request.template_id + + if request.capacity is not None: + output["capacity"] = marshal_Capacity(request.capacity, defaults) + + if request.loadbalancer is not None: + output["loadbalancer"] = marshal_Loadbalancer(request.loadbalancer, defaults) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_Metric( + request: Metric, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("managed_metric", request.managed_metric), + OneOfPossibility("cockpit_metric_name", request.cockpit_metric_name), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.operator is not None: + output["operator"] = str(request.operator) + + if request.aggregate is not None: + output["aggregate"] = str(request.aggregate) + + if request.sampling_range_min is not None: + output["sampling_range_min"] = request.sampling_range_min + + if request.threshold is not None: + output["threshold"] = request.threshold + + return output + + +def marshal_CreateInstancePolicyRequest( + request: CreateInstancePolicyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("metric", request.metric), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.action is not None: + output["action"] = str(request.action) + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.value is not None: + output["value"] = request.value + + if request.priority is not None: + output["priority"] = request.priority + + if request.instance_group_id is not None: + output["instance_group_id"] = request.instance_group_id + + return output + + +def marshal_VolumeInstanceTemplateFromEmpty( + request: VolumeInstanceTemplateFromEmpty, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_VolumeInstanceTemplateFromSnapshot( + request: VolumeInstanceTemplateFromSnapshot, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.snapshot_id is not None: + output["snapshot_id"] = request.snapshot_id + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_VolumeInstanceTemplate( + request: VolumeInstanceTemplate, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("from_empty", request.from_empty), + OneOfPossibility("from_snapshot", request.from_snapshot), + ] + ), + ) + output.update( + resolve_one_of( + [ + OneOfPossibility("perf_iops", request.perf_iops), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.boot is not None: + output["boot"] = request.boot + + if request.volume_type is not None: + output["volume_type"] = str(request.volume_type) + + return output + + +def marshal_CreateInstanceTemplateRequest( + request: CreateInstanceTemplateRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.commercial_type is not None: + output["commercial_type"] = request.commercial_type + + if request.volumes is not None: + output["volumes"] = { + key: marshal_VolumeInstanceTemplate(value, defaults) + for key, value in request.volumes.items() + } + + if request.image_id is not None: + output["image_id"] = request.image_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.security_group_id is not None: + output["security_group_id"] = request.security_group_id + + if request.name is not None: + output["name"] = request.name + + if request.placement_group_id is not None: + output["placement_group_id"] = request.placement_group_id + + if request.public_ips_v4_count is not None: + output["public_ips_v4_count"] = request.public_ips_v4_count + + if request.public_ips_v6_count is not None: + output["public_ips_v6_count"] = request.public_ips_v6_count + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.private_network_ids is not None: + output["private_network_ids"] = request.private_network_ids + + if request.cloud_init is not None: + output["cloud_init"] = request.cloud_init + + return output + + +def marshal_UpdateInstanceGroupRequestCapacity( + request: UpdateInstanceGroupRequestCapacity, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.max_replicas is not None: + output["max_replicas"] = request.max_replicas + + if request.min_replicas is not None: + output["min_replicas"] = request.min_replicas + + if request.cooldown_delay is not None: + output["cooldown_delay"] = request.cooldown_delay + + return output + + +def marshal_UpdateInstanceGroupRequestLoadbalancer( + request: UpdateInstanceGroupRequestLoadbalancer, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.backend_ids is not None: + output["backend_ids"] = request.backend_ids + + return output + + +def marshal_UpdateInstanceGroupRequest( + request: UpdateInstanceGroupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.capacity is not None: + output["capacity"] = marshal_UpdateInstanceGroupRequestCapacity( + request.capacity, defaults + ) + + if request.loadbalancer is not None: + output["loadbalancer"] = marshal_UpdateInstanceGroupRequestLoadbalancer( + request.loadbalancer, defaults + ) + + return output + + +def marshal_UpdateInstancePolicyRequestMetric( + request: UpdateInstancePolicyRequestMetric, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("managed_metric", request.managed_metric), + OneOfPossibility("cockpit_metric_name", request.cockpit_metric_name), + ] + ), + ) + + if request.operator is not None: + output["operator"] = str(request.operator) + + if request.aggregate is not None: + output["aggregate"] = str(request.aggregate) + + if request.name is not None: + output["name"] = request.name + + if request.sampling_range_min is not None: + output["sampling_range_min"] = request.sampling_range_min + + if request.threshold is not None: + output["threshold"] = request.threshold + + return output + + +def marshal_UpdateInstancePolicyRequest( + request: UpdateInstancePolicyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("metric", request.metric), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.action is not None: + output["action"] = str(request.action) + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.value is not None: + output["value"] = request.value + + if request.priority is not None: + output["priority"] = request.priority + + return output + + +def marshal_UpdateInstanceTemplateRequest( + request: UpdateInstanceTemplateRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.commercial_type is not None: + output["commercial_type"] = request.commercial_type + + if request.image_id is not None: + output["image_id"] = request.image_id + + if request.volumes is not None: + output["volumes"] = { + key: marshal_VolumeInstanceTemplate(value, defaults) + for key, value in request.volumes.items() + } + + if request.tags is not None: + output["tags"] = request.tags + + if request.security_group_id is not None: + output["security_group_id"] = request.security_group_id + + if request.placement_group_id is not None: + output["placement_group_id"] = request.placement_group_id + + if request.public_ips_v4_count is not None: + output["public_ips_v4_count"] = request.public_ips_v4_count + + if request.public_ips_v6_count is not None: + output["public_ips_v6_count"] = request.public_ips_v6_count + + if request.name is not None: + output["name"] = request.name + + if request.private_network_ids is not None: + output["private_network_ids"] = request.private_network_ids + + if request.cloud_init is not None: + output["cloud_init"] = request.cloud_init + + return output diff --git a/scaleway-async/scaleway_async/autoscaling/v1alpha1/types.py b/scaleway-async/scaleway_async/autoscaling/v1alpha1/types.py new file mode 100644 index 00000000..f1ecfd81 --- /dev/null +++ b/scaleway-async/scaleway_async/autoscaling/v1alpha1/types.py @@ -0,0 +1,1067 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class InstanceGroupEventLevel(str, Enum, metaclass=StrEnumMeta): + INFO = "info" + SUCCESS = "success" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class InstanceGroupEventSource(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SOURCE = "unknown_source" + WATCHER = "watcher" + SCALER = "scaler" + INSTANCE_MANAGER = "instance_manager" + SUPERVISOR = "supervisor" + + def __str__(self) -> str: + return str(self.value) + + +class InstancePolicyAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + SCALE_UP = "scale_up" + SCALE_DOWN = "scale_down" + + def __str__(self) -> str: + return str(self.value) + + +class InstancePolicyType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + FLAT_COUNT = "flat_count" + PERCENT_OF_TOTAL_GROUP = "percent_of_total_group" + SET_TOTAL_GROUP = "set_total_group" + + def __str__(self) -> str: + return str(self.value) + + +class InstanceTemplateStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class ListInstanceGroupEventsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ListInstanceGroupsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ListInstancePoliciesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ListInstanceTemplatesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class MetricAggregate(str, Enum, metaclass=StrEnumMeta): + AGGREGATE_UNKNOWN = "aggregate_unknown" + AGGREGATE_AVERAGE = "aggregate_average" + AGGREGATE_MAX = "aggregate_max" + AGGREGATE_MIN = "aggregate_min" + AGGREGATE_SUM = "aggregate_sum" + + def __str__(self) -> str: + return str(self.value) + + +class MetricManagedMetric(str, Enum, metaclass=StrEnumMeta): + MANAGED_METRIC_UNKNOWN = "managed_metric_unknown" + MANAGED_METRIC_INSTANCE_CPU = "managed_metric_instance_cpu" + MANAGED_METRIC_INSTANCE_NETWORK_IN = "managed_metric_instance_network_in" + MANAGED_METRIC_INSTANCE_NETWORK_OUT = "managed_metric_instance_network_out" + MANAGED_LOADBALANCER_BACKEND_CONNECTIONS_RATE = ( + "managed_loadbalancer_backend_connections_rate" + ) + MANAGED_LOADBALANCER_BACKEND_THROUGHPUT = "managed_loadbalancer_backend_throughput" + + def __str__(self) -> str: + return str(self.value) + + +class MetricOperator(str, Enum, metaclass=StrEnumMeta): + OPERATOR_UNKNOWN = "operator_unknown" + OPERATOR_GREATER_THAN = "operator_greater_than" + OPERATOR_LESS_THAN = "operator_less_than" + + def __str__(self) -> str: + return str(self.value) + + +class UpdateInstancePolicyRequestMetricAggregate(str, Enum, metaclass=StrEnumMeta): + AGGREGATE_UNKNOWN = "aggregate_unknown" + AGGREGATE_AVERAGE = "aggregate_average" + AGGREGATE_MAX = "aggregate_max" + AGGREGATE_MIN = "aggregate_min" + AGGREGATE_SUM = "aggregate_sum" + + def __str__(self) -> str: + return str(self.value) + + +class UpdateInstancePolicyRequestMetricManagedMetric(str, Enum, metaclass=StrEnumMeta): + MANAGED_METRIC_UNKNOWN = "managed_metric_unknown" + MANAGED_METRIC_INSTANCE_CPU = "managed_metric_instance_cpu" + MANAGED_METRIC_INSTANCE_NETWORK_IN = "managed_metric_instance_network_in" + MANAGED_METRIC_INSTANCE_NETWORK_OUT = "managed_metric_instance_network_out" + MANAGED_LOADBALANCER_BACKEND_CONNECTIONS_RATE = ( + "managed_loadbalancer_backend_connections_rate" + ) + MANAGED_LOADBALANCER_BACKEND_THROUGHPUT = "managed_loadbalancer_backend_throughput" + + def __str__(self) -> str: + return str(self.value) + + +class UpdateInstancePolicyRequestMetricOperator(str, Enum, metaclass=StrEnumMeta): + OPERATOR_UNKNOWN = "operator_unknown" + OPERATOR_GREATER_THAN = "operator_greater_than" + OPERATOR_LESS_THAN = "operator_less_than" + + def __str__(self) -> str: + return str(self.value) + + +class VolumeInstanceTemplateVolumeType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_VOLUME_TYPE = "unknown_volume_type" + L_SSD = "l_ssd" + SBS = "sbs" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class VolumeInstanceTemplateFromEmpty: + size: int + + +@dataclass +class VolumeInstanceTemplateFromSnapshot: + snapshot_id: str + + size: Optional[int] + + +@dataclass +class Capacity: + max_replicas: int + """ + Maximum count of Instances for the Instance group. + """ + + min_replicas: int + """ + Minimum count of Instances for the Instance group. + """ + + cooldown_delay: Optional[str] + """ + Time (in seconds) after a scaling action during which requests to carry out a new scaling action will be denied. + """ + + +@dataclass +class Loadbalancer: + id: str + """ + Load Balancer ID. + """ + + backend_ids: List[str] + """ + Load Balancer backend IDs. + """ + + private_network_id: str + """ + ID of the Private Network attached to the Load Balancer. + """ + + +@dataclass +class Metric: + name: str + """ + Name or description of the metric policy. + """ + + operator: MetricOperator + """ + Operator used when comparing the threshold value of the chosen `metric` to the actual sampled and aggregated value. + """ + + aggregate: MetricAggregate + """ + How the values sampled for the `metric` should be aggregated. + """ + + sampling_range_min: int + """ + Interval of time, in minutes, during which metric is sampled. + """ + + threshold: float + """ + Threshold value to measure the aggregated sampled `metric` value against. Combined with the `operator` field, determines whether a scaling action should be triggered. + """ + + managed_metric: Optional[MetricManagedMetric] + + cockpit_metric_name: Optional[str] + + +@dataclass +class VolumeInstanceTemplate: + name: str + """ + Name of the volume. + """ + + tags: List[str] + """ + List of tags assigned to the volume. + """ + + boot: bool + """ + Force the Instance to boot on this volume. + """ + + volume_type: VolumeInstanceTemplateVolumeType + """ + Type of the volume. + """ + + from_empty: Optional[VolumeInstanceTemplateFromEmpty] + + from_snapshot: Optional[VolumeInstanceTemplateFromSnapshot] + + perf_iops: Optional[int] + + +@dataclass +class InstanceGroupEvent: + id: str + """ + Instance group event ID. + """ + + source: InstanceGroupEventSource + """ + Log source. + """ + + level: InstanceGroupEventLevel + """ + The severity of the log. + """ + + name: str + """ + Log title. + """ + + created_at: Optional[datetime] + """ + Date and time of the log. + """ + + details: Optional[str] + """ + Full text of the log. + """ + + +@dataclass +class InstanceGroup: + id: str + """ + Instance group ID. + """ + + project_id: str + """ + Project ID of the Instance group. + """ + + name: str + """ + Name of the Instance group. + """ + + tags: List[str] + """ + Instance group tags. + """ + + instance_template_id: str + """ + Template ID (ID of the Instance template to attach to the Instance group). + """ + + capacity: Capacity + """ + Specification of the minimum and maximum replicas for the Instance group, and the cooldown interval between two scaling events. + """ + + loadbalancer: Loadbalancer + """ + Specification of the Load Balancer linked to the Instance group. + """ + + error_messages: List[str] + """ + Any configuration errors for dependencies (Load Balancer, Private Network, Instance template etc.). + """ + + created_at: Optional[datetime] + """ + Date on which the Instance group was created. + """ + + updated_at: Optional[datetime] + """ + Date on which the Instance group was last updated. + """ + + +@dataclass +class InstancePolicy: + id: str + """ + Scaling policy ID. + """ + + name: str + """ + Name of scaling policy. + """ + + action: InstancePolicyAction + """ + Action to execute when the metric-based condition is met. + """ + + type_: InstancePolicyType + """ + How to use the number defined in `value` when determining by how many Instances to scale up/down. + """ + + value: int + """ + Number representing the magnitude of the scaling action to take for the Instance group. + """ + + priority: int + """ + Priority of this policy compared to all other scaling policies. The lower the number, the higher the priority (higher priority will be processed sooner in the order). + """ + + instance_group_id: str + """ + Instance group ID related to this policy. + """ + + metric: Optional[Metric] + + +@dataclass +class InstanceTemplate: + id: str + """ + ID of Instance template resource. + """ + + commercial_type: str + """ + Name of Instance commercial type. + """ + + volumes: Dict[str, VolumeInstanceTemplate] + """ + Template of Instance volume. + """ + + tags: List[str] + """ + List of tags for the Instance template. + """ + + project_id: str + """ + ID of the Project containing the Instance template resource. + """ + + name: str + """ + Name of Instance template. + """ + + private_network_ids: List[str] + """ + Private Network IDs to attach to the new Instance. + """ + + image_id: Optional[str] + """ + Instance image ID. Can be an ID of a marketplace or personal image. This image must be compatible with `volume` and `commercial_type` template. + """ + + security_group_id: Optional[str] + """ + Instance security group ID (optional). + """ + + placement_group_id: Optional[str] + """ + Instance placement group ID. This is optional, but it is highly recommended to set a preference for Instance location within Availability Zone. + """ + + public_ips_v4_count: Optional[int] + """ + Number of flexible IPv4 addresses to attach to the new Instance. + """ + + public_ips_v6_count: Optional[int] + """ + Number of flexible IPv6 addresses to attach to the new Instance. + """ + + status: InstanceTemplateStatus + """ + Status of Instance template. + """ + + cloud_init: Optional[str] + """ + Cloud-config file must be passed in Base64 format. Cloud-config files are special scripts designed to be run by the cloud-init process. These are generally used for initial configuration on the very first boot of a server. + """ + + created_at: Optional[datetime] + """ + Date on which the Instance template was created. + """ + + updated_at: Optional[datetime] + """ + Date on which the Instance template was last updated. + """ + + +@dataclass +class UpdateInstanceGroupRequestCapacity: + max_replicas: Optional[int] + """ + Maximum count of Instances for the Instance group. + """ + + min_replicas: Optional[int] + """ + Minimum count of Instances for the Instance group. + """ + + cooldown_delay: Optional[str] + """ + Time (in seconds) after a scaling action during which requests to carry out a new scaling action will be denied. + """ + + +@dataclass +class UpdateInstanceGroupRequestLoadbalancer: + backend_ids: Optional[List[str]] + """ + Load Balancer backend IDs. + """ + + +@dataclass +class UpdateInstancePolicyRequestMetric: + operator: UpdateInstancePolicyRequestMetricOperator + """ + Operator used when comparing the threshold value of the chosen `metric` to the actual sampled and aggregated value. + """ + + aggregate: UpdateInstancePolicyRequestMetricAggregate + """ + How the values sampled for the `metric` should be aggregated. + """ + + name: Optional[str] + """ + Name or description of your metric policy. + """ + + sampling_range_min: Optional[int] + """ + Interval of time, in minutes, during which metric is sampled. + """ + + threshold: Optional[float] + """ + Threshold value to measure the aggregated sampled `metric` value against. Combined with the `operator` field, determines whether a scaling action should be triggered. + """ + + managed_metric: Optional[UpdateInstancePolicyRequestMetricManagedMetric] + + cockpit_metric_name: Optional[str] + + +@dataclass +class CreateInstanceGroupRequest: + name: str + """ + Name of Instance group. + """ + + template_id: str + """ + Template ID (ID of the Instance template to attach to the Instance group). + """ + + capacity: Capacity + """ + Specification of the minimum and maximum replicas for the Instance group, and the cooldown interval between two scaling events. + """ + + loadbalancer: Loadbalancer + """ + Specification of the Load Balancer to link to the Instance group. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only Instance groups from this Project will be returned. + """ + + tags: Optional[List[str]] + """ + List of tags for the Instance group. + """ + + +@dataclass +class CreateInstancePolicyRequest: + name: str + """ + Name of the policy. + """ + + action: InstancePolicyAction + """ + Action to execute when the metric-based condition is met. + """ + + type_: InstancePolicyType + """ + How to use the number defined in `value` when determining by how many Instances to scale up/down. + """ + + value: int + """ + Value representing the magnitude of the scaling action to take for the Instance group. Depending on the `type` parameter, this number could represent a total number of Instances in the group, a number of Instances to add, or a percentage to scale the group by. + """ + + priority: int + """ + Priority of this policy compared to all other scaling policies. This determines the processing order. The lower the number, the higher the priority. + """ + + instance_group_id: str + """ + Instance group ID related to this policy. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + metric: Optional[Metric] + + +@dataclass +class CreateInstanceTemplateRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + commercial_type: str + """ + Name of Instance commercial type. + """ + + volumes: Dict[str, VolumeInstanceTemplate] + """ + Template of Instance volume. + """ + + image_id: Optional[str] + """ + Instance image ID. Can be an ID of a marketplace or personal image. This image must be compatible with `volume` and `commercial_type` template. + """ + + tags: Optional[List[str]] + """ + List of tags for the Instance template. + """ + + security_group_id: Optional[str] + """ + Instance security group ID (optional). + """ + + name: str + """ + Name of Instance template. + """ + + placement_group_id: Optional[str] + """ + Instance placement group ID. This is optional, but it is highly recommended to set a preference for Instance location within Availability Zone. + """ + + public_ips_v4_count: Optional[int] + """ + Number of flexible IPv4 addresses to attach to the new Instance. + """ + + public_ips_v6_count: Optional[int] + """ + Number of flexible IPv6 addresses to attach to the new Instance. + """ + + project_id: Optional[str] + """ + ID of the Project containing the Instance template resource. + """ + + private_network_ids: Optional[List[str]] + """ + Private Network IDs to attach to the new Instance. + """ + + cloud_init: Optional[str] + """ + Cloud-config file must be passed in Base64 format. Cloud-config files are special scripts designed to be run by the cloud-init process. These are generally used for initial configuration on the very first boot of a server. + """ + + +@dataclass +class DeleteInstanceGroupRequest: + instance_group_id: str + """ + ID of the Instance group to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteInstancePolicyRequest: + policy_id: str + """ + ID of the policy to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteInstanceTemplateRequest: + template_id: str + """ + ID of the template to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetInstanceGroupRequest: + instance_group_id: str + """ + ID of the requested Instance group. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetInstancePolicyRequest: + policy_id: str + """ + Policy ID. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetInstanceTemplateRequest: + template_id: str + """ + Template ID of the resource. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ListInstanceGroupEventsRequest: + instance_group_id: str + """ + List all event logs for the Instance group ID. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListInstanceGroupEventsRequestOrderBy] + """ + Sort order of Instance groups in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of Instance groups to return per page. + """ + + +@dataclass +class ListInstanceGroupEventsResponse: + instance_events: List[InstanceGroupEvent] + """ + Paginated list of Instance groups. + """ + + total_count: int + """ + Count of all Instance groups matching the requested criteria. + """ + + +@dataclass +class ListInstanceGroupsRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListInstanceGroupsRequestOrderBy] + """ + Sort order of Instance groups in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of Instance groups to return per page. + """ + + +@dataclass +class ListInstanceGroupsResponse: + instance_groups: List[InstanceGroup] + """ + Paginated list of Instance groups. + """ + + total_count: int + """ + Count of all Instance groups matching the requested criteria. + """ + + +@dataclass +class ListInstancePoliciesRequest: + instance_group_id: str + """ + Instance group ID. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListInstancePoliciesRequestOrderBy] + """ + Sort order of Instance groups in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of scaling policies to return per page. + """ + + +@dataclass +class ListInstancePoliciesResponse: + policies: List[InstancePolicy] + """ + Paginated list of policies. + """ + + total_count: int + """ + Count of all policies matching the requested criteria. + """ + + +@dataclass +class ListInstanceTemplatesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListInstanceTemplatesRequestOrderBy] + """ + Sort order of Instance groups in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of Instance groups to return per page. + """ + + +@dataclass +class ListInstanceTemplatesResponse: + total_count: int + """ + Count of all templates matching the requested criteria. + """ + + instance_templates: List[InstanceTemplate] + """ + Paginated list of Instance templates. + """ + + +@dataclass +class UpdateInstanceGroupRequest: + instance_group_id: str + """ + Instance group ID to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name of Instance group. + """ + + tags: Optional[List[str]] + """ + List of tags for the Load Balancer. + """ + + capacity: Optional[UpdateInstanceGroupRequestCapacity] + """ + Specification of the minimum and maximum replicas for the Instance group, and the cooldown interval between two scaling events. + """ + + loadbalancer: Optional[UpdateInstanceGroupRequestLoadbalancer] + """ + Specification of the Load Balancer to link to the Instance group. + """ + + +@dataclass +class UpdateInstancePolicyRequest: + policy_id: str + """ + Policy ID to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Policy name to update. + """ + + action: Optional[InstancePolicyAction] + """ + Action to update (action to execute when the metric-based condition is met). + """ + + type_: Optional[InstancePolicyType] + """ + Type to update (how to use the number defined in `value` when determining by how many Instances to scale up/down). + """ + + value: Optional[int] + """ + Value to update (number representing the magnitude of the scaling action to take for the Instance group). + """ + + priority: Optional[int] + """ + Priority to update (priority of this policy compared to all other scaling policies. The lower the number, the higher the priority). + """ + + metric: Optional[UpdateInstancePolicyRequestMetric] + + +@dataclass +class UpdateInstanceTemplateRequest: + template_id: str + """ + Template ID of the resource. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + commercial_type: Optional[str] + """ + Name of Instance commercial type. + """ + + image_id: Optional[str] + """ + Instance image ID. Can be an ID of a marketplace or personal image. This image must be compatible with `volume` and `commercial_type` template. + """ + + volumes: Optional[Dict[str, VolumeInstanceTemplate]] + """ + Template of Instance volume. + """ + + tags: Optional[List[str]] + """ + List of tags for the Instance template. + """ + + security_group_id: Optional[str] + """ + Instance security group ID (optional). + """ + + placement_group_id: Optional[str] + """ + Instance placement group ID. This is optional, but it is highly recommended to set a preference for Instance location within Availability Zone. + """ + + public_ips_v4_count: Optional[int] + """ + Number of flexible IPv4 addresses to attach to the new Instance. + """ + + public_ips_v6_count: Optional[int] + """ + Number of flexible IPv6 addresses to attach to the new Instance. + """ + + name: Optional[str] + """ + Name of Instance template. + """ + + private_network_ids: Optional[List[str]] + """ + Private Network IDs to attach to the new Instance. + """ + + cloud_init: Optional[str] + """ + Cloud-config file must be passed in Base64 format. Cloud-config files are special scripts designed to be run by the cloud-init process. These are generally used for initial configuration on the very first boot of a server. + """ diff --git a/scaleway-async/scaleway_async/baremetal/v1/__init__.py b/scaleway-async/scaleway_async/baremetal/v1/__init__.py index 6381cd5e..f1ec9f1e 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/__init__.py +++ b/scaleway-async/scaleway_async/baremetal/v1/__init__.py @@ -8,6 +8,10 @@ from .types import ListSettingsRequestOrderBy from .types import OfferStock from .types import OfferSubscriptionPeriod +from .types import SchemaFilesystemFormat +from .types import SchemaPartitionLabel +from .types import SchemaPoolType +from .types import SchemaRAIDLevel from .types import ServerBootType from .types import ServerInstallStatus from .content import SERVER_INSTALL_TRANSIENT_STATUSES @@ -18,9 +22,22 @@ from .types import ServerStatus from .content import SERVER_TRANSIENT_STATUSES from .types import SettingType +from .types import SchemaPartition +from .types import SchemaPool +from .types import SchemaDisk +from .types import SchemaFilesystem +from .types import SchemaRAID +from .types import SchemaZFS +from .types import CertificationOption +from .types import LicenseOption +from .types import PrivateNetworkOption +from .types import PublicBandwidthOption +from .types import RemoteAccessOption +from .types import Schema from .types import OSOSField from .types import CPU from .types import Disk +from .types import GPU from .types import Memory from .types import OfferOptionOffer from .types import PersistentMemory @@ -43,6 +60,7 @@ from .types import DeleteOptionServerRequest from .types import DeleteServerRequest from .types import GetBMCAccessRequest +from .types import GetDefaultPartitioningSchemaRequest from .types import GetOSRequest from .types import GetOfferRequest from .types import GetOptionRequest @@ -63,6 +81,7 @@ from .types import ListServersResponse from .types import ListSettingsRequest from .types import ListSettingsResponse +from .types import MigrateServerToMonthlyOfferRequest from .types import PrivateNetworkApiAddServerPrivateNetworkRequest from .types import PrivateNetworkApiDeleteServerPrivateNetworkRequest from .types import PrivateNetworkApiListServerPrivateNetworksRequest @@ -76,6 +95,7 @@ from .types import UpdateIPRequest from .types import UpdateServerRequest from .types import UpdateSettingRequest +from .types import ValidatePartitioningSchemaRequest from .api import BaremetalV1API from .api import BaremetalV1PrivateNetworkAPI @@ -88,6 +108,10 @@ "ListSettingsRequestOrderBy", "OfferStock", "OfferSubscriptionPeriod", + "SchemaFilesystemFormat", + "SchemaPartitionLabel", + "SchemaPoolType", + "SchemaRAIDLevel", "ServerBootType", "ServerInstallStatus", "SERVER_INSTALL_TRANSIENT_STATUSES", @@ -98,9 +122,22 @@ "ServerStatus", "SERVER_TRANSIENT_STATUSES", "SettingType", + "SchemaPartition", + "SchemaPool", + "SchemaDisk", + "SchemaFilesystem", + "SchemaRAID", + "SchemaZFS", + "CertificationOption", + "LicenseOption", + "PrivateNetworkOption", + "PublicBandwidthOption", + "RemoteAccessOption", + "Schema", "OSOSField", "CPU", "Disk", + "GPU", "Memory", "OfferOptionOffer", "PersistentMemory", @@ -123,6 +160,7 @@ "DeleteOptionServerRequest", "DeleteServerRequest", "GetBMCAccessRequest", + "GetDefaultPartitioningSchemaRequest", "GetOSRequest", "GetOfferRequest", "GetOptionRequest", @@ -143,6 +181,7 @@ "ListServersResponse", "ListSettingsRequest", "ListSettingsResponse", + "MigrateServerToMonthlyOfferRequest", "PrivateNetworkApiAddServerPrivateNetworkRequest", "PrivateNetworkApiDeleteServerPrivateNetworkRequest", "PrivateNetworkApiListServerPrivateNetworksRequest", @@ -156,6 +195,7 @@ "UpdateIPRequest", "UpdateServerRequest", "UpdateSettingRequest", + "ValidatePartitioningSchemaRequest", "BaremetalV1API", "BaremetalV1PrivateNetworkAPI", ] diff --git a/scaleway-async/scaleway_async/baremetal/v1/api.py b/scaleway-async/scaleway_async/baremetal/v1/api.py index e50e52d2..24f8f916 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/api.py +++ b/scaleway-async/scaleway_async/baremetal/v1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, @@ -41,6 +41,7 @@ PrivateNetworkApiAddServerPrivateNetworkRequest, PrivateNetworkApiSetServerPrivateNetworksRequest, RebootServerRequest, + Schema, Server, ServerEvent, ServerPrivateNetwork, @@ -51,11 +52,13 @@ UpdateIPRequest, UpdateServerRequest, UpdateSettingRequest, + ValidatePartitioningSchemaRequest, ) from .content import ( SERVER_TRANSIENT_STATUSES, ) from .marshalling import ( + unmarshal_Schema, unmarshal_IP, unmarshal_OS, unmarshal_Offer, @@ -84,18 +87,19 @@ marshal_UpdateIPRequest, marshal_UpdateServerRequest, marshal_UpdateSettingRequest, + marshal_ValidatePartitioningSchemaRequest, ) class BaremetalV1API(API): """ - This API allows to manage your Elastic Metal server. + This API allows you to manage your Elastic Metal servers. """ async def list_servers( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListServersRequestOrderBy] = None, @@ -152,7 +156,7 @@ async def list_servers( async def list_servers_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListServersRequestOrderBy] = None, @@ -206,7 +210,7 @@ async def get_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Get a specific Elastic Metal server. @@ -238,7 +242,7 @@ async def wait_for_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Server, Union[bool, Awaitable[bool]]]] = None, ) -> Server: """ @@ -277,7 +281,7 @@ async def create_server( offer_id: str, name: str, description: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, @@ -338,7 +342,7 @@ async def update_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, @@ -389,11 +393,12 @@ async def install_server( os_id: str, hostname: str, ssh_key_ids: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, user: Optional[str] = None, password: Optional[str] = None, service_user: Optional[str] = None, service_password: Optional[str] = None, + partitioning_schema: Optional[Schema] = None, ) -> Server: """ Install an Elastic Metal server. @@ -407,6 +412,7 @@ async def install_server( :param password: Password used for the installation. :param service_user: User used for the service to install. :param service_password: Password used for the service to install. + :param partitioning_schema: Partitioning schema. :return: :class:`Server ` Usage: @@ -437,6 +443,7 @@ async def install_server( password=password, service_user=service_user, service_password=service_password, + partitioning_schema=partitioning_schema, ), self.client, ), @@ -449,7 +456,7 @@ async def get_server_metrics( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetServerMetricsResponse: """ Return server metrics. @@ -481,7 +488,7 @@ async def delete_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Delete an Elastic Metal server. @@ -513,7 +520,7 @@ async def reboot_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, boot_type: Optional[ServerBootType] = None, ) -> Server: """ @@ -555,7 +562,7 @@ async def start_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, boot_type: Optional[ServerBootType] = None, ) -> Server: """ @@ -597,7 +604,7 @@ async def stop_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Stop an Elastic Metal server. @@ -630,7 +637,7 @@ async def list_server_events( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListServerEventsRequestOrderBy] = None, @@ -673,7 +680,7 @@ async def list_server_events_all( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListServerEventsRequestOrderBy] = None, @@ -709,12 +716,93 @@ async def list_server_events_all( }, ) + async def get_default_partitioning_schema( + self, + *, + offer_id: str, + os_id: str, + zone: Optional[ScwZone] = None, + ) -> Schema: + """ + Get default partitioning schema. + Get the default partitioning schema for the given offer ID and OS ID. + :param offer_id: ID of the offer. + :param os_id: ID of the OS. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Schema ` + + Usage: + :: + + result = await api.get_default_partitioning_schema( + offer_id="example", + os_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/baremetal/v1/zones/{param_zone}/partitioning-schemas/default", + params={ + "offer_id": offer_id, + "os_id": os_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Schema(res.json()) + + async def validate_partitioning_schema( + self, + *, + offer_id: str, + os_id: str, + zone: Optional[ScwZone] = None, + partitioning_schema: Optional[Schema] = None, + ) -> None: + """ + Validate client partitioning schema. + Validate the incoming partitioning schema from a user before installing the server. Return default ErrorCode if invalid. + :param offer_id: Offer ID of the server. + :param os_id: OS ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param partitioning_schema: Partitioning schema. + + Usage: + :: + + result = await api.validate_partitioning_schema( + offer_id="example", + os_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/baremetal/v1/zones/{param_zone}/partitioning-schemas/validate", + body=marshal_ValidatePartitioningSchemaRequest( + ValidatePartitioningSchemaRequest( + offer_id=offer_id, + os_id=os_id, + zone=zone, + partitioning_schema=partitioning_schema, + ), + self.client, + ), + ) + + self._throw_on_error(res) + async def start_bmc_access( self, *, server_id: str, ip: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> BMCAccess: """ Start BMC access. @@ -759,7 +847,7 @@ async def get_bmc_access( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> BMCAccess: """ Get BMC access. @@ -791,7 +879,7 @@ async def stop_bmc_access( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Stop BMC access. @@ -822,7 +910,7 @@ async def update_ip( *, server_id: str, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, reverse: Optional[str] = None, ) -> IP: """ @@ -869,7 +957,7 @@ async def add_option_server( *, server_id: str, option_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, expires_at: Optional[datetime] = None, ) -> Server: """ @@ -916,7 +1004,7 @@ async def delete_option_server( *, server_id: str, option_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Delete server option. @@ -947,13 +1035,46 @@ async def delete_option_server( self._throw_on_error(res) return unmarshal_Server(res.json()) + async def migrate_server_to_monthly_offer( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> Server: + """ + Migrate server offer. + Migrate server with hourly offer to monthly offer. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Server ` + + Usage: + :: + + result = await api.migrate_server_to_monthly_offer( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/baremetal/v1/zones/{param_zone}/servers/{param_server_id}/migrate-offer-monthly", + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + async def list_offers( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, subscription_period: Optional[OfferSubscriptionPeriod] = None, + name: Optional[str] = None, ) -> ListOffersResponse: """ List offers. @@ -962,6 +1083,7 @@ async def list_offers( :param page: Page number. :param page_size: Number of offers per page. :param subscription_period: Subscription period type to filter offers by. + :param name: Offer name to filter offers by. :return: :class:`ListOffersResponse ` Usage: @@ -976,6 +1098,7 @@ async def list_offers( "GET", f"/baremetal/v1/zones/{param_zone}/offers", params={ + "name": name, "page": page, "page_size": page_size or self.client.default_page_size, "subscription_period": subscription_period, @@ -988,10 +1111,11 @@ async def list_offers( async def list_offers_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, subscription_period: Optional[OfferSubscriptionPeriod] = None, + name: Optional[str] = None, ) -> List[Offer]: """ List offers. @@ -1000,6 +1124,7 @@ async def list_offers_all( :param page: Page number. :param page_size: Number of offers per page. :param subscription_period: Subscription period type to filter offers by. + :param name: Offer name to filter offers by. :return: :class:`List[Offer] ` Usage: @@ -1017,6 +1142,7 @@ async def list_offers_all( "page": page, "page_size": page_size, "subscription_period": subscription_period, + "name": name, }, ) @@ -1024,7 +1150,7 @@ async def get_offer( self, *, offer_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Offer: """ Get offer. @@ -1056,7 +1182,7 @@ async def get_option( self, *, option_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Option: """ Get option. @@ -1087,7 +1213,7 @@ async def get_option( async def list_options( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, offer_id: Optional[str] = None, @@ -1128,7 +1254,7 @@ async def list_options( async def list_options_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, offer_id: Optional[str] = None, @@ -1166,7 +1292,7 @@ async def list_options_all( async def list_settings( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSettingsRequestOrderBy] = None, @@ -1207,7 +1333,7 @@ async def list_settings( async def list_settings_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSettingsRequestOrderBy] = None, @@ -1246,7 +1372,7 @@ async def update_setting( self, *, setting_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, enabled: Optional[bool] = None, ) -> Setting: """ @@ -1287,7 +1413,7 @@ async def update_setting( async def list_os( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, offer_id: Optional[str] = None, @@ -1325,7 +1451,7 @@ async def list_os( async def list_os_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, offer_id: Optional[str] = None, @@ -1361,7 +1487,7 @@ async def get_os( self, *, os_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> OS: """ Get OS with an ID. @@ -1392,7 +1518,7 @@ async def get_os( class BaremetalV1PrivateNetworkAPI(API): """ - Elastic Metal Private Network API. + Elastic Metal - Private Network API. """ async def add_server_private_network( @@ -1400,7 +1526,7 @@ async def add_server_private_network( *, server_id: str, private_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ServerPrivateNetwork: """ Add a server to a Private Network. @@ -1442,7 +1568,7 @@ async def set_server_private_networks( *, server_id: str, private_network_ids: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetServerPrivateNetworksResponse: """ Set multiple Private Networks on a server. @@ -1482,7 +1608,7 @@ async def set_server_private_networks( async def list_server_private_networks( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1532,7 +1658,7 @@ async def list_server_private_networks( async def list_server_private_networks_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1580,7 +1706,7 @@ async def delete_server_private_network( *, server_id: str, private_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a Private Network. diff --git a/scaleway-async/scaleway_async/baremetal/v1/content.py b/scaleway-async/scaleway_async/baremetal/v1/content.py index e0817ef4..cc244bae 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/content.py +++ b/scaleway-async/scaleway_async/baremetal/v1/content.py @@ -29,6 +29,7 @@ ServerStatus.DELETING, ServerStatus.ORDERED, ServerStatus.RESETTING, + ServerStatus.MIGRATING, ] """ Lists transient statutes of the enum :class:`ServerStatus `. diff --git a/scaleway-async/scaleway_async/baremetal/v1/marshalling.py b/scaleway-async/scaleway_async/baremetal/v1/marshalling.py index 60471d4d..594312c7 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/marshalling.py +++ b/scaleway-async/scaleway_async/baremetal/v1/marshalling.py @@ -14,11 +14,24 @@ resolve_one_of, ) from .types import ( + SchemaPartition, + SchemaPool, + SchemaDisk, + SchemaFilesystem, + SchemaRAID, + SchemaZFS, + Schema, IP, OSOSField, OS, + CertificationOption, + LicenseOption, + PrivateNetworkOption, + PublicBandwidthOption, + RemoteAccessOption, CPU, Disk, + GPU, Memory, OfferOptionOffer, PersistentMemory, @@ -54,9 +67,189 @@ UpdateIPRequest, UpdateServerRequest, UpdateSettingRequest, + ValidatePartitioningSchemaRequest, ) +def unmarshal_SchemaPartition(data: Any) -> SchemaPartition: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaPartition' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("label", None) + if field is not None: + args["label"] = field + + field = data.get("number", None) + if field is not None: + args["number"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("use_all_available_space", None) + if field is not None: + args["use_all_available_space"] = field + + return SchemaPartition(**args) + + +def unmarshal_SchemaPool(data: Any) -> SchemaPool: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaPool' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("devices", None) + if field is not None: + args["devices"] = field + + field = data.get("options", None) + if field is not None: + args["options"] = field + + field = data.get("filesystem_options", None) + if field is not None: + args["filesystem_options"] = field + + return SchemaPool(**args) + + +def unmarshal_SchemaDisk(data: Any) -> SchemaDisk: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaDisk' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("device", None) + if field is not None: + args["device"] = field + + field = data.get("partitions", None) + if field is not None: + args["partitions"] = ( + [unmarshal_SchemaPartition(v) for v in field] if field is not None else None + ) + + return SchemaDisk(**args) + + +def unmarshal_SchemaFilesystem(data: Any) -> SchemaFilesystem: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaFilesystem' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("device", None) + if field is not None: + args["device"] = field + + field = data.get("format", None) + if field is not None: + args["format"] = field + + field = data.get("mountpoint", None) + if field is not None: + args["mountpoint"] = field + + return SchemaFilesystem(**args) + + +def unmarshal_SchemaRAID(data: Any) -> SchemaRAID: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaRAID' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("level", None) + if field is not None: + args["level"] = field + + field = data.get("devices", None) + if field is not None: + args["devices"] = field + + return SchemaRAID(**args) + + +def unmarshal_SchemaZFS(data: Any) -> SchemaZFS: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaZFS' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pools", None) + if field is not None: + args["pools"] = ( + [unmarshal_SchemaPool(v) for v in field] if field is not None else None + ) + + return SchemaZFS(**args) + + +def unmarshal_Schema(data: Any) -> Schema: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Schema' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("disks", None) + if field is not None: + args["disks"] = ( + [unmarshal_SchemaDisk(v) for v in field] if field is not None else None + ) + + field = data.get("raids", None) + if field is not None: + args["raids"] = ( + [unmarshal_SchemaRAID(v) for v in field] if field is not None else None + ) + + field = data.get("filesystems", None) + if field is not None: + args["filesystems"] = ( + [unmarshal_SchemaFilesystem(v) for v in field] + if field is not None + else None + ) + + field = data.get("zfs", None) + if field is not None: + args["zfs"] = unmarshal_SchemaZFS(field) + else: + args["zfs"] = None + + return Schema(**args) + + def unmarshal_IP(data: Any) -> IP: if not isinstance(data, dict): raise TypeError( @@ -111,6 +304,8 @@ def unmarshal_OSOSField(data: Any) -> OSOSField: field = data.get("default_value", None) if field is not None: args["default_value"] = field + else: + args["default_value"] = None return OSOSField(**args) @@ -139,41 +334,122 @@ def unmarshal_OS(data: Any) -> OS: if field is not None: args["logo_url"] = field - field = data.get("enabled", None) - if field is not None: - args["enabled"] = field - - field = data.get("license_required", None) - if field is not None: - args["license_required"] = field - - field = data.get("allowed", None) - if field is not None: - args["allowed"] = field - field = data.get("ssh", None) if field is not None: args["ssh"] = unmarshal_OSOSField(field) + else: + args["ssh"] = None field = data.get("user", None) if field is not None: args["user"] = unmarshal_OSOSField(field) + else: + args["user"] = None field = data.get("password", None) if field is not None: args["password"] = unmarshal_OSOSField(field) + else: + args["password"] = None field = data.get("service_user", None) if field is not None: args["service_user"] = unmarshal_OSOSField(field) + else: + args["service_user"] = None field = data.get("service_password", None) if field is not None: args["service_password"] = unmarshal_OSOSField(field) + else: + args["service_password"] = None + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + field = data.get("license_required", None) + if field is not None: + args["license_required"] = field + + field = data.get("allowed", None) + if field is not None: + args["allowed"] = field + + field = data.get("custom_partitioning_supported", None) + if field is not None: + args["custom_partitioning_supported"] = field return OS(**args) +def unmarshal_CertificationOption(data: Any) -> CertificationOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CertificationOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return CertificationOption(**args) + + +def unmarshal_LicenseOption(data: Any) -> LicenseOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'LicenseOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("os_id", None) + if field is not None: + args["os_id"] = field + + return LicenseOption(**args) + + +def unmarshal_PrivateNetworkOption(data: Any) -> PrivateNetworkOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PrivateNetworkOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bandwidth_in_bps", None) + if field is not None: + args["bandwidth_in_bps"] = field + + return PrivateNetworkOption(**args) + + +def unmarshal_PublicBandwidthOption(data: Any) -> PublicBandwidthOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicBandwidthOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bandwidth_in_bps", None) + if field is not None: + args["bandwidth_in_bps"] = field + + return PublicBandwidthOption(**args) + + +def unmarshal_RemoteAccessOption(data: Any) -> RemoteAccessOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RemoteAccessOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return RemoteAccessOption(**args) + + def unmarshal_CPU(data: Any) -> CPU: if not isinstance(data, dict): raise TypeError( @@ -217,13 +493,32 @@ def unmarshal_Disk(data: Any) -> Disk: if field is not None: args["capacity"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field return Disk(**args) +def unmarshal_GPU(data: Any) -> GPU: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GPU' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("vram", None) + if field is not None: + args["vram"] = field + + return GPU(**args) + + def unmarshal_Memory(data: Any) -> Memory: if not isinstance(data, dict): raise TypeError( @@ -236,7 +531,7 @@ def unmarshal_Memory(data: Any) -> Memory: if field is not None: args["capacity"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -282,10 +577,44 @@ def unmarshal_OfferOptionOffer(data: Any) -> OfferOptionOffer: field = data.get("price", None) if field is not None: args["price"] = unmarshal_Money(field) + else: + args["price"] = None field = data.get("os_id", None) if field is not None: args["os_id"] = field + else: + args["os_id"] = None + + field = data.get("license", None) + if field is not None: + args["license"] = unmarshal_LicenseOption(field) + else: + args["license"] = None + + field = data.get("public_bandwidth", None) + if field is not None: + args["public_bandwidth"] = unmarshal_PublicBandwidthOption(field) + else: + args["public_bandwidth"] = None + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_PrivateNetworkOption(field) + else: + args["private_network"] = None + + field = data.get("remote_access", None) + if field is not None: + args["remote_access"] = unmarshal_RemoteAccessOption(field) + else: + args["remote_access"] = None + + field = data.get("certification", None) + if field is not None: + args["certification"] = unmarshal_CertificationOption(field) + else: + args["certification"] = None return OfferOptionOffer(**args) @@ -302,7 +631,7 @@ def unmarshal_PersistentMemory(data: Any) -> PersistentMemory: if field is not None: args["capacity"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -356,6 +685,10 @@ def unmarshal_Offer(data: Any) -> Offer: if field is not None: args["bandwidth"] = field + field = data.get("max_bandwidth", None) + if field is not None: + args["max_bandwidth"] = field + field = data.get("commercial_range", None) if field is not None: args["commercial_range"] = field @@ -370,14 +703,6 @@ def unmarshal_Offer(data: Any) -> Offer: if field is not None: args["enable"] = field - field = data.get("price_per_hour", None) - if field is not None: - args["price_per_hour"] = unmarshal_Money(field) - - field = data.get("price_per_month", None) - if field is not None: - args["price_per_month"] = unmarshal_Money(field) - field = data.get("cpus", None) if field is not None: args["cpus"] = [unmarshal_CPU(v) for v in field] if field is not None else None @@ -388,6 +713,18 @@ def unmarshal_Offer(data: Any) -> Offer: [unmarshal_Memory(v) for v in field] if field is not None else None ) + field = data.get("price_per_hour", None) + if field is not None: + args["price_per_hour"] = unmarshal_Money(field) + else: + args["price_per_hour"] = None + + field = data.get("price_per_month", None) + if field is not None: + args["price_per_month"] = unmarshal_Money(field) + else: + args["price_per_month"] = None + field = data.get("quota_name", None) if field is not None: args["quota_name"] = field @@ -438,9 +775,21 @@ def unmarshal_Offer(data: Any) -> Offer: if field is not None: args["tags"] = field + field = data.get("gpus", None) + if field is not None: + args["gpus"] = [unmarshal_GPU(v) for v in field] if field is not None else None + field = data.get("fee", None) if field is not None: args["fee"] = unmarshal_Money(field) + else: + args["fee"] = None + + field = data.get("monthly_offer_id", None) + if field is not None: + args["monthly_offer_id"] = field + else: + args["monthly_offer_id"] = None return Offer(**args) @@ -465,6 +814,36 @@ def unmarshal_Option(data: Any) -> Option: if field is not None: args["manageable"] = field + field = data.get("license", None) + if field is not None: + args["license"] = unmarshal_LicenseOption(field) + else: + args["license"] = None + + field = data.get("public_bandwidth", None) + if field is not None: + args["public_bandwidth"] = unmarshal_PublicBandwidthOption(field) + else: + args["public_bandwidth"] = None + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_PrivateNetworkOption(field) + else: + args["private_network"] = None + + field = data.get("remote_access", None) + if field is not None: + args["remote_access"] = unmarshal_RemoteAccessOption(field) + else: + args["remote_access"] = None + + field = data.get("certification", None) + if field is not None: + args["certification"] = unmarshal_CertificationOption(field) + else: + args["certification"] = None + return Option(**args) @@ -499,14 +878,20 @@ def unmarshal_ServerPrivateNetwork(data: Any) -> ServerPrivateNetwork: field = data.get("vlan", None) if field is not None: args["vlan"] = field + else: + args["vlan"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return ServerPrivateNetwork(**args) @@ -547,6 +932,12 @@ def unmarshal_ServerInstall(data: Any) -> ServerInstall: if field is not None: args["service_url"] = field + field = data.get("partitioning_schema", None) + if field is not None: + args["partitioning_schema"] = unmarshal_Schema(field) + else: + args["partitioning_schema"] = None + return ServerInstall(**args) @@ -577,6 +968,38 @@ def unmarshal_ServerOption(data: Any) -> ServerOption: field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + field = data.get("license", None) + if field is not None: + args["license"] = unmarshal_LicenseOption(field) + else: + args["license"] = None + + field = data.get("public_bandwidth", None) + if field is not None: + args["public_bandwidth"] = unmarshal_PublicBandwidthOption(field) + else: + args["public_bandwidth"] = None + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_PrivateNetworkOption(field) + else: + args["private_network"] = None + + field = data.get("remote_access", None) + if field is not None: + args["remote_access"] = unmarshal_RemoteAccessOption(field) + else: + args["remote_access"] = None + + field = data.get("certification", None) + if field is not None: + args["certification"] = unmarshal_CertificationOption(field) + else: + args["certification"] = None return ServerOption(**args) @@ -635,10 +1058,14 @@ def unmarshal_Server(data: Any) -> Server: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("offer_id", None) if field is not None: @@ -681,10 +1108,14 @@ def unmarshal_Server(data: Any) -> Server: field = data.get("install", None) if field is not None: args["install"] = unmarshal_ServerInstall(field) + else: + args["install"] = None field = data.get("rescue_server", None) if field is not None: args["rescue_server"] = unmarshal_ServerRescueServer(field) + else: + args["rescue_server"] = None return Server(**args) @@ -701,7 +1132,7 @@ def unmarshal_Setting(data: Any) -> Setting: if field is not None: args["id"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -739,6 +1170,8 @@ def unmarshal_BMCAccess(data: Any) -> BMCAccess: field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None return BMCAccess(**args) @@ -754,6 +1187,8 @@ def unmarshal_GetServerMetricsResponse(data: Any) -> GetServerMetricsResponse: field = data.get("pings", None) if field is not None: args["pings"] = unmarshal_TimeSeries(field) + else: + args["pings"] = None return GetServerMetricsResponse(**args) @@ -838,10 +1273,14 @@ def unmarshal_ServerEvent(data: Any) -> ServerEvent: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return ServerEvent(**args) @@ -962,7 +1401,140 @@ def marshal_AddOptionServerRequest( output: Dict[str, Any] = {} if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() + + return output + + +def marshal_SchemaPartition( + request: SchemaPartition, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.label is not None: + output["label"] = str(request.label) + + if request.number is not None: + output["number"] = request.number + + if request.size is not None: + output["size"] = request.size + + if request.use_all_available_space is not None: + output["use_all_available_space"] = request.use_all_available_space + + return output + + +def marshal_SchemaPool( + request: SchemaPool, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.devices is not None: + output["devices"] = request.devices + + if request.options is not None: + output["options"] = request.options + + if request.filesystem_options is not None: + output["filesystem_options"] = request.filesystem_options + + return output + + +def marshal_SchemaDisk( + request: SchemaDisk, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.device is not None: + output["device"] = request.device + + if request.partitions is not None: + output["partitions"] = [ + marshal_SchemaPartition(item, defaults) for item in request.partitions + ] + + return output + + +def marshal_SchemaFilesystem( + request: SchemaFilesystem, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.device is not None: + output["device"] = request.device + + if request.format is not None: + output["format"] = str(request.format) + + if request.mountpoint is not None: + output["mountpoint"] = request.mountpoint + + return output + + +def marshal_SchemaRAID( + request: SchemaRAID, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.level is not None: + output["level"] = str(request.level) + + if request.devices is not None: + output["devices"] = request.devices + + return output + + +def marshal_SchemaZFS( + request: SchemaZFS, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.pools is not None: + output["pools"] = [marshal_SchemaPool(item, defaults) for item in request.pools] + + return output + + +def marshal_Schema( + request: Schema, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.disks is not None: + output["disks"] = [marshal_SchemaDisk(item, defaults) for item in request.disks] + + if request.raids is not None: + output["raids"] = [marshal_SchemaRAID(item, defaults) for item in request.raids] + + if request.filesystems is not None: + output["filesystems"] = [ + marshal_SchemaFilesystem(item, defaults) for item in request.filesystems + ] + + if request.zfs is not None: + output["zfs"] = marshal_SchemaZFS(request.zfs, defaults) return output @@ -994,6 +1566,11 @@ def marshal_CreateServerRequestInstall( if request.service_password is not None: output["service_password"] = request.service_password + if request.partitioning_schema is not None: + output["partitioning_schema"] = marshal_Schema( + request.partitioning_schema, defaults + ) + return output @@ -1030,8 +1607,8 @@ def marshal_CreateServerRequest( output["tags"] = request.tags if request.install is not None: - output["install"] = ( - marshal_CreateServerRequestInstall(request.install, defaults), + output["install"] = marshal_CreateServerRequestInstall( + request.install, defaults ) if request.option_ids is not None: @@ -1067,6 +1644,11 @@ def marshal_InstallServerRequest( if request.service_password is not None: output["service_password"] = request.service_password + if request.partitioning_schema is not None: + output["partitioning_schema"] = marshal_Schema( + request.partitioning_schema, defaults + ) + return output @@ -1170,3 +1752,23 @@ def marshal_UpdateSettingRequest( output["enabled"] = request.enabled return output + + +def marshal_ValidatePartitioningSchemaRequest( + request: ValidatePartitioningSchemaRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.os_id is not None: + output["os_id"] = request.os_id + + if request.partitioning_schema is not None: + output["partitioning_schema"] = marshal_Schema( + request.partitioning_schema, defaults + ) + + return output diff --git a/scaleway-async/scaleway_async/baremetal/v1/types.py b/scaleway-async/scaleway_async/baremetal/v1/types.py index 74e29494..fac2f380 100644 --- a/scaleway-async/scaleway_async/baremetal/v1/types.py +++ b/scaleway-async/scaleway_async/baremetal/v1/types.py @@ -10,7 +10,7 @@ from scaleway_core.bridge import ( Money, TimeSeries, - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -87,6 +87,57 @@ def __str__(self) -> str: return str(self.value) +class SchemaFilesystemFormat(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_FORMAT = "unknown_format" + FAT32 = "fat32" + EXT4 = "ext4" + SWAP = "swap" + ZFS = "zfs" + XFS = "xfs" + + def __str__(self) -> str: + return str(self.value) + + +class SchemaPartitionLabel(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PARTITION_LABEL = "unknown_partition_label" + UEFI = "uefi" + LEGACY = "legacy" + ROOT = "root" + BOOT = "boot" + SWAP = "swap" + DATA = "data" + HOME = "home" + RAID = "raid" + ZFS = "zfs" + + def __str__(self) -> str: + return str(self.value) + + +class SchemaPoolType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + NO_RAID = "no_raid" + MIRROR = "mirror" + RAIDZ1 = "raidz1" + RAIDZ2 = "raidz2" + + def __str__(self) -> str: + return str(self.value) + + +class SchemaRAIDLevel(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_RAID_LEVEL = "unknown_raid_level" + RAID_LEVEL_0 = "raid_level_0" + RAID_LEVEL_1 = "raid_level_1" + RAID_LEVEL_5 = "raid_level_5" + RAID_LEVEL_6 = "raid_level_6" + RAID_LEVEL_10 = "raid_level_10" + + def __str__(self) -> str: + return str(self.value) + + class ServerBootType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_BOOT_TYPE = "unknown_boot_type" NORMAL = "normal" @@ -152,6 +203,7 @@ class ServerStatus(str, Enum, metaclass=StrEnumMeta): OUT_OF_STOCK = "out_of_stock" ORDERED = "ordered" RESETTING = "resetting" + MIGRATING = "migrating" def __str__(self) -> str: return str(self.value) @@ -165,6 +217,96 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class SchemaPartition: + label: SchemaPartitionLabel + + number: int + + size: int + + use_all_available_space: bool + + +@dataclass +class SchemaPool: + name: str + + type_: SchemaPoolType + + devices: List[str] + + options: List[str] + + filesystem_options: List[str] + + +@dataclass +class SchemaDisk: + device: str + + partitions: List[SchemaPartition] + + +@dataclass +class SchemaFilesystem: + device: str + + format: SchemaFilesystemFormat + + mountpoint: str + + +@dataclass +class SchemaRAID: + name: str + + level: SchemaRAIDLevel + + devices: List[str] + + +@dataclass +class SchemaZFS: + pools: List[SchemaPool] + + +@dataclass +class CertificationOption: + pass + + +@dataclass +class LicenseOption: + os_id: str + + +@dataclass +class PrivateNetworkOption: + bandwidth_in_bps: int + + +@dataclass +class PublicBandwidthOption: + bandwidth_in_bps: int + + +@dataclass +class RemoteAccessOption: + pass + + +@dataclass +class Schema: + disks: List[SchemaDisk] + + raids: List[SchemaRAID] + + filesystems: List[SchemaFilesystem] + + zfs: Optional[SchemaZFS] + + @dataclass class OSOSField: editable: bool @@ -215,6 +357,19 @@ class Disk: """ +@dataclass +class GPU: + name: str + """ + Name of the GPU. + """ + + vram: int + """ + Capacity of the vram in bytes. + """ + + @dataclass class Memory: capacity: int @@ -273,9 +428,19 @@ class OfferOptionOffer: os_id: Optional[str] """ - ID of the OS linked to the option. + Deprecated, use LicenseOptionVars.os_id instead. """ + license: Optional[LicenseOption] + + public_bandwidth: Optional[PublicBandwidthOption] + + private_network: Optional[PrivateNetworkOption] + + remote_access: Optional[RemoteAccessOption] + + certification: Optional[CertificationOption] + @dataclass class PersistentMemory: @@ -372,6 +537,11 @@ class ServerInstall: Address of the installed service. """ + partitioning_schema: Optional[Schema] + """ + Partitioning schema. + """ + @dataclass class ServerOption: @@ -400,6 +570,16 @@ class ServerOption: Auto expiration date for compatible options. """ + license: Optional[LicenseOption] + + public_bandwidth: Optional[PublicBandwidthOption] + + private_network: Optional[PrivateNetworkOption] + + remote_access: Optional[RemoteAccessOption] + + certification: Optional[CertificationOption] + @dataclass class ServerRescueServer: @@ -451,6 +631,11 @@ class CreateServerRequestInstall: Password used for the service to install. """ + partitioning_schema: Optional[Schema] + """ + Partitioning schema. + """ + @dataclass class OS: @@ -474,21 +659,6 @@ class OS: URL of this OS's logo. """ - enabled: bool - """ - Defines if the operating system is enabled or not. - """ - - license_required: bool - """ - License required (check server options for pricing details). - """ - - allowed: bool - """ - Defines if a specific Organization is allowed to install this OS type. - """ - ssh: Optional[OSOSField] """ Object defining the SSH requirements to install the OS. @@ -514,6 +684,26 @@ class OS: Object defining the password requirements to install the service. """ + enabled: bool + """ + Defines if the operating system is enabled or not. + """ + + license_required: bool + """ + License required (check server options for pricing details). + """ + + allowed: bool + """ + Defines if a specific Organization is allowed to install this OS type. + """ + + custom_partitioning_supported: bool + """ + Defines if custom partitioning is supported by this OS. + """ + @dataclass class Offer: @@ -537,6 +727,11 @@ class Offer: Public bandwidth available (in bits/s) with the offer. """ + max_bandwidth: int + """ + Maximum public bandwidth available (in bits/s) depending on available options. + """ + commercial_range: str """ Commercial range of the offer. @@ -552,24 +747,24 @@ class Offer: Defines whether the offer is currently available. """ - price_per_hour: Optional[Money] + cpus: List[CPU] """ - Price of the offer for the next 60 minutes (a server order at 11h32 will be payed until 12h32). + CPU specifications of the offer. """ - price_per_month: Optional[Money] + memories: List[Memory] """ - Monthly price of the offer, if subscribing on a monthly basis. + Memory specifications of the offer. """ - cpus: List[CPU] + price_per_hour: Optional[Money] """ - CPU specifications of the offer. + Price of the offer for the next 60 minutes (a server order at 11h32 will be paid until 12h32). """ - memories: List[Memory] + price_per_month: Optional[Money] """ - Memory specifications of the offer. + Monthly price of the offer, if subscribing on a monthly basis. """ quota_name: str @@ -622,11 +817,21 @@ class Offer: Array of tags attached to the offer. """ + gpus: List[GPU] + """ + GPU specifications of the offer. + """ + fee: Optional[Money] """ One time fee invoiced by Scaleway for the setup and activation of the server. """ + monthly_offer_id: Optional[str] + """ + Exist only for hourly offers, to migrate to the monthly offer. + """ + @dataclass class Option: @@ -645,6 +850,16 @@ class Option: Defines whether the option is manageable (could be added or removed). """ + license: Optional[LicenseOption] + + public_bandwidth: Optional[PublicBandwidthOption] + + private_network: Optional[PrivateNetworkOption] + + remote_access: Optional[RemoteAccessOption] + + certification: Optional[CertificationOption] + @dataclass class ServerEvent: @@ -784,7 +999,7 @@ class Server: Boot type of the server. """ - zone: Zone + zone: ScwZone """ Zone in which is the server located. """ @@ -845,7 +1060,7 @@ class AddOptionServerRequest: ID of the option to add. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -896,7 +1111,7 @@ class CreateServerRequest: Description associated with the server, max 255 characters. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -933,7 +1148,7 @@ class DeleteOptionServerRequest: ID of the option to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -946,7 +1161,7 @@ class DeleteServerRequest: ID of the server to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -959,7 +1174,25 @@ class GetBMCAccessRequest: ID of the server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetDefaultPartitioningSchemaRequest: + offer_id: str + """ + ID of the offer. + """ + + os_id: str + """ + ID of the OS. + """ + + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -972,7 +1205,7 @@ class GetOSRequest: ID of the OS. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -985,7 +1218,7 @@ class GetOfferRequest: ID of the researched Offer. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -998,7 +1231,7 @@ class GetOptionRequest: ID of the option. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1011,7 +1244,7 @@ class GetServerMetricsRequest: Server ID to get the metrics. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1032,7 +1265,7 @@ class GetServerRequest: ID of the server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1060,7 +1293,7 @@ class InstallServerRequest: SSH key IDs authorized on the server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1085,10 +1318,15 @@ class InstallServerRequest: Password used for the service to install. """ + partitioning_schema: Optional[Schema] + """ + Partitioning schema. + """ + @dataclass class ListOSRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1124,7 +1362,7 @@ class ListOSResponse: @dataclass class ListOffersRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1144,6 +1382,11 @@ class ListOffersRequest: Subscription period type to filter offers by. """ + name: Optional[str] + """ + Offer name to filter offers by. + """ + @dataclass class ListOffersResponse: @@ -1160,7 +1403,7 @@ class ListOffersResponse: @dataclass class ListOptionsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1206,7 +1449,7 @@ class ListServerEventsRequest: ID of the server events searched. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1249,7 +1492,7 @@ class ListServerPrivateNetworksResponse: @dataclass class ListServersRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1315,7 +1558,7 @@ class ListServersResponse: @dataclass class ListSettingsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1354,6 +1597,19 @@ class ListSettingsResponse: """ +@dataclass +class MigrateServerToMonthlyOfferRequest: + server_id: str + """ + ID of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class PrivateNetworkApiAddServerPrivateNetworkRequest: server_id: str @@ -1366,7 +1622,7 @@ class PrivateNetworkApiAddServerPrivateNetworkRequest: The ID of the Private Network. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1384,7 +1640,7 @@ class PrivateNetworkApiDeleteServerPrivateNetworkRequest: The ID of the Private Network. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1392,7 +1648,7 @@ class PrivateNetworkApiDeleteServerPrivateNetworkRequest: @dataclass class PrivateNetworkApiListServerPrivateNetworksRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1445,7 +1701,7 @@ class PrivateNetworkApiSetServerPrivateNetworksRequest: The IDs of the Private Networks. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1458,7 +1714,7 @@ class RebootServerRequest: ID of the server to reboot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1486,7 +1742,7 @@ class StartBMCAccessRequest: The IP authorized to connect to the server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1499,7 +1755,7 @@ class StartServerRequest: ID of the server to start. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1517,7 +1773,7 @@ class StopBMCAccessRequest: ID of the server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1530,7 +1786,7 @@ class StopServerRequest: ID of the server to stop. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1548,7 +1804,7 @@ class UpdateIPRequest: ID of the IP to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1566,7 +1822,7 @@ class UpdateServerRequest: ID of the server to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1594,7 +1850,7 @@ class UpdateSettingRequest: ID of the setting. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1603,3 +1859,26 @@ class UpdateSettingRequest: """ Defines whether the setting is enabled. """ + + +@dataclass +class ValidatePartitioningSchemaRequest: + offer_id: str + """ + Offer ID of the server. + """ + + os_id: str + """ + OS ID. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + partitioning_schema: Optional[Schema] + """ + Partitioning schema. + """ diff --git a/scaleway-async/scaleway_async/baremetal/v3/__init__.py b/scaleway-async/scaleway_async/baremetal/v3/__init__.py new file mode 100644 index 00000000..990fa6b2 --- /dev/null +++ b/scaleway-async/scaleway_async/baremetal/v3/__init__.py @@ -0,0 +1,27 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import ListServerPrivateNetworksRequestOrderBy +from .types import ServerPrivateNetworkStatus +from .content import SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES +from .types import ServerPrivateNetwork +from .types import ListServerPrivateNetworksResponse +from .types import PrivateNetworkApiAddServerPrivateNetworkRequest +from .types import PrivateNetworkApiDeleteServerPrivateNetworkRequest +from .types import PrivateNetworkApiListServerPrivateNetworksRequest +from .types import PrivateNetworkApiSetServerPrivateNetworksRequest +from .types import SetServerPrivateNetworksResponse +from .api import BaremetalV3PrivateNetworkAPI + +__all__ = [ + "ListServerPrivateNetworksRequestOrderBy", + "ServerPrivateNetworkStatus", + "SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES", + "ServerPrivateNetwork", + "ListServerPrivateNetworksResponse", + "PrivateNetworkApiAddServerPrivateNetworkRequest", + "PrivateNetworkApiDeleteServerPrivateNetworkRequest", + "PrivateNetworkApiListServerPrivateNetworksRequest", + "PrivateNetworkApiSetServerPrivateNetworksRequest", + "SetServerPrivateNetworksResponse", + "BaremetalV3PrivateNetworkAPI", +] diff --git a/scaleway-async/scaleway_async/baremetal/v3/api.py b/scaleway-async/scaleway_async/baremetal/v3/api.py new file mode 100644 index 00000000..2aa48dfc --- /dev/null +++ b/scaleway-async/scaleway_async/baremetal/v3/api.py @@ -0,0 +1,262 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Dict, List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + validate_path_param, + fetch_all_pages_async, +) +from .types import ( + ListServerPrivateNetworksRequestOrderBy, + ListServerPrivateNetworksResponse, + PrivateNetworkApiAddServerPrivateNetworkRequest, + PrivateNetworkApiSetServerPrivateNetworksRequest, + ServerPrivateNetwork, + SetServerPrivateNetworksResponse, +) +from .marshalling import ( + unmarshal_ServerPrivateNetwork, + unmarshal_ListServerPrivateNetworksResponse, + unmarshal_SetServerPrivateNetworksResponse, + marshal_PrivateNetworkApiAddServerPrivateNetworkRequest, + marshal_PrivateNetworkApiSetServerPrivateNetworksRequest, +) + + +class BaremetalV3PrivateNetworkAPI(API): + """ + Elastic Metal - Private Networks API. + """ + + async def add_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> ServerPrivateNetwork: + """ + Add a server to a Private Network. + Add an Elastic Metal server to a Private Network. + :param server_id: UUID of the server. + :param private_network_id: UUID of the Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param ipam_ip_ids: IPAM IDs of an IPs to attach to the server. + :return: :class:`ServerPrivateNetwork ` + + Usage: + :: + + result = await api.add_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/baremetal/v3/zones/{param_zone}/servers/{param_server_id}/private-networks", + body=marshal_PrivateNetworkApiAddServerPrivateNetworkRequest( + PrivateNetworkApiAddServerPrivateNetworkRequest( + server_id=server_id, + private_network_id=private_network_id, + zone=zone, + ipam_ip_ids=ipam_ip_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ServerPrivateNetwork(res.json()) + + async def set_server_private_networks( + self, + *, + server_id: str, + per_private_network_ipam_ip_ids: Dict[str, List[str]], + zone: Optional[ScwZone] = None, + ) -> SetServerPrivateNetworksResponse: + """ + Set multiple Private Networks on a server. + Configure multiple Private Networks on an Elastic Metal server. + :param server_id: UUID of the server. + :param per_private_network_ipam_ip_ids: Object where the keys are the UUIDs of Private Networks and the values are arrays of IPAM IDs representing the IPs to assign to this Elastic Metal server on the Private Network. If the array supplied for a Private Network is empty, the next available IP from the Private Network's CIDR block will automatically be used for attachment. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`SetServerPrivateNetworksResponse ` + + Usage: + :: + + result = await api.set_server_private_networks( + server_id="example", + per_private_network_ipam_ip_ids={}, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "PUT", + f"/baremetal/v3/zones/{param_zone}/servers/{param_server_id}/private-networks", + body=marshal_PrivateNetworkApiSetServerPrivateNetworksRequest( + PrivateNetworkApiSetServerPrivateNetworksRequest( + server_id=server_id, + per_private_network_ipam_ip_ids=per_private_network_ipam_ip_ids, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetServerPrivateNetworksResponse(res.json()) + + async def list_server_private_networks( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + server_id: Optional[str] = None, + private_network_id: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> ListServerPrivateNetworksResponse: + """ + List the Private Networks of a server. + List the Private Networks of an Elastic Metal server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order for the returned Private Networks. + :param page: Page number for the returned Private Networks. + :param page_size: Maximum number of Private Networks per page. + :param server_id: Filter Private Networks by server UUID. + :param private_network_id: Filter Private Networks by Private Network UUID. + :param organization_id: Filter Private Networks by organization UUID. + :param project_id: Filter Private Networks by project UUID. + :param ipam_ip_ids: Filter Private Networks by IPAM IP UUIDs. + :return: :class:`ListServerPrivateNetworksResponse ` + + Usage: + :: + + result = await api.list_server_private_networks() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/baremetal/v3/zones/{param_zone}/server-private-networks", + params={ + "ipam_ip_ids": ipam_ip_ids, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "private_network_id": private_network_id, + "project_id": project_id or self.client.default_project_id, + "server_id": server_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServerPrivateNetworksResponse(res.json()) + + async def list_server_private_networks_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + server_id: Optional[str] = None, + private_network_id: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> List[ServerPrivateNetwork]: + """ + List the Private Networks of a server. + List the Private Networks of an Elastic Metal server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order for the returned Private Networks. + :param page: Page number for the returned Private Networks. + :param page_size: Maximum number of Private Networks per page. + :param server_id: Filter Private Networks by server UUID. + :param private_network_id: Filter Private Networks by Private Network UUID. + :param organization_id: Filter Private Networks by organization UUID. + :param project_id: Filter Private Networks by project UUID. + :param ipam_ip_ids: Filter Private Networks by IPAM IP UUIDs. + :return: :class:`List[ServerPrivateNetwork] ` + + Usage: + :: + + result = await api.list_server_private_networks_all() + """ + + return await fetch_all_pages_async( + type=ListServerPrivateNetworksResponse, + key="server_private_networks", + fetcher=self.list_server_private_networks, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "server_id": server_id, + "private_network_id": private_network_id, + "organization_id": organization_id, + "project_id": project_id, + "ipam_ip_ids": ipam_ip_ids, + }, + ) + + async def delete_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a Private Network. + :param server_id: UUID of the server. + :param private_network_id: UUID of the Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + param_private_network_id = validate_path_param( + "private_network_id", private_network_id + ) + + res = self._request( + "DELETE", + f"/baremetal/v3/zones/{param_zone}/servers/{param_server_id}/private-networks/{param_private_network_id}", + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/baremetal/v3/content.py b/scaleway-async/scaleway_async/baremetal/v3/content.py new file mode 100644 index 00000000..66774cc7 --- /dev/null +++ b/scaleway-async/scaleway_async/baremetal/v3/content.py @@ -0,0 +1,15 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + ServerPrivateNetworkStatus, +) + +SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES: List[ServerPrivateNetworkStatus] = [ + ServerPrivateNetworkStatus.ATTACHING, + ServerPrivateNetworkStatus.DETACHING, +] +""" +Lists transient statutes of the enum :class:`ServerPrivateNetworkStatus `. +""" diff --git a/scaleway-async/scaleway_async/baremetal/v3/marshalling.py b/scaleway-async/scaleway_async/baremetal/v3/marshalling.py new file mode 100644 index 00000000..d1c8dee3 --- /dev/null +++ b/scaleway-async/scaleway_async/baremetal/v3/marshalling.py @@ -0,0 +1,142 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from .types import ( + ServerPrivateNetwork, + ListServerPrivateNetworksResponse, + SetServerPrivateNetworksResponse, + PrivateNetworkApiAddServerPrivateNetworkRequest, + PrivateNetworkApiSetServerPrivateNetworksRequest, +) + + +def unmarshal_ServerPrivateNetwork(data: Any) -> ServerPrivateNetwork: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerPrivateNetwork' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("server_id", None) + if field is not None: + args["server_id"] = field + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("ipam_ip_ids", None) + if field is not None: + args["ipam_ip_ids"] = field + + field = data.get("vlan", None) + if field is not None: + args["vlan"] = field + else: + args["vlan"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return ServerPrivateNetwork(**args) + + +def unmarshal_ListServerPrivateNetworksResponse( + data: Any, +) -> ListServerPrivateNetworksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServerPrivateNetworksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("server_private_networks", None) + if field is not None: + args["server_private_networks"] = ( + [unmarshal_ServerPrivateNetwork(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListServerPrivateNetworksResponse(**args) + + +def unmarshal_SetServerPrivateNetworksResponse( + data: Any, +) -> SetServerPrivateNetworksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetServerPrivateNetworksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("server_private_networks", None) + if field is not None: + args["server_private_networks"] = ( + [unmarshal_ServerPrivateNetwork(v) for v in field] + if field is not None + else None + ) + + return SetServerPrivateNetworksResponse(**args) + + +def marshal_PrivateNetworkApiAddServerPrivateNetworkRequest( + request: PrivateNetworkApiAddServerPrivateNetworkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + if request.ipam_ip_ids is not None: + output["ipam_ip_ids"] = request.ipam_ip_ids + + return output + + +def marshal_PrivateNetworkApiSetServerPrivateNetworksRequest( + request: PrivateNetworkApiSetServerPrivateNetworksRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.per_private_network_ipam_ip_ids is not None: + output["per_private_network_ipam_ip_ids"] = { + key: value for key, value in request.per_private_network_ipam_ip_ids.items() + } + + return output diff --git a/scaleway-async/scaleway_async/baremetal/v3/types.py b/scaleway-async/scaleway_async/baremetal/v3/types.py new file mode 100644 index 00000000..e4831889 --- /dev/null +++ b/scaleway-async/scaleway_async/baremetal/v3/types.py @@ -0,0 +1,204 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class ListServerPrivateNetworksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + UPDATED_AT_ASC = "updated_at_asc" + UPDATED_AT_DESC = "updated_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ServerPrivateNetworkStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + ATTACHING = "attaching" + ATTACHED = "attached" + ERROR = "error" + DETACHING = "detaching" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ServerPrivateNetwork: + id: str + """ + UUID of the Server-to-Private Network mapping. + """ + + project_id: str + """ + Private Network Project UUID. + """ + + server_id: str + """ + Server UUID. + """ + + private_network_id: str + """ + Private Network UUID. + """ + + status: ServerPrivateNetworkStatus + """ + Configuration status of the Private Network. + """ + + ipam_ip_ids: List[str] + """ + IPAM IP IDs of the server, if it has any. + """ + + vlan: Optional[int] + """ + VLAN UUID associated with the Private Network. + """ + + created_at: Optional[datetime] + """ + Private Network creation date. + """ + + updated_at: Optional[datetime] + """ + Date the Private Network was last modified. + """ + + +@dataclass +class ListServerPrivateNetworksResponse: + server_private_networks: List[ServerPrivateNetwork] + + total_count: int + + +@dataclass +class PrivateNetworkApiAddServerPrivateNetworkRequest: + server_id: str + """ + UUID of the server. + """ + + private_network_id: str + """ + UUID of the Private Network. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + ipam_ip_ids: Optional[List[str]] + """ + IPAM IDs of an IPs to attach to the server. + """ + + +@dataclass +class PrivateNetworkApiDeleteServerPrivateNetworkRequest: + server_id: str + """ + UUID of the server. + """ + + private_network_id: str + """ + UUID of the Private Network. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class PrivateNetworkApiListServerPrivateNetworksRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] + """ + Sort order for the returned Private Networks. + """ + + page: Optional[int] + """ + Page number for the returned Private Networks. + """ + + page_size: Optional[int] + """ + Maximum number of Private Networks per page. + """ + + server_id: Optional[str] + """ + Filter Private Networks by server UUID. + """ + + private_network_id: Optional[str] + """ + Filter Private Networks by Private Network UUID. + """ + + organization_id: Optional[str] + """ + Filter Private Networks by organization UUID. + """ + + project_id: Optional[str] + """ + Filter Private Networks by project UUID. + """ + + ipam_ip_ids: Optional[List[str]] + """ + Filter Private Networks by IPAM IP UUIDs. + """ + + +@dataclass +class PrivateNetworkApiSetServerPrivateNetworksRequest: + server_id: str + """ + UUID of the server. + """ + + per_private_network_ipam_ip_ids: Dict[str, List[str]] + """ + Object where the keys are the UUIDs of Private Networks and the values are arrays of IPAM IDs representing the IPs to assign to this Elastic Metal server on the Private Network. If the array supplied for a Private Network is empty, the next available IP from the Private Network's CIDR block will automatically be used for attachment. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SetServerPrivateNetworksResponse: + server_private_networks: List[ServerPrivateNetwork] diff --git a/scaleway-async/scaleway_async/billing/v2alpha1/api.py b/scaleway-async/scaleway_async/billing/v2alpha1/api.py index 112aad4e..3c113924 100644 --- a/scaleway-async/scaleway_async/billing/v2alpha1/api.py +++ b/scaleway-async/scaleway_async/billing/v2alpha1/api.py @@ -33,7 +33,7 @@ class BillingV2Alpha1API(API): """ - This API allows you to query your consumption. + This API allows you to manage and query your Scaleway billing and consumption. """ async def get_consumption( diff --git a/scaleway-async/scaleway_async/billing/v2alpha1/marshalling.py b/scaleway-async/scaleway_async/billing/v2alpha1/marshalling.py index 351e16f2..58682a3f 100644 --- a/scaleway-async/scaleway_async/billing/v2alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/billing/v2alpha1/marshalling.py @@ -48,6 +48,8 @@ def unmarshal_GetConsumptionResponseConsumption( field = data.get("value", None) if field is not None: args["value"] = unmarshal_Money(field) + else: + args["value"] = None return GetConsumptionResponseConsumption(**args) @@ -71,6 +73,8 @@ def unmarshal_GetConsumptionResponse(data: Any) -> GetConsumptionResponse: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return GetConsumptionResponse(**args) @@ -86,6 +90,8 @@ def unmarshal_DiscountCoupon(data: Any) -> DiscountCoupon: field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None return DiscountCoupon(**args) @@ -98,7 +104,7 @@ def unmarshal_DiscountFilter(data: Any) -> DiscountFilter: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -106,6 +112,10 @@ def unmarshal_DiscountFilter(data: Any) -> DiscountFilter: if field is not None: args["value"] = field + field = data.get("exclude", None) + if field is not None: + args["exclude"] = field + return DiscountFilter(**args) @@ -156,18 +166,26 @@ def unmarshal_Discount(data: Any) -> Discount: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("start_date", None) if field is not None: args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None field = data.get("stop_date", None) if field is not None: args["stop_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stop_date"] = None field = data.get("coupon", None) if field is not None: args["coupon"] = unmarshal_DiscountCoupon(field) + else: + args["coupon"] = None return Discount(**args) @@ -216,24 +234,34 @@ def unmarshal_Invoice(data: Any) -> Invoice: field = data.get("start_date", None) if field is not None: args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None field = data.get("issued_date", None) if field is not None: args["issued_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["issued_date"] = None field = data.get("due_date", None) if field is not None: args["due_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["due_date"] = None field = data.get("total_untaxed", None) if field is not None: args["total_untaxed"] = unmarshal_Money(field) + else: + args["total_untaxed"] = None field = data.get("total_taxed", None) if field is not None: args["total_taxed"] = unmarshal_Money(field) + else: + args["total_taxed"] = None return Invoice(**args) diff --git a/scaleway-async/scaleway_async/billing/v2alpha1/types.py b/scaleway-async/scaleway_async/billing/v2alpha1/types.py index 34ea0916..e4458efc 100644 --- a/scaleway-async/scaleway_async/billing/v2alpha1/types.py +++ b/scaleway-async/scaleway_async/billing/v2alpha1/types.py @@ -102,6 +102,11 @@ class DiscountFilter: Value of filter, it can be a product/range/region/zone value. """ + exclude: bool + """ + Boolean to describe if filter is an excluding filter. + """ + @dataclass class GetConsumptionResponseConsumption: diff --git a/scaleway-async/scaleway_async/billing/v2beta1/api.py b/scaleway-async/scaleway_async/billing/v2beta1/api.py index e9fec27b..3b1e1350 100644 --- a/scaleway-async/scaleway_async/billing/v2beta1/api.py +++ b/scaleway-async/scaleway_async/billing/v2beta1/api.py @@ -44,7 +44,7 @@ class BillingV2Beta1API(API): """ - This API allows you to query your consumption. + This API allows you to manage and query your Scaleway billing and consumption. """ async def list_consumptions( @@ -438,7 +438,10 @@ async def list_discounts( ) -> ListDiscountsResponse: """ List discounts. - List all discounts for your organization and usable categories, products, offers, references, regions and zones where the discount can be applied. + List all discounts for your Organization and usable categories, products, offers, references, regions and zones where the discount can be applied. As a reseller: + - If you do not specify an `organization_id` you will list the discounts applied to your own Organization and your customers + - If you indicate your `organization_id` you will list only the discounts applied to your Organization + - If you indicate `the organization_id` of one of your customers, you will list the discounts applied to their Organization. :param order_by: Order discounts in the response by their description. :param page: Positive integer to choose the page to return. :param page_size: Positive integer lower or equal to 100 to select the number of items to return. @@ -476,7 +479,10 @@ async def list_discounts_all( ) -> List[Discount]: """ List discounts. - List all discounts for your organization and usable categories, products, offers, references, regions and zones where the discount can be applied. + List all discounts for your Organization and usable categories, products, offers, references, regions and zones where the discount can be applied. As a reseller: + - If you do not specify an `organization_id` you will list the discounts applied to your own Organization and your customers + - If you indicate your `organization_id` you will list only the discounts applied to your Organization + - If you indicate `the organization_id` of one of your customers, you will list the discounts applied to their Organization. :param order_by: Order discounts in the response by their description. :param page: Positive integer to choose the page to return. :param page_size: Positive integer lower or equal to 100 to select the number of items to return. diff --git a/scaleway-async/scaleway_async/billing/v2beta1/marshalling.py b/scaleway-async/scaleway_async/billing/v2beta1/marshalling.py index 48328d55..19355940 100644 --- a/scaleway-async/scaleway_async/billing/v2beta1/marshalling.py +++ b/scaleway-async/scaleway_async/billing/v2beta1/marshalling.py @@ -44,28 +44,38 @@ def unmarshal_Invoice(data: Any) -> Invoice: field = data.get("start_date", None) if field is not None: args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None field = data.get("stop_date", None) if field is not None: args["stop_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stop_date"] = None field = data.get("billing_period", None) if field is not None: args["billing_period"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["billing_period"] = None field = data.get("issued_date", None) if field is not None: args["issued_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["issued_date"] = None field = data.get("due_date", None) if field is not None: args["due_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["due_date"] = None - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -84,22 +94,32 @@ def unmarshal_Invoice(data: Any) -> Invoice: field = data.get("total_untaxed", None) if field is not None: args["total_untaxed"] = unmarshal_Money(field) + else: + args["total_untaxed"] = None field = data.get("total_taxed", None) if field is not None: args["total_taxed"] = unmarshal_Money(field) + else: + args["total_taxed"] = None field = data.get("total_tax", None) if field is not None: args["total_tax"] = unmarshal_Money(field) + else: + args["total_tax"] = None field = data.get("total_discount", None) if field is not None: args["total_discount"] = unmarshal_Money(field) + else: + args["total_discount"] = None field = data.get("total_undiscount", None) if field is not None: args["total_undiscount"] = unmarshal_Money(field) + else: + args["total_undiscount"] = None return Invoice(**args) @@ -145,6 +165,8 @@ def unmarshal_ListConsumptionsResponseConsumption( field = data.get("value", None) if field is not None: args["value"] = unmarshal_Money(field) + else: + args["value"] = None return ListConsumptionsResponseConsumption(**args) @@ -176,6 +198,8 @@ def unmarshal_ListConsumptionsResponse(data: Any) -> ListConsumptionsResponse: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return ListConsumptionsResponse(**args) @@ -191,6 +215,8 @@ def unmarshal_DiscountCoupon(data: Any) -> DiscountCoupon: field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None return DiscountCoupon(**args) @@ -203,7 +229,7 @@ def unmarshal_DiscountFilter(data: Any) -> DiscountFilter: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -211,6 +237,10 @@ def unmarshal_DiscountFilter(data: Any) -> DiscountFilter: if field is not None: args["value"] = field + field = data.get("exclude", None) + if field is not None: + args["exclude"] = field + return DiscountFilter(**args) @@ -261,18 +291,26 @@ def unmarshal_Discount(data: Any) -> Discount: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("start_date", None) if field is not None: args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None field = data.get("stop_date", None) if field is not None: args["stop_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stop_date"] = None field = data.get("coupon", None) if field is not None: args["coupon"] = unmarshal_DiscountCoupon(field) + else: + args["coupon"] = None return Discount(**args) @@ -338,10 +376,14 @@ def unmarshal_ListTaxesResponseTax(data: Any) -> ListTaxesResponseTax: field = data.get("rate", None) if field is not None: args["rate"] = field + else: + args["rate"] = None field = data.get("total_tax_value", None) if field is not None: args["total_tax_value"] = field + else: + args["total_tax_value"] = None return ListTaxesResponseTax(**args) @@ -369,5 +411,7 @@ def unmarshal_ListTaxesResponse(data: Any) -> ListTaxesResponse: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return ListTaxesResponse(**args) diff --git a/scaleway-async/scaleway_async/billing/v2beta1/types.py b/scaleway-async/scaleway_async/billing/v2beta1/types.py index bf0979ca..3bb5b5d2 100644 --- a/scaleway-async/scaleway_async/billing/v2beta1/types.py +++ b/scaleway-async/scaleway_async/billing/v2beta1/types.py @@ -94,6 +94,10 @@ def __str__(self) -> str: class ListDiscountsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATION_DATE_DESC = "creation_date_desc" CREATION_DATE_ASC = "creation_date_asc" + START_DATE_DESC = "start_date_desc" + START_DATE_ASC = "start_date_asc" + STOP_DATE_DESC = "stop_date_desc" + STOP_DATE_ASC = "stop_date_asc" def __str__(self) -> str: return str(self.value) @@ -149,6 +153,11 @@ class DiscountFilter: Value of filter. """ + exclude: bool + """ + Boolean to describe if filter is an excluding filter. + """ + @dataclass class ListConsumptionsResponseConsumption: @@ -202,7 +211,7 @@ class Discount: organization_id: str """ - The organization ID of the discount. + The Organization ID of the discount. """ description: str diff --git a/scaleway-async/scaleway_async/block/v1/__init__.py b/scaleway-async/scaleway_async/block/v1/__init__.py new file mode 100644 index 00000000..1e48ec13 --- /dev/null +++ b/scaleway-async/scaleway_async/block/v1/__init__.py @@ -0,0 +1,75 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import ListSnapshotsRequestOrderBy +from .types import ListVolumesRequestOrderBy +from .types import ReferenceStatus +from .content import REFERENCE_TRANSIENT_STATUSES +from .types import ReferenceType +from .types import SnapshotStatus +from .content import SNAPSHOT_TRANSIENT_STATUSES +from .types import StorageClass +from .types import VolumeStatus +from .content import VOLUME_TRANSIENT_STATUSES +from .types import Reference +from .types import SnapshotParentVolume +from .types import VolumeSpecifications +from .types import CreateVolumeRequestFromEmpty +from .types import CreateVolumeRequestFromSnapshot +from .types import Snapshot +from .types import VolumeType +from .types import Volume +from .types import CreateSnapshotRequest +from .types import CreateVolumeRequest +from .types import DeleteSnapshotRequest +from .types import DeleteVolumeRequest +from .types import ExportSnapshotToObjectStorageRequest +from .types import GetSnapshotRequest +from .types import GetVolumeRequest +from .types import ImportSnapshotFromObjectStorageRequest +from .types import ListSnapshotsRequest +from .types import ListSnapshotsResponse +from .types import ListVolumeTypesRequest +from .types import ListVolumeTypesResponse +from .types import ListVolumesRequest +from .types import ListVolumesResponse +from .types import UpdateSnapshotRequest +from .types import UpdateVolumeRequest +from .api import BlockV1API + +__all__ = [ + "ListSnapshotsRequestOrderBy", + "ListVolumesRequestOrderBy", + "ReferenceStatus", + "REFERENCE_TRANSIENT_STATUSES", + "ReferenceType", + "SnapshotStatus", + "SNAPSHOT_TRANSIENT_STATUSES", + "StorageClass", + "VolumeStatus", + "VOLUME_TRANSIENT_STATUSES", + "Reference", + "SnapshotParentVolume", + "VolumeSpecifications", + "CreateVolumeRequestFromEmpty", + "CreateVolumeRequestFromSnapshot", + "Snapshot", + "VolumeType", + "Volume", + "CreateSnapshotRequest", + "CreateVolumeRequest", + "DeleteSnapshotRequest", + "DeleteVolumeRequest", + "ExportSnapshotToObjectStorageRequest", + "GetSnapshotRequest", + "GetVolumeRequest", + "ImportSnapshotFromObjectStorageRequest", + "ListSnapshotsRequest", + "ListSnapshotsResponse", + "ListVolumeTypesRequest", + "ListVolumeTypesResponse", + "ListVolumesRequest", + "ListVolumesResponse", + "UpdateSnapshotRequest", + "UpdateVolumeRequest", + "BlockV1API", +] diff --git a/scaleway-async/scaleway_async/block/v1/api.py b/scaleway-async/scaleway_async/block/v1/api.py new file mode 100644 index 00000000..da4caa99 --- /dev/null +++ b/scaleway-async/scaleway_async/block/v1/api.py @@ -0,0 +1,837 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + ListSnapshotsRequestOrderBy, + ListVolumesRequestOrderBy, + CreateSnapshotRequest, + CreateVolumeRequest, + CreateVolumeRequestFromEmpty, + CreateVolumeRequestFromSnapshot, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + ListSnapshotsResponse, + ListVolumeTypesResponse, + ListVolumesResponse, + Snapshot, + UpdateSnapshotRequest, + UpdateVolumeRequest, + Volume, + VolumeType, +) +from .content import ( + SNAPSHOT_TRANSIENT_STATUSES, + VOLUME_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_Snapshot, + unmarshal_Volume, + unmarshal_ListSnapshotsResponse, + unmarshal_ListVolumeTypesResponse, + unmarshal_ListVolumesResponse, + marshal_CreateSnapshotRequest, + marshal_CreateVolumeRequest, + marshal_ExportSnapshotToObjectStorageRequest, + marshal_ImportSnapshotFromObjectStorageRequest, + marshal_UpdateSnapshotRequest, + marshal_UpdateVolumeRequest, +) + + +class BlockV1API(API): + """ + This API allows you to manage your Block Storage volumes. + """ + + async def list_volume_types( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListVolumeTypesResponse: + """ + List volume types. + List all available volume types in a specified zone. The volume types listed are ordered by name in ascending order. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :return: :class:`ListVolumeTypesResponse ` + + Usage: + :: + + result = await api.list_volume_types() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volume-types", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListVolumeTypesResponse(res.json()) + + async def list_volume_types_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[VolumeType]: + """ + List volume types. + List all available volume types in a specified zone. The volume types listed are ordered by name in ascending order. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :return: :class:`List[VolumeType] ` + + Usage: + :: + + result = await api.list_volume_types_all() + """ + + return await fetch_all_pages_async( + type=ListVolumeTypesResponse, + key="volume_types", + fetcher=self.list_volume_types, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + }, + ) + + async def list_volumes( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListVolumesRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListVolumesResponse: + """ + List volumes. + List all existing volumes in a specified zone. By default, the volumes listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param name: Filter the return volumes by their names. + :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. + :return: :class:`ListVolumesResponse ` + + Usage: + :: + + result = await api.list_volumes() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volumes", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "product_resource_id": product_resource_id, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListVolumesResponse(res.json()) + + async def list_volumes_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListVolumesRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Volume]: + """ + List volumes. + List all existing volumes in a specified zone. By default, the volumes listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param name: Filter the return volumes by their names. + :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. + :return: :class:`List[Volume] ` + + Usage: + :: + + result = await api.list_volumes_all() + """ + + return await fetch_all_pages_async( + type=ListVolumesResponse, + key="volumes", + fetcher=self.list_volumes, + args={ + "zone": zone, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "page": page, + "page_size": page_size, + "name": name, + "product_resource_id": product_resource_id, + "tags": tags, + }, + ) + + async def create_volume( + self, + *, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + perf_iops: Optional[int] = None, + project_id: Optional[str] = None, + from_empty: Optional[CreateVolumeRequestFromEmpty] = None, + from_snapshot: Optional[CreateVolumeRequestFromSnapshot] = None, + tags: Optional[List[str]] = None, + ) -> Volume: + """ + Create a volume. + To create a new volume from scratch, you must specify `from_empty` and the `size`. + To create a volume from an existing snapshot, specify `from_snapshot` and the `snapshot_id` in the request payload instead, size is optional and can be specified if you need to extend the original size. The volume will take on the same volume class and underlying IOPS limitations as the original snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the volume. + :param perf_iops: The maximum IO/s expected, according to the different options available in stock (`5000 | 15000`). + One-Of ('requirements'): at most one of 'perf_iops' could be set. + :param project_id: UUID of the project the volume belongs to. + :param from_empty: Specify the size of the new volume if creating a new one from scratch. + One-Of ('from'): at most one of 'from_empty', 'from_snapshot' could be set. + :param from_snapshot: Specify the snapshot ID of the original snapshot. + One-Of ('from'): at most one of 'from_empty', 'from_snapshot' could be set. + :param tags: List of tags assigned to the volume. + :return: :class:`Volume ` + + Usage: + :: + + result = await api.create_volume() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/volumes", + body=marshal_CreateVolumeRequest( + CreateVolumeRequest( + zone=zone, + name=name or random_name(prefix="vol"), + project_id=project_id, + tags=tags, + from_empty=from_empty, + from_snapshot=from_snapshot, + perf_iops=perf_iops, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + async def get_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + ) -> Volume: + """ + Get a volume. + Retrieve technical information about a specific volume. Details such as size, type, and status are returned in the response. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Volume ` + + Usage: + :: + + result = await api.get_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + async def wait_for_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[Volume, Union[bool, Awaitable[bool]]]] = None, + ) -> Volume: + """ + Get a volume. + Retrieve technical information about a specific volume. Details such as size, type, and status are returned in the response. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Volume ` + + Usage: + :: + + result = await api.get_volume( + volume_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in VOLUME_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_volume, + options=options, + args={ + "volume_id": volume_id, + "zone": zone, + }, + ) + + async def delete_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a detached volume. + You must specify the `volume_id` of the volume you want to delete. The volume must not be in the `in_use` status. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "DELETE", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + ) + + self._throw_on_error(res) + + async def update_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + size: Optional[int] = None, + tags: Optional[List[str]] = None, + perf_iops: Optional[int] = None, + ) -> Volume: + """ + Update a volume. + Update the technical details of a volume, such as its name, tags, or its new size and `volume_type` (within the same Block Storage class). + You can only resize a volume to a larger size. It is currently not possible to change your Block Storage Class. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: When defined, is the new name of the volume. + :param size: Size in bytes of the volume, with a granularity of 1 GB (10^9 bytes). + Must be compliant with the minimum (1GB) and maximum (10TB) allowed size. + :param tags: List of tags assigned to the volume. + :param perf_iops: The selected value must be available for the volume's current storage class. + :return: :class:`Volume ` + + Usage: + :: + + result = await api.update_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "PATCH", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + body=marshal_UpdateVolumeRequest( + UpdateVolumeRequest( + volume_id=volume_id, + zone=zone, + name=name, + size=size, + tags=tags, + perf_iops=perf_iops, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + async def list_snapshots( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + volume_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListSnapshotsResponse: + """ + List all snapshots. + List all available snapshots in a specified zone. By default, the snapshots listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param volume_id: Filter snapshots by the ID of the original volume. + :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. + :return: :class:`ListSnapshotsResponse ` + + Usage: + :: + + result = await api.list_snapshots() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/snapshots", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + "volume_id": volume_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListSnapshotsResponse(res.json()) + + async def list_snapshots_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + volume_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Snapshot]: + """ + List all snapshots. + List all available snapshots in a specified zone. By default, the snapshots listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param volume_id: Filter snapshots by the ID of the original volume. + :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. + :return: :class:`List[Snapshot] ` + + Usage: + :: + + result = await api.list_snapshots_all() + """ + + return await fetch_all_pages_async( + type=ListSnapshotsResponse, + key="snapshots", + fetcher=self.list_snapshots, + args={ + "zone": zone, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "page": page, + "page_size": page_size, + "volume_id": volume_id, + "name": name, + "tags": tags, + }, + ) + + async def get_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + ) -> Snapshot: + """ + Get a snapshot. + Retrieve technical information about a specific snapshot. Details such as size, volume type, and status are returned in the response. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.get_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def wait_for_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + options: Optional[ + WaitForOptions[Snapshot, Union[bool, Awaitable[bool]]] + ] = None, + ) -> Snapshot: + """ + Get a snapshot. + Retrieve technical information about a specific snapshot. Details such as size, volume type, and status are returned in the response. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.get_snapshot( + snapshot_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in SNAPSHOT_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_snapshot, + options=options, + args={ + "snapshot_id": snapshot_id, + "zone": zone, + }, + ) + + async def create_snapshot( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> Snapshot: + """ + Create a snapshot of a volume. + To create a snapshot, the volume must be in the `in_use` or the `available` status. + If your volume is in a transient state, you need to wait until the end of the current operation. + :param volume_id: UUID of the volume to snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the snapshot. + :param project_id: UUID of the project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.create_snapshot( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots", + body=marshal_CreateSnapshotRequest( + CreateSnapshotRequest( + volume_id=volume_id, + zone=zone, + name=name or random_name(prefix="snp"), + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def import_snapshot_from_object_storage( + self, + *, + bucket: str, + key: str, + name: str, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + size: Optional[int] = None, + ) -> Snapshot: + """ + Import a snapshot from a Scaleway Object Storage bucket. + The bucket must contain a QCOW2 image. + The bucket can be imported into any Availability Zone as long as it is in the same region as the bucket. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param name: Name of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: UUID of the Project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :param size: Size of the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.import_snapshot_from_object_storage( + bucket="example", + key="example", + name="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots/import-from-object-storage", + body=marshal_ImportSnapshotFromObjectStorageRequest( + ImportSnapshotFromObjectStorageRequest( + bucket=bucket, + key=key, + name=name, + zone=zone, + project_id=project_id, + tags=tags, + size=size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def export_snapshot_to_object_storage( + self, + *, + snapshot_id: str, + bucket: str, + key: str, + zone: Optional[ScwZone] = None, + ) -> Snapshot: + """ + Export a snapshot to a Scaleway Object Storage bucket. + The snapshot is exported in QCOW2 format. + The snapshot must not be in transient state. + :param snapshot_id: UUID of the snapshot. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.export_snapshot_to_object_storage( + snapshot_id="example", + bucket="example", + key="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}/export-to-object-storage", + body=marshal_ExportSnapshotToObjectStorageRequest( + ExportSnapshotToObjectStorageRequest( + snapshot_id=snapshot_id, + bucket=bucket, + key=key, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def delete_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a snapshot. + You must specify the `snapshot_id` of the snapshot you want to delete. The snapshot must not be in use. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "DELETE", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + + async def update_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> Snapshot: + """ + Update a snapshot. + Update the name or tags of the snapshot. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: When defined, is the name of the snapshot. + :param tags: List of tags assigned to the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.update_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "PATCH", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + body=marshal_UpdateSnapshotRequest( + UpdateSnapshotRequest( + snapshot_id=snapshot_id, + zone=zone, + name=name, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) diff --git a/scaleway-async/scaleway_async/block/v1/content.py b/scaleway-async/scaleway_async/block/v1/content.py new file mode 100644 index 00000000..a6cf1ee6 --- /dev/null +++ b/scaleway-async/scaleway_async/block/v1/content.py @@ -0,0 +1,36 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + ReferenceStatus, + SnapshotStatus, + VolumeStatus, +) + +REFERENCE_TRANSIENT_STATUSES: List[ReferenceStatus] = [ + ReferenceStatus.ATTACHING, + ReferenceStatus.DETACHING, + ReferenceStatus.CREATING, +] +""" +Lists transient statutes of the enum :class:`ReferenceStatus `. +""" +SNAPSHOT_TRANSIENT_STATUSES: List[SnapshotStatus] = [ + SnapshotStatus.CREATING, + SnapshotStatus.DELETING, + SnapshotStatus.EXPORTING, +] +""" +Lists transient statutes of the enum :class:`SnapshotStatus `. +""" +VOLUME_TRANSIENT_STATUSES: List[VolumeStatus] = [ + VolumeStatus.CREATING, + VolumeStatus.DELETING, + VolumeStatus.RESIZING, + VolumeStatus.SNAPSHOTTING, + VolumeStatus.UPDATING, +] +""" +Lists transient statutes of the enum :class:`VolumeStatus `. +""" diff --git a/scaleway-async/scaleway_async/block/v1/marshalling.py b/scaleway-async/scaleway_async/block/v1/marshalling.py new file mode 100644 index 00000000..d1aef668 --- /dev/null +++ b/scaleway-async/scaleway_async/block/v1/marshalling.py @@ -0,0 +1,521 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + Reference, + SnapshotParentVolume, + Snapshot, + VolumeSpecifications, + Volume, + ListSnapshotsResponse, + VolumeType, + ListVolumeTypesResponse, + ListVolumesResponse, + CreateSnapshotRequest, + CreateVolumeRequestFromEmpty, + CreateVolumeRequestFromSnapshot, + CreateVolumeRequest, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + UpdateSnapshotRequest, + UpdateVolumeRequest, +) + + +def unmarshal_Reference(data: Any) -> Reference: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Reference' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("product_resource_type", None) + if field is not None: + args["product_resource_type"] = field + + field = data.get("product_resource_id", None) + if field is not None: + args["product_resource_id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + return Reference(**args) + + +def unmarshal_SnapshotParentVolume(data: Any) -> SnapshotParentVolume: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SnapshotParentVolume' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + return SnapshotParentVolume(**args) + + +def unmarshal_Snapshot(data: Any) -> Snapshot: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Snapshot' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("references", None) + if field is not None: + args["references"] = ( + [unmarshal_Reference(v) for v in field] if field is not None else None + ) + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("class", None) + if field is not None: + args["class_"] = field + + field = data.get("parent_volume", None) + if field is not None: + args["parent_volume"] = unmarshal_SnapshotParentVolume(field) + else: + args["parent_volume"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Snapshot(**args) + + +def unmarshal_VolumeSpecifications(data: Any) -> VolumeSpecifications: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeSpecifications' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("class", None) + if field is not None: + args["class_"] = field + + field = data.get("perf_iops", None) + if field is not None: + args["perf_iops"] = field + else: + args["perf_iops"] = None + + return VolumeSpecifications(**args) + + +def unmarshal_Volume(data: Any) -> Volume: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Volume' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("references", None) + if field is not None: + args["references"] = ( + [unmarshal_Reference(v) for v in field] if field is not None else None + ) + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("parent_snapshot_id", None) + if field is not None: + args["parent_snapshot_id"] = field + else: + args["parent_snapshot_id"] = None + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("specs", None) + if field is not None: + args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None + + field = data.get("last_detached_at", None) + if field is not None: + args["last_detached_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["last_detached_at"] = None + + return Volume(**args) + + +def unmarshal_ListSnapshotsResponse(data: Any) -> ListSnapshotsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSnapshotsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("snapshots", None) + if field is not None: + args["snapshots"] = ( + [unmarshal_Snapshot(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListSnapshotsResponse(**args) + + +def unmarshal_VolumeType(data: Any) -> VolumeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("pricing", None) + if field is not None: + args["pricing"] = unmarshal_Money(field) + else: + args["pricing"] = None + + field = data.get("snapshot_pricing", None) + if field is not None: + args["snapshot_pricing"] = unmarshal_Money(field) + else: + args["snapshot_pricing"] = None + + field = data.get("specs", None) + if field is not None: + args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None + + return VolumeType(**args) + + +def unmarshal_ListVolumeTypesResponse(data: Any) -> ListVolumeTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListVolumeTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("volume_types", None) + if field is not None: + args["volume_types"] = ( + [unmarshal_VolumeType(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListVolumeTypesResponse(**args) + + +def unmarshal_ListVolumesResponse(data: Any) -> ListVolumesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListVolumesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("volumes", None) + if field is not None: + args["volumes"] = ( + [unmarshal_Volume(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListVolumesResponse(**args) + + +def marshal_CreateSnapshotRequest( + request: CreateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.volume_id is not None: + output["volume_id"] = request.volume_id + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_CreateVolumeRequestFromEmpty( + request: CreateVolumeRequestFromEmpty, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_CreateVolumeRequestFromSnapshot( + request: CreateVolumeRequestFromSnapshot, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.snapshot_id is not None: + output["snapshot_id"] = request.snapshot_id + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_CreateVolumeRequest( + request: CreateVolumeRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("from_empty", request.from_empty), + OneOfPossibility("from_snapshot", request.from_snapshot), + ] + ), + ) + output.update( + resolve_one_of( + [ + OneOfPossibility("perf_iops", request.perf_iops), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_ExportSnapshotToObjectStorageRequest( + request: ExportSnapshotToObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + return output + + +def marshal_ImportSnapshotFromObjectStorageRequest( + request: ImportSnapshotFromObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_UpdateSnapshotRequest( + request: UpdateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_UpdateVolumeRequest( + request: UpdateVolumeRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.size is not None: + output["size"] = request.size + + if request.tags is not None: + output["tags"] = request.tags + + if request.perf_iops is not None: + output["perf_iops"] = request.perf_iops + + return output diff --git a/scaleway-async/scaleway_async/block/v1/types.py b/scaleway-async/scaleway_async/block/v1/types.py new file mode 100644 index 00000000..d666ce94 --- /dev/null +++ b/scaleway-async/scaleway_async/block/v1/types.py @@ -0,0 +1,731 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Money, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class ListSnapshotsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListVolumesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ReferenceStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + ATTACHING = "attaching" + ATTACHED = "attached" + DETACHING = "detaching" + DETACHED = "detached" + CREATING = "creating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class ReferenceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + LINK = "link" + EXCLUSIVE = "exclusive" + READ_ONLY = "read_only" + + def __str__(self) -> str: + return str(self.value) + + +class SnapshotStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + AVAILABLE = "available" + ERROR = "error" + DELETING = "deleting" + DELETED = "deleted" + IN_USE = "in_use" + LOCKED = "locked" + EXPORTING = "exporting" + + def __str__(self) -> str: + return str(self.value) + + +class StorageClass(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STORAGE_CLASS = "unknown_storage_class" + UNSPECIFIED = "unspecified" + BSSD = "bssd" + SBS = "sbs" + + def __str__(self) -> str: + return str(self.value) + + +class VolumeStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + AVAILABLE = "available" + IN_USE = "in_use" + DELETING = "deleting" + DELETED = "deleted" + RESIZING = "resizing" + ERROR = "error" + SNAPSHOTTING = "snapshotting" + LOCKED = "locked" + UPDATING = "updating" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class Reference: + id: str + """ + UUID of the reference. + """ + + product_resource_type: str + """ + Type of resource to which the reference is associated. + """ + + product_resource_id: str + """ + UUID of the product resource it refers to (according to the product_resource_type). + """ + + type_: ReferenceType + """ + Type of reference (link, exclusive, read_only). + """ + + status: ReferenceStatus + """ + Status of the reference. Statuses include `attaching`, `attached`, and `detaching`. + """ + + created_at: Optional[datetime] + """ + Creation date of the reference. + """ + + +@dataclass +class SnapshotParentVolume: + id: str + """ + Parent volume UUID (volume from which the snapshot originates). + """ + + name: str + """ + Name of the parent volume. + """ + + type_: str + """ + Volume type of the parent volume. + """ + + status: VolumeStatus + """ + Current status the parent volume. + """ + + +@dataclass +class VolumeSpecifications: + class_: StorageClass + """ + The storage class of the volume. + """ + + perf_iops: Optional[int] + """ + The maximum IO/s expected, according to the different options available in stock (`5000 | 15000`). + """ + + +@dataclass +class CreateVolumeRequestFromEmpty: + size: int + """ + Must be compliant with the minimum (1 GB) and maximum (10 TB) allowed size. + """ + + +@dataclass +class CreateVolumeRequestFromSnapshot: + snapshot_id: str + """ + Source snapshot from which volume will be created. + """ + + size: Optional[int] + """ + Must be compliant with the minimum (1 GB) and maximum (10 TB) allowed size. +Size is optional and is used only if a resize of the volume is requested, otherwise original snapshot size will be used. + """ + + +@dataclass +class Snapshot: + id: str + """ + UUID of the snapshot. + """ + + name: str + """ + Name of the snapshot. + """ + + size: int + """ + Size in bytes of the snapshot. + """ + + project_id: str + """ + UUID of the project the snapshot belongs to. + """ + + references: List[Reference] + """ + List of the references to the snapshot. + """ + + status: SnapshotStatus + """ + Current status of the snapshot (available, in_use, ...). + """ + + tags: List[str] + """ + List of tags assigned to the volume. + """ + + zone: ScwZone + """ + Snapshot zone. + """ + + class_: StorageClass + """ + Storage class of the snapshot. + """ + + parent_volume: Optional[SnapshotParentVolume] + """ + If the parent volume was deleted, value is null. + """ + + created_at: Optional[datetime] + """ + Creation date of the snapshot. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the properties of a snapshot. + """ + + +@dataclass +class VolumeType: + type_: str + """ + Volume type. + """ + + pricing: Optional[Money] + """ + Price of the volume billed in GB/hour. + """ + + snapshot_pricing: Optional[Money] + """ + Price of the snapshot billed in GB/hour. + """ + + specs: Optional[VolumeSpecifications] + """ + Volume specifications of the volume type. + """ + + +@dataclass +class Volume: + id: str + """ + UUID of the volume. + """ + + name: str + """ + Name of the volume. + """ + + type_: str + """ + Volume type. + """ + + size: int + """ + Volume size in bytes. + """ + + project_id: str + """ + UUID of the project to which the volume belongs. + """ + + references: List[Reference] + """ + List of the references to the volume. + """ + + created_at: Optional[datetime] + """ + Creation date of the volume. + """ + + updated_at: Optional[datetime] + """ + Last update of the properties of a volume. + """ + + parent_snapshot_id: Optional[str] + """ + When a volume is created from a snapshot, is the UUID of the snapshot from which the volume has been created. + """ + + status: VolumeStatus + """ + Current status of the volume (available, in_use, ...). + """ + + tags: List[str] + """ + List of tags assigned to the volume. + """ + + zone: ScwZone + """ + Volume zone. + """ + + specs: Optional[VolumeSpecifications] + """ + Specifications of the volume. + """ + + last_detached_at: Optional[datetime] + """ + Last time the volume was detached. + """ + + +@dataclass +class CreateSnapshotRequest: + volume_id: str + """ + UUID of the volume to snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name of the snapshot. + """ + + project_id: Optional[str] + """ + UUID of the project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + +@dataclass +class CreateVolumeRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name of the volume. + """ + + project_id: Optional[str] + """ + UUID of the project the volume belongs to. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the volume. + """ + + from_empty: Optional[CreateVolumeRequestFromEmpty] + + from_snapshot: Optional[CreateVolumeRequestFromSnapshot] + + perf_iops: Optional[int] + + +@dataclass +class DeleteSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ExportSnapshotToObjectStorageRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ImportSnapshotFromObjectStorageRequest: + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + name: str + """ + Name of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + UUID of the Project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + size: Optional[int] + """ + Size of the snapshot. + """ + + +@dataclass +class ListSnapshotsRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListSnapshotsRequestOrderBy] + """ + Criteria to use when ordering the list. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + volume_id: Optional[str] + """ + Filter snapshots by the ID of the original volume. + """ + + name: Optional[str] + """ + Filter snapshots by their names. + """ + + tags: Optional[List[str]] + """ + Filter by tags. Only snapshots with one or more matching tags will be returned. + """ + + +@dataclass +class ListSnapshotsResponse: + snapshots: List[Snapshot] + """ + Paginated returned list of snapshots. + """ + + total_count: int + """ + Total number of snpashots in the project. + """ + + +@dataclass +class ListVolumeTypesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + +@dataclass +class ListVolumeTypesResponse: + volume_types: List[VolumeType] + """ + Returns paginated list of volume-types. + """ + + total_count: int + """ + Total number of volume-types currently available in stock. + """ + + +@dataclass +class ListVolumesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListVolumesRequestOrderBy] + """ + Criteria to use when ordering the list. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + name: Optional[str] + """ + Filter the return volumes by their names. + """ + + product_resource_id: Optional[str] + """ + Filter by a product resource ID linked to this volume (such as an Instance ID). + """ + + tags: Optional[List[str]] + """ + Filter by tags. Only volumes with one or more matching tags will be returned. + """ + + +@dataclass +class ListVolumesResponse: + volumes: List[Volume] + """ + Paginated returned list of volumes. + """ + + total_count: int + """ + Total number of volumes in the project. + """ + + +@dataclass +class UpdateSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + When defined, is the name of the snapshot. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + +@dataclass +class UpdateVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + When defined, is the new name of the volume. + """ + + size: Optional[int] + """ + Size in bytes of the volume, with a granularity of 1 GB (10^9 bytes). +Must be compliant with the minimum (1GB) and maximum (10TB) allowed size. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the volume. + """ + + perf_iops: Optional[int] + """ + The selected value must be available for the volume's current storage class. + """ diff --git a/scaleway-async/scaleway_async/block/v1alpha1/__init__.py b/scaleway-async/scaleway_async/block/v1alpha1/__init__.py index 67c4ae05..93d2a254 100644 --- a/scaleway-async/scaleway_async/block/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/block/v1alpha1/__init__.py @@ -22,8 +22,11 @@ from .types import CreateVolumeRequest from .types import DeleteSnapshotRequest from .types import DeleteVolumeRequest +from .types import ExportSnapshotToObjectStorageRequest from .types import GetSnapshotRequest from .types import GetVolumeRequest +from .types import ImportSnapshotFromObjectStorageRequest +from .types import ImportSnapshotFromS3Request from .types import ListSnapshotsRequest from .types import ListSnapshotsResponse from .types import ListVolumeTypesRequest @@ -57,8 +60,11 @@ "CreateVolumeRequest", "DeleteSnapshotRequest", "DeleteVolumeRequest", + "ExportSnapshotToObjectStorageRequest", "GetSnapshotRequest", "GetVolumeRequest", + "ImportSnapshotFromObjectStorageRequest", + "ImportSnapshotFromS3Request", "ListSnapshotsRequest", "ListSnapshotsResponse", "ListVolumeTypesRequest", diff --git a/scaleway-async/scaleway_async/block/v1alpha1/api.py b/scaleway-async/scaleway_async/block/v1alpha1/api.py index 5eb3248c..970ed99c 100644 --- a/scaleway-async/scaleway_async/block/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/block/v1alpha1/api.py @@ -5,10 +5,11 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, + random_name, validate_path_param, fetch_all_pages_async, wait_for_resource_async, @@ -20,6 +21,9 @@ CreateVolumeRequest, CreateVolumeRequestFromEmpty, CreateVolumeRequestFromSnapshot, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + ImportSnapshotFromS3Request, ListSnapshotsResponse, ListVolumeTypesResponse, ListVolumesResponse, @@ -41,6 +45,9 @@ unmarshal_ListVolumesResponse, marshal_CreateSnapshotRequest, marshal_CreateVolumeRequest, + marshal_ExportSnapshotToObjectStorageRequest, + marshal_ImportSnapshotFromObjectStorageRequest, + marshal_ImportSnapshotFromS3Request, marshal_UpdateSnapshotRequest, marshal_UpdateVolumeRequest, ) @@ -48,13 +55,13 @@ class BlockV1Alpha1API(API): """ - This API allows you to use and manage your Block Storage volumes. + This API allows you to manage your Block Storage volumes. """ async def list_volume_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListVolumeTypesResponse: @@ -89,7 +96,7 @@ async def list_volume_types( async def list_volume_types_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[VolumeType]: @@ -121,7 +128,7 @@ async def list_volume_types_all( async def list_volumes( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListVolumesRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -129,6 +136,7 @@ async def list_volumes( page_size: Optional[int] = None, name: Optional[str] = None, product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> ListVolumesResponse: """ List volumes. @@ -141,6 +149,7 @@ async def list_volumes( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param name: Filter the return volumes by their names. :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. :return: :class:`ListVolumesResponse ` Usage: @@ -163,6 +172,7 @@ async def list_volumes( "page_size": page_size or self.client.default_page_size, "product_resource_id": product_resource_id, "project_id": project_id or self.client.default_project_id, + "tags": tags, }, ) @@ -172,7 +182,7 @@ async def list_volumes( async def list_volumes_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListVolumesRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -180,6 +190,7 @@ async def list_volumes_all( page_size: Optional[int] = None, name: Optional[str] = None, product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> List[Volume]: """ List volumes. @@ -192,6 +203,7 @@ async def list_volumes_all( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param name: Filter the return volumes by their names. :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. :return: :class:`List[Volume] ` Usage: @@ -213,14 +225,15 @@ async def list_volumes_all( "page_size": page_size, "name": name, "product_resource_id": product_resource_id, + "tags": tags, }, ) async def create_volume( self, *, - name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, perf_iops: Optional[int] = None, project_id: Optional[str] = None, from_empty: Optional[CreateVolumeRequestFromEmpty] = None, @@ -231,8 +244,8 @@ async def create_volume( Create a volume. To create a new volume from scratch, you must specify `from_empty` and the `size`. To create a volume from an existing snapshot, specify `from_snapshot` and the `snapshot_id` in the request payload instead, size is optional and can be specified if you need to extend the original size. The volume will take on the same volume class and underlying IOPS limitations as the original snapshot. - :param name: Name of the volume. :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the volume. :param perf_iops: The maximum IO/s expected, according to the different options available in stock (`5000 | 15000`). One-Of ('requirements'): at most one of 'perf_iops' could be set. :param project_id: UUID of the project the volume belongs to. @@ -246,9 +259,7 @@ async def create_volume( Usage: :: - result = await api.create_volume( - name="example", - ) + result = await api.create_volume() """ param_zone = validate_path_param("zone", zone or self.client.default_zone) @@ -258,8 +269,8 @@ async def create_volume( f"/block/v1alpha1/zones/{param_zone}/volumes", body=marshal_CreateVolumeRequest( CreateVolumeRequest( - name=name, zone=zone, + name=name or random_name(prefix="vol"), project_id=project_id, tags=tags, from_empty=from_empty, @@ -277,7 +288,7 @@ async def get_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Volume: """ Get a volume. @@ -309,7 +320,7 @@ async def wait_for_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Volume, Union[bool, Awaitable[bool]]]] = None, ) -> Volume: """ @@ -346,7 +357,7 @@ async def delete_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a detached volume. @@ -376,7 +387,7 @@ async def update_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, size: Optional[int] = None, tags: Optional[List[str]] = None, @@ -428,7 +439,7 @@ async def update_volume( async def list_snapshots( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListSnapshotsRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -436,6 +447,7 @@ async def list_snapshots( page_size: Optional[int] = None, volume_id: Optional[str] = None, name: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> ListSnapshotsResponse: """ List all snapshots. @@ -448,6 +460,7 @@ async def list_snapshots( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param volume_id: Filter snapshots by the ID of the original volume. :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. :return: :class:`ListSnapshotsResponse ` Usage: @@ -469,6 +482,7 @@ async def list_snapshots( "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, + "tags": tags, "volume_id": volume_id, }, ) @@ -479,7 +493,7 @@ async def list_snapshots( async def list_snapshots_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListSnapshotsRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -487,6 +501,7 @@ async def list_snapshots_all( page_size: Optional[int] = None, volume_id: Optional[str] = None, name: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> List[Snapshot]: """ List all snapshots. @@ -499,6 +514,7 @@ async def list_snapshots_all( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param volume_id: Filter snapshots by the ID of the original volume. :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. :return: :class:`List[Snapshot] ` Usage: @@ -520,6 +536,7 @@ async def list_snapshots_all( "page_size": page_size, "volume_id": volume_id, "name": name, + "tags": tags, }, ) @@ -527,7 +544,7 @@ async def get_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Snapshot: """ Get a snapshot. @@ -559,7 +576,7 @@ async def wait_for_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[ WaitForOptions[Snapshot, Union[bool, Awaitable[bool]]] ] = None, @@ -598,8 +615,8 @@ async def create_snapshot( self, *, volume_id: str, - name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, ) -> Snapshot: @@ -608,8 +625,8 @@ async def create_snapshot( To create a snapshot, the volume must be in the `in_use` or the `available` status. If your volume is in a transient state, you need to wait until the end of the current operation. :param volume_id: UUID of the volume to snapshot. - :param name: Name of the snapshot. :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the snapshot. :param project_id: UUID of the project to which the volume and the snapshot belong. :param tags: List of tags assigned to the snapshot. :return: :class:`Snapshot ` @@ -619,7 +636,6 @@ async def create_snapshot( result = await api.create_snapshot( volume_id="example", - name="example", ) """ @@ -631,10 +647,172 @@ async def create_snapshot( body=marshal_CreateSnapshotRequest( CreateSnapshotRequest( volume_id=volume_id, + zone=zone, + name=name or random_name(prefix="snp"), + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def import_snapshot_from_s3( + self, + *, + bucket: str, + key: str, + name: str, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + size: Optional[int] = None, + ) -> Snapshot: + """ + (Deprecated in favor of `ImportSnapshotFromObjectStorage`). + Import a snapshot from a Scaleway Object Storage bucket + The bucket must contain a QCOW2 image. + The bucket can be imported into any Availability Zone as long as it is in the same region as the bucket. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param name: Name of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: UUID of the Project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :param size: Size of the snapshot. + :return: :class:`Snapshot ` + :deprecated + + Usage: + :: + + result = await api.import_snapshot_from_s3( + bucket="example", + key="example", + name="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1alpha1/zones/{param_zone}/snapshots/import-from-s3", + body=marshal_ImportSnapshotFromS3Request( + ImportSnapshotFromS3Request( + bucket=bucket, + key=key, + name=name, + zone=zone, + project_id=project_id, + tags=tags, + size=size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def import_snapshot_from_object_storage( + self, + *, + bucket: str, + key: str, + name: str, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + size: Optional[int] = None, + ) -> Snapshot: + """ + Import a snapshot from a Scaleway Object Storage bucket. + The bucket must contain a QCOW2 image. + The bucket can be imported into any Availability Zone as long as it is in the same region as the bucket. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param name: Name of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: UUID of the Project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :param size: Size of the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.import_snapshot_from_object_storage( + bucket="example", + key="example", + name="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1alpha1/zones/{param_zone}/snapshots/import-from-object-storage", + body=marshal_ImportSnapshotFromObjectStorageRequest( + ImportSnapshotFromObjectStorageRequest( + bucket=bucket, + key=key, name=name, zone=zone, project_id=project_id, tags=tags, + size=size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def export_snapshot_to_object_storage( + self, + *, + snapshot_id: str, + bucket: str, + key: str, + zone: Optional[ScwZone] = None, + ) -> Snapshot: + """ + Export a snapshot to a Scaleway Object Storage bucket. + The snapshot is exported in QCOW2 format. + The snapshot must not be in transient state. + :param snapshot_id: UUID of the snapshot. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.export_snapshot_to_object_storage( + snapshot_id="example", + bucket="example", + key="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "POST", + f"/block/v1alpha1/zones/{param_zone}/snapshots/{param_snapshot_id}/export-to-object-storage", + body=marshal_ExportSnapshotToObjectStorageRequest( + ExportSnapshotToObjectStorageRequest( + snapshot_id=snapshot_id, + bucket=bucket, + key=key, + zone=zone, ), self.client, ), @@ -647,7 +825,7 @@ async def delete_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a snapshot. @@ -677,7 +855,7 @@ async def update_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, ) -> Snapshot: diff --git a/scaleway-async/scaleway_async/block/v1alpha1/content.py b/scaleway-async/scaleway_async/block/v1alpha1/content.py index a657c57f..a6cf1ee6 100644 --- a/scaleway-async/scaleway_async/block/v1alpha1/content.py +++ b/scaleway-async/scaleway_async/block/v1alpha1/content.py @@ -19,6 +19,7 @@ SNAPSHOT_TRANSIENT_STATUSES: List[SnapshotStatus] = [ SnapshotStatus.CREATING, SnapshotStatus.DELETING, + SnapshotStatus.EXPORTING, ] """ Lists transient statutes of the enum :class:`SnapshotStatus `. @@ -28,6 +29,7 @@ VolumeStatus.DELETING, VolumeStatus.RESIZING, VolumeStatus.SNAPSHOTTING, + VolumeStatus.UPDATING, ] """ Lists transient statutes of the enum :class:`VolumeStatus `. diff --git a/scaleway-async/scaleway_async/block/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/block/v1alpha1/marshalling.py index 4381f821..e7289e49 100644 --- a/scaleway-async/scaleway_async/block/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/block/v1alpha1/marshalling.py @@ -26,6 +26,9 @@ CreateVolumeRequestFromEmpty, CreateVolumeRequestFromSnapshot, CreateVolumeRequest, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + ImportSnapshotFromS3Request, UpdateSnapshotRequest, UpdateVolumeRequest, ) @@ -51,7 +54,7 @@ def unmarshal_Reference(data: Any) -> Reference: if field is not None: args["product_resource_id"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -62,6 +65,8 @@ def unmarshal_Reference(data: Any) -> Reference: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return Reference(**args) @@ -82,7 +87,7 @@ def unmarshal_SnapshotParentVolume(data: Any) -> SnapshotParentVolume: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -135,21 +140,27 @@ def unmarshal_Snapshot(data: Any) -> Snapshot: if field is not None: args["zone"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field field = data.get("parent_volume", None) if field is not None: args["parent_volume"] = unmarshal_SnapshotParentVolume(field) + else: + args["parent_volume"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Snapshot(**args) @@ -162,13 +173,15 @@ def unmarshal_VolumeSpecifications(data: Any) -> VolumeSpecifications: args: Dict[str, Any] = {} - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field field = data.get("perf_iops", None) if field is not None: args["perf_iops"] = field + else: + args["perf_iops"] = None return VolumeSpecifications(**args) @@ -189,7 +202,7 @@ def unmarshal_Volume(data: Any) -> Volume: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -210,14 +223,20 @@ def unmarshal_Volume(data: Any) -> Volume: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("parent_snapshot_id", None) if field is not None: args["parent_snapshot_id"] = field + else: + args["parent_snapshot_id"] = None field = data.get("status", None) if field is not None: @@ -234,12 +253,16 @@ def unmarshal_Volume(data: Any) -> Volume: field = data.get("specs", None) if field is not None: args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None field = data.get("last_detached_at", None) if field is not None: args["last_detached_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_detached_at"] = None return Volume(**args) @@ -273,21 +296,27 @@ def unmarshal_VolumeType(data: Any) -> VolumeType: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field field = data.get("pricing", None) if field is not None: args["pricing"] = unmarshal_Money(field) + else: + args["pricing"] = None field = data.get("snapshot_pricing", None) if field is not None: args["snapshot_pricing"] = unmarshal_Money(field) + else: + args["snapshot_pricing"] = None field = data.get("specs", None) if field is not None: args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None return VolumeType(**args) @@ -415,6 +444,75 @@ def marshal_CreateVolumeRequest( return output +def marshal_ExportSnapshotToObjectStorageRequest( + request: ExportSnapshotToObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + return output + + +def marshal_ImportSnapshotFromObjectStorageRequest( + request: ImportSnapshotFromObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_ImportSnapshotFromS3Request( + request: ImportSnapshotFromS3Request, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.size is not None: + output["size"] = request.size + + return output + + def marshal_UpdateSnapshotRequest( request: UpdateSnapshotRequest, defaults: ProfileDefaults, diff --git a/scaleway-async/scaleway_async/block/v1alpha1/types.py b/scaleway-async/scaleway_async/block/v1alpha1/types.py index cc1ceb20..2f15d1ec 100644 --- a/scaleway-async/scaleway_async/block/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/block/v1alpha1/types.py @@ -9,7 +9,7 @@ from scaleway_core.bridge import ( Money, - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -68,6 +68,7 @@ class SnapshotStatus(str, Enum, metaclass=StrEnumMeta): DELETED = "deleted" IN_USE = "in_use" LOCKED = "locked" + EXPORTING = "exporting" def __str__(self) -> str: return str(self.value) @@ -94,6 +95,7 @@ class VolumeStatus(str, Enum, metaclass=StrEnumMeta): ERROR = "error" SNAPSHOTTING = "snapshotting" LOCKED = "locked" + UPDATING = "updating" def __str__(self) -> str: return str(self.value) @@ -123,7 +125,7 @@ class Reference: status: ReferenceStatus """ - Status of reference (attaching, attached, detaching). + Status of the reference. Statuses include `attaching`, `attached`, and `detaching`. """ created_at: Optional[datetime] @@ -227,7 +229,7 @@ class Snapshot: List of tags assigned to the volume. """ - zone: Zone + zone: ScwZone """ Snapshot zone. """ @@ -333,7 +335,7 @@ class Volume: List of tags assigned to the volume. """ - zone: Zone + zone: ScwZone """ Volume zone. """ @@ -356,14 +358,14 @@ class CreateSnapshotRequest: UUID of the volume to snapshot. """ - name: str + zone: Optional[ScwZone] """ - Name of the snapshot. + Zone to target. If none is passed will use default zone from the config. """ - zone: Optional[Zone] + name: Optional[str] """ - Zone to target. If none is passed will use default zone from the config. + Name of the snapshot. """ project_id: Optional[str] @@ -379,14 +381,14 @@ class CreateSnapshotRequest: @dataclass class CreateVolumeRequest: - name: str + zone: Optional[ScwZone] """ - Name of the volume. + Zone to target. If none is passed will use default zone from the config. """ - zone: Optional[Zone] + name: Optional[str] """ - Zone to target. If none is passed will use default zone from the config. + Name of the volume. """ project_id: Optional[str] @@ -413,7 +415,7 @@ class DeleteSnapshotRequest: UUID of the snapshot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -426,7 +428,30 @@ class DeleteVolumeRequest: UUID of the volume. """ - zone: Optional[Zone] + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ExportSnapshotToObjectStorageRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -439,7 +464,7 @@ class GetSnapshotRequest: UUID of the snapshot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -452,15 +477,91 @@ class GetVolumeRequest: UUID of the volume. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ +@dataclass +class ImportSnapshotFromObjectStorageRequest: + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + name: str + """ + Name of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + UUID of the Project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + size: Optional[int] + """ + Size of the snapshot. + """ + + +@dataclass +class ImportSnapshotFromS3Request: + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + name: str + """ + Name of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + UUID of the Project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + size: Optional[int] + """ + Size of the snapshot. + """ + + @dataclass class ListSnapshotsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -500,6 +601,11 @@ class ListSnapshotsRequest: Filter snapshots by their names. """ + tags: Optional[List[str]] + """ + Filter by tags. Only snapshots with one or more matching tags will be returned. + """ + @dataclass class ListSnapshotsResponse: @@ -516,7 +622,7 @@ class ListSnapshotsResponse: @dataclass class ListVolumeTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -547,7 +653,7 @@ class ListVolumeTypesResponse: @dataclass class ListVolumesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -587,6 +693,11 @@ class ListVolumesRequest: Filter by a product resource ID linked to this volume (such as an Instance ID). """ + tags: Optional[List[str]] + """ + Filter by tags. Only volumes with one or more matching tags will be returned. + """ + @dataclass class ListVolumesResponse: @@ -608,7 +719,7 @@ class UpdateSnapshotRequest: UUID of the snapshot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -631,7 +742,7 @@ class UpdateVolumeRequest: UUID of the volume. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway-async/scaleway_async/cockpit/v1/__init__.py b/scaleway-async/scaleway_async/cockpit/v1/__init__.py new file mode 100644 index 00000000..44d90e37 --- /dev/null +++ b/scaleway-async/scaleway_async/cockpit/v1/__init__.py @@ -0,0 +1,149 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import AlertState +from .types import DataSourceOrigin +from .types import DataSourceType +from .types import GrafanaUserRole +from .types import ListDataSourcesRequestOrderBy +from .types import ListGrafanaUsersRequestOrderBy +from .types import ListPlansRequestOrderBy +from .types import ListTokensRequestOrderBy +from .types import PlanName +from .types import TokenScope +from .types import UsageUnit +from .types import PreconfiguredAlertData +from .types import ContactPointEmail +from .types import GetConfigResponseRetention +from .types import Alert +from .types import ContactPoint +from .types import DataSource +from .types import GrafanaProductDashboard +from .types import GrafanaUser +from .types import Plan +from .types import Token +from .types import Usage +from .types import AlertManager +from .types import DisableAlertRulesResponse +from .types import EnableAlertRulesResponse +from .types import GetConfigResponse +from .types import GlobalApiCreateGrafanaUserRequest +from .types import GlobalApiDeleteGrafanaUserRequest +from .types import GlobalApiGetCurrentPlanRequest +from .types import GlobalApiGetGrafanaProductDashboardRequest +from .types import GlobalApiGetGrafanaRequest +from .types import GlobalApiListGrafanaProductDashboardsRequest +from .types import GlobalApiListGrafanaUsersRequest +from .types import GlobalApiListPlansRequest +from .types import GlobalApiResetGrafanaUserPasswordRequest +from .types import GlobalApiSelectPlanRequest +from .types import GlobalApiSyncGrafanaDataSourcesRequest +from .types import Grafana +from .types import ListAlertsResponse +from .types import ListContactPointsResponse +from .types import ListDataSourcesResponse +from .types import ListGrafanaProductDashboardsResponse +from .types import ListGrafanaUsersResponse +from .types import ListPlansResponse +from .types import ListTokensResponse +from .types import RegionalApiCreateContactPointRequest +from .types import RegionalApiCreateDataSourceRequest +from .types import RegionalApiCreateTokenRequest +from .types import RegionalApiDeleteContactPointRequest +from .types import RegionalApiDeleteDataSourceRequest +from .types import RegionalApiDeleteTokenRequest +from .types import RegionalApiDisableAlertManagerRequest +from .types import RegionalApiDisableAlertRulesRequest +from .types import RegionalApiDisableManagedAlertsRequest +from .types import RegionalApiEnableAlertManagerRequest +from .types import RegionalApiEnableAlertRulesRequest +from .types import RegionalApiEnableManagedAlertsRequest +from .types import RegionalApiGetAlertManagerRequest +from .types import RegionalApiGetConfigRequest +from .types import RegionalApiGetDataSourceRequest +from .types import RegionalApiGetTokenRequest +from .types import RegionalApiGetUsageOverviewRequest +from .types import RegionalApiListAlertsRequest +from .types import RegionalApiListContactPointsRequest +from .types import RegionalApiListDataSourcesRequest +from .types import RegionalApiListTokensRequest +from .types import RegionalApiTriggerTestAlertRequest +from .types import RegionalApiUpdateContactPointRequest +from .types import RegionalApiUpdateDataSourceRequest +from .types import UsageOverview +from .api import CockpitV1GlobalAPI +from .api import CockpitV1RegionalAPI + +__all__ = [ + "AlertState", + "DataSourceOrigin", + "DataSourceType", + "GrafanaUserRole", + "ListDataSourcesRequestOrderBy", + "ListGrafanaUsersRequestOrderBy", + "ListPlansRequestOrderBy", + "ListTokensRequestOrderBy", + "PlanName", + "TokenScope", + "UsageUnit", + "PreconfiguredAlertData", + "ContactPointEmail", + "GetConfigResponseRetention", + "Alert", + "ContactPoint", + "DataSource", + "GrafanaProductDashboard", + "GrafanaUser", + "Plan", + "Token", + "Usage", + "AlertManager", + "DisableAlertRulesResponse", + "EnableAlertRulesResponse", + "GetConfigResponse", + "GlobalApiCreateGrafanaUserRequest", + "GlobalApiDeleteGrafanaUserRequest", + "GlobalApiGetCurrentPlanRequest", + "GlobalApiGetGrafanaProductDashboardRequest", + "GlobalApiGetGrafanaRequest", + "GlobalApiListGrafanaProductDashboardsRequest", + "GlobalApiListGrafanaUsersRequest", + "GlobalApiListPlansRequest", + "GlobalApiResetGrafanaUserPasswordRequest", + "GlobalApiSelectPlanRequest", + "GlobalApiSyncGrafanaDataSourcesRequest", + "Grafana", + "ListAlertsResponse", + "ListContactPointsResponse", + "ListDataSourcesResponse", + "ListGrafanaProductDashboardsResponse", + "ListGrafanaUsersResponse", + "ListPlansResponse", + "ListTokensResponse", + "RegionalApiCreateContactPointRequest", + "RegionalApiCreateDataSourceRequest", + "RegionalApiCreateTokenRequest", + "RegionalApiDeleteContactPointRequest", + "RegionalApiDeleteDataSourceRequest", + "RegionalApiDeleteTokenRequest", + "RegionalApiDisableAlertManagerRequest", + "RegionalApiDisableAlertRulesRequest", + "RegionalApiDisableManagedAlertsRequest", + "RegionalApiEnableAlertManagerRequest", + "RegionalApiEnableAlertRulesRequest", + "RegionalApiEnableManagedAlertsRequest", + "RegionalApiGetAlertManagerRequest", + "RegionalApiGetConfigRequest", + "RegionalApiGetDataSourceRequest", + "RegionalApiGetTokenRequest", + "RegionalApiGetUsageOverviewRequest", + "RegionalApiListAlertsRequest", + "RegionalApiListContactPointsRequest", + "RegionalApiListDataSourcesRequest", + "RegionalApiListTokensRequest", + "RegionalApiTriggerTestAlertRequest", + "RegionalApiUpdateContactPointRequest", + "RegionalApiUpdateDataSourceRequest", + "UsageOverview", + "CockpitV1GlobalAPI", + "CockpitV1RegionalAPI", +] diff --git a/scaleway-async/scaleway_async/cockpit/v1/api.py b/scaleway-async/scaleway_async/cockpit/v1/api.py new file mode 100644 index 00000000..a7a8f167 --- /dev/null +++ b/scaleway-async/scaleway_async/cockpit/v1/api.py @@ -0,0 +1,1679 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + validate_path_param, + fetch_all_pages_async, +) +from .types import ( + AlertState, + DataSourceOrigin, + DataSourceType, + GrafanaUserRole, + ListDataSourcesRequestOrderBy, + ListGrafanaUsersRequestOrderBy, + ListPlansRequestOrderBy, + ListTokensRequestOrderBy, + PlanName, + TokenScope, + AlertManager, + ContactPoint, + ContactPointEmail, + DataSource, + DisableAlertRulesResponse, + EnableAlertRulesResponse, + GetConfigResponse, + GlobalApiCreateGrafanaUserRequest, + GlobalApiResetGrafanaUserPasswordRequest, + GlobalApiSelectPlanRequest, + GlobalApiSyncGrafanaDataSourcesRequest, + Grafana, + GrafanaProductDashboard, + GrafanaUser, + ListAlertsResponse, + ListContactPointsResponse, + ListDataSourcesResponse, + ListGrafanaProductDashboardsResponse, + ListGrafanaUsersResponse, + ListPlansResponse, + ListTokensResponse, + Plan, + RegionalApiCreateContactPointRequest, + RegionalApiCreateDataSourceRequest, + RegionalApiCreateTokenRequest, + RegionalApiDeleteContactPointRequest, + RegionalApiDisableAlertManagerRequest, + RegionalApiDisableAlertRulesRequest, + RegionalApiDisableManagedAlertsRequest, + RegionalApiEnableAlertManagerRequest, + RegionalApiEnableAlertRulesRequest, + RegionalApiEnableManagedAlertsRequest, + RegionalApiTriggerTestAlertRequest, + RegionalApiUpdateContactPointRequest, + RegionalApiUpdateDataSourceRequest, + Token, + UsageOverview, +) +from .marshalling import ( + unmarshal_ContactPoint, + unmarshal_DataSource, + unmarshal_GrafanaProductDashboard, + unmarshal_GrafanaUser, + unmarshal_Plan, + unmarshal_Token, + unmarshal_AlertManager, + unmarshal_DisableAlertRulesResponse, + unmarshal_EnableAlertRulesResponse, + unmarshal_GetConfigResponse, + unmarshal_Grafana, + unmarshal_ListAlertsResponse, + unmarshal_ListContactPointsResponse, + unmarshal_ListDataSourcesResponse, + unmarshal_ListGrafanaProductDashboardsResponse, + unmarshal_ListGrafanaUsersResponse, + unmarshal_ListPlansResponse, + unmarshal_ListTokensResponse, + unmarshal_UsageOverview, + marshal_GlobalApiCreateGrafanaUserRequest, + marshal_GlobalApiResetGrafanaUserPasswordRequest, + marshal_GlobalApiSelectPlanRequest, + marshal_GlobalApiSyncGrafanaDataSourcesRequest, + marshal_RegionalApiCreateContactPointRequest, + marshal_RegionalApiCreateDataSourceRequest, + marshal_RegionalApiCreateTokenRequest, + marshal_RegionalApiDeleteContactPointRequest, + marshal_RegionalApiDisableAlertManagerRequest, + marshal_RegionalApiDisableAlertRulesRequest, + marshal_RegionalApiDisableManagedAlertsRequest, + marshal_RegionalApiEnableAlertManagerRequest, + marshal_RegionalApiEnableAlertRulesRequest, + marshal_RegionalApiEnableManagedAlertsRequest, + marshal_RegionalApiTriggerTestAlertRequest, + marshal_RegionalApiUpdateContactPointRequest, + marshal_RegionalApiUpdateDataSourceRequest, +) + + +class CockpitV1GlobalAPI(API): + """ + The Cockpit Global API allows you to manage your Cockpit's Grafana. + """ + + async def get_grafana( + self, + *, + project_id: Optional[str] = None, + ) -> Grafana: + """ + Get your Cockpit's Grafana. + Retrieve information on your Cockpit's Grafana, specified by the ID of the Project the Cockpit belongs to. + The output returned displays the URL to access your Cockpit's Grafana. + :param project_id: ID of the Project. + :return: :class:`Grafana ` + + Usage: + :: + + result = await api.get_grafana() + """ + + res = self._request( + "GET", + "/cockpit/v1/grafana", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Grafana(res.json()) + + async def sync_grafana_data_sources( + self, + *, + project_id: Optional[str] = None, + ) -> None: + """ + Synchronize Grafana data sources. + Trigger the synchronization of all your data sources and the alert manager in the relevant regions. The alert manager will only be synchronized if you have enabled it. + :param project_id: ID of the Project to target. + + Usage: + :: + + result = await api.sync_grafana_data_sources() + """ + + res = self._request( + "POST", + "/cockpit/v1/grafana/sync-data-sources", + body=marshal_GlobalApiSyncGrafanaDataSourcesRequest( + GlobalApiSyncGrafanaDataSourcesRequest( + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def create_grafana_user( + self, + *, + login: str, + project_id: Optional[str] = None, + role: Optional[GrafanaUserRole] = None, + ) -> GrafanaUser: + """ + Create a Grafana user. + Create a Grafana user to connect to your Cockpit's Grafana. Upon creation, your user password displays only once, so make sure that you save it. + Each Grafana user is associated with a role: viewer or editor. A viewer can only view dashboards, whereas an editor can create and edit dashboards. Note that the `admin` username is not available for creation. + :param login: Username of the Grafana user. Note that the `admin` username is not available for creation. + :param project_id: ID of the Project in which to create the Grafana user. + :param role: Role assigned to the Grafana user. + :return: :class:`GrafanaUser ` + + Usage: + :: + + result = await api.create_grafana_user( + login="example", + ) + """ + + res = self._request( + "POST", + "/cockpit/v1/grafana/users", + body=marshal_GlobalApiCreateGrafanaUserRequest( + GlobalApiCreateGrafanaUserRequest( + login=login, + project_id=project_id, + role=role, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_GrafanaUser(res.json()) + + async def list_grafana_users( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListGrafanaUsersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListGrafanaUsersResponse: + """ + List Grafana users. + List all Grafana users created in your Cockpit's Grafana. By default, the Grafana users returned in the list are ordered in ascending order. + :param page: Page number. + :param page_size: Page size. + :param order_by: Order of the Grafana users. + :param project_id: ID of the Project to target. + :return: :class:`ListGrafanaUsersResponse ` + + Usage: + :: + + result = await api.list_grafana_users() + """ + + res = self._request( + "GET", + "/cockpit/v1/grafana/users", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListGrafanaUsersResponse(res.json()) + + async def list_grafana_users_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListGrafanaUsersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[GrafanaUser]: + """ + List Grafana users. + List all Grafana users created in your Cockpit's Grafana. By default, the Grafana users returned in the list are ordered in ascending order. + :param page: Page number. + :param page_size: Page size. + :param order_by: Order of the Grafana users. + :param project_id: ID of the Project to target. + :return: :class:`List[GrafanaUser] ` + + Usage: + :: + + result = await api.list_grafana_users_all() + """ + + return await fetch_all_pages_async( + type=ListGrafanaUsersResponse, + key="grafana_users", + fetcher=self.list_grafana_users, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def delete_grafana_user( + self, + *, + project_id: Optional[str] = None, + grafana_user_id: int, + ) -> None: + """ + Delete a Grafana user. + Delete a Grafana user from your Cockpit's Grafana, specified by the ID of the Project the Cockpit belongs to, and the ID of the Grafana user. + :param project_id: ID of the Project to target. + :param grafana_user_id: ID of the Grafana user. + + Usage: + :: + + result = await api.delete_grafana_user( + grafana_user_id=1, + ) + """ + + param_grafana_user_id = validate_path_param("grafana_user_id", grafana_user_id) + + res = self._request( + "DELETE", + f"/cockpit/v1/grafana/users/{param_grafana_user_id}", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + + async def reset_grafana_user_password( + self, + *, + project_id: Optional[str] = None, + grafana_user_id: int, + ) -> GrafanaUser: + """ + Reset a Grafana user password. + Reset the password of a Grafana user, specified by the ID of the Project the Cockpit belongs to, and the ID of the Grafana user. + A new password regenerates and only displays once. Make sure that you save it. + :param project_id: ID of the Project to target. + :param grafana_user_id: ID of the Grafana user. + :return: :class:`GrafanaUser ` + + Usage: + :: + + result = await api.reset_grafana_user_password( + grafana_user_id=1, + ) + """ + + param_grafana_user_id = validate_path_param("grafana_user_id", grafana_user_id) + + res = self._request( + "POST", + f"/cockpit/v1/grafana/users/{param_grafana_user_id}/reset-password", + body=marshal_GlobalApiResetGrafanaUserPasswordRequest( + GlobalApiResetGrafanaUserPasswordRequest( + project_id=project_id, + grafana_user_id=grafana_user_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_GrafanaUser(res.json()) + + async def list_grafana_product_dashboards( + self, + *, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + tags: Optional[List[str]] = None, + ) -> ListGrafanaProductDashboardsResponse: + """ + List Scaleway resources dashboards. + Retrieve a list of available dashboards in Grafana, for all Scaleway resources which are integrated with Cockpit. + :param project_id: ID of the Project to target. + :param page: Page number. + :param page_size: Page size. + :param tags: Tags to filter for. + :return: :class:`ListGrafanaProductDashboardsResponse ` + + Usage: + :: + + result = await api.list_grafana_product_dashboards() + """ + + res = self._request( + "GET", + "/cockpit/v1/grafana/product-dashboards", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListGrafanaProductDashboardsResponse(res.json()) + + async def list_grafana_product_dashboards_all( + self, + *, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + tags: Optional[List[str]] = None, + ) -> List[GrafanaProductDashboard]: + """ + List Scaleway resources dashboards. + Retrieve a list of available dashboards in Grafana, for all Scaleway resources which are integrated with Cockpit. + :param project_id: ID of the Project to target. + :param page: Page number. + :param page_size: Page size. + :param tags: Tags to filter for. + :return: :class:`List[GrafanaProductDashboard] ` + + Usage: + :: + + result = await api.list_grafana_product_dashboards_all() + """ + + return await fetch_all_pages_async( + type=ListGrafanaProductDashboardsResponse, + key="dashboards", + fetcher=self.list_grafana_product_dashboards, + args={ + "project_id": project_id, + "page": page, + "page_size": page_size, + "tags": tags, + }, + ) + + async def get_grafana_product_dashboard( + self, + *, + project_id: Optional[str] = None, + dashboard_name: str, + ) -> GrafanaProductDashboard: + """ + Get Scaleway resource dashboard. + Retrieve information about the dashboard of a Scaleway resource in Grafana, specified by the ID of the Project the Cockpit belongs to, and the name of the dashboard. + :param project_id: ID of the Project the dashboard belongs to. + :param dashboard_name: Name of the dashboard. + :return: :class:`GrafanaProductDashboard ` + + Usage: + :: + + result = await api.get_grafana_product_dashboard( + dashboard_name="example", + ) + """ + + param_dashboard_name = validate_path_param("dashboard_name", dashboard_name) + + res = self._request( + "GET", + f"/cockpit/v1/grafana/product-dashboards/{param_dashboard_name}", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_GrafanaProductDashboard(res.json()) + + async def list_plans( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListPlansRequestOrderBy] = None, + ) -> ListPlansResponse: + """ + List plan types. + Retrieve a list of available pricing plan types. + Deprecated: retention is now managed at the data source level. + :param page: Page number. + :param page_size: Page size. + :param order_by: + :return: :class:`ListPlansResponse ` + :deprecated + + Usage: + :: + + result = await api.list_plans() + """ + + res = self._request( + "GET", + "/cockpit/v1/plans", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPlansResponse(res.json()) + + async def list_plans_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListPlansRequestOrderBy] = None, + ) -> List[Plan]: + """ + List plan types. + Retrieve a list of available pricing plan types. + Deprecated: retention is now managed at the data source level. + :param page: Page number. + :param page_size: Page size. + :param order_by: + :return: :class:`List[Plan] ` + :deprecated + + Usage: + :: + + result = await api.list_plans_all() + """ + + return await fetch_all_pages_async( + type=ListPlansResponse, + key="plans", + fetcher=self.list_plans, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + async def select_plan( + self, + *, + project_id: Optional[str] = None, + plan_name: Optional[PlanName] = None, + ) -> Plan: + """ + Apply a pricing plan. + Apply a pricing plan on a given Project. You must specify the ID of the pricing plan type. Note that you will be billed for the plan you apply. + Deprecated: retention is now managed at the data source level. + :param project_id: ID of the Project. + :param plan_name: Name of the pricing plan. + :return: :class:`Plan ` + :deprecated + + Usage: + :: + + result = await api.select_plan() + """ + + res = self._request( + "PATCH", + "/cockpit/v1/plans", + body=marshal_GlobalApiSelectPlanRequest( + GlobalApiSelectPlanRequest( + project_id=project_id, + plan_name=plan_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + async def get_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> Plan: + """ + Get current plan. + Retrieve a pricing plan for the given Project, specified by the ID of the Project. + Deprecated: retention is now managed at the data source level. + :param project_id: ID of the Project. + :return: :class:`Plan ` + :deprecated + + Usage: + :: + + result = await api.get_current_plan() + """ + + res = self._request( + "GET", + "/cockpit/v1/current-plan", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + +class CockpitV1RegionalAPI(API): + """ + The Cockpit API allows you to create data sources and Cockpit tokens to store and query data types such as metrics, logs, and traces. You can also push your data into Cockpit, and send alerts to your contact points when your resources may require your attention, using the regional Alert manager. + """ + + async def get_config( + self, + *, + region: Optional[ScwRegion] = None, + ) -> GetConfigResponse: + """ + Get the Cockpit configuration. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`GetConfigResponse ` + + Usage: + :: + + result = await api.get_config() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/config", + ) + + self._throw_on_error(res) + return unmarshal_GetConfigResponse(res.json()) + + async def create_data_source( + self, + *, + name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + type_: Optional[DataSourceType] = None, + retention_days: Optional[int] = None, + ) -> DataSource: + """ + Create a data source. + You must specify the data source type upon creation. Available data source types include: + - metrics + - logs + - traces + The name of the data source will then be used as reference to name the associated Grafana data source. + :param name: Data source name. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project the data source belongs to. + :param type_: Data source type. + :param retention_days: Default values are 30 days for metrics, 7 days for logs and traces. + :return: :class:`DataSource ` + + Usage: + :: + + result = await api.create_data_source( + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/data-sources", + body=marshal_RegionalApiCreateDataSourceRequest( + RegionalApiCreateDataSourceRequest( + name=name, + region=region, + project_id=project_id, + type_=type_, + retention_days=retention_days, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DataSource(res.json()) + + async def get_data_source( + self, + *, + data_source_id: str, + region: Optional[ScwRegion] = None, + ) -> DataSource: + """ + Get a data source. + Retrieve information about a given data source, specified by the data source ID. The data source's information such as its name, type, URL, origin, and retention period, is returned. + :param data_source_id: ID of the relevant data source. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DataSource ` + + Usage: + :: + + result = await api.get_data_source( + data_source_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_data_source_id = validate_path_param("data_source_id", data_source_id) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/data-sources/{param_data_source_id}", + ) + + self._throw_on_error(res) + return unmarshal_DataSource(res.json()) + + async def delete_data_source( + self, + *, + data_source_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a data source. + Delete a given data source, specified by the data source ID. Note that deleting a data source is irreversible, and cannot be undone. + :param data_source_id: ID of the data source to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_data_source( + data_source_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_data_source_id = validate_path_param("data_source_id", data_source_id) + + res = self._request( + "DELETE", + f"/cockpit/v1/regions/{param_region}/data-sources/{param_data_source_id}", + ) + + self._throw_on_error(res) + + async def list_data_sources( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDataSourcesRequestOrderBy] = None, + project_id: Optional[str] = None, + origin: Optional[DataSourceOrigin] = None, + types: Optional[List[DataSourceType]] = None, + ) -> ListDataSourcesResponse: + """ + List data sources. + Retrieve the list of data sources available in the specified region. By default, the data sources returned in the list are ordered by creation date, in ascending order. + You can list data sources by Project, type and origin. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Number of data sources to return per page. + :param order_by: Sort order for data sources in the response. + :param project_id: Project ID to filter for, only data sources from this Project will be returned. + :param origin: Origin to filter for, only data sources with matching origin will be returned. + :param types: Types to filter for, only data sources with matching types will be returned. + :return: :class:`ListDataSourcesResponse ` + + Usage: + :: + + result = await api.list_data_sources() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/data-sources", + params={ + "order_by": order_by, + "origin": origin, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "types": types, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDataSourcesResponse(res.json()) + + async def list_data_sources_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDataSourcesRequestOrderBy] = None, + project_id: Optional[str] = None, + origin: Optional[DataSourceOrigin] = None, + types: Optional[List[DataSourceType]] = None, + ) -> List[DataSource]: + """ + List data sources. + Retrieve the list of data sources available in the specified region. By default, the data sources returned in the list are ordered by creation date, in ascending order. + You can list data sources by Project, type and origin. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Number of data sources to return per page. + :param order_by: Sort order for data sources in the response. + :param project_id: Project ID to filter for, only data sources from this Project will be returned. + :param origin: Origin to filter for, only data sources with matching origin will be returned. + :param types: Types to filter for, only data sources with matching types will be returned. + :return: :class:`List[DataSource] ` + + Usage: + :: + + result = await api.list_data_sources_all() + """ + + return await fetch_all_pages_async( + type=ListDataSourcesResponse, + key="data_sources", + fetcher=self.list_data_sources, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "origin": origin, + "types": types, + }, + ) + + async def update_data_source( + self, + *, + data_source_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + retention_days: Optional[int] = None, + ) -> DataSource: + """ + Update a data source. + Update a given data source name, specified by the data source ID. + :param data_source_id: ID of the data source to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Updated name of the data source. + :param retention_days: BETA - Duration for which the data will be retained in the data source. + :return: :class:`DataSource ` + + Usage: + :: + + result = await api.update_data_source( + data_source_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_data_source_id = validate_path_param("data_source_id", data_source_id) + + res = self._request( + "PATCH", + f"/cockpit/v1/regions/{param_region}/data-sources/{param_data_source_id}", + body=marshal_RegionalApiUpdateDataSourceRequest( + RegionalApiUpdateDataSourceRequest( + data_source_id=data_source_id, + region=region, + name=name, + retention_days=retention_days, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DataSource(res.json()) + + async def get_usage_overview( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + interval: Optional[str] = None, + ) -> UsageOverview: + """ + Get data source usage overview. + Retrieve the data source usage overview per type for the specified Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: + :param interval: + :return: :class:`UsageOverview ` + + Usage: + :: + + result = await api.get_usage_overview() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/usage-overview", + params={ + "interval": interval, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_UsageOverview(res.json()) + + async def create_token( + self, + *, + name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + token_scopes: Optional[List[TokenScope]] = None, + ) -> Token: + """ + Create a token. + Give your token the relevant scopes to ensure it has the right permissions to interact with your data sources and the Alert manager. Make sure that you create your token in the same regions as the data sources you want to use it for. + Upon creation, your token's secret key display only once. Make sure that you save it. + :param name: Name of the token. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project the token belongs to. + :param token_scopes: Token permission scopes. + :return: :class:`Token ` + + Usage: + :: + + result = await api.create_token( + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/tokens", + body=marshal_RegionalApiCreateTokenRequest( + RegionalApiCreateTokenRequest( + name=name, + region=region, + project_id=project_id, + token_scopes=token_scopes, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Token(res.json()) + + async def list_tokens( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListTokensRequestOrderBy] = None, + project_id: Optional[str] = None, + token_scopes: Optional[List[TokenScope]] = None, + ) -> ListTokensResponse: + """ + List tokens. + Retrieve a list of all tokens in the specified region. By default, tokens returned in the list are ordered by creation date, in ascending order. + You can filter tokens by Project ID and token scopes. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Number of tokens to return per page. + :param order_by: Order in which to return results. + :param project_id: ID of the Project the tokens belong to. + :param token_scopes: Token scopes to filter for. + :return: :class:`ListTokensResponse ` + + Usage: + :: + + result = await api.list_tokens() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/tokens", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "token_scopes": token_scopes, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListTokensResponse(res.json()) + + async def list_tokens_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListTokensRequestOrderBy] = None, + project_id: Optional[str] = None, + token_scopes: Optional[List[TokenScope]] = None, + ) -> List[Token]: + """ + List tokens. + Retrieve a list of all tokens in the specified region. By default, tokens returned in the list are ordered by creation date, in ascending order. + You can filter tokens by Project ID and token scopes. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Number of tokens to return per page. + :param order_by: Order in which to return results. + :param project_id: ID of the Project the tokens belong to. + :param token_scopes: Token scopes to filter for. + :return: :class:`List[Token] ` + + Usage: + :: + + result = await api.list_tokens_all() + """ + + return await fetch_all_pages_async( + type=ListTokensResponse, + key="tokens", + fetcher=self.list_tokens, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "token_scopes": token_scopes, + }, + ) + + async def get_token( + self, + *, + token_id: str, + region: Optional[ScwRegion] = None, + ) -> Token: + """ + Get a token. + Retrieve information about a given token, specified by the token ID. The token's information such as its scopes, is returned. + :param token_id: Token ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Token ` + + Usage: + :: + + result = await api.get_token( + token_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_token_id = validate_path_param("token_id", token_id) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/tokens/{param_token_id}", + ) + + self._throw_on_error(res) + return unmarshal_Token(res.json()) + + async def delete_token( + self, + *, + token_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a token. + Delete a given token, specified by the token ID. Deleting a token is irreversible and cannot be undone. + :param token_id: ID of the token to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_token( + token_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_token_id = validate_path_param("token_id", token_id) + + res = self._request( + "DELETE", + f"/cockpit/v1/regions/{param_region}/tokens/{param_token_id}", + ) + + self._throw_on_error(res) + + async def get_alert_manager( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AlertManager: + """ + Get the Alert manager. + Retrieve information about the Alert manager which is unique per Project and region. By default the Alert manager is disabled. + The output returned displays a URL to access the Alert manager, and whether the Alert manager and managed alerts are enabled. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: Project ID of the requested Alert manager. + :return: :class:`AlertManager ` + + Usage: + :: + + result = await api.get_alert_manager() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/alert-manager", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_AlertManager(res.json()) + + async def enable_alert_manager( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AlertManager: + """ + Enable the Alert manager. + Enabling the Alert manager allows you to enable managed alerts and create contact points in the specified Project and region, to be notified when your Scaleway resources may require your attention. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to enable the Alert manager in. + :return: :class:`AlertManager ` + + Usage: + :: + + result = await api.enable_alert_manager() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/enable", + body=marshal_RegionalApiEnableAlertManagerRequest( + RegionalApiEnableAlertManagerRequest( + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AlertManager(res.json()) + + async def disable_alert_manager( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AlertManager: + """ + Disable the Alert manager. + Disabling the Alert manager deletes the contact points you have created and disables managed alerts in the specified Project and region. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to disable the Alert manager in. + :return: :class:`AlertManager ` + + Usage: + :: + + result = await api.disable_alert_manager() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/disable", + body=marshal_RegionalApiDisableAlertManagerRequest( + RegionalApiDisableAlertManagerRequest( + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AlertManager(res.json()) + + async def create_contact_point( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + email: Optional[ContactPointEmail] = None, + send_resolved_notifications: Optional[bool] = None, + ) -> ContactPoint: + """ + Create a contact point. + Contact points are email addresses associated with the default receiver, that the Alert manager sends alerts to. + The source of the alerts are data sources within the same Project and region as the Alert manager. + If you need to receive alerts for other receivers, you can create additional contact points and receivers in Grafana. Make sure that you select the Scaleway Alert manager. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to create the contact point in. + :param email: Email address of the contact point to create. + One-Of ('configuration'): at most one of 'email' could be set. + :param send_resolved_notifications: Send an email notification when an alert is marked as resolved. + :return: :class:`ContactPoint ` + + Usage: + :: + + result = await api.create_contact_point() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/contact-points", + body=marshal_RegionalApiCreateContactPointRequest( + RegionalApiCreateContactPointRequest( + region=region, + project_id=project_id, + send_resolved_notifications=send_resolved_notifications, + email=email, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ContactPoint(res.json()) + + async def list_contact_points( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> ListContactPointsResponse: + """ + List contact points. + Retrieve a list of contact points for the specified Project. The response lists all contact points and receivers created in Grafana or via the API. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Total count of contact points to return per page. + :param project_id: ID of the Project containing the contact points to list. + :return: :class:`ListContactPointsResponse ` + + Usage: + :: + + result = await api.list_contact_points() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/alert-manager/contact-points", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListContactPointsResponse(res.json()) + + async def list_contact_points_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> List[ContactPoint]: + """ + List contact points. + Retrieve a list of contact points for the specified Project. The response lists all contact points and receivers created in Grafana or via the API. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Total count of contact points to return per page. + :param project_id: ID of the Project containing the contact points to list. + :return: :class:`List[ContactPoint] ` + + Usage: + :: + + result = await api.list_contact_points_all() + """ + + return await fetch_all_pages_async( + type=ListContactPointsResponse, + key="contact_points", + fetcher=self.list_contact_points, + args={ + "region": region, + "page": page, + "page_size": page_size, + "project_id": project_id, + }, + ) + + async def update_contact_point( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + email: Optional[ContactPointEmail] = None, + send_resolved_notifications: Optional[bool] = None, + ) -> ContactPoint: + """ + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project containing the contact point to update. + :param email: Email address of the contact point to update. + One-Of ('configuration'): at most one of 'email' could be set. + :param send_resolved_notifications: Enable or disable notifications when alert is resolved. + :return: :class:`ContactPoint ` + + Usage: + :: + + result = await api.update_contact_point() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "PATCH", + f"/cockpit/v1/regions/{param_region}/alert-manager/contact-points", + body=marshal_RegionalApiUpdateContactPointRequest( + RegionalApiUpdateContactPointRequest( + region=region, + project_id=project_id, + send_resolved_notifications=send_resolved_notifications, + email=email, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ContactPoint(res.json()) + + async def delete_contact_point( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + email: Optional[ContactPointEmail] = None, + ) -> None: + """ + Delete a contact point. + Delete a contact point associated with the default receiver. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project containing the contact point to delete. + :param email: Email address of the contact point to delete. + One-Of ('configuration'): at most one of 'email' could be set. + + Usage: + :: + + result = await api.delete_contact_point() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/contact-points/delete", + body=marshal_RegionalApiDeleteContactPointRequest( + RegionalApiDeleteContactPointRequest( + region=region, + project_id=project_id, + email=email, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def list_alerts( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + is_enabled: Optional[bool] = None, + is_preconfigured: Optional[bool] = None, + state: Optional[AlertState] = None, + data_source_id: Optional[str] = None, + ) -> ListAlertsResponse: + """ + List alerts. + List preconfigured and/or custom alerts for the specified Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: Project ID to filter for, only alerts from this Project will be returned. + :param is_enabled: True returns only enabled alerts. False returns only disabled alerts. If omitted, no alert filtering is applied. Other filters may still apply. + :param is_preconfigured: True returns only preconfigured alerts. False returns only custom alerts. If omitted, no filtering is applied on alert types. Other filters may still apply. + :param state: Valid values to filter on are `inactive`, `pending` and `firing`. If omitted, no filtering is applied on alert states. Other filters may still apply. + :param data_source_id: If omitted, only alerts from the default scaleway data source will be listed. + :return: :class:`ListAlertsResponse ` + + Usage: + :: + + result = await api.list_alerts() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/alerts", + params={ + "data_source_id": data_source_id, + "is_enabled": is_enabled, + "is_preconfigured": is_preconfigured, + "project_id": project_id or self.client.default_project_id, + "state": state, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListAlertsResponse(res.json()) + + async def enable_managed_alerts( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AlertManager: + """ + Enable managed alerts. + Enable the sending of managed alerts for the specified Project. Managed alerts are predefined alerts that apply to Scaleway recources integrated with Cockpit by default. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :return: :class:`AlertManager ` + + Usage: + :: + + result = await api.enable_managed_alerts() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/managed-alerts/enable", + body=marshal_RegionalApiEnableManagedAlertsRequest( + RegionalApiEnableManagedAlertsRequest( + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AlertManager(res.json()) + + async def disable_managed_alerts( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AlertManager: + """ + Disable managed alerts. + Disable the sending of managed alerts for the specified Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :return: :class:`AlertManager ` + + Usage: + :: + + result = await api.disable_managed_alerts() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/managed-alerts/disable", + body=marshal_RegionalApiDisableManagedAlertsRequest( + RegionalApiDisableManagedAlertsRequest( + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AlertManager(res.json()) + + async def enable_alert_rules( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + rule_ids: Optional[List[str]] = None, + ) -> EnableAlertRulesResponse: + """ + Enable preconfigured alert rules. + Enable alert rules from the list of available preconfigured rules. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: + :param rule_ids: + :return: :class:`EnableAlertRulesResponse ` + + Usage: + :: + + result = await api.enable_alert_rules() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/enable-alert-rules", + body=marshal_RegionalApiEnableAlertRulesRequest( + RegionalApiEnableAlertRulesRequest( + region=region, + project_id=project_id, + rule_ids=rule_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_EnableAlertRulesResponse(res.json()) + + async def disable_alert_rules( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + rule_ids: Optional[List[str]] = None, + ) -> DisableAlertRulesResponse: + """ + Disable preconfigured alert rules. + Disable alert rules from the list of available preconfigured rules. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: + :param rule_ids: + :return: :class:`DisableAlertRulesResponse ` + + Usage: + :: + + result = await api.disable_alert_rules() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/disable-alert-rules", + body=marshal_RegionalApiDisableAlertRulesRequest( + RegionalApiDisableAlertRulesRequest( + region=region, + project_id=project_id, + rule_ids=rule_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DisableAlertRulesResponse(res.json()) + + async def trigger_test_alert( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> None: + """ + Trigger a test alert. + Send a test alert to the Alert manager to make sure your contact points get notified. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + + Usage: + :: + + result = await api.trigger_test_alert() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/trigger-test-alert", + body=marshal_RegionalApiTriggerTestAlertRequest( + RegionalApiTriggerTestAlertRequest( + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/cockpit/v1/marshalling.py b/scaleway-async/scaleway_async/cockpit/v1/marshalling.py new file mode 100644 index 00000000..ae31225c --- /dev/null +++ b/scaleway-async/scaleway_async/cockpit/v1/marshalling.py @@ -0,0 +1,1051 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + TokenScope, + ContactPointEmail, + ContactPoint, + DataSource, + GrafanaProductDashboard, + GrafanaUser, + Plan, + Token, + AlertManager, + DisableAlertRulesResponse, + EnableAlertRulesResponse, + GetConfigResponseRetention, + GetConfigResponse, + Grafana, + PreconfiguredAlertData, + Alert, + ListAlertsResponse, + ListContactPointsResponse, + ListDataSourcesResponse, + ListGrafanaProductDashboardsResponse, + ListGrafanaUsersResponse, + ListPlansResponse, + ListTokensResponse, + Usage, + UsageOverview, + GlobalApiCreateGrafanaUserRequest, + GlobalApiResetGrafanaUserPasswordRequest, + GlobalApiSelectPlanRequest, + GlobalApiSyncGrafanaDataSourcesRequest, + RegionalApiCreateContactPointRequest, + RegionalApiCreateDataSourceRequest, + RegionalApiCreateTokenRequest, + RegionalApiDeleteContactPointRequest, + RegionalApiDisableAlertManagerRequest, + RegionalApiDisableAlertRulesRequest, + RegionalApiDisableManagedAlertsRequest, + RegionalApiEnableAlertManagerRequest, + RegionalApiEnableAlertRulesRequest, + RegionalApiEnableManagedAlertsRequest, + RegionalApiTriggerTestAlertRequest, + RegionalApiUpdateContactPointRequest, + RegionalApiUpdateDataSourceRequest, +) + + +def unmarshal_ContactPointEmail(data: Any) -> ContactPointEmail: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContactPointEmail' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("to", None) + if field is not None: + args["to"] = field + + return ContactPointEmail(**args) + + +def unmarshal_ContactPoint(data: Any) -> ContactPoint: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContactPoint' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("send_resolved_notifications", None) + if field is not None: + args["send_resolved_notifications"] = field + + field = data.get("email", None) + if field is not None: + args["email"] = unmarshal_ContactPointEmail(field) + else: + args["email"] = None + + return ContactPoint(**args) + + +def unmarshal_DataSource(data: Any) -> DataSource: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DataSource' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("url", None) + if field is not None: + args["url"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("origin", None) + if field is not None: + args["origin"] = field + + field = data.get("synchronized_with_grafana", None) + if field is not None: + args["synchronized_with_grafana"] = field + + field = data.get("retention_days", None) + if field is not None: + args["retention_days"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return DataSource(**args) + + +def unmarshal_GrafanaProductDashboard(data: Any) -> GrafanaProductDashboard: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GrafanaProductDashboard' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("title", None) + if field is not None: + args["title"] = field + + field = data.get("url", None) + if field is not None: + args["url"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("variables", None) + if field is not None: + args["variables"] = field + + return GrafanaProductDashboard(**args) + + +def unmarshal_GrafanaUser(data: Any) -> GrafanaUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GrafanaUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("login", None) + if field is not None: + args["login"] = field + + field = data.get("role", None) + if field is not None: + args["role"] = field + + field = data.get("password", None) + if field is not None: + args["password"] = field + else: + args["password"] = None + + return GrafanaUser(**args) + + +def unmarshal_Plan(data: Any) -> Plan: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Plan' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("sample_ingestion_price", None) + if field is not None: + args["sample_ingestion_price"] = field + + field = data.get("logs_ingestion_price", None) + if field is not None: + args["logs_ingestion_price"] = field + + field = data.get("traces_ingestion_price", None) + if field is not None: + args["traces_ingestion_price"] = field + + field = data.get("monthly_price", None) + if field is not None: + args["monthly_price"] = field + + field = data.get("retention_metrics_interval", None) + if field is not None: + args["retention_metrics_interval"] = field + else: + args["retention_metrics_interval"] = None + + field = data.get("retention_logs_interval", None) + if field is not None: + args["retention_logs_interval"] = field + else: + args["retention_logs_interval"] = None + + field = data.get("retention_traces_interval", None) + if field is not None: + args["retention_traces_interval"] = field + else: + args["retention_traces_interval"] = None + + return Plan(**args) + + +def unmarshal_Token(data: Any) -> Token: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Token' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("scopes", None) + if field is not None: + args["scopes"] = [TokenScope(v) for v in field] if field is not None else None + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("secret_key", None) + if field is not None: + args["secret_key"] = field + else: + args["secret_key"] = None + + return Token(**args) + + +def unmarshal_AlertManager(data: Any) -> AlertManager: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AlertManager' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("alert_manager_enabled", None) + if field is not None: + args["alert_manager_enabled"] = field + + field = data.get("managed_alerts_enabled", None) + if field is not None: + args["managed_alerts_enabled"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("alert_manager_url", None) + if field is not None: + args["alert_manager_url"] = field + else: + args["alert_manager_url"] = None + + return AlertManager(**args) + + +def unmarshal_DisableAlertRulesResponse(data: Any) -> DisableAlertRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DisableAlertRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("disabled_rule_ids", None) + if field is not None: + args["disabled_rule_ids"] = field + + return DisableAlertRulesResponse(**args) + + +def unmarshal_EnableAlertRulesResponse(data: Any) -> EnableAlertRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EnableAlertRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enabled_rule_ids", None) + if field is not None: + args["enabled_rule_ids"] = field + + return EnableAlertRulesResponse(**args) + + +def unmarshal_GetConfigResponseRetention(data: Any) -> GetConfigResponseRetention: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetConfigResponseRetention' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("min_days", None) + if field is not None: + args["min_days"] = field + + field = data.get("max_days", None) + if field is not None: + args["max_days"] = field + + field = data.get("default_days", None) + if field is not None: + args["default_days"] = field + + return GetConfigResponseRetention(**args) + + +def unmarshal_GetConfigResponse(data: Any) -> GetConfigResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetConfigResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("custom_metrics_retention", None) + if field is not None: + args["custom_metrics_retention"] = unmarshal_GetConfigResponseRetention(field) + else: + args["custom_metrics_retention"] = None + + field = data.get("custom_logs_retention", None) + if field is not None: + args["custom_logs_retention"] = unmarshal_GetConfigResponseRetention(field) + else: + args["custom_logs_retention"] = None + + field = data.get("custom_traces_retention", None) + if field is not None: + args["custom_traces_retention"] = unmarshal_GetConfigResponseRetention(field) + else: + args["custom_traces_retention"] = None + + field = data.get("product_metrics_retention", None) + if field is not None: + args["product_metrics_retention"] = unmarshal_GetConfigResponseRetention(field) + else: + args["product_metrics_retention"] = None + + field = data.get("product_logs_retention", None) + if field is not None: + args["product_logs_retention"] = unmarshal_GetConfigResponseRetention(field) + else: + args["product_logs_retention"] = None + + return GetConfigResponse(**args) + + +def unmarshal_Grafana(data: Any) -> Grafana: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Grafana' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("grafana_url", None) + if field is not None: + args["grafana_url"] = field + + return Grafana(**args) + + +def unmarshal_PreconfiguredAlertData(data: Any) -> PreconfiguredAlertData: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PreconfiguredAlertData' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("preconfigured_rule_id", None) + if field is not None: + args["preconfigured_rule_id"] = field + + field = data.get("display_name", None) + if field is not None: + args["display_name"] = field + + field = data.get("display_description", None) + if field is not None: + args["display_description"] = field + + return PreconfiguredAlertData(**args) + + +def unmarshal_Alert(data: Any) -> Alert: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Alert' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("preconfigured", None) + if field is not None: + args["preconfigured"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("rule", None) + if field is not None: + args["rule"] = field + + field = data.get("duration", None) + if field is not None: + args["duration"] = field + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + field = data.get("annotations", None) + if field is not None: + args["annotations"] = field + + field = data.get("data_source_id", None) + if field is not None: + args["data_source_id"] = field + + field = data.get("state", None) + if field is not None: + args["state"] = field + else: + args["state"] = None + + field = data.get("preconfigured_data", None) + if field is not None: + args["preconfigured_data"] = unmarshal_PreconfiguredAlertData(field) + else: + args["preconfigured_data"] = None + + return Alert(**args) + + +def unmarshal_ListAlertsResponse(data: Any) -> ListAlertsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListAlertsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("alerts", None) + if field is not None: + args["alerts"] = ( + [unmarshal_Alert(v) for v in field] if field is not None else None + ) + + return ListAlertsResponse(**args) + + +def unmarshal_ListContactPointsResponse(data: Any) -> ListContactPointsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListContactPointsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("contact_points", None) + if field is not None: + args["contact_points"] = ( + [unmarshal_ContactPoint(v) for v in field] if field is not None else None + ) + + field = data.get("has_additional_receivers", None) + if field is not None: + args["has_additional_receivers"] = field + + field = data.get("has_additional_contact_points", None) + if field is not None: + args["has_additional_contact_points"] = field + + return ListContactPointsResponse(**args) + + +def unmarshal_ListDataSourcesResponse(data: Any) -> ListDataSourcesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDataSourcesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("data_sources", None) + if field is not None: + args["data_sources"] = ( + [unmarshal_DataSource(v) for v in field] if field is not None else None + ) + + return ListDataSourcesResponse(**args) + + +def unmarshal_ListGrafanaProductDashboardsResponse( + data: Any, +) -> ListGrafanaProductDashboardsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGrafanaProductDashboardsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("dashboards", None) + if field is not None: + args["dashboards"] = ( + [unmarshal_GrafanaProductDashboard(v) for v in field] + if field is not None + else None + ) + + return ListGrafanaProductDashboardsResponse(**args) + + +def unmarshal_ListGrafanaUsersResponse(data: Any) -> ListGrafanaUsersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGrafanaUsersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("grafana_users", None) + if field is not None: + args["grafana_users"] = ( + [unmarshal_GrafanaUser(v) for v in field] if field is not None else None + ) + + return ListGrafanaUsersResponse(**args) + + +def unmarshal_ListPlansResponse(data: Any) -> ListPlansResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPlansResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("plans", None) + if field is not None: + args["plans"] = ( + [unmarshal_Plan(v) for v in field] if field is not None else None + ) + + return ListPlansResponse(**args) + + +def unmarshal_ListTokensResponse(data: Any) -> ListTokensResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListTokensResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("tokens", None) + if field is not None: + args["tokens"] = ( + [unmarshal_Token(v) for v in field] if field is not None else None + ) + + return ListTokensResponse(**args) + + +def unmarshal_Usage(data: Any) -> Usage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Usage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("data_source_origin", None) + if field is not None: + args["data_source_origin"] = field + + field = data.get("data_source_type", None) + if field is not None: + args["data_source_type"] = field + + field = data.get("unit", None) + if field is not None: + args["unit"] = field + + field = data.get("quantity_over_interval", None) + if field is not None: + args["quantity_over_interval"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("data_source_id", None) + if field is not None: + args["data_source_id"] = field + else: + args["data_source_id"] = None + + field = data.get("interval", None) + if field is not None: + args["interval"] = field + else: + args["interval"] = None + + return Usage(**args) + + +def unmarshal_UsageOverview(data: Any) -> UsageOverview: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'UsageOverview' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("scaleway_metrics_usage", None) + if field is not None: + args["scaleway_metrics_usage"] = unmarshal_Usage(field) + else: + args["scaleway_metrics_usage"] = None + + field = data.get("scaleway_logs_usage", None) + if field is not None: + args["scaleway_logs_usage"] = unmarshal_Usage(field) + else: + args["scaleway_logs_usage"] = None + + field = data.get("external_metrics_usage", None) + if field is not None: + args["external_metrics_usage"] = unmarshal_Usage(field) + else: + args["external_metrics_usage"] = None + + field = data.get("external_logs_usage", None) + if field is not None: + args["external_logs_usage"] = unmarshal_Usage(field) + else: + args["external_logs_usage"] = None + + field = data.get("external_traces_usage", None) + if field is not None: + args["external_traces_usage"] = unmarshal_Usage(field) + else: + args["external_traces_usage"] = None + + return UsageOverview(**args) + + +def marshal_GlobalApiCreateGrafanaUserRequest( + request: GlobalApiCreateGrafanaUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.login is not None: + output["login"] = request.login + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.role is not None: + output["role"] = str(request.role) + + return output + + +def marshal_GlobalApiResetGrafanaUserPasswordRequest( + request: GlobalApiResetGrafanaUserPasswordRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_GlobalApiSelectPlanRequest( + request: GlobalApiSelectPlanRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.plan_name is not None: + output["plan_name"] = str(request.plan_name) + + return output + + +def marshal_GlobalApiSyncGrafanaDataSourcesRequest( + request: GlobalApiSyncGrafanaDataSourcesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ContactPointEmail( + request: ContactPointEmail, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.to is not None: + output["to"] = request.to + + return output + + +def marshal_RegionalApiCreateContactPointRequest( + request: RegionalApiCreateContactPointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("email", request.email), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.send_resolved_notifications is not None: + output["send_resolved_notifications"] = request.send_resolved_notifications + + return output + + +def marshal_RegionalApiCreateDataSourceRequest( + request: RegionalApiCreateDataSourceRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.retention_days is not None: + output["retention_days"] = request.retention_days + + return output + + +def marshal_RegionalApiCreateTokenRequest( + request: RegionalApiCreateTokenRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.token_scopes is not None: + output["token_scopes"] = [str(item) for item in request.token_scopes] + + return output + + +def marshal_RegionalApiDeleteContactPointRequest( + request: RegionalApiDeleteContactPointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("email", request.email), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiDisableAlertManagerRequest( + request: RegionalApiDisableAlertManagerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiDisableAlertRulesRequest( + request: RegionalApiDisableAlertRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.rule_ids is not None: + output["rule_ids"] = request.rule_ids + + return output + + +def marshal_RegionalApiDisableManagedAlertsRequest( + request: RegionalApiDisableManagedAlertsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiEnableAlertManagerRequest( + request: RegionalApiEnableAlertManagerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiEnableAlertRulesRequest( + request: RegionalApiEnableAlertRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.rule_ids is not None: + output["rule_ids"] = request.rule_ids + + return output + + +def marshal_RegionalApiEnableManagedAlertsRequest( + request: RegionalApiEnableManagedAlertsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiTriggerTestAlertRequest( + request: RegionalApiTriggerTestAlertRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiUpdateContactPointRequest( + request: RegionalApiUpdateContactPointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("email", request.email), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.send_resolved_notifications is not None: + output["send_resolved_notifications"] = request.send_resolved_notifications + + return output + + +def marshal_RegionalApiUpdateDataSourceRequest( + request: RegionalApiUpdateDataSourceRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.retention_days is not None: + output["retention_days"] = request.retention_days + + return output diff --git a/scaleway-async/scaleway_async/cockpit/v1/types.py b/scaleway-async/scaleway_async/cockpit/v1/types.py new file mode 100644 index 00000000..17ca2ebe --- /dev/null +++ b/scaleway-async/scaleway_async/cockpit/v1/types.py @@ -0,0 +1,1437 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class AlertState(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATE = "unknown_state" + INACTIVE = "inactive" + PENDING = "pending" + FIRING = "firing" + + def __str__(self) -> str: + return str(self.value) + + +class DataSourceOrigin(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ORIGIN = "unknown_origin" + SCALEWAY = "scaleway" + EXTERNAL = "external" + CUSTOM = "custom" + + def __str__(self) -> str: + return str(self.value) + + +class DataSourceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + METRICS = "metrics" + LOGS = "logs" + TRACES = "traces" + + def __str__(self) -> str: + return str(self.value) + + +class GrafanaUserRole(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ROLE = "unknown_role" + EDITOR = "editor" + VIEWER = "viewer" + + def __str__(self) -> str: + return str(self.value) + + +class ListDataSourcesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + TYPE_ASC = "type_asc" + TYPE_DESC = "type_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListGrafanaUsersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + LOGIN_ASC = "login_asc" + LOGIN_DESC = "login_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPlansRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListTokensRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class PlanName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + FREE = "free" + PREMIUM = "premium" + CUSTOM = "custom" + + def __str__(self) -> str: + return str(self.value) + + +class TokenScope(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SCOPE = "unknown_scope" + READ_ONLY_METRICS = "read_only_metrics" + WRITE_ONLY_METRICS = "write_only_metrics" + FULL_ACCESS_METRICS_RULES = "full_access_metrics_rules" + READ_ONLY_LOGS = "read_only_logs" + WRITE_ONLY_LOGS = "write_only_logs" + FULL_ACCESS_LOGS_RULES = "full_access_logs_rules" + FULL_ACCESS_ALERT_MANAGER = "full_access_alert_manager" + READ_ONLY_TRACES = "read_only_traces" + WRITE_ONLY_TRACES = "write_only_traces" + + def __str__(self) -> str: + return str(self.value) + + +class UsageUnit(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_UNIT = "unknown_unit" + BYTES = "bytes" + SAMPLES = "samples" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class PreconfiguredAlertData: + """ + Structure for additional data relative to preconfigured alerts. + """ + + preconfigured_rule_id: str + """ + ID of the preconfigured rule if the alert is preconfigured. + """ + + display_name: str + """ + Human readable name of the alert. + """ + + display_description: str + """ + Human readable description of the alert. + """ + + +@dataclass +class ContactPointEmail: + to: str + + +@dataclass +class GetConfigResponseRetention: + min_days: int + + max_days: int + + default_days: int + + +@dataclass +class Alert: + """ + Structure representing an alert. + """ + + region: ScwRegion + """ + The region in which the alert is defined. + """ + + preconfigured: bool + """ + Indicates if the alert is preconfigured or custom. + """ + + name: str + """ + Name of the alert. + """ + + rule: str + """ + Rule defining the alert condition. + """ + + duration: str + """ + Duration for which the alert must be active before firing. The format of this duration follows the prometheus duration format. + """ + + enabled: bool + """ + Indicates if the alert is enabled or disabled. Only preconfigured alerts can be disabled. + """ + + annotations: Dict[str, str] + """ + Annotations for the alert, used to provide additional information about the alert. + """ + + data_source_id: str + """ + ID of the data source containing the alert rule. + """ + + state: Optional[AlertState] + """ + Current state of the alert. Possible states are `inactive`, `pending`, and `firing`. + """ + + preconfigured_data: Optional[PreconfiguredAlertData] + """ + Contains additional data for preconfigured alerts, such as the rule ID, display name, and description. Only present if the alert is preconfigured. + """ + + +@dataclass +class ContactPoint: + """ + Contact point. + """ + + region: ScwRegion + """ + Region. + """ + + send_resolved_notifications: bool + """ + Send an email notification when an alert is marked as resolved. + """ + + email: Optional[ContactPointEmail] + + +@dataclass +class DataSource: + """ + Data source. + """ + + id: str + """ + ID of the data source. + """ + + project_id: str + """ + ID of the Project the data source belongs to. + """ + + name: str + """ + Data source name. + """ + + url: str + """ + Data source URL. + """ + + type_: DataSourceType + """ + Data source type. + """ + + origin: DataSourceOrigin + """ + Data source origin. + """ + + synchronized_with_grafana: bool + """ + Indicates whether the data source is synchronized with Grafana. + """ + + retention_days: int + """ + BETA - Duration for which the data will be retained in the data source. + """ + + region: ScwRegion + """ + Region of the data source. + """ + + created_at: Optional[datetime] + """ + Date the data source was created. + """ + + updated_at: Optional[datetime] + """ + Date the data source was last updated. + """ + + +@dataclass +class GrafanaProductDashboard: + """ + Grafana dashboard. + """ + + name: str + """ + Dashboard name. + """ + + title: str + """ + Dashboard title. + """ + + url: str + """ + Dashboard URL. + """ + + tags: List[str] + """ + Dashboard tags. + """ + + variables: List[str] + """ + Dashboard variables. + """ + + +@dataclass +class GrafanaUser: + """ + Grafana user. + """ + + id: int + """ + ID of the Grafana user. + """ + + login: str + """ + Username of the Grafana user. + """ + + role: GrafanaUserRole + """ + Role assigned to the Grafana user. + """ + + password: Optional[str] + """ + Grafana user's password. + """ + + +@dataclass +class Plan: + """ + Type of pricing plan. + """ + + name: PlanName + """ + Name of a given pricing plan. + """ + + sample_ingestion_price: int + """ + Ingestion price in cents for 1 million samples. + """ + + logs_ingestion_price: int + """ + Ingestion price in cents for 1 GB of logs. + """ + + traces_ingestion_price: int + """ + Ingestion price in cents for 1 GB of traces. + """ + + monthly_price: int + """ + Retention price in euros per month. + """ + + retention_metrics_interval: Optional[str] + """ + Interval of time during which Scaleway's Cockpit keeps your metrics. + """ + + retention_logs_interval: Optional[str] + """ + Interval of time during which Scaleway's Cockpit keeps your logs. + """ + + retention_traces_interval: Optional[str] + """ + Interval of time during which Scaleway's Cockpit keeps your traces. + """ + + +@dataclass +class Token: + """ + Token. + """ + + id: str + """ + ID of the token. + """ + + project_id: str + """ + ID of the Project the token belongs to. + """ + + name: str + """ + Name of the token. + """ + + scopes: List[TokenScope] + """ + Token permission scopes. + """ + + region: ScwRegion + """ + Regions where the token is located. + """ + + created_at: Optional[datetime] + """ + Token creation date. + """ + + updated_at: Optional[datetime] + """ + Token last modification date. + """ + + secret_key: Optional[str] + """ + Token secret key. + """ + + +@dataclass +class Usage: + """ + Data source usage. + """ + + project_id: str + """ + ID of the Project the data source belongs to. + """ + + data_source_origin: DataSourceOrigin + """ + Origin of the data source. + """ + + data_source_type: DataSourceType + """ + Type of the data source. + """ + + unit: UsageUnit + """ + Unit of the data source usage. + """ + + quantity_over_interval: int + """ + Data source usage for the given interval. + """ + + region: ScwRegion + """ + Region of the data source usage. + """ + + data_source_id: Optional[str] + """ + ID of the data source. + """ + + interval: Optional[str] + """ + Interval for the data source usage. + """ + + +@dataclass +class AlertManager: + """ + Alert manager information. + """ + + alert_manager_enabled: bool + """ + The Alert manager is enabled. + """ + + managed_alerts_enabled: bool + """ + Managed alerts are enabled. + """ + + region: ScwRegion + """ + Regions where the Alert manager is enabled. + """ + + alert_manager_url: Optional[str] + """ + Alert manager URL. + """ + + +@dataclass +class DisableAlertRulesResponse: + disabled_rule_ids: List[str] + + +@dataclass +class EnableAlertRulesResponse: + enabled_rule_ids: List[str] + + +@dataclass +class GetConfigResponse: + """ + Cockpit configuration. + """ + + custom_metrics_retention: Optional[GetConfigResponseRetention] + """ + Custom metrics retention configuration. + """ + + custom_logs_retention: Optional[GetConfigResponseRetention] + """ + Custom logs retention configuration. + """ + + custom_traces_retention: Optional[GetConfigResponseRetention] + """ + Custom traces retention configuration. + """ + + product_metrics_retention: Optional[GetConfigResponseRetention] + """ + Scaleway metrics retention configuration. + """ + + product_logs_retention: Optional[GetConfigResponseRetention] + """ + Scaleway logs retention configuration. + """ + + +@dataclass +class GlobalApiCreateGrafanaUserRequest: + """ + Create a Grafana user. + """ + + login: str + """ + Username of the Grafana user. Note that the `admin` username is not available for creation. + """ + + project_id: Optional[str] + """ + ID of the Project in which to create the Grafana user. + """ + + role: Optional[GrafanaUserRole] + """ + Role assigned to the Grafana user. + """ + + +@dataclass +class GlobalApiDeleteGrafanaUserRequest: + """ + Delete a Grafana user. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + grafana_user_id: int + """ + ID of the Grafana user. + """ + + +@dataclass +class GlobalApiGetCurrentPlanRequest: + """ + Retrieve a pricing plan for the given Project. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class GlobalApiGetGrafanaProductDashboardRequest: + """ + Retrieve a specific dashboard. + """ + + project_id: Optional[str] + """ + ID of the Project the dashboard belongs to. + """ + + dashboard_name: str + """ + Name of the dashboard. + """ + + +@dataclass +class GlobalApiGetGrafanaRequest: + """ + Request a Grafana. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class GlobalApiListGrafanaProductDashboardsRequest: + """ + Retrieve a list of available product dashboards. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size. + """ + + tags: Optional[List[str]] + """ + Tags to filter for. + """ + + +@dataclass +class GlobalApiListGrafanaUsersRequest: + """ + List all Grafana users. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size. + """ + + order_by: Optional[ListGrafanaUsersRequestOrderBy] + """ + Order of the Grafana users. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + +@dataclass +class GlobalApiListPlansRequest: + """ + Retrieve a list of available pricing plans. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size. + """ + + order_by: Optional[ListPlansRequestOrderBy] + + +@dataclass +class GlobalApiResetGrafanaUserPasswordRequest: + """ + Reset a Grafana user's password. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + grafana_user_id: int + """ + ID of the Grafana user. + """ + + +@dataclass +class GlobalApiSelectPlanRequest: + """ + Select a specific pricing plan. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + plan_name: Optional[PlanName] + """ + Name of the pricing plan. + """ + + +@dataclass +class GlobalApiSyncGrafanaDataSourcesRequest: + """ + Trigger the synchronization of all data sources created in the relevant regions. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + +@dataclass +class Grafana: + """ + Grafana user. + """ + + grafana_url: str + """ + URL to access your Cockpit's Grafana. + """ + + +@dataclass +class ListAlertsResponse: + """ + Retrieve a list of alerts matching the request. + """ + + total_count: int + """ + Total count of alerts matching the request. + """ + + alerts: List[Alert] + """ + List of alerts matching the applied filters. + """ + + +@dataclass +class ListContactPointsResponse: + """ + Response returned when listing contact points. + """ + + total_count: int + """ + Total count of contact points associated with the default receiver. + """ + + contact_points: List[ContactPoint] + """ + List of contact points associated with the default receiver. + """ + + has_additional_receivers: bool + """ + Indicates whether the Alert manager has other receivers than the default one. + """ + + has_additional_contact_points: bool + """ + Indicates whether there are unmanaged contact points on the default receiver. + """ + + +@dataclass +class ListDataSourcesResponse: + """ + Response returned when listing data sources. + """ + + total_count: int + """ + Total count of data sources matching the request. + """ + + data_sources: List[DataSource] + """ + Data sources matching the request within the pagination. + """ + + +@dataclass +class ListGrafanaProductDashboardsResponse: + """ + Output returned when listing dashboards. + """ + + total_count: int + """ + Total count of Grafana dashboards. + """ + + dashboards: List[GrafanaProductDashboard] + """ + Grafana dashboards information. + """ + + +@dataclass +class ListGrafanaUsersResponse: + """ + Ouptut returned when listing Grafana users. + """ + + total_count: int + """ + Total count of Grafana users. + """ + + grafana_users: List[GrafanaUser] + """ + Grafana users information. + """ + + +@dataclass +class ListPlansResponse: + """ + Output returned when listing pricing plans. + """ + + total_count: int + """ + Total count of available pricing plans. + """ + + plans: List[Plan] + """ + Plan types information. + """ + + +@dataclass +class ListTokensResponse: + """ + Response returned when listing tokens. + """ + + total_count: int + """ + Total count of tokens matching the request. + """ + + tokens: List[Token] + """ + Tokens matching the request within the pagination. + """ + + +@dataclass +class RegionalApiCreateContactPointRequest: + """ + Create a contact point. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to create the contact point in. + """ + + send_resolved_notifications: Optional[bool] + """ + Send an email notification when an alert is marked as resolved. + """ + + email: Optional[ContactPointEmail] + + +@dataclass +class RegionalApiCreateDataSourceRequest: + """ + Create a data source. + """ + + name: str + """ + Data source name. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project the data source belongs to. + """ + + type_: Optional[DataSourceType] + """ + Data source type. + """ + + retention_days: Optional[int] + """ + Default values are 30 days for metrics, 7 days for logs and traces. + """ + + +@dataclass +class RegionalApiCreateTokenRequest: + """ + Create a token. + """ + + name: str + """ + Name of the token. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project the token belongs to. + """ + + token_scopes: Optional[List[TokenScope]] + """ + Token permission scopes. + """ + + +@dataclass +class RegionalApiDeleteContactPointRequest: + """ + Delete a contact point. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project containing the contact point to delete. + """ + + email: Optional[ContactPointEmail] + + +@dataclass +class RegionalApiDeleteDataSourceRequest: + """ + Delete a data source. + """ + + data_source_id: str + """ + ID of the data source to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RegionalApiDeleteTokenRequest: + """ + Delete a token. + """ + + token_id: str + """ + ID of the token to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RegionalApiDisableAlertManagerRequest: + """ + Disable the Alert manager. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to disable the Alert manager in. + """ + + +@dataclass +class RegionalApiDisableAlertRulesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + + rule_ids: Optional[List[str]] + + +@dataclass +class RegionalApiDisableManagedAlertsRequest: + """ + Disable the sending of managed alerts. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class RegionalApiEnableAlertManagerRequest: + """ + Enable the Alert manager. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to enable the Alert manager in. + """ + + +@dataclass +class RegionalApiEnableAlertRulesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + + rule_ids: Optional[List[str]] + + +@dataclass +class RegionalApiEnableManagedAlertsRequest: + """ + Enable the sending of managed alerts. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class RegionalApiGetAlertManagerRequest: + """ + Get the Alert manager. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + Project ID of the requested Alert manager. + """ + + +@dataclass +class RegionalApiGetConfigRequest: + """ + Get Cockpit configuration. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RegionalApiGetDataSourceRequest: + """ + Retrieve a data source. + """ + + data_source_id: str + """ + ID of the relevant data source. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RegionalApiGetTokenRequest: + """ + Get a token. + """ + + token_id: str + """ + Token ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RegionalApiGetUsageOverviewRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + + interval: Optional[str] + + +@dataclass +class RegionalApiListAlertsRequest: + """ + Retrieve a list of alerts. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only alerts from this Project will be returned. + """ + + is_enabled: Optional[bool] + """ + True returns only enabled alerts. False returns only disabled alerts. If omitted, no alert filtering is applied. Other filters may still apply. + """ + + is_preconfigured: Optional[bool] + """ + True returns only preconfigured alerts. False returns only custom alerts. If omitted, no filtering is applied on alert types. Other filters may still apply. + """ + + state: Optional[AlertState] + """ + Valid values to filter on are `inactive`, `pending` and `firing`. If omitted, no filtering is applied on alert states. Other filters may still apply. + """ + + data_source_id: Optional[str] + """ + If omitted, only alerts from the default scaleway data source will be listed. + """ + + +@dataclass +class RegionalApiListContactPointsRequest: + """ + List contact points. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Total count of contact points to return per page. + """ + + project_id: Optional[str] + """ + ID of the Project containing the contact points to list. + """ + + +@dataclass +class RegionalApiListDataSourcesRequest: + """ + List data sources. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of data sources to return per page. + """ + + order_by: Optional[ListDataSourcesRequestOrderBy] + """ + Sort order for data sources in the response. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only data sources from this Project will be returned. + """ + + origin: Optional[DataSourceOrigin] + """ + Origin to filter for, only data sources with matching origin will be returned. + """ + + types: Optional[List[DataSourceType]] + """ + Types to filter for, only data sources with matching types will be returned. + """ + + +@dataclass +class RegionalApiListTokensRequest: + """ + List tokens. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of tokens to return per page. + """ + + order_by: Optional[ListTokensRequestOrderBy] + """ + Order in which to return results. + """ + + project_id: Optional[str] + """ + ID of the Project the tokens belong to. + """ + + token_scopes: Optional[List[TokenScope]] + """ + Token scopes to filter for. + """ + + +@dataclass +class RegionalApiTriggerTestAlertRequest: + """ + Request to trigger a test alert. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class RegionalApiUpdateContactPointRequest: + """ + Update a contact point. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project containing the contact point to update. + """ + + send_resolved_notifications: Optional[bool] + """ + Enable or disable notifications when alert is resolved. + """ + + email: Optional[ContactPointEmail] + + +@dataclass +class RegionalApiUpdateDataSourceRequest: + """ + Update a data source name. + """ + + data_source_id: str + """ + ID of the data source to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Updated name of the data source. + """ + + retention_days: Optional[int] + """ + BETA - Duration for which the data will be retained in the data source. + """ + + +@dataclass +class UsageOverview: + scaleway_metrics_usage: Optional[Usage] + + scaleway_logs_usage: Optional[Usage] + + external_metrics_usage: Optional[Usage] + + external_logs_usage: Optional[Usage] + + external_traces_usage: Optional[Usage] diff --git a/scaleway-async/scaleway_async/cockpit/v1beta1/api.py b/scaleway-async/scaleway_async/cockpit/v1beta1/api.py index 0f4a1c00..920c84d5 100644 --- a/scaleway-async/scaleway_async/cockpit/v1beta1/api.py +++ b/scaleway-async/scaleway_async/cockpit/v1beta1/api.py @@ -85,7 +85,7 @@ class CockpitV1Beta1API(API): """ - The Cockpit API allows you to activate your Cockpit to store metrics and logs. It also provides you with a dedicated Grafana for dashboarding to visualize your metrics and logs. + This API allows you to manage your Scaleway Cockpit, for storing and visualizing metrics and logs. """ async def activate_cockpit( diff --git a/scaleway-async/scaleway_async/cockpit/v1beta1/marshalling.py b/scaleway-async/scaleway_async/cockpit/v1beta1/marshalling.py index edf291af..916db34e 100644 --- a/scaleway-async/scaleway_async/cockpit/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/cockpit/v1beta1/marshalling.py @@ -73,6 +73,8 @@ def unmarshal_ContactPoint(data: Any) -> ContactPoint: field = data.get("email", None) if field is not None: args["email"] = unmarshal_ContactPointEmail(field) + else: + args["email"] = None return ContactPoint(**args) @@ -101,7 +103,7 @@ def unmarshal_Datasource(data: Any) -> Datasource: if field is not None: args["url"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -166,6 +168,8 @@ def unmarshal_GrafanaUser(data: Any) -> GrafanaUser: field = data.get("password", None) if field is not None: args["password"] = field + else: + args["password"] = None return GrafanaUser(**args) @@ -240,18 +244,26 @@ def unmarshal_Token(data: Any) -> Token: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("scopes", None) if field is not None: args["scopes"] = unmarshal_TokenScopes(field) + else: + args["scopes"] = None field = data.get("secret_key", None) if field is not None: args["secret_key"] = field + else: + args["secret_key"] = None return Token(**args) @@ -322,14 +334,20 @@ def unmarshal_Plan(data: Any) -> Plan: field = data.get("retention_metrics_interval", None) if field is not None: args["retention_metrics_interval"] = field + else: + args["retention_metrics_interval"] = None field = data.get("retention_logs_interval", None) if field is not None: args["retention_logs_interval"] = field + else: + args["retention_logs_interval"] = None field = data.get("retention_traces_interval", None) if field is not None: args["retention_traces_interval"] = field + else: + args["retention_traces_interval"] = None return Plan(**args) @@ -357,18 +375,26 @@ def unmarshal_Cockpit(data: Any) -> Cockpit: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("endpoints", None) if field is not None: args["endpoints"] = unmarshal_CockpitEndpoints(field) + else: + args["endpoints"] = None field = data.get("plan", None) if field is not None: args["plan"] = unmarshal_Plan(field) + else: + args["plan"] = None return Cockpit(**args) @@ -589,9 +615,7 @@ def marshal_CreateContactPointRequest( output["project_id"] = request.project_id or defaults.default_project_id if request.contact_point is not None: - output["contact_point"] = ( - marshal_ContactPoint(request.contact_point, defaults), - ) + output["contact_point"] = marshal_ContactPoint(request.contact_point, defaults) return output @@ -684,7 +708,7 @@ def marshal_CreateTokenRequest( output["name"] = request.name if request.scopes is not None: - output["scopes"] = (marshal_TokenScopes(request.scopes, defaults),) + output["scopes"] = marshal_TokenScopes(request.scopes, defaults) return output @@ -711,9 +735,7 @@ def marshal_DeleteContactPointRequest( output["project_id"] = request.project_id or defaults.default_project_id if request.contact_point is not None: - output["contact_point"] = ( - marshal_ContactPoint(request.contact_point, defaults), - ) + output["contact_point"] = marshal_ContactPoint(request.contact_point, defaults) return output diff --git a/scaleway-async/scaleway_async/container/v1beta1/__init__.py b/scaleway-async/scaleway_async/container/v1beta1/__init__.py index e4706cb5..a1de41c3 100644 --- a/scaleway-async/scaleway_async/container/v1beta1/__init__.py +++ b/scaleway-async/scaleway_async/container/v1beta1/__init__.py @@ -3,6 +3,7 @@ from .types import ContainerHttpOption from .types import ContainerPrivacy from .types import ContainerProtocol +from .types import ContainerSandbox from .types import ContainerStatus from .content import CONTAINER_TRANSIENT_STATUSES from .types import CronStatus @@ -22,6 +23,10 @@ from .types import TriggerInputType from .types import TriggerStatus from .content import TRIGGER_TRANSIENT_STATUSES +from .types import ContainerHealthCheckSpecHTTPProbe +from .types import ContainerHealthCheckSpecTCPProbe +from .types import ContainerHealthCheckSpec +from .types import ContainerScalingOption from .types import SecretHashedValue from .types import TriggerMnqNatsClientConfig from .types import TriggerMnqSqsClientConfig @@ -56,7 +61,6 @@ from .types import GetNamespaceRequest from .types import GetTokenRequest from .types import GetTriggerRequest -from .types import IssueJWTRequest from .types import ListContainersRequest from .types import ListContainersResponse from .types import ListCronsRequest @@ -79,6 +83,7 @@ "ContainerHttpOption", "ContainerPrivacy", "ContainerProtocol", + "ContainerSandbox", "ContainerStatus", "CONTAINER_TRANSIENT_STATUSES", "CronStatus", @@ -98,6 +103,10 @@ "TriggerInputType", "TriggerStatus", "TRIGGER_TRANSIENT_STATUSES", + "ContainerHealthCheckSpecHTTPProbe", + "ContainerHealthCheckSpecTCPProbe", + "ContainerHealthCheckSpec", + "ContainerScalingOption", "SecretHashedValue", "TriggerMnqNatsClientConfig", "TriggerMnqSqsClientConfig", @@ -132,7 +141,6 @@ "GetNamespaceRequest", "GetTokenRequest", "GetTriggerRequest", - "IssueJWTRequest", "ListContainersRequest", "ListContainersResponse", "ListCronsRequest", diff --git a/scaleway-async/scaleway_async/container/v1beta1/api.py b/scaleway-async/scaleway_async/container/v1beta1/api.py index 8c81acab..9e82e482 100644 --- a/scaleway-async/scaleway_async/container/v1beta1/api.py +++ b/scaleway-async/scaleway_async/container/v1beta1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( OneOfPossibility, @@ -21,6 +21,7 @@ ContainerHttpOption, ContainerPrivacy, ContainerProtocol, + ContainerSandbox, ListContainersRequestOrderBy, ListCronsRequestOrderBy, ListDomainsRequestOrderBy, @@ -28,6 +29,8 @@ ListTokensRequestOrderBy, ListTriggersRequestOrderBy, Container, + ContainerHealthCheckSpec, + ContainerScalingOption, CreateContainerRequest, CreateCronRequest, CreateDomainRequest, @@ -91,13 +94,13 @@ class ContainerV1Beta1API(API): """ - Serverless Containers API. + This API allows you to manage your Serverless Containers. """ async def list_namespaces( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -147,7 +150,7 @@ async def list_namespaces( async def list_namespaces_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -192,7 +195,7 @@ async def get_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Get a namespace. @@ -226,7 +229,7 @@ async def wait_for_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[Namespace, Union[bool, Awaitable[bool]]] ] = None, @@ -264,12 +267,13 @@ async def wait_for_namespace( async def create_namespace( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, environment_variables: Optional[Dict[str, str]] = None, project_id: Optional[str] = None, description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, + tags: Optional[List[str]] = None, ) -> Namespace: """ Create a new namespace. @@ -280,6 +284,7 @@ async def create_namespace( :param project_id: UUID of the Project in which the namespace will be created. :param description: Description of the namespace to create. :param secret_environment_variables: Secret environment variables of the namespace to create. + :param tags: Tags of the Serverless Container Namespace. :return: :class:`Namespace ` Usage: @@ -303,6 +308,7 @@ async def create_namespace( project_id=project_id, description=description, secret_environment_variables=secret_environment_variables, + tags=tags, ), self.client, ), @@ -315,10 +321,11 @@ async def update_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, environment_variables: Optional[Dict[str, str]] = None, description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, + tags: Optional[List[str]] = None, ) -> Namespace: """ Update an existing namespace. @@ -328,6 +335,7 @@ async def update_namespace( :param environment_variables: Environment variables of the namespace to update. :param description: Description of the namespace to update. :param secret_environment_variables: Secret environment variables of the namespace to update. + :param tags: Tags of the Serverless Container Namespace. :return: :class:`Namespace ` Usage: @@ -353,6 +361,7 @@ async def update_namespace( environment_variables=environment_variables, description=description, secret_environment_variables=secret_environment_variables, + tags=tags, ), self.client, ), @@ -365,7 +374,7 @@ async def delete_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Delete an existing namespace. @@ -399,7 +408,7 @@ async def list_containers( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListContainersRequestOrderBy] = None, @@ -454,7 +463,7 @@ async def list_containers_all( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListContainersRequestOrderBy] = None, @@ -503,7 +512,7 @@ async def get_container( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Container: """ Get a container. @@ -537,7 +546,7 @@ async def wait_for_container( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[Container, Union[bool, Awaitable[bool]]] ] = None, @@ -577,7 +586,7 @@ async def create_container( *, namespace_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, environment_variables: Optional[Dict[str, str]] = None, min_scale: Optional[int] = None, max_scale: Optional[int] = None, @@ -592,6 +601,11 @@ async def create_container( port: Optional[int] = None, secret_environment_variables: Optional[List[Secret]] = None, http_option: Optional[ContainerHttpOption] = None, + sandbox: Optional[ContainerSandbox] = None, + local_storage_limit: Optional[int] = None, + scaling_option: Optional[ContainerScalingOption] = None, + health_check: Optional[ContainerHealthCheckSpec] = None, + tags: Optional[List[str]] = None, ) -> Container: """ Create a new container. @@ -615,6 +629,14 @@ async def create_container( :param http_option: Possible values: - redirected: Responds to HTTP request with a 301 redirect to ask the clients to use HTTPS. - enabled: Serve both HTTP and HTTPS traffic. + :param sandbox: Execution environment of the container. + :param local_storage_limit: Local storage limit of the container (in MB). + :param scaling_option: Possible values: + - concurrent_requests_threshold: Scale depending on the number of concurrent requests being processed per container instance. + - cpu_usage_threshold: Scale depending on the CPU usage of a container instance. + - memory_usage_threshold: Scale depending on the memory usage of a container instance. + :param health_check: Health check configuration of the container. + :param tags: Tags of the Serverless Container. :return: :class:`Container ` Usage: @@ -652,6 +674,11 @@ async def create_container( port=port, secret_environment_variables=secret_environment_variables, http_option=http_option, + sandbox=sandbox, + local_storage_limit=local_storage_limit, + scaling_option=scaling_option, + health_check=health_check, + tags=tags, ), self.client, ), @@ -664,7 +691,7 @@ async def update_container( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, environment_variables: Optional[Dict[str, str]] = None, min_scale: Optional[int] = None, max_scale: Optional[int] = None, @@ -680,6 +707,11 @@ async def update_container( port: Optional[int] = None, secret_environment_variables: Optional[List[Secret]] = None, http_option: Optional[ContainerHttpOption] = None, + sandbox: Optional[ContainerSandbox] = None, + local_storage_limit: Optional[int] = None, + scaling_option: Optional[ContainerScalingOption] = None, + health_check: Optional[ContainerHealthCheckSpec] = None, + tags: Optional[List[str]] = None, ) -> Container: """ Update an existing container. @@ -703,6 +735,14 @@ async def update_container( :param http_option: Possible values: - redirected: Responds to HTTP request with a 301 redirect to ask the clients to use HTTPS. - enabled: Serve both HTTP and HTTPS traffic. + :param sandbox: Execution environment of the container. + :param local_storage_limit: Local storage limit of the container (in MB). + :param scaling_option: Possible values: + - concurrent_requests_threshold: Scale depending on the number of concurrent requests being processed per container instance. + - cpu_usage_threshold: Scale depending on the CPU usage of a container instance. + - memory_usage_threshold: Scale depending on the memory usage of a container instance. + :param health_check: Health check configuration of the container. + :param tags: Tags of the Serverless Container. :return: :class:`Container ` Usage: @@ -740,6 +780,11 @@ async def update_container( port=port, secret_environment_variables=secret_environment_variables, http_option=http_option, + sandbox=sandbox, + local_storage_limit=local_storage_limit, + scaling_option=scaling_option, + health_check=health_check, + tags=tags, ), self.client, ), @@ -752,7 +797,7 @@ async def delete_container( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Container: """ Delete a container. @@ -786,7 +831,7 @@ async def deploy_container( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Container: """ Deploy a container. @@ -821,7 +866,7 @@ async def list_crons( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListCronsRequestOrderBy] = None, @@ -865,7 +910,7 @@ async def list_crons_all( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListCronsRequestOrderBy] = None, @@ -904,7 +949,7 @@ async def get_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cron: """ Get a cron. @@ -938,7 +983,7 @@ async def wait_for_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Cron, Union[bool, Awaitable[bool]]]] = None, ) -> Cron: """ @@ -976,7 +1021,7 @@ async def create_cron( *, container_id: str, schedule: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, args: Optional[Dict[str, Any]] = None, name: Optional[str] = None, ) -> Cron: @@ -1024,7 +1069,7 @@ async def update_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, container_id: Optional[str] = None, schedule: Optional[str] = None, args: Optional[Dict[str, Any]] = None, @@ -1077,7 +1122,7 @@ async def delete_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cron: """ Delete an existing cron. @@ -1111,14 +1156,14 @@ async def list_domains( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDomainsRequestOrderBy] = None, ) -> ListDomainsResponse: """ - List all domain name bindings. - List all domain name bindings in a specified region. + List all custom domains. + List all custom domains in a specified region. :param container_id: UUID of the container the domain belongs to. :param region: Region to target. If none is passed will use default region from the config. :param page: Page number. @@ -1156,14 +1201,14 @@ async def list_domains_all( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDomainsRequestOrderBy] = None, ) -> List[Domain]: """ - List all domain name bindings. - List all domain name bindings in a specified region. + List all custom domains. + List all custom domains in a specified region. :param container_id: UUID of the container the domain belongs to. :param region: Region to target. If none is passed will use default region from the config. :param page: Page number. @@ -1196,11 +1241,11 @@ async def get_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ - Get a domain name binding. - Get a domain name binding for the container with the specified ID. + Get a custom domain. + Get a custom domain for the container with the specified ID. :param domain_id: UUID of the domain to get. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Domain ` @@ -1230,12 +1275,12 @@ async def wait_for_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Domain, Union[bool, Awaitable[bool]]]] = None, ) -> Domain: """ - Get a domain name binding. - Get a domain name binding for the container with the specified ID. + Get a custom domain. + Get a custom domain for the container with the specified ID. :param domain_id: UUID of the domain to get. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Domain ` @@ -1268,11 +1313,11 @@ async def create_domain( *, hostname: str, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ - Create a domain name binding. - Create a domain name binding for the container with the specified ID. + Create a custom domain. + Create a custom domain for the container with the specified ID. :param hostname: Domain to assign. :param container_id: UUID of the container to assign the domain to. :param region: Region to target. If none is passed will use default region from the config. @@ -1311,11 +1356,11 @@ async def delete_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ - Delete a domain name binding. - Delete the domain name binding with the specific ID. + Delete a custom domain. + Delete the custom domain with the specific ID. :param domain_id: UUID of the domain to delete. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Domain ` @@ -1341,57 +1386,10 @@ async def delete_domain( self._throw_on_error(res) return unmarshal_Domain(res.json()) - async def issue_jwt( - self, - *, - region: Optional[Region] = None, - container_id: Optional[str] = None, - namespace_id: Optional[str] = None, - expires_at: Optional[datetime] = None, - ) -> Token: - """ - Create a JWT token. - Deprecated in favor of CreateToken. - :param region: Region to target. If none is passed will use default region from the config. - :param container_id: - One-Of ('scope'): at most one of 'container_id', 'namespace_id' could be set. - :param namespace_id: - One-Of ('scope'): at most one of 'container_id', 'namespace_id' could be set. - :param expires_at: - :return: :class:`Token ` - :deprecated - - Usage: - :: - - result = await api.issue_jwt() - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - - res = self._request( - "GET", - f"/containers/v1beta1/regions/{param_region}/issue-jwt", - params={ - "expires_at": expires_at, - **resolve_one_of( - [ - OneOfPossibility("container_id", container_id), - OneOfPossibility("namespace_id", namespace_id), - ] - ), - }, - ) - - self._throw_on_error(res) - return unmarshal_Token(res.json()) - async def create_token( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, container_id: Optional[str] = None, namespace_id: Optional[str] = None, description: Optional[str] = None, @@ -1440,7 +1438,7 @@ async def get_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Token: """ Get a token. @@ -1474,7 +1472,7 @@ async def wait_for_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Token, Union[bool, Awaitable[bool]]]] = None, ) -> Token: """ @@ -1510,7 +1508,7 @@ async def wait_for_token( async def list_tokens( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTokensRequestOrderBy] = None, @@ -1556,7 +1554,7 @@ async def list_tokens( async def list_tokens_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTokensRequestOrderBy] = None, @@ -1598,7 +1596,7 @@ async def delete_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Token: """ Delete a token. @@ -1633,7 +1631,7 @@ async def create_trigger( *, name: str, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, scw_sqs_config: Optional[CreateTriggerRequestMnqSqsClientConfig] = None, scw_nats_config: Optional[CreateTriggerRequestMnqNatsClientConfig] = None, @@ -1691,7 +1689,7 @@ async def get_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Trigger: """ Get a trigger. @@ -1725,7 +1723,7 @@ async def wait_for_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Trigger, Union[bool, Awaitable[bool]]]] = None, ) -> Trigger: """ @@ -1761,7 +1759,7 @@ async def wait_for_trigger( async def list_triggers( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTriggersRequestOrderBy] = None, @@ -1817,7 +1815,7 @@ async def list_triggers( async def list_triggers_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTriggersRequestOrderBy] = None, @@ -1865,7 +1863,7 @@ async def update_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, description: Optional[str] = None, sqs_config: Optional[UpdateTriggerRequestSqsClientConfig] = None, @@ -1916,7 +1914,7 @@ async def delete_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Trigger: """ Delete a trigger. diff --git a/scaleway-async/scaleway_async/container/v1beta1/marshalling.py b/scaleway-async/scaleway_async/container/v1beta1/marshalling.py index 224844ea..95e0e527 100644 --- a/scaleway-async/scaleway_async/container/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/container/v1beta1/marshalling.py @@ -10,6 +10,10 @@ resolve_one_of, ) from .types import ( + ContainerHealthCheckSpecHTTPProbe, + ContainerHealthCheckSpecTCPProbe, + ContainerHealthCheckSpec, + ContainerScalingOption, SecretHashedValue, Container, Cron, @@ -44,6 +48,98 @@ ) +def unmarshal_ContainerHealthCheckSpecHTTPProbe( + data: Any, +) -> ContainerHealthCheckSpecHTTPProbe: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContainerHealthCheckSpecHTTPProbe' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("path", None) + if field is not None: + args["path"] = field + + return ContainerHealthCheckSpecHTTPProbe(**args) + + +def unmarshal_ContainerHealthCheckSpecTCPProbe( + data: Any, +) -> ContainerHealthCheckSpecTCPProbe: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContainerHealthCheckSpecTCPProbe' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return ContainerHealthCheckSpecTCPProbe(**args) + + +def unmarshal_ContainerHealthCheckSpec(data: Any) -> ContainerHealthCheckSpec: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContainerHealthCheckSpec' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("failure_threshold", None) + if field is not None: + args["failure_threshold"] = field + + field = data.get("http", None) + if field is not None: + args["http"] = unmarshal_ContainerHealthCheckSpecHTTPProbe(field) + else: + args["http"] = None + + field = data.get("tcp", None) + if field is not None: + args["tcp"] = unmarshal_ContainerHealthCheckSpecTCPProbe(field) + else: + args["tcp"] = None + + field = data.get("interval", None) + if field is not None: + args["interval"] = field + else: + args["interval"] = None + + return ContainerHealthCheckSpec(**args) + + +def unmarshal_ContainerScalingOption(data: Any) -> ContainerScalingOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContainerScalingOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("concurrent_requests_threshold", None) + if field is not None: + args["concurrent_requests_threshold"] = field + else: + args["concurrent_requests_threshold"] = None + + field = data.get("cpu_usage_threshold", None) + if field is not None: + args["cpu_usage_threshold"] = field + else: + args["cpu_usage_threshold"] = None + + field = data.get("memory_usage_threshold", None) + if field is not None: + args["memory_usage_threshold"] = field + else: + args["memory_usage_threshold"] = None + + return ContainerScalingOption(**args) + + def unmarshal_SecretHashedValue(data: Any) -> SecretHashedValue: if not isinstance(data, dict): raise TypeError( @@ -115,21 +211,27 @@ def unmarshal_Container(data: Any) -> Container: if field is not None: args["registry_image"] = field - field = data.get("max_concurrency", None) - if field is not None: - args["max_concurrency"] = field - field = data.get("timeout", None) if field is not None: args["timeout"] = field + else: + args["timeout"] = None field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None + + field = data.get("max_concurrency", None) + if field is not None: + args["max_concurrency"] = field field = data.get("domain_name", None) if field is not None: @@ -155,10 +257,52 @@ def unmarshal_Container(data: Any) -> Container: if field is not None: args["http_option"] = field + field = data.get("sandbox", None) + if field is not None: + args["sandbox"] = field + + field = data.get("local_storage_limit", None) + if field is not None: + args["local_storage_limit"] = field + field = data.get("region", None) if field is not None: args["region"] = field + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("scaling_option", None) + if field is not None: + args["scaling_option"] = unmarshal_ContainerScalingOption(field) + else: + args["scaling_option"] = None + + field = data.get("health_check", None) + if field is not None: + args["health_check"] = unmarshal_ContainerHealthCheckSpec(field) + else: + args["health_check"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("ready_at", None) + if field is not None: + args["ready_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["ready_at"] = None + return Container(**args) @@ -193,6 +337,8 @@ def unmarshal_Cron(data: Any) -> Cron: field = data.get("args", None) if field is not None: args["args"] = field + else: + args["args"] = None return Cron(**args) @@ -228,6 +374,8 @@ def unmarshal_Domain(data: Any) -> Domain: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None return Domain(**args) @@ -284,13 +432,33 @@ def unmarshal_Namespace(data: Any) -> Namespace: if field is not None: args["region"] = field + field = data.get("tags", None) + if field is not None: + args["tags"] = field + field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Namespace(**args) @@ -318,22 +486,32 @@ def unmarshal_Token(data: Any) -> Token: field = data.get("container_id", None) if field is not None: args["container_id"] = field + else: + args["container_id"] = None field = data.get("namespace_id", None) if field is not None: args["namespace_id"] = field + else: + args["namespace_id"] = None field = data.get("public_key", None) if field is not None: args["public_key"] = field + else: + args["public_key"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None return Token(**args) @@ -365,6 +543,8 @@ def unmarshal_TriggerMnqNatsClientConfig(data: Any) -> TriggerMnqNatsClientConfi field = data.get("mnq_credential_id", None) if field is not None: args["mnq_credential_id"] = field + else: + args["mnq_credential_id"] = None return TriggerMnqNatsClientConfig(**args) @@ -392,6 +572,8 @@ def unmarshal_TriggerMnqSqsClientConfig(data: Any) -> TriggerMnqSqsClientConfig: field = data.get("mnq_credential_id", None) if field is not None: args["mnq_credential_id"] = field + else: + args["mnq_credential_id"] = None return TriggerMnqSqsClientConfig(**args) @@ -458,18 +640,26 @@ def unmarshal_Trigger(data: Any) -> Trigger: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("scw_sqs_config", None) if field is not None: args["scw_sqs_config"] = unmarshal_TriggerMnqSqsClientConfig(field) + else: + args["scw_sqs_config"] = None field = data.get("scw_nats_config", None) if field is not None: args["scw_nats_config"] = unmarshal_TriggerMnqNatsClientConfig(field) + else: + args["scw_nats_config"] = None field = data.get("sqs_config", None) if field is not None: args["sqs_config"] = unmarshal_TriggerSqsClientConfig(field) + else: + args["sqs_config"] = None return Trigger(**args) @@ -600,6 +790,73 @@ def unmarshal_ListTriggersResponse(data: Any) -> ListTriggersResponse: return ListTriggersResponse(**args) +def marshal_ContainerHealthCheckSpecHTTPProbe( + request: ContainerHealthCheckSpecHTTPProbe, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.path is not None: + output["path"] = request.path + + return output + + +def marshal_ContainerHealthCheckSpecTCPProbe( + request: ContainerHealthCheckSpecTCPProbe, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_ContainerHealthCheckSpec( + request: ContainerHealthCheckSpec, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("http", request.http), + OneOfPossibility("tcp", request.tcp), + ] + ), + ) + + if request.failure_threshold is not None: + output["failure_threshold"] = request.failure_threshold + + if request.interval is not None: + output["interval"] = request.interval + + return output + + +def marshal_ContainerScalingOption( + request: ContainerScalingOption, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility( + "concurrent_requests_threshold", + request.concurrent_requests_threshold, + ), + OneOfPossibility("cpu_usage_threshold", request.cpu_usage_threshold), + OneOfPossibility( + "memory_usage_threshold", request.memory_usage_threshold + ), + ] + ), + ) + + return output + + def marshal_Secret( request: Secret, defaults: ProfileDefaults, @@ -672,6 +929,25 @@ def marshal_CreateContainerRequest( if request.http_option is not None: output["http_option"] = str(request.http_option) + if request.sandbox is not None: + output["sandbox"] = str(request.sandbox) + + if request.local_storage_limit is not None: + output["local_storage_limit"] = request.local_storage_limit + + if request.scaling_option is not None: + output["scaling_option"] = marshal_ContainerScalingOption( + request.scaling_option, defaults + ) + + if request.health_check is not None: + output["health_check"] = marshal_ContainerHealthCheckSpec( + request.health_check, defaults + ) + + if request.tags is not None: + output["tags"] = request.tags + return output @@ -735,6 +1011,9 @@ def marshal_CreateNamespaceRequest( for item in request.secret_environment_variables ] + if request.tags is not None: + output["tags"] = request.tags + return output @@ -756,7 +1035,7 @@ def marshal_CreateTokenRequest( output["description"] = request.description if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -902,6 +1181,25 @@ def marshal_UpdateContainerRequest( if request.http_option is not None: output["http_option"] = str(request.http_option) + if request.sandbox is not None: + output["sandbox"] = str(request.sandbox) + + if request.local_storage_limit is not None: + output["local_storage_limit"] = request.local_storage_limit + + if request.scaling_option is not None: + output["scaling_option"] = marshal_ContainerScalingOption( + request.scaling_option, defaults + ) + + if request.health_check is not None: + output["health_check"] = marshal_ContainerHealthCheckSpec( + request.health_check, defaults + ) + + if request.tags is not None: + output["tags"] = request.tags + return output @@ -944,6 +1242,9 @@ def marshal_UpdateNamespaceRequest( for item in request.secret_environment_variables ] + if request.tags is not None: + output["tags"] = request.tags + return output diff --git a/scaleway-async/scaleway_async/container/v1beta1/types.py b/scaleway-async/scaleway_async/container/v1beta1/types.py index 6d3f779a..f4e775dc 100644 --- a/scaleway-async/scaleway_async/container/v1beta1/types.py +++ b/scaleway-async/scaleway_async/container/v1beta1/types.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -42,6 +42,15 @@ def __str__(self) -> str: return str(self.value) +class ContainerSandbox(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SANDBOX = "unknown_sandbox" + V1 = "v1" + V2 = "v2" + + def __str__(self) -> str: + return str(self.value) + + class ContainerStatus(str, Enum, metaclass=StrEnumMeta): UNKNOWN = "unknown" READY = "ready" @@ -182,6 +191,46 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class ContainerHealthCheckSpecHTTPProbe: + path: str + """ + Path to use for the HTTP health check. + """ + + +@dataclass +class ContainerHealthCheckSpecTCPProbe: + pass + + +@dataclass +class ContainerHealthCheckSpec: + failure_threshold: int + """ + During a deployment, if a newly created container fails to pass the health check, the deployment is aborted. +As a result, lowering this value can help to reduce the time it takes to detect a failed deployment. + """ + + interval: Optional[str] + """ + Period between health checks. + """ + + http: Optional[ContainerHealthCheckSpecHTTPProbe] + + tcp: Optional[ContainerHealthCheckSpecTCPProbe] + + +@dataclass +class ContainerScalingOption: + concurrent_requests_threshold: Optional[int] + + cpu_usage_threshold: Optional[int] + + memory_usage_threshold: Optional[int] + + @dataclass class SecretHashedValue: key: str @@ -367,11 +416,6 @@ class Container: Name of the registry image (e.g. "rg.fr-par.scw.cloud/something/image:tag"). """ - max_concurrency: int - """ - Number of maximum concurrent executions of the container. - """ - timeout: Optional[str] """ Processing time limit for the container. @@ -387,6 +431,11 @@ class Container: Description of the container. """ + max_concurrency: int + """ + Number of maximum concurrent executions of the container. + """ + domain_name: str """ Domain name attributed to the contaioner. @@ -414,11 +463,54 @@ class Container: - enabled: Serve both HTTP and HTTPS traffic. """ - region: Region + sandbox: ContainerSandbox + """ + Execution environment of the container. + """ + + local_storage_limit: int + """ + Local storage limit of the container (in MB). + """ + + region: ScwRegion """ Region in which the container will be deployed. """ + tags: List[str] + """ + List of tags applied to the Serverless Container. + """ + + scaling_option: Optional[ContainerScalingOption] + """ + Possible values: +- concurrent_requests_threshold: Scale depending on the number of concurrent requests being processed per container instance. +- cpu_usage_threshold: Scale depending on the CPU usage of a container instance. +- memory_usage_threshold: Scale depending on the memory usage of a container instance. + """ + + health_check: Optional[ContainerHealthCheckSpec] + """ + Health check configuration of the container. + """ + + created_at: Optional[datetime] + """ + Creation date of the container. + """ + + updated_at: Optional[datetime] + """ + Last update date of the container. + """ + + ready_at: Optional[datetime] + """ + Last date when the container was successfully deployed and set to ready. + """ + @dataclass class Cron: @@ -533,11 +625,16 @@ class Namespace: Secret environment variables of the namespace. """ - region: Region + region: ScwRegion """ Region in which the namespace will be created. """ + tags: List[str] + """ + List of tags applied to the Serverless Container Namespace. + """ + error_message: Optional[str] """ Last error message of the namesace. @@ -548,6 +645,16 @@ class Namespace: Description of the endpoint. """ + created_at: Optional[datetime] + """ + Creation date of the namespace. + """ + + updated_at: Optional[datetime] + """ + Last update date of the namespace. + """ + @dataclass class Token: @@ -649,7 +756,7 @@ class CreateContainerRequest: Name of the container. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -726,6 +833,34 @@ class CreateContainerRequest: - enabled: Serve both HTTP and HTTPS traffic. """ + sandbox: Optional[ContainerSandbox] + """ + Execution environment of the container. + """ + + local_storage_limit: Optional[int] + """ + Local storage limit of the container (in MB). + """ + + scaling_option: Optional[ContainerScalingOption] + """ + Possible values: +- concurrent_requests_threshold: Scale depending on the number of concurrent requests being processed per container instance. +- cpu_usage_threshold: Scale depending on the CPU usage of a container instance. +- memory_usage_threshold: Scale depending on the memory usage of a container instance. + """ + + health_check: Optional[ContainerHealthCheckSpec] + """ + Health check configuration of the container. + """ + + tags: Optional[List[str]] + """ + Tags of the Serverless Container. + """ + @dataclass class CreateCronRequest: @@ -739,7 +874,7 @@ class CreateCronRequest: UNIX cron shedule. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -767,7 +902,7 @@ class CreateDomainRequest: UUID of the container to assign the domain to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -775,7 +910,7 @@ class CreateDomainRequest: @dataclass class CreateNamespaceRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -805,10 +940,15 @@ class CreateNamespaceRequest: Secret environment variables of the namespace to create. """ + tags: Optional[List[str]] + """ + Tags of the Serverless Container Namespace. + """ + @dataclass class CreateTokenRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -840,7 +980,7 @@ class CreateTriggerRequest: ID of the container to trigger. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -864,7 +1004,7 @@ class DeleteContainerRequest: UUID of the container to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -877,7 +1017,7 @@ class DeleteCronRequest: UUID of the cron to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -890,7 +1030,7 @@ class DeleteDomainRequest: UUID of the domain to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -903,7 +1043,7 @@ class DeleteNamespaceRequest: UUID of the namespace to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -916,7 +1056,7 @@ class DeleteTokenRequest: UUID of the token to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -929,7 +1069,7 @@ class DeleteTriggerRequest: ID of the trigger to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -942,7 +1082,7 @@ class DeployContainerRequest: UUID of the container to deploy. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -955,7 +1095,7 @@ class GetContainerRequest: UUID of the container to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -968,7 +1108,7 @@ class GetCronRequest: UUID of the cron to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -981,7 +1121,7 @@ class GetDomainRequest: UUID of the domain to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -994,7 +1134,7 @@ class GetNamespaceRequest: UUID of the namespace to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1007,7 +1147,7 @@ class GetTokenRequest: UUID of the token to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1020,26 +1160,12 @@ class GetTriggerRequest: ID of the trigger to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ -@dataclass -class IssueJWTRequest: - region: Optional[Region] - """ - Region to target. If none is passed will use default region from the config. - """ - - expires_at: Optional[datetime] - - container_id: Optional[str] - - namespace_id: Optional[str] - - @dataclass class ListContainersRequest: namespace_id: str @@ -1047,7 +1173,7 @@ class ListContainersRequest: UUID of the namespace the container belongs to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1103,7 +1229,7 @@ class ListCronsRequest: UUID of the container invoked by the cron. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1144,7 +1270,7 @@ class ListDomainsRequest: UUID of the container the domain belongs to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1180,7 +1306,7 @@ class ListDomainsResponse: @dataclass class ListNamespacesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1231,7 +1357,7 @@ class ListNamespacesResponse: @dataclass class ListTokensRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1271,7 +1397,7 @@ class ListTokensResponse: @dataclass class ListTriggersRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1318,7 +1444,7 @@ class UpdateContainerRequest: UUID of the container to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1391,6 +1517,34 @@ class UpdateContainerRequest: - enabled: Serve both HTTP and HTTPS traffic. """ + sandbox: Optional[ContainerSandbox] + """ + Execution environment of the container. + """ + + local_storage_limit: Optional[int] + """ + Local storage limit of the container (in MB). + """ + + scaling_option: Optional[ContainerScalingOption] + """ + Possible values: +- concurrent_requests_threshold: Scale depending on the number of concurrent requests being processed per container instance. +- cpu_usage_threshold: Scale depending on the CPU usage of a container instance. +- memory_usage_threshold: Scale depending on the memory usage of a container instance. + """ + + health_check: Optional[ContainerHealthCheckSpec] + """ + Health check configuration of the container. + """ + + tags: Optional[List[str]] + """ + Tags of the Serverless Container. + """ + @dataclass class UpdateCronRequest: @@ -1399,7 +1553,7 @@ class UpdateCronRequest: UUID of the cron to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1432,7 +1586,7 @@ class UpdateNamespaceRequest: UUID of the namespace to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1452,6 +1606,11 @@ class UpdateNamespaceRequest: Secret environment variables of the namespace to update. """ + tags: Optional[List[str]] + """ + Tags of the Serverless Container Namespace. + """ + @dataclass class UpdateTriggerRequest: @@ -1460,7 +1619,7 @@ class UpdateTriggerRequest: ID of the trigger to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway-async/scaleway_async/dedibox/__init__.py b/scaleway-async/scaleway_async/dedibox/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway-async/scaleway_async/dedibox/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway-async/scaleway_async/dedibox/v1/__init__.py b/scaleway-async/scaleway_async/dedibox/v1/__init__.py new file mode 100644 index 00000000..e6b1144a --- /dev/null +++ b/scaleway-async/scaleway_async/dedibox/v1/__init__.py @@ -0,0 +1,541 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import AttachFailoverIPToMacAddressRequestMacType +from .types import BMCAccessStatus +from .content import BMC_ACCESS_TRANSIENT_STATUSES +from .types import BackupStatus +from .types import FailoverBlockVersion +from .types import FailoverIPInterfaceType +from .types import FailoverIPStatus +from .types import FailoverIPVersion +from .types import GetRpnStatusResponseStatus +from .types import IPSemantic +from .types import IPStatus +from .types import IPVersion +from .types import IPv6BlockDelegationStatus +from .content import I_PV6_BLOCK_DELEGATION_TRANSIENT_STATUSES +from .types import InvoicePaymentMethod +from .types import InvoiceStatus +from .types import ListFailoverIPsRequestOrderBy +from .types import ListInvoicesRequestOrderBy +from .types import ListOSRequestOrderBy +from .types import ListOffersRequestOrderBy +from .types import ListRefundsRequestOrderBy +from .types import ListRpnCapableSanServersRequestOrderBy +from .types import ListRpnCapableServersRequestOrderBy +from .types import ListRpnGroupMembersRequestOrderBy +from .types import ListRpnGroupsRequestOrderBy +from .types import ListRpnInvitesRequestOrderBy +from .types import ListRpnSansRequestOrderBy +from .types import ListRpnServerCapabilitiesRequestOrderBy +from .types import ListRpnV2CapableResourcesRequestOrderBy +from .types import ListRpnV2GroupLogsRequestOrderBy +from .types import ListRpnV2GroupsRequestOrderBy +from .types import ListRpnV2MembersRequestOrderBy +from .types import ListRpnV2MembersRequestType +from .types import ListServerDisksRequestOrderBy +from .types import ListServerEventsRequestOrderBy +from .types import ListServersRequestOrderBy +from .types import ListServicesRequestOrderBy +from .types import LogAction +from .types import LogStatus +from .types import MemoryType +from .types import NetworkInterfaceInterfaceType +from .types import OSArch +from .types import OSType +from .types import OfferAntiDosInfoType +from .types import OfferCatalog +from .types import OfferPaymentFrequency +from .types import OfferSANInfoType +from .types import OfferServerInfoStock +from .types import PartitionFileSystem +from .types import PartitionType +from .types import RaidArrayRaidLevel +from .types import RefundMethod +from .types import RefundStatus +from .types import RescueProtocol +from .types import RpnGroupMemberStatus +from .content import RPN_GROUP_MEMBER_TRANSIENT_STATUSES +from .types import RpnGroupType +from .types import RpnSanIpType +from .types import RpnSanStatus +from .content import RPN_SAN_TRANSIENT_STATUSES +from .types import RpnV2GroupStatus +from .content import RPN_V2_GROUP_TRANSIENT_STATUSES +from .types import RpnV2GroupType +from .types import RpnV2MemberStatus +from .content import RPN_V2_MEMBER_TRANSIENT_STATUSES +from .types import ServerDiskType +from .types import ServerInstallStatus +from .content import SERVER_INSTALL_TRANSIENT_STATUSES +from .types import ServerStatus +from .content import SERVER_TRANSIENT_STATUSES +from .types import ServiceLevelLevel +from .types import ServiceProvisioningStatus +from .content import SERVICE_PROVISIONING_TRANSIENT_STATUSES +from .types import ServiceType +from .types import OfferAntiDosInfo +from .types import OfferBackupInfo +from .types import OfferBandwidthInfo +from .types import OfferLicenseInfo +from .types import OfferRPNInfo +from .types import OfferSANInfo +from .types import OfferStorageInfo +from .types import IP +from .types import Offer +from .types import NetworkInterface +from .types import OS +from .types import ServerLocation +from .types import ServerOption +from .types import ServiceLevel +from .types import RpnSan +from .types import RpnGroup +from .types import RpnV2GroupSubnet +from .types import Server +from .types import FailoverBlock +from .types import RpnSanIpRpnV2Group +from .types import RpnSanIpServer +from .types import RpnSanServer +from .types import RpnV2Group +from .types import RpnV2Member +from .types import ServerDisk +from .types import Service +from .types import GetIPv6BlockQuotasResponseQuota +from .types import InstallPartition +from .types import FailoverIP +from .types import ListIPv6BlockSubnetsAvailableResponseSubnet +from .types import InvoiceSummary +from .types import RpnSanIp +from .types import RefundSummary +from .types import RpnGroupMember +from .types import RpnSanSummary +from .types import RpnServerCapability +from .types import Log +from .types import ServerEvent +from .types import ServerSummary +from .types import CPU +from .types import Disk +from .types import Memory +from .types import PersistentMemory +from .types import RaidController +from .types import RaidArray +from .types import Partition +from .types import UpdatableRaidArray +from .types import AttachFailoverIPToMacAddressRequest +from .types import AttachFailoverIPsRequest +from .types import BMCAccess +from .types import Backup +from .types import BillingApiCanOrderRequest +from .types import BillingApiDownloadInvoiceRequest +from .types import BillingApiDownloadRefundRequest +from .types import BillingApiGetInvoiceRequest +from .types import BillingApiGetRefundRequest +from .types import BillingApiListInvoicesRequest +from .types import BillingApiListRefundsRequest +from .types import CanOrderResponse +from .types import CancelServerInstallRequest +from .types import CreateFailoverIPsRequest +from .types import CreateFailoverIPsResponse +from .types import CreateServerRequest +from .types import DeleteFailoverIPRequest +from .types import DeleteServerRequest +from .types import DeleteServiceRequest +from .types import DetachFailoverIPFromMacAddressRequest +from .types import DetachFailoverIPsRequest +from .types import GetBMCAccessRequest +from .types import GetFailoverIPRequest +from .types import GetIPv6BlockQuotasResponse +from .types import GetOSRequest +from .types import GetOfferRequest +from .types import GetOrderedServiceRequest +from .types import GetRaidRequest +from .types import GetRemainingQuotaRequest +from .types import GetRemainingQuotaResponse +from .types import GetRescueRequest +from .types import GetRpnStatusResponse +from .types import GetServerBackupRequest +from .types import GetServerDefaultPartitioningRequest +from .types import GetServerInstallRequest +from .types import GetServerRequest +from .types import GetServiceRequest +from .types import IPv6Block +from .types import IPv6BlockApiCreateIPv6BlockRequest +from .types import IPv6BlockApiCreateIPv6BlockSubnetRequest +from .types import IPv6BlockApiDeleteIPv6BlockRequest +from .types import IPv6BlockApiGetIPv6BlockQuotasRequest +from .types import IPv6BlockApiGetIPv6BlockRequest +from .types import IPv6BlockApiListIPv6BlockSubnetsAvailableRequest +from .types import IPv6BlockApiUpdateIPv6BlockRequest +from .types import InstallServerRequest +from .types import Invoice +from .types import ListFailoverIPsRequest +from .types import ListFailoverIPsResponse +from .types import ListIPv6BlockSubnetsAvailableResponse +from .types import ListInvoicesResponse +from .types import ListIpsResponse +from .types import ListOSRequest +from .types import ListOSResponse +from .types import ListOffersRequest +from .types import ListOffersResponse +from .types import ListRefundsResponse +from .types import ListRpnCapableSanServersResponse +from .types import ListRpnCapableServersResponse +from .types import ListRpnGroupMembersResponse +from .types import ListRpnGroupsResponse +from .types import ListRpnInvitesResponse +from .types import ListRpnSansResponse +from .types import ListRpnServerCapabilitiesResponse +from .types import ListRpnV2CapableResourcesResponse +from .types import ListRpnV2GroupLogsResponse +from .types import ListRpnV2GroupsResponse +from .types import ListRpnV2MembersResponse +from .types import ListServerDisksRequest +from .types import ListServerDisksResponse +from .types import ListServerEventsRequest +from .types import ListServerEventsResponse +from .types import ListServersRequest +from .types import ListServersResponse +from .types import ListServicesRequest +from .types import ListServicesResponse +from .types import ListSubscribableServerOptionsRequest +from .types import ListSubscribableServerOptionsResponse +from .types import OfferFailoverBlockInfo +from .types import OfferFailoverIpInfo +from .types import OfferServerInfo +from .types import OfferServiceLevelInfo +from .types import Raid +from .types import RebootServerRequest +from .types import Refund +from .types import Rescue +from .types import RpnApiGetRpnStatusRequest +from .types import RpnApiListRpnServerCapabilitiesRequest +from .types import RpnSanApiAddIpRequest +from .types import RpnSanApiCreateRpnSanRequest +from .types import RpnSanApiDeleteRpnSanRequest +from .types import RpnSanApiGetRpnSanRequest +from .types import RpnSanApiListAvailableIpsRequest +from .types import RpnSanApiListIpsRequest +from .types import RpnSanApiListRpnSansRequest +from .types import RpnSanApiRemoveIpRequest +from .types import RpnV1ApiAcceptRpnInviteRequest +from .types import RpnV1ApiAddRpnGroupMembersRequest +from .types import RpnV1ApiCreateRpnGroupRequest +from .types import RpnV1ApiDeleteRpnGroupMembersRequest +from .types import RpnV1ApiDeleteRpnGroupRequest +from .types import RpnV1ApiGetRpnGroupRequest +from .types import RpnV1ApiLeaveRpnGroupRequest +from .types import RpnV1ApiListRpnCapableSanServersRequest +from .types import RpnV1ApiListRpnCapableServersRequest +from .types import RpnV1ApiListRpnGroupMembersRequest +from .types import RpnV1ApiListRpnGroupsRequest +from .types import RpnV1ApiListRpnInvitesRequest +from .types import RpnV1ApiRefuseRpnInviteRequest +from .types import RpnV1ApiRpnGroupInviteRequest +from .types import RpnV1ApiUpdateRpnGroupNameRequest +from .types import RpnV2ApiAddRpnV2MembersRequest +from .types import RpnV2ApiCreateRpnV2GroupRequest +from .types import RpnV2ApiDeleteRpnV2GroupRequest +from .types import RpnV2ApiDeleteRpnV2MembersRequest +from .types import RpnV2ApiDisableRpnV2GroupCompatibilityRequest +from .types import RpnV2ApiEnableRpnV2GroupCompatibilityRequest +from .types import RpnV2ApiGetRpnV2GroupRequest +from .types import RpnV2ApiListRpnV2CapableResourcesRequest +from .types import RpnV2ApiListRpnV2GroupLogsRequest +from .types import RpnV2ApiListRpnV2GroupsRequest +from .types import RpnV2ApiListRpnV2MembersRequest +from .types import RpnV2ApiUpdateRpnV2GroupNameRequest +from .types import RpnV2ApiUpdateRpnV2VlanForMembersRequest +from .types import ServerDefaultPartitioning +from .types import ServerInstall +from .types import StartBMCAccessRequest +from .types import StartRescueRequest +from .types import StartServerRequest +from .types import StopBMCAccessRequest +from .types import StopRescueRequest +from .types import StopServerRequest +from .types import SubscribeServerOptionRequest +from .types import SubscribeStorageOptionsRequest +from .types import SubscribeStorageOptionsResponse +from .types import UpdateRaidRequest +from .types import UpdateReverseRequest +from .types import UpdateServerBackupRequest +from .types import UpdateServerRequest +from .types import UpdateServerTagsRequest +from .api import DediboxV1API +from .api import DediboxV1BillingAPI +from .api import DediboxV1IPv6BlockAPI +from .api import DediboxV1RpnAPI +from .api import DediboxV1RpnSanAPI +from .api import DediboxV1RpnV1API +from .api import DediboxV1RpnV2API + +__all__ = [ + "AttachFailoverIPToMacAddressRequestMacType", + "BMCAccessStatus", + "BMC_ACCESS_TRANSIENT_STATUSES", + "BackupStatus", + "FailoverBlockVersion", + "FailoverIPInterfaceType", + "FailoverIPStatus", + "FailoverIPVersion", + "GetRpnStatusResponseStatus", + "IPSemantic", + "IPStatus", + "IPVersion", + "IPv6BlockDelegationStatus", + "I_PV6_BLOCK_DELEGATION_TRANSIENT_STATUSES", + "InvoicePaymentMethod", + "InvoiceStatus", + "ListFailoverIPsRequestOrderBy", + "ListInvoicesRequestOrderBy", + "ListOSRequestOrderBy", + "ListOffersRequestOrderBy", + "ListRefundsRequestOrderBy", + "ListRpnCapableSanServersRequestOrderBy", + "ListRpnCapableServersRequestOrderBy", + "ListRpnGroupMembersRequestOrderBy", + "ListRpnGroupsRequestOrderBy", + "ListRpnInvitesRequestOrderBy", + "ListRpnSansRequestOrderBy", + "ListRpnServerCapabilitiesRequestOrderBy", + "ListRpnV2CapableResourcesRequestOrderBy", + "ListRpnV2GroupLogsRequestOrderBy", + "ListRpnV2GroupsRequestOrderBy", + "ListRpnV2MembersRequestOrderBy", + "ListRpnV2MembersRequestType", + "ListServerDisksRequestOrderBy", + "ListServerEventsRequestOrderBy", + "ListServersRequestOrderBy", + "ListServicesRequestOrderBy", + "LogAction", + "LogStatus", + "MemoryType", + "NetworkInterfaceInterfaceType", + "OSArch", + "OSType", + "OfferAntiDosInfoType", + "OfferCatalog", + "OfferPaymentFrequency", + "OfferSANInfoType", + "OfferServerInfoStock", + "PartitionFileSystem", + "PartitionType", + "RaidArrayRaidLevel", + "RefundMethod", + "RefundStatus", + "RescueProtocol", + "RpnGroupMemberStatus", + "RPN_GROUP_MEMBER_TRANSIENT_STATUSES", + "RpnGroupType", + "RpnSanIpType", + "RpnSanStatus", + "RPN_SAN_TRANSIENT_STATUSES", + "RpnV2GroupStatus", + "RPN_V2_GROUP_TRANSIENT_STATUSES", + "RpnV2GroupType", + "RpnV2MemberStatus", + "RPN_V2_MEMBER_TRANSIENT_STATUSES", + "ServerDiskType", + "ServerInstallStatus", + "SERVER_INSTALL_TRANSIENT_STATUSES", + "ServerStatus", + "SERVER_TRANSIENT_STATUSES", + "ServiceLevelLevel", + "ServiceProvisioningStatus", + "SERVICE_PROVISIONING_TRANSIENT_STATUSES", + "ServiceType", + "OfferAntiDosInfo", + "OfferBackupInfo", + "OfferBandwidthInfo", + "OfferLicenseInfo", + "OfferRPNInfo", + "OfferSANInfo", + "OfferStorageInfo", + "IP", + "Offer", + "NetworkInterface", + "OS", + "ServerLocation", + "ServerOption", + "ServiceLevel", + "RpnSan", + "RpnGroup", + "RpnV2GroupSubnet", + "Server", + "FailoverBlock", + "RpnSanIpRpnV2Group", + "RpnSanIpServer", + "RpnSanServer", + "RpnV2Group", + "RpnV2Member", + "ServerDisk", + "Service", + "GetIPv6BlockQuotasResponseQuota", + "InstallPartition", + "FailoverIP", + "ListIPv6BlockSubnetsAvailableResponseSubnet", + "InvoiceSummary", + "RpnSanIp", + "RefundSummary", + "RpnGroupMember", + "RpnSanSummary", + "RpnServerCapability", + "Log", + "ServerEvent", + "ServerSummary", + "CPU", + "Disk", + "Memory", + "PersistentMemory", + "RaidController", + "RaidArray", + "Partition", + "UpdatableRaidArray", + "AttachFailoverIPToMacAddressRequest", + "AttachFailoverIPsRequest", + "BMCAccess", + "Backup", + "BillingApiCanOrderRequest", + "BillingApiDownloadInvoiceRequest", + "BillingApiDownloadRefundRequest", + "BillingApiGetInvoiceRequest", + "BillingApiGetRefundRequest", + "BillingApiListInvoicesRequest", + "BillingApiListRefundsRequest", + "CanOrderResponse", + "CancelServerInstallRequest", + "CreateFailoverIPsRequest", + "CreateFailoverIPsResponse", + "CreateServerRequest", + "DeleteFailoverIPRequest", + "DeleteServerRequest", + "DeleteServiceRequest", + "DetachFailoverIPFromMacAddressRequest", + "DetachFailoverIPsRequest", + "GetBMCAccessRequest", + "GetFailoverIPRequest", + "GetIPv6BlockQuotasResponse", + "GetOSRequest", + "GetOfferRequest", + "GetOrderedServiceRequest", + "GetRaidRequest", + "GetRemainingQuotaRequest", + "GetRemainingQuotaResponse", + "GetRescueRequest", + "GetRpnStatusResponse", + "GetServerBackupRequest", + "GetServerDefaultPartitioningRequest", + "GetServerInstallRequest", + "GetServerRequest", + "GetServiceRequest", + "IPv6Block", + "IPv6BlockApiCreateIPv6BlockRequest", + "IPv6BlockApiCreateIPv6BlockSubnetRequest", + "IPv6BlockApiDeleteIPv6BlockRequest", + "IPv6BlockApiGetIPv6BlockQuotasRequest", + "IPv6BlockApiGetIPv6BlockRequest", + "IPv6BlockApiListIPv6BlockSubnetsAvailableRequest", + "IPv6BlockApiUpdateIPv6BlockRequest", + "InstallServerRequest", + "Invoice", + "ListFailoverIPsRequest", + "ListFailoverIPsResponse", + "ListIPv6BlockSubnetsAvailableResponse", + "ListInvoicesResponse", + "ListIpsResponse", + "ListOSRequest", + "ListOSResponse", + "ListOffersRequest", + "ListOffersResponse", + "ListRefundsResponse", + "ListRpnCapableSanServersResponse", + "ListRpnCapableServersResponse", + "ListRpnGroupMembersResponse", + "ListRpnGroupsResponse", + "ListRpnInvitesResponse", + "ListRpnSansResponse", + "ListRpnServerCapabilitiesResponse", + "ListRpnV2CapableResourcesResponse", + "ListRpnV2GroupLogsResponse", + "ListRpnV2GroupsResponse", + "ListRpnV2MembersResponse", + "ListServerDisksRequest", + "ListServerDisksResponse", + "ListServerEventsRequest", + "ListServerEventsResponse", + "ListServersRequest", + "ListServersResponse", + "ListServicesRequest", + "ListServicesResponse", + "ListSubscribableServerOptionsRequest", + "ListSubscribableServerOptionsResponse", + "OfferFailoverBlockInfo", + "OfferFailoverIpInfo", + "OfferServerInfo", + "OfferServiceLevelInfo", + "Raid", + "RebootServerRequest", + "Refund", + "Rescue", + "RpnApiGetRpnStatusRequest", + "RpnApiListRpnServerCapabilitiesRequest", + "RpnSanApiAddIpRequest", + "RpnSanApiCreateRpnSanRequest", + "RpnSanApiDeleteRpnSanRequest", + "RpnSanApiGetRpnSanRequest", + "RpnSanApiListAvailableIpsRequest", + "RpnSanApiListIpsRequest", + "RpnSanApiListRpnSansRequest", + "RpnSanApiRemoveIpRequest", + "RpnV1ApiAcceptRpnInviteRequest", + "RpnV1ApiAddRpnGroupMembersRequest", + "RpnV1ApiCreateRpnGroupRequest", + "RpnV1ApiDeleteRpnGroupMembersRequest", + "RpnV1ApiDeleteRpnGroupRequest", + "RpnV1ApiGetRpnGroupRequest", + "RpnV1ApiLeaveRpnGroupRequest", + "RpnV1ApiListRpnCapableSanServersRequest", + "RpnV1ApiListRpnCapableServersRequest", + "RpnV1ApiListRpnGroupMembersRequest", + "RpnV1ApiListRpnGroupsRequest", + "RpnV1ApiListRpnInvitesRequest", + "RpnV1ApiRefuseRpnInviteRequest", + "RpnV1ApiRpnGroupInviteRequest", + "RpnV1ApiUpdateRpnGroupNameRequest", + "RpnV2ApiAddRpnV2MembersRequest", + "RpnV2ApiCreateRpnV2GroupRequest", + "RpnV2ApiDeleteRpnV2GroupRequest", + "RpnV2ApiDeleteRpnV2MembersRequest", + "RpnV2ApiDisableRpnV2GroupCompatibilityRequest", + "RpnV2ApiEnableRpnV2GroupCompatibilityRequest", + "RpnV2ApiGetRpnV2GroupRequest", + "RpnV2ApiListRpnV2CapableResourcesRequest", + "RpnV2ApiListRpnV2GroupLogsRequest", + "RpnV2ApiListRpnV2GroupsRequest", + "RpnV2ApiListRpnV2MembersRequest", + "RpnV2ApiUpdateRpnV2GroupNameRequest", + "RpnV2ApiUpdateRpnV2VlanForMembersRequest", + "ServerDefaultPartitioning", + "ServerInstall", + "StartBMCAccessRequest", + "StartRescueRequest", + "StartServerRequest", + "StopBMCAccessRequest", + "StopRescueRequest", + "StopServerRequest", + "SubscribeServerOptionRequest", + "SubscribeStorageOptionsRequest", + "SubscribeStorageOptionsResponse", + "UpdateRaidRequest", + "UpdateReverseRequest", + "UpdateServerBackupRequest", + "UpdateServerRequest", + "UpdateServerTagsRequest", + "DediboxV1API", + "DediboxV1BillingAPI", + "DediboxV1IPv6BlockAPI", + "DediboxV1RpnAPI", + "DediboxV1RpnSanAPI", + "DediboxV1RpnV1API", + "DediboxV1RpnV2API", +] diff --git a/scaleway-async/scaleway_async/dedibox/v1/api.py b/scaleway-async/scaleway_async/dedibox/v1/api.py new file mode 100644 index 00000000..6bb5efd2 --- /dev/null +++ b/scaleway-async/scaleway_async/dedibox/v1/api.py @@ -0,0 +1,4727 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.bridge import ( + ScwFile, + Zone as ScwZone, + unmarshal_ScwFile, +) +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + AttachFailoverIPToMacAddressRequestMacType, + ListFailoverIPsRequestOrderBy, + ListInvoicesRequestOrderBy, + ListOSRequestOrderBy, + ListOffersRequestOrderBy, + ListRefundsRequestOrderBy, + ListRpnCapableSanServersRequestOrderBy, + ListRpnCapableServersRequestOrderBy, + ListRpnGroupMembersRequestOrderBy, + ListRpnGroupsRequestOrderBy, + ListRpnInvitesRequestOrderBy, + ListRpnSansRequestOrderBy, + ListRpnServerCapabilitiesRequestOrderBy, + ListRpnV2CapableResourcesRequestOrderBy, + ListRpnV2GroupLogsRequestOrderBy, + ListRpnV2GroupsRequestOrderBy, + ListRpnV2MembersRequestOrderBy, + ListRpnV2MembersRequestType, + ListServerDisksRequestOrderBy, + ListServerEventsRequestOrderBy, + ListServersRequestOrderBy, + ListServicesRequestOrderBy, + OSType, + OfferCatalog, + RpnSanIpType, + RpnV2GroupType, + AttachFailoverIPToMacAddressRequest, + AttachFailoverIPsRequest, + BMCAccess, + Backup, + CanOrderResponse, + CreateFailoverIPsRequest, + CreateFailoverIPsResponse, + CreateServerRequest, + DetachFailoverIPsRequest, + FailoverIP, + GetIPv6BlockQuotasResponse, + GetRemainingQuotaResponse, + GetRpnStatusResponse, + IP, + IPv6Block, + IPv6BlockApiCreateIPv6BlockRequest, + IPv6BlockApiCreateIPv6BlockSubnetRequest, + IPv6BlockApiUpdateIPv6BlockRequest, + InstallPartition, + InstallServerRequest, + Invoice, + InvoiceSummary, + ListFailoverIPsResponse, + ListIPv6BlockSubnetsAvailableResponse, + ListInvoicesResponse, + ListIpsResponse, + ListOSResponse, + ListOffersResponse, + ListRefundsResponse, + ListRpnCapableSanServersResponse, + ListRpnCapableServersResponse, + ListRpnGroupMembersResponse, + ListRpnGroupsResponse, + ListRpnInvitesResponse, + ListRpnSansResponse, + ListRpnServerCapabilitiesResponse, + ListRpnV2CapableResourcesResponse, + ListRpnV2GroupLogsResponse, + ListRpnV2GroupsResponse, + ListRpnV2MembersResponse, + ListServerDisksResponse, + ListServerEventsResponse, + ListServersResponse, + ListServicesResponse, + ListSubscribableServerOptionsResponse, + Log, + OS, + Offer, + Raid, + Refund, + RefundSummary, + Rescue, + RpnGroup, + RpnGroupMember, + RpnSan, + RpnSanApiAddIpRequest, + RpnSanApiCreateRpnSanRequest, + RpnSanApiRemoveIpRequest, + RpnSanServer, + RpnSanSummary, + RpnServerCapability, + RpnV1ApiAddRpnGroupMembersRequest, + RpnV1ApiCreateRpnGroupRequest, + RpnV1ApiDeleteRpnGroupMembersRequest, + RpnV1ApiLeaveRpnGroupRequest, + RpnV1ApiRpnGroupInviteRequest, + RpnV1ApiUpdateRpnGroupNameRequest, + RpnV2ApiAddRpnV2MembersRequest, + RpnV2ApiCreateRpnV2GroupRequest, + RpnV2ApiDeleteRpnV2MembersRequest, + RpnV2ApiEnableRpnV2GroupCompatibilityRequest, + RpnV2ApiUpdateRpnV2GroupNameRequest, + RpnV2ApiUpdateRpnV2VlanForMembersRequest, + RpnV2Group, + RpnV2Member, + Server, + ServerDefaultPartitioning, + ServerDisk, + ServerEvent, + ServerInstall, + ServerSummary, + Service, + StartBMCAccessRequest, + StartRescueRequest, + SubscribeServerOptionRequest, + SubscribeStorageOptionsRequest, + SubscribeStorageOptionsResponse, + UpdatableRaidArray, + UpdateRaidRequest, + UpdateReverseRequest, + UpdateServerBackupRequest, + UpdateServerRequest, + UpdateServerTagsRequest, +) +from .content import ( + BMC_ACCESS_TRANSIENT_STATUSES, + RPN_SAN_TRANSIENT_STATUSES, + RPN_V2_GROUP_TRANSIENT_STATUSES, + SERVER_INSTALL_TRANSIENT_STATUSES, + SERVER_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_IP, + unmarshal_Offer, + unmarshal_OS, + unmarshal_RpnSan, + unmarshal_RpnGroup, + unmarshal_Server, + unmarshal_RpnV2Group, + unmarshal_Service, + unmarshal_FailoverIP, + unmarshal_BMCAccess, + unmarshal_Backup, + unmarshal_CanOrderResponse, + unmarshal_CreateFailoverIPsResponse, + unmarshal_GetIPv6BlockQuotasResponse, + unmarshal_GetRemainingQuotaResponse, + unmarshal_GetRpnStatusResponse, + unmarshal_IPv6Block, + unmarshal_Invoice, + unmarshal_ListFailoverIPsResponse, + unmarshal_ListIPv6BlockSubnetsAvailableResponse, + unmarshal_ListInvoicesResponse, + unmarshal_ListIpsResponse, + unmarshal_ListOSResponse, + unmarshal_ListOffersResponse, + unmarshal_ListRefundsResponse, + unmarshal_ListRpnCapableSanServersResponse, + unmarshal_ListRpnCapableServersResponse, + unmarshal_ListRpnGroupMembersResponse, + unmarshal_ListRpnGroupsResponse, + unmarshal_ListRpnInvitesResponse, + unmarshal_ListRpnSansResponse, + unmarshal_ListRpnServerCapabilitiesResponse, + unmarshal_ListRpnV2CapableResourcesResponse, + unmarshal_ListRpnV2GroupLogsResponse, + unmarshal_ListRpnV2GroupsResponse, + unmarshal_ListRpnV2MembersResponse, + unmarshal_ListServerDisksResponse, + unmarshal_ListServerEventsResponse, + unmarshal_ListServersResponse, + unmarshal_ListServicesResponse, + unmarshal_ListSubscribableServerOptionsResponse, + unmarshal_Raid, + unmarshal_Refund, + unmarshal_Rescue, + unmarshal_ServerDefaultPartitioning, + unmarshal_ServerInstall, + unmarshal_SubscribeStorageOptionsResponse, + marshal_AttachFailoverIPToMacAddressRequest, + marshal_AttachFailoverIPsRequest, + marshal_CreateFailoverIPsRequest, + marshal_CreateServerRequest, + marshal_DetachFailoverIPsRequest, + marshal_IPv6BlockApiCreateIPv6BlockRequest, + marshal_IPv6BlockApiCreateIPv6BlockSubnetRequest, + marshal_IPv6BlockApiUpdateIPv6BlockRequest, + marshal_InstallServerRequest, + marshal_RpnSanApiAddIpRequest, + marshal_RpnSanApiCreateRpnSanRequest, + marshal_RpnSanApiRemoveIpRequest, + marshal_RpnV1ApiAddRpnGroupMembersRequest, + marshal_RpnV1ApiCreateRpnGroupRequest, + marshal_RpnV1ApiDeleteRpnGroupMembersRequest, + marshal_RpnV1ApiLeaveRpnGroupRequest, + marshal_RpnV1ApiRpnGroupInviteRequest, + marshal_RpnV1ApiUpdateRpnGroupNameRequest, + marshal_RpnV2ApiAddRpnV2MembersRequest, + marshal_RpnV2ApiCreateRpnV2GroupRequest, + marshal_RpnV2ApiDeleteRpnV2MembersRequest, + marshal_RpnV2ApiEnableRpnV2GroupCompatibilityRequest, + marshal_RpnV2ApiUpdateRpnV2GroupNameRequest, + marshal_RpnV2ApiUpdateRpnV2VlanForMembersRequest, + marshal_StartBMCAccessRequest, + marshal_StartRescueRequest, + marshal_SubscribeServerOptionRequest, + marshal_SubscribeStorageOptionsRequest, + marshal_UpdateRaidRequest, + marshal_UpdateReverseRequest, + marshal_UpdateServerBackupRequest, + marshal_UpdateServerRequest, + marshal_UpdateServerTagsRequest, +) + + +class DediboxV1API(API): + """ + Dedibox Phoenix API. + """ + + async def list_servers( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServersRequestOrderBy] = None, + project_id: Optional[str] = None, + search: Optional[str] = None, + ) -> ListServersResponse: + """ + List baremetal servers for project. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server per page. + :param order_by: Order of the servers. + :param project_id: Filter servers by project ID. + :param search: Filter servers by hostname. + :return: :class:`ListServersResponse ` + + Usage: + :: + + result = await api.list_servers() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "search": search, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServersResponse(res.json()) + + async def list_servers_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServersRequestOrderBy] = None, + project_id: Optional[str] = None, + search: Optional[str] = None, + ) -> List[ServerSummary]: + """ + List baremetal servers for project. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server per page. + :param order_by: Order of the servers. + :param project_id: Filter servers by project ID. + :param search: Filter servers by hostname. + :return: :class:`List[ServerSummary] ` + + Usage: + :: + + result = await api.list_servers_all() + """ + + return await fetch_all_pages_async( + type=ListServersResponse, + key="servers", + fetcher=self.list_servers, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "search": search, + }, + ) + + async def get_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> Server: + """ + Get a specific baremetal server. + Get the server associated with the given ID. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Server ` + + Usage: + :: + + result = await api.get_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}", + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + + async def wait_for_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[Server, Union[bool, Awaitable[bool]]]] = None, + ) -> Server: + """ + Get a specific baremetal server. + Get the server associated with the given ID. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Server ` + + Usage: + :: + + result = await api.get_server( + server_id=1, + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in SERVER_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_server, + options=options, + args={ + "server_id": server_id, + "zone": zone, + }, + ) + + async def get_server_backup( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> Backup: + """ + :param server_id: Server ID of the backup. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Backup ` + + Usage: + :: + + result = await api.get_server_backup( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/backups", + ) + + self._throw_on_error(res) + return unmarshal_Backup(res.json()) + + async def update_server_backup( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + password: Optional[str] = None, + autologin: Optional[bool] = None, + acl_enabled: Optional[bool] = None, + ) -> Backup: + """ + :param server_id: Server ID to update backup. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param password: Password of the server backup. + :param autologin: Autologin of the server backup. + :param acl_enabled: Boolean to enable or disable ACL. + :return: :class:`Backup ` + + Usage: + :: + + result = await api.update_server_backup( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/backups", + body=marshal_UpdateServerBackupRequest( + UpdateServerBackupRequest( + server_id=server_id, + zone=zone, + password=password, + autologin=autologin, + acl_enabled=acl_enabled, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Backup(res.json()) + + async def list_subscribable_server_options( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListSubscribableServerOptionsResponse: + """ + List subscribable server options. + List subscribable options associated to the given server ID. + :param server_id: Server ID of the subscribable server options. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of subscribable server option per page. + :return: :class:`ListSubscribableServerOptionsResponse ` + + Usage: + :: + + result = await api.list_subscribable_server_options( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/subscribable-server-options", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListSubscribableServerOptionsResponse(res.json()) + + async def list_subscribable_server_options_all( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[Offer]: + """ + List subscribable server options. + List subscribable options associated to the given server ID. + :param server_id: Server ID of the subscribable server options. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of subscribable server option per page. + :return: :class:`List[Offer] ` + + Usage: + :: + + result = await api.list_subscribable_server_options_all( + server_id=1, + ) + """ + + return await fetch_all_pages_async( + type=ListSubscribableServerOptionsResponse, + key="server_options", + fetcher=self.list_subscribable_server_options, + args={ + "server_id": server_id, + "zone": zone, + "page": page, + "page_size": page_size, + }, + ) + + async def subscribe_server_option( + self, + *, + server_id: int, + option_id: int, + zone: Optional[ScwZone] = None, + ) -> Service: + """ + Subscribe server option. + Subscribe option for the given server ID. + :param server_id: Server ID to subscribe server option. + :param option_id: Option ID to subscribe. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Service ` + + Usage: + :: + + result = await api.subscribe_server_option( + server_id=1, + option_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/subscribe-server-option", + body=marshal_SubscribeServerOptionRequest( + SubscribeServerOptionRequest( + server_id=server_id, + option_id=option_id, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + async def create_server( + self, + *, + offer_id: int, + server_option_ids: List[int], + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + datacenter_name: Optional[str] = None, + ) -> Service: + """ + Create a baremetal server. + Create a new baremetal server. The order return you a service ID to follow the provisionning status you could call GetService. + :param offer_id: Offer ID of the new server. + :param server_option_ids: Server option IDs of the new server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID of the new server. + :param datacenter_name: Datacenter name of the new server. + :return: :class:`Service ` + + Usage: + :: + + result = await api.create_server( + offer_id=1, + server_option_ids=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers", + body=marshal_CreateServerRequest( + CreateServerRequest( + offer_id=offer_id, + server_option_ids=server_option_ids, + zone=zone, + project_id=project_id, + datacenter_name=datacenter_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + async def subscribe_storage_options( + self, + *, + server_id: int, + options_ids: List[int], + zone: Optional[ScwZone] = None, + ) -> SubscribeStorageOptionsResponse: + """ + Subscribe storage server option. + Subscribe storage option for the given server ID. + :param server_id: Server ID of the storage options to subscribe. + :param options_ids: Option IDs of the storage options to subscribe. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`SubscribeStorageOptionsResponse ` + + Usage: + :: + + result = await api.subscribe_storage_options( + server_id=1, + options_ids=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/subscribe-storage-options", + body=marshal_SubscribeStorageOptionsRequest( + SubscribeStorageOptionsRequest( + server_id=server_id, + options_ids=options_ids, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SubscribeStorageOptionsResponse(res.json()) + + async def update_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + hostname: Optional[str] = None, + enable_ipv6: Optional[bool] = None, + ) -> Server: + """ + Update a baremetal server. + Update the server associated with the given ID. + :param server_id: Server ID to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param hostname: Hostname of the server to update. + :param enable_ipv6: Flag to enable or not the IPv6 of server. + :return: :class:`Server ` + + Usage: + :: + + result = await api.update_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}", + body=marshal_UpdateServerRequest( + UpdateServerRequest( + server_id=server_id, + zone=zone, + hostname=hostname, + enable_ipv6=enable_ipv6, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + + async def update_server_tags( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + tags: Optional[List[str]] = None, + ) -> Server: + """ + :param server_id: Server ID to update the tags. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param tags: Tags of server to update. + :return: :class:`Server ` + + Usage: + :: + + result = await api.update_server_tags( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/tags", + body=marshal_UpdateServerTagsRequest( + UpdateServerTagsRequest( + server_id=server_id, + zone=zone, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + + async def reboot_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Reboot a baremetal server. + Reboot the server associated with the given ID, use boot param to reboot in rescue. + :param server_id: Server ID to reboot. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.reboot_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/reboot", + body={}, + ) + + self._throw_on_error(res) + + async def start_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Start a baremetal server. + Start the server associated with the given ID. + :param server_id: Server ID to start. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.start_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/start", + body={}, + ) + + self._throw_on_error(res) + + async def stop_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Stop a baremetal server. + Stop the server associated with the given ID. + :param server_id: Server ID to stop. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.stop_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/stop", + body={}, + ) + + self._throw_on_error(res) + + async def delete_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a baremetal server. + Delete the server associated with the given ID. + :param server_id: Server ID to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}", + ) + + self._throw_on_error(res) + + async def list_server_events( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServerEventsRequestOrderBy] = None, + ) -> ListServerEventsResponse: + """ + List server events. + List events associated to the given server ID. + :param server_id: Server ID of the server events. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server event per page. + :param order_by: Order of the server events. + :return: :class:`ListServerEventsResponse ` + + Usage: + :: + + result = await api.list_server_events( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/events", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServerEventsResponse(res.json()) + + async def list_server_events_all( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServerEventsRequestOrderBy] = None, + ) -> List[ServerEvent]: + """ + List server events. + List events associated to the given server ID. + :param server_id: Server ID of the server events. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server event per page. + :param order_by: Order of the server events. + :return: :class:`List[ServerEvent] ` + + Usage: + :: + + result = await api.list_server_events_all( + server_id=1, + ) + """ + + return await fetch_all_pages_async( + type=ListServerEventsResponse, + key="events", + fetcher=self.list_server_events, + args={ + "server_id": server_id, + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + async def list_server_disks( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServerDisksRequestOrderBy] = None, + ) -> ListServerDisksResponse: + """ + List server disks. + List disks associated to the given server ID. + :param server_id: Server ID of the server disks. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server disk per page. + :param order_by: Order of the server disks. + :return: :class:`ListServerDisksResponse ` + + Usage: + :: + + result = await api.list_server_disks( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/disks", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServerDisksResponse(res.json()) + + async def list_server_disks_all( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServerDisksRequestOrderBy] = None, + ) -> List[ServerDisk]: + """ + List server disks. + List disks associated to the given server ID. + :param server_id: Server ID of the server disks. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server disk per page. + :param order_by: Order of the server disks. + :return: :class:`List[ServerDisk] ` + + Usage: + :: + + result = await api.list_server_disks_all( + server_id=1, + ) + """ + + return await fetch_all_pages_async( + type=ListServerDisksResponse, + key="disks", + fetcher=self.list_server_disks, + args={ + "server_id": server_id, + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + async def get_ordered_service( + self, + *, + ordered_service_id: int, + zone: Optional[ScwZone] = None, + ) -> Service: + """ + :param ordered_service_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Service ` + + Usage: + :: + + result = await api.get_ordered_service( + ordered_service_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ordered_service_id = validate_path_param( + "ordered_service_id", ordered_service_id + ) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/ordered-services/{param_ordered_service_id}", + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + async def get_service( + self, + *, + service_id: int, + zone: Optional[ScwZone] = None, + ) -> Service: + """ + Get a specific service. + Get the service associated with the given ID. + :param service_id: ID of the service. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Service ` + + Usage: + :: + + result = await api.get_service( + service_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_service_id = validate_path_param("service_id", service_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/zones/{param_zone}/services/{param_service_id}", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + async def delete_service( + self, + *, + service_id: int, + zone: Optional[ScwZone] = None, + ) -> Service: + """ + Delete a specific service. + Delete the service associated with the given ID. + :param service_id: ID of the service. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Service ` + + Usage: + :: + + result = await api.delete_service( + service_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_service_id = validate_path_param("service_id", service_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/zones/{param_zone}/services/{param_service_id}", + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + async def list_services( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServicesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListServicesResponse: + """ + List services. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of service per page. + :param order_by: Order of the services. + :param project_id: Project ID. + :return: :class:`ListServicesResponse ` + + Usage: + :: + + result = await api.list_services() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/services", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServicesResponse(res.json()) + + async def list_services_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServicesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[Service]: + """ + List services. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of service per page. + :param order_by: Order of the services. + :param project_id: Project ID. + :return: :class:`List[Service] ` + + Usage: + :: + + result = await api.list_services_all() + """ + + return await fetch_all_pages_async( + type=ListServicesResponse, + key="services", + fetcher=self.list_services, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def install_server( + self, + *, + server_id: int, + os_id: int, + hostname: str, + zone: Optional[ScwZone] = None, + user_login: Optional[str] = None, + user_password: Optional[str] = None, + panel_password: Optional[str] = None, + root_password: Optional[str] = None, + partitions: Optional[List[InstallPartition]] = None, + ssh_key_ids: Optional[List[str]] = None, + license_offer_id: Optional[int] = None, + ip_id: Optional[int] = None, + ) -> ServerInstall: + """ + Install a baremetal server. + Install an OS on the server associated with the given ID. + :param server_id: Server ID to install. + :param os_id: OS ID to install on the server. + :param hostname: Hostname of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param user_login: User to install on the server. + :param user_password: User password to install on the server. + :param panel_password: Panel password to install on the server. + :param root_password: Root password to install on the server. + :param partitions: Partitions to install on the server. + :param ssh_key_ids: SSH key IDs authorized on the server. + :param license_offer_id: Offer ID of license to install on server. + :param ip_id: IP to link at the license to install on server. + :return: :class:`ServerInstall ` + + Usage: + :: + + result = await api.install_server( + server_id=1, + os_id=1, + hostname="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/install", + body=marshal_InstallServerRequest( + InstallServerRequest( + server_id=server_id, + os_id=os_id, + hostname=hostname, + zone=zone, + user_login=user_login, + user_password=user_password, + panel_password=panel_password, + root_password=root_password, + partitions=partitions, + ssh_key_ids=ssh_key_ids, + license_offer_id=license_offer_id, + ip_id=ip_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ServerInstall(res.json()) + + async def get_server_install( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> ServerInstall: + """ + Get a specific server installation status. + Get the server installation status associated with the given server ID. + :param server_id: Server ID of the server to install. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerInstall ` + + Usage: + :: + + result = await api.get_server_install( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/install", + ) + + self._throw_on_error(res) + return unmarshal_ServerInstall(res.json()) + + async def wait_for_server_install( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + options: Optional[ + WaitForOptions[ServerInstall, Union[bool, Awaitable[bool]]] + ] = None, + ) -> ServerInstall: + """ + Get a specific server installation status. + Get the server installation status associated with the given server ID. + :param server_id: Server ID of the server to install. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerInstall ` + + Usage: + :: + + result = await api.get_server_install( + server_id=1, + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in SERVER_INSTALL_TRANSIENT_STATUSES + ) + + return await wait_for_resource_async( + fetcher=self.get_server_install, + options=options, + args={ + "server_id": server_id, + "zone": zone, + }, + ) + + async def cancel_server_install( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Cancels the current (running) server installation. + Cancels the current server installation associated with the given server ID. + :param server_id: Server ID of the server to cancel install. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.cancel_server_install( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/cancel-install", + ) + + self._throw_on_error(res) + + async def get_server_default_partitioning( + self, + *, + server_id: int, + os_id: int, + zone: Optional[ScwZone] = None, + ) -> ServerDefaultPartitioning: + """ + Get server default partitioning. + Get the server default partitioning schema associated with the given server ID and OS ID. + :param server_id: ID of the server. + :param os_id: OS ID of the default partitioning. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerDefaultPartitioning ` + + Usage: + :: + + result = await api.get_server_default_partitioning( + server_id=1, + os_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + param_os_id = validate_path_param("os_id", os_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/partitioning/{param_os_id}", + ) + + self._throw_on_error(res) + return unmarshal_ServerDefaultPartitioning(res.json()) + + async def start_bmc_access( + self, + *, + server_id: int, + ip: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Start BMC (Baseboard Management Controller) access for a given baremetal server. + Start BMC (Baseboard Management Controller) access associated with the given ID. + The BMC (Baseboard Management Controller) access is available one hour after the installation of the server. + :param server_id: ID of the server to start the BMC access. + :param ip: The IP authorized to connect to the given server. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.start_bmc_access( + server_id=1, + ip="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/bmc-access", + body=marshal_StartBMCAccessRequest( + StartBMCAccessRequest( + server_id=server_id, + ip=ip, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def get_bmc_access( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> BMCAccess: + """ + Get BMC (Baseboard Management Controller) access for a given baremetal server. + Get the BMC (Baseboard Management Controller) access associated with the given ID. + :param server_id: ID of the server to get BMC access. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`BMCAccess ` + + Usage: + :: + + result = await api.get_bmc_access( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/bmc-access", + ) + + self._throw_on_error(res) + return unmarshal_BMCAccess(res.json()) + + async def wait_for_bmc_access( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + options: Optional[ + WaitForOptions[BMCAccess, Union[bool, Awaitable[bool]]] + ] = None, + ) -> BMCAccess: + """ + Get BMC (Baseboard Management Controller) access for a given baremetal server. + Get the BMC (Baseboard Management Controller) access associated with the given ID. + :param server_id: ID of the server to get BMC access. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`BMCAccess ` + + Usage: + :: + + result = await api.get_bmc_access( + server_id=1, + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in BMC_ACCESS_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_bmc_access, + options=options, + args={ + "server_id": server_id, + "zone": zone, + }, + ) + + async def stop_bmc_access( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Stop BMC (Baseboard Management Controller) access for a given baremetal server. + Stop BMC (Baseboard Management Controller) access associated with the given ID. + :param server_id: ID of the server to stop BMC access. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.stop_bmc_access( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/bmc-access", + ) + + self._throw_on_error(res) + + async def list_offers( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOffersRequestOrderBy] = None, + commercial_range: Optional[str] = None, + catalog: Optional[OfferCatalog] = None, + project_id: Optional[str] = None, + is_failover_ip: Optional[bool] = None, + is_failover_block: Optional[bool] = None, + sold_in: Optional[List[str]] = None, + available_only: Optional[bool] = None, + is_rpn_san: Optional[bool] = None, + ) -> ListOffersResponse: + """ + List offers. + List all available server offers. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of offer per page. + :param order_by: Order of the offers. + :param commercial_range: Filter on commercial range. + :param catalog: Filter on catalog. + :param project_id: Project ID. + :param is_failover_ip: Get the current failover IP offer. + :param is_failover_block: Get the current failover IP block offer. + :param sold_in: Filter offers depending on their datacenter. + :param available_only: Set this filter to true to only return available offers. + :param is_rpn_san: Get the RPN SAN offers. + :return: :class:`ListOffersResponse ` + + Usage: + :: + + result = await api.list_offers() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/offers", + params={ + "available_only": available_only, + "catalog": catalog, + "commercial_range": commercial_range, + "is_failover_block": is_failover_block, + "is_failover_ip": is_failover_ip, + "is_rpn_san": is_rpn_san, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "sold_in": ",".join(sold_in) if sold_in and len(sold_in) > 0 else None, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListOffersResponse(res.json()) + + async def list_offers_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOffersRequestOrderBy] = None, + commercial_range: Optional[str] = None, + catalog: Optional[OfferCatalog] = None, + project_id: Optional[str] = None, + is_failover_ip: Optional[bool] = None, + is_failover_block: Optional[bool] = None, + sold_in: Optional[List[str]] = None, + available_only: Optional[bool] = None, + is_rpn_san: Optional[bool] = None, + ) -> List[Offer]: + """ + List offers. + List all available server offers. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of offer per page. + :param order_by: Order of the offers. + :param commercial_range: Filter on commercial range. + :param catalog: Filter on catalog. + :param project_id: Project ID. + :param is_failover_ip: Get the current failover IP offer. + :param is_failover_block: Get the current failover IP block offer. + :param sold_in: Filter offers depending on their datacenter. + :param available_only: Set this filter to true to only return available offers. + :param is_rpn_san: Get the RPN SAN offers. + :return: :class:`List[Offer] ` + + Usage: + :: + + result = await api.list_offers_all() + """ + + return await fetch_all_pages_async( + type=ListOffersResponse, + key="offers", + fetcher=self.list_offers, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + "commercial_range": commercial_range, + "catalog": catalog, + "project_id": project_id, + "is_failover_ip": is_failover_ip, + "is_failover_block": is_failover_block, + "sold_in": sold_in, + "available_only": available_only, + "is_rpn_san": is_rpn_san, + }, + ) + + async def get_offer( + self, + *, + offer_id: int, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + ) -> Offer: + """ + Get offer. + Return specific offer for the given ID. + :param offer_id: ID of offer. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID. + :return: :class:`Offer ` + + Usage: + :: + + result = await api.get_offer( + offer_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_offer_id = validate_path_param("offer_id", offer_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/offers/{param_offer_id}", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Offer(res.json()) + + async def list_os( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOSRequestOrderBy] = None, + type_: Optional[OSType] = None, + project_id: Optional[str] = None, + ) -> ListOSResponse: + """ + List all available OS that can be install on a baremetal server. + :param server_id: Filter OS by compatible server ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of OS per page. + :param order_by: Order of the OS. + :param type_: Type of the OS. + :param project_id: Project ID. + :return: :class:`ListOSResponse ` + + Usage: + :: + + result = await api.list_os( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/os", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "server_id": server_id, + "type": type_, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListOSResponse(res.json()) + + async def list_os_all( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOSRequestOrderBy] = None, + type_: Optional[OSType] = None, + project_id: Optional[str] = None, + ) -> List[OS]: + """ + List all available OS that can be install on a baremetal server. + :param server_id: Filter OS by compatible server ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of OS per page. + :param order_by: Order of the OS. + :param type_: Type of the OS. + :param project_id: Project ID. + :return: :class:`List[OS] ` + + Usage: + :: + + result = await api.list_os_all( + server_id=1, + ) + """ + + return await fetch_all_pages_async( + type=ListOSResponse, + key="os", + fetcher=self.list_os, + args={ + "server_id": server_id, + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + "type_": type_, + "project_id": project_id, + }, + ) + + async def get_os( + self, + *, + os_id: int, + server_id: int, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + ) -> OS: + """ + Get an OS with a given ID. + Return specific OS for the given ID. + :param os_id: ID of the OS. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID. + :return: :class:`OS ` + + Usage: + :: + + result = await api.get_os( + os_id=1, + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_os_id = validate_path_param("os_id", os_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/os/{param_os_id}", + params={ + "project_id": project_id or self.client.default_project_id, + "server_id": server_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_OS(res.json()) + + async def update_reverse( + self, + *, + ip_id: int, + reverse: str, + zone: Optional[ScwZone] = None, + ) -> IP: + """ + Update reverse of ip. + Update reverse of ip associated with the given ID. + :param ip_id: ID of the IP. + :param reverse: Reverse to apply on the IP. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`IP ` + + Usage: + :: + + result = await api.update_reverse( + ip_id=1, + reverse="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/zones/{param_zone}/reverses/{param_ip_id}", + body=marshal_UpdateReverseRequest( + UpdateReverseRequest( + ip_id=ip_id, + reverse=reverse, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + async def create_failover_i_ps( + self, + *, + offer_id: int, + quantity: int, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + ) -> CreateFailoverIPsResponse: + """ + Order failover IPs. + Order X failover IPs. + :param offer_id: Failover IP offer ID. + :param quantity: Quantity. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID. + :return: :class:`CreateFailoverIPsResponse ` + + Usage: + :: + + result = await api.create_failover_i_ps( + offer_id=1, + quantity=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/failover-ips", + body=marshal_CreateFailoverIPsRequest( + CreateFailoverIPsRequest( + offer_id=offer_id, + quantity=quantity, + zone=zone, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CreateFailoverIPsResponse(res.json()) + + async def attach_failover_i_ps( + self, + *, + server_id: int, + fips_ids: List[int], + zone: Optional[ScwZone] = None, + ) -> None: + """ + Attach failovers on baremetal server. + Attach failovers on the server associated with the given ID. + :param server_id: ID of the server. + :param fips_ids: List of ID of failovers IP to attach. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.attach_failover_i_ps( + server_id=1, + fips_ids=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/failover-ips/attach", + body=marshal_AttachFailoverIPsRequest( + AttachFailoverIPsRequest( + server_id=server_id, + fips_ids=fips_ids, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def detach_failover_i_ps( + self, + *, + fips_ids: List[int], + zone: Optional[ScwZone] = None, + ) -> None: + """ + Detach failovers on baremetal server. + Detach failovers on the server associated with the given ID. + :param fips_ids: List of IDs of failovers IP to detach. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.detach_failover_i_ps( + fips_ids=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/failover-ips/detach", + body=marshal_DetachFailoverIPsRequest( + DetachFailoverIPsRequest( + fips_ids=fips_ids, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def attach_failover_ip_to_mac_address( + self, + *, + ip_id: int, + zone: Optional[ScwZone] = None, + type_: Optional[AttachFailoverIPToMacAddressRequestMacType] = None, + mac: Optional[str] = None, + ) -> IP: + """ + Attach a failover IP to a MAC address. + :param ip_id: ID of the failover IP. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param type_: A mac type. + :param mac: A valid mac address (existing or not). + :return: :class:`IP ` + + Usage: + :: + + result = await api.attach_failover_ip_to_mac_address( + ip_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/failover-ips/{param_ip_id}/attach-to-mac-address", + body=marshal_AttachFailoverIPToMacAddressRequest( + AttachFailoverIPToMacAddressRequest( + ip_id=ip_id, + zone=zone, + type_=type_, + mac=mac, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + async def detach_failover_ip_from_mac_address( + self, + *, + ip_id: int, + zone: Optional[ScwZone] = None, + ) -> IP: + """ + Detach a failover IP from a MAC address. + :param ip_id: ID of the failover IP. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`IP ` + + Usage: + :: + + result = await api.detach_failover_ip_from_mac_address( + ip_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/failover-ips/{param_ip_id}/detach-from-mac-address", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + async def delete_failover_ip( + self, + *, + ip_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a failover server. + Delete the failover associated with the given ID. + :param ip_id: ID of the failover IP to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_failover_ip( + ip_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/zones/{param_zone}/failover-ips/{param_ip_id}", + ) + + self._throw_on_error(res) + + async def list_failover_i_ps( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListFailoverIPsRequestOrderBy] = None, + project_id: Optional[str] = None, + search: Optional[str] = None, + only_available: Optional[bool] = None, + ) -> ListFailoverIPsResponse: + """ + List failovers for project. + List failovers servers for project. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of failovers IP per page. + :param order_by: Order of the failovers IP. + :param project_id: Filter failovers IP by project ID. + :param search: Filter failovers IP which matching with this field. + :param only_available: True: return all failovers IP not attached on server + false: return all failovers IP attached on server. + :return: :class:`ListFailoverIPsResponse ` + + Usage: + :: + + result = await api.list_failover_i_ps() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/failover-ips", + params={ + "only_available": only_available, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "search": search, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListFailoverIPsResponse(res.json()) + + async def list_failover_i_ps_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListFailoverIPsRequestOrderBy] = None, + project_id: Optional[str] = None, + search: Optional[str] = None, + only_available: Optional[bool] = None, + ) -> List[FailoverIP]: + """ + List failovers for project. + List failovers servers for project. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of failovers IP per page. + :param order_by: Order of the failovers IP. + :param project_id: Filter failovers IP by project ID. + :param search: Filter failovers IP which matching with this field. + :param only_available: True: return all failovers IP not attached on server + false: return all failovers IP attached on server. + :return: :class:`List[FailoverIP] ` + + Usage: + :: + + result = await api.list_failover_i_ps_all() + """ + + return await fetch_all_pages_async( + type=ListFailoverIPsResponse, + key="failover_ips", + fetcher=self.list_failover_i_ps, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "search": search, + "only_available": only_available, + }, + ) + + async def get_failover_ip( + self, + *, + ip_id: int, + zone: Optional[ScwZone] = None, + ) -> FailoverIP: + """ + Get a specific baremetal server. + Get the server associated with the given ID. + :param ip_id: ID of the failover IP. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`FailoverIP ` + + Usage: + :: + + result = await api.get_failover_ip( + ip_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/failover-ips/{param_ip_id}", + ) + + self._throw_on_error(res) + return unmarshal_FailoverIP(res.json()) + + async def get_remaining_quota( + self, + *, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + ) -> GetRemainingQuotaResponse: + """ + Get remaining quota. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID. + :return: :class:`GetRemainingQuotaResponse ` + + Usage: + :: + + result = await api.get_remaining_quota() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/remaining-quota", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_GetRemainingQuotaResponse(res.json()) + + async def get_raid( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> Raid: + """ + Get raid. + Return raid for the given server ID. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Raid ` + + Usage: + :: + + result = await api.get_raid( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/raid", + ) + + self._throw_on_error(res) + return unmarshal_Raid(res.json()) + + async def update_raid( + self, + *, + server_id: int, + raid_arrays: List[UpdatableRaidArray], + zone: Optional[ScwZone] = None, + ) -> None: + """ + Update RAID. + Update RAID associated with the given server ID. + :param server_id: ID of the server. + :param raid_arrays: RAIDs to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.update_raid( + server_id=1, + raid_arrays=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/update-raid", + body=marshal_UpdateRaidRequest( + UpdateRaidRequest( + server_id=server_id, + raid_arrays=raid_arrays, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def start_rescue( + self, + *, + server_id: int, + os_id: int, + zone: Optional[ScwZone] = None, + ) -> Rescue: + """ + Start in rescue baremetal server. + Start in rescue the server associated with the given ID. + :param server_id: ID of the server to start rescue. + :param os_id: OS ID to use to start rescue. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Rescue ` + + Usage: + :: + + result = await api.start_rescue( + server_id=1, + os_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/rescue", + body=marshal_StartRescueRequest( + StartRescueRequest( + server_id=server_id, + os_id=os_id, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Rescue(res.json()) + + async def get_rescue( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> Rescue: + """ + Get rescue information. + Return rescue information for the given server ID. + :param server_id: ID of the server to get rescue. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Rescue ` + + Usage: + :: + + result = await api.get_rescue( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/rescue", + ) + + self._throw_on_error(res) + return unmarshal_Rescue(res.json()) + + async def stop_rescue( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Stop rescue on baremetal server. + Stop rescue on the server associated with the given ID. + :param server_id: ID of the server to stop rescue. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.stop_rescue( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/rescue", + ) + + self._throw_on_error(res) + + +class DediboxV1BillingAPI(API): + """ + Dedibox Phoenix Billing API. + """ + + async def list_invoices( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListInvoicesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListInvoicesResponse: + """ + :param page: + :param page_size: + :param order_by: + :param project_id: + :return: :class:`ListInvoicesResponse ` + + Usage: + :: + + result = await api.list_invoices() + """ + + res = self._request( + "GET", + "/dedibox/v1/invoices", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInvoicesResponse(res.json()) + + async def list_invoices_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListInvoicesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[InvoiceSummary]: + """ + :param page: + :param page_size: + :param order_by: + :param project_id: + :return: :class:`List[InvoiceSummary] ` + + Usage: + :: + + result = await api.list_invoices_all() + """ + + return await fetch_all_pages_async( + type=ListInvoicesResponse, + key="invoices", + fetcher=self.list_invoices, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def get_invoice( + self, + *, + invoice_id: int, + ) -> Invoice: + """ + :param invoice_id: + :return: :class:`Invoice ` + + Usage: + :: + + result = await api.get_invoice( + invoice_id=1, + ) + """ + + param_invoice_id = validate_path_param("invoice_id", invoice_id) + + res = self._request( + "GET", + f"/dedibox/v1/invoices/{param_invoice_id}", + ) + + self._throw_on_error(res) + return unmarshal_Invoice(res.json()) + + async def download_invoice( + self, + *, + invoice_id: int, + ) -> ScwFile: + """ + :param invoice_id: + :return: :class:`ScwFile ` + + Usage: + :: + + result = await api.download_invoice( + invoice_id=1, + ) + """ + + param_invoice_id = validate_path_param("invoice_id", invoice_id) + + res = self._request( + "GET", + f"/dedibox/v1/invoices/{param_invoice_id}/download", + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + async def list_refunds( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRefundsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRefundsResponse: + """ + :param page: + :param page_size: + :param order_by: + :param project_id: + :return: :class:`ListRefundsResponse ` + + Usage: + :: + + result = await api.list_refunds() + """ + + res = self._request( + "GET", + "/dedibox/v1/refunds", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRefundsResponse(res.json()) + + async def list_refunds_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRefundsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RefundSummary]: + """ + :param page: + :param page_size: + :param order_by: + :param project_id: + :return: :class:`List[RefundSummary] ` + + Usage: + :: + + result = await api.list_refunds_all() + """ + + return await fetch_all_pages_async( + type=ListRefundsResponse, + key="refunds", + fetcher=self.list_refunds, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def get_refund( + self, + *, + refund_id: int, + ) -> Refund: + """ + :param refund_id: + :return: :class:`Refund ` + + Usage: + :: + + result = await api.get_refund( + refund_id=1, + ) + """ + + param_refund_id = validate_path_param("refund_id", refund_id) + + res = self._request( + "GET", + f"/dedibox/v1/refunds/{param_refund_id}", + ) + + self._throw_on_error(res) + return unmarshal_Refund(res.json()) + + async def download_refund( + self, + *, + refund_id: int, + ) -> ScwFile: + """ + :param refund_id: + :return: :class:`ScwFile ` + + Usage: + :: + + result = await api.download_refund( + refund_id=1, + ) + """ + + param_refund_id = validate_path_param("refund_id", refund_id) + + res = self._request( + "GET", + f"/dedibox/v1/refunds/{param_refund_id}/download", + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + async def can_order( + self, + *, + project_id: Optional[str] = None, + ) -> CanOrderResponse: + """ + :param project_id: + :return: :class:`CanOrderResponse ` + + Usage: + :: + + result = await api.can_order() + """ + + res = self._request( + "GET", + "/dedibox/v1/can-order", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_CanOrderResponse(res.json()) + + +class DediboxV1IPv6BlockAPI(API): + """ + Dedibox Phoenix IPv6 Block API. + """ + + async def get_i_pv6_block_quotas( + self, + *, + project_id: Optional[str] = None, + ) -> GetIPv6BlockQuotasResponse: + """ + Get IPv6 block quota. + Get IPv6 block quota with the given project ID. + /48 one per organization. + /56 link to your number of server. + /64 link to your number of failover IP. + :param project_id: ID of the project. + :return: :class:`GetIPv6BlockQuotasResponse ` + + Usage: + :: + + result = await api.get_i_pv6_block_quotas() + """ + + res = self._request( + "GET", + "/dedibox/v1/ipv6-block-quotas", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_GetIPv6BlockQuotasResponse(res.json()) + + async def create_i_pv6_block( + self, + *, + project_id: Optional[str] = None, + ) -> IPv6Block: + """ + Create IPv6 block for baremetal server. + Create IPv6 block associated with the given project ID. + :param project_id: ID of the project. + :return: :class:`IPv6Block ` + + Usage: + :: + + result = await api.create_i_pv6_block() + """ + + res = self._request( + "POST", + "/dedibox/v1/ipv6-block", + body=marshal_IPv6BlockApiCreateIPv6BlockRequest( + IPv6BlockApiCreateIPv6BlockRequest( + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IPv6Block(res.json()) + + async def get_i_pv6_block( + self, + *, + project_id: Optional[str] = None, + ) -> IPv6Block: + """ + Get a specific IPv6 block. + Get the IPv6 block associated with the given ID. + :param project_id: ID of the project. + :return: :class:`IPv6Block ` + + Usage: + :: + + result = await api.get_i_pv6_block() + """ + + res = self._request( + "GET", + "/dedibox/v1/ipv6-block", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_IPv6Block(res.json()) + + async def update_i_pv6_block( + self, + *, + block_id: int, + nameservers: Optional[List[str]] = None, + ) -> IPv6Block: + """ + Update IPv6 block. + Update DNS associated to IPv6 block. + If DNS is used, minimum of 2 is necessary and maximum of 5 (no duplicate). + :param block_id: ID of the IPv6 block. + :param nameservers: DNS to link to the IPv6. + :return: :class:`IPv6Block ` + + Usage: + :: + + result = await api.update_i_pv6_block( + block_id=1, + ) + """ + + param_block_id = validate_path_param("block_id", block_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/ipv6-blocks/{param_block_id}", + body=marshal_IPv6BlockApiUpdateIPv6BlockRequest( + IPv6BlockApiUpdateIPv6BlockRequest( + block_id=block_id, + nameservers=nameservers, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IPv6Block(res.json()) + + async def delete_i_pv6_block( + self, + *, + block_id: int, + ) -> None: + """ + Delete IPv6 block. + Delete IPv6 block subnet with the given ID. + :param block_id: ID of the IPv6 block to delete. + + Usage: + :: + + result = await api.delete_i_pv6_block( + block_id=1, + ) + """ + + param_block_id = validate_path_param("block_id", block_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/ipv6-blocks/{param_block_id}", + ) + + self._throw_on_error(res) + + async def create_i_pv6_block_subnet( + self, + *, + block_id: int, + address: str, + cidr: int, + ) -> IPv6Block: + """ + Create IPv6 block subnet. + Create IPv6 block subnet for the given IP ID. + /48 could create subnet in /56 (quota link to your number of server). + /56 could create subnet in /64 (quota link to your number of failover IP). + :param block_id: ID of the IPv6 block. + :param address: Address of the IPv6. + :param cidr: Classless InterDomain Routing notation of the IPv6. + :return: :class:`IPv6Block ` + + Usage: + :: + + result = await api.create_i_pv6_block_subnet( + block_id=1, + address="example", + cidr=1, + ) + """ + + param_block_id = validate_path_param("block_id", block_id) + + res = self._request( + "POST", + f"/dedibox/v1/ipv6-blocks/{param_block_id}/subnets", + body=marshal_IPv6BlockApiCreateIPv6BlockSubnetRequest( + IPv6BlockApiCreateIPv6BlockSubnetRequest( + block_id=block_id, + address=address, + cidr=cidr, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IPv6Block(res.json()) + + async def list_i_pv6_block_subnets_available( + self, + *, + block_id: int, + ) -> ListIPv6BlockSubnetsAvailableResponse: + """ + List available IPv6 block subnets. + List all available IPv6 block subnets for given IP ID. + :param block_id: ID of the IPv6 block. + :return: :class:`ListIPv6BlockSubnetsAvailableResponse ` + + Usage: + :: + + result = await api.list_i_pv6_block_subnets_available( + block_id=1, + ) + """ + + param_block_id = validate_path_param("block_id", block_id) + + res = self._request( + "GET", + f"/dedibox/v1/ipv6-blocks/{param_block_id}/subnets", + ) + + self._throw_on_error(res) + return unmarshal_ListIPv6BlockSubnetsAvailableResponse(res.json()) + + +class DediboxV1RpnAPI(API): + """ + Dedibox Phoenix RPN API. + """ + + async def list_rpn_server_capabilities( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnServerCapabilitiesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnServerCapabilitiesResponse: + """ + :param page: Page number. + :param page_size: Number of servers per page. + :param order_by: Order of the servers. + :param project_id: Filter servers by project ID. + :return: :class:`ListRpnServerCapabilitiesResponse ` + + Usage: + :: + + result = await api.list_rpn_server_capabilities() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpn/server-capabilities", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnServerCapabilitiesResponse(res.json()) + + async def list_rpn_server_capabilities_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnServerCapabilitiesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnServerCapability]: + """ + :param page: Page number. + :param page_size: Number of servers per page. + :param order_by: Order of the servers. + :param project_id: Filter servers by project ID. + :return: :class:`List[RpnServerCapability] ` + + Usage: + :: + + result = await api.list_rpn_server_capabilities_all() + """ + + return await fetch_all_pages_async( + type=ListRpnServerCapabilitiesResponse, + key="servers", + fetcher=self.list_rpn_server_capabilities, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def get_rpn_status( + self, + *, + project_id: Optional[str] = None, + rpnv1_group_id: Optional[int] = None, + rpnv2_group_id: Optional[int] = None, + ) -> GetRpnStatusResponse: + """ + :param project_id: A project ID. + :param rpnv1_group_id: An RPN v1 group ID. + :param rpnv2_group_id: An RPN v2 group ID. + :return: :class:`GetRpnStatusResponse ` + + Usage: + :: + + result = await api.get_rpn_status() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpn/status", + params={ + "project_id": project_id or self.client.default_project_id, + "rpnv1_group_id": rpnv1_group_id, + "rpnv2_group_id": rpnv2_group_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_GetRpnStatusResponse(res.json()) + + +class DediboxV1RpnSanAPI(API): + """ + Dedibox Phoenix RPN SAN API. + """ + + async def list_rpn_sans( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnSansRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnSansResponse: + """ + :param page: Page number. + :param page_size: Number of RPN SANs per page. + :param order_by: Order of the RPN SANs. + :param project_id: Filter RPN SANs by project ID. + :return: :class:`ListRpnSansResponse ` + + Usage: + :: + + result = await api.list_rpn_sans() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpn-sans", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnSansResponse(res.json()) + + async def list_rpn_sans_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnSansRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnSanSummary]: + """ + :param page: Page number. + :param page_size: Number of RPN SANs per page. + :param order_by: Order of the RPN SANs. + :param project_id: Filter RPN SANs by project ID. + :return: :class:`List[RpnSanSummary] ` + + Usage: + :: + + result = await api.list_rpn_sans_all() + """ + + return await fetch_all_pages_async( + type=ListRpnSansResponse, + key="rpn_sans", + fetcher=self.list_rpn_sans, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def get_rpn_san( + self, + *, + rpn_san_id: int, + ) -> RpnSan: + """ + :param rpn_san_id: RPN SAN ID. + :return: :class:`RpnSan ` + + Usage: + :: + + result = await api.get_rpn_san( + rpn_san_id=1, + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}", + ) + + self._throw_on_error(res) + return unmarshal_RpnSan(res.json()) + + async def wait_for_rpn_san( + self, + *, + rpn_san_id: int, + options: Optional[WaitForOptions[RpnSan, Union[bool, Awaitable[bool]]]] = None, + ) -> RpnSan: + """ + :param rpn_san_id: RPN SAN ID. + :return: :class:`RpnSan ` + + Usage: + :: + + result = await api.get_rpn_san( + rpn_san_id=1, + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in RPN_SAN_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_rpn_san, + options=options, + args={ + "rpn_san_id": rpn_san_id, + }, + ) + + async def delete_rpn_san( + self, + *, + rpn_san_id: int, + ) -> None: + """ + :param rpn_san_id: RPN SAN ID. + + Usage: + :: + + result = await api.delete_rpn_san( + rpn_san_id=1, + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}", + ) + + self._throw_on_error(res) + + async def create_rpn_san( + self, + *, + offer_id: int, + project_id: Optional[str] = None, + ) -> Service: + """ + :param offer_id: Offer ID. + :param project_id: Your project ID. + :return: :class:`Service ` + + Usage: + :: + + result = await api.create_rpn_san( + offer_id=1, + ) + """ + + res = self._request( + "POST", + "/dedibox/v1/rpn-sans", + body=marshal_RpnSanApiCreateRpnSanRequest( + RpnSanApiCreateRpnSanRequest( + offer_id=offer_id, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + async def list_ips( + self, + *, + rpn_san_id: int, + type_: Optional[RpnSanIpType] = None, + ) -> ListIpsResponse: + """ + :param rpn_san_id: RPN SAN ID. + :param type_: Filter by IP type (server | rpnv2_subnet). + :return: :class:`ListIpsResponse ` + + Usage: + :: + + result = await api.list_ips( + rpn_san_id=1, + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}/ips", + params={ + "type": type_, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListIpsResponse(res.json()) + + async def add_ip( + self, + *, + rpn_san_id: int, + ip_ids: List[int], + ) -> None: + """ + :param rpn_san_id: RPN SAN ID. + :param ip_ids: An array of IP ID. + + Usage: + :: + + result = await api.add_ip( + rpn_san_id=1, + ip_ids=[], + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}/ips", + body=marshal_RpnSanApiAddIpRequest( + RpnSanApiAddIpRequest( + rpn_san_id=rpn_san_id, + ip_ids=ip_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def remove_ip( + self, + *, + rpn_san_id: int, + ip_ids: List[int], + ) -> None: + """ + :param rpn_san_id: RPN SAN ID. + :param ip_ids: An array of IP ID. + + Usage: + :: + + result = await api.remove_ip( + rpn_san_id=1, + ip_ids=[], + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}/ips", + body=marshal_RpnSanApiRemoveIpRequest( + RpnSanApiRemoveIpRequest( + rpn_san_id=rpn_san_id, + ip_ids=ip_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def list_available_ips( + self, + *, + rpn_san_id: int, + type_: Optional[RpnSanIpType] = None, + ) -> ListIpsResponse: + """ + :param rpn_san_id: RPN SAN ID. + :param type_: Filter by IP type (server | rpnv2_subnet). + :return: :class:`ListIpsResponse ` + + Usage: + :: + + result = await api.list_available_ips( + rpn_san_id=1, + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}/available-ips", + params={ + "type": type_, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListIpsResponse(res.json()) + + +class DediboxV1RpnV1API(API): + """ + Dedibox Phoenix RPN v1 API. + """ + + async def list_rpn_groups( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnGroupsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnGroupsResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v1 groups per page. + :param order_by: Order of the rpn v1 groups. + :param project_id: Filter rpn v1 groups by project ID. + :return: :class:`ListRpnGroupsResponse ` + + Usage: + :: + + result = await api.list_rpn_groups() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv1/groups", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnGroupsResponse(res.json()) + + async def list_rpn_groups_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnGroupsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnGroup]: + """ + :param page: Page number. + :param page_size: Number of rpn v1 groups per page. + :param order_by: Order of the rpn v1 groups. + :param project_id: Filter rpn v1 groups by project ID. + :return: :class:`List[RpnGroup] ` + + Usage: + :: + + result = await api.list_rpn_groups_all() + """ + + return await fetch_all_pages_async( + type=ListRpnGroupsResponse, + key="rpn_groups", + fetcher=self.list_rpn_groups, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def get_rpn_group( + self, + *, + group_id: int, + ) -> RpnGroup: + """ + :param group_id: Rpn v1 group ID. + :return: :class:`RpnGroup ` + + Usage: + :: + + result = await api.get_rpn_group( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpnv1/groups/{param_group_id}", + ) + + self._throw_on_error(res) + return unmarshal_RpnGroup(res.json()) + + async def create_rpn_group( + self, + *, + name: str, + server_ids: Optional[List[int]] = None, + san_server_ids: Optional[List[int]] = None, + project_id: Optional[str] = None, + ) -> RpnGroup: + """ + :param name: Rpn v1 group name. + :param server_ids: A collection of rpn v1 capable servers. + :param san_server_ids: A collection of rpn v1 capable rpn sans servers. + :param project_id: A project ID. + :return: :class:`RpnGroup ` + + Usage: + :: + + result = await api.create_rpn_group( + name="example", + ) + """ + + res = self._request( + "POST", + "/dedibox/v1/rpnv1/groups", + body=marshal_RpnV1ApiCreateRpnGroupRequest( + RpnV1ApiCreateRpnGroupRequest( + name=name, + server_ids=server_ids, + san_server_ids=san_server_ids, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnGroup(res.json()) + + async def delete_rpn_group( + self, + *, + group_id: int, + ) -> None: + """ + :param group_id: Rpn v1 group ID. + + Usage: + :: + + result = await api.delete_rpn_group( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpnv1/groups/{param_group_id}", + ) + + self._throw_on_error(res) + + async def update_rpn_group_name( + self, + *, + group_id: int, + name: Optional[str] = None, + ) -> RpnGroup: + """ + :param group_id: Rpn v1 group ID. + :param name: New rpn v1 group name. + :return: :class:`RpnGroup ` + + Usage: + :: + + result = await api.update_rpn_group_name( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/rpnv1/groups/{param_group_id}", + body=marshal_RpnV1ApiUpdateRpnGroupNameRequest( + RpnV1ApiUpdateRpnGroupNameRequest( + group_id=group_id, + name=name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnGroup(res.json()) + + async def list_rpn_group_members( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnGroupMembersRequestOrderBy] = None, + group_id: int, + project_id: Optional[str] = None, + ) -> ListRpnGroupMembersResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v1 group members per page. + :param order_by: Order of the rpn v1 group members. + :param group_id: Filter rpn v1 group members by group ID. + :param project_id: A project ID. + :return: :class:`ListRpnGroupMembersResponse ` + + Usage: + :: + + result = await api.list_rpn_group_members( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpnv1/groups/{param_group_id}/members", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnGroupMembersResponse(res.json()) + + async def list_rpn_group_members_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnGroupMembersRequestOrderBy] = None, + group_id: int, + project_id: Optional[str] = None, + ) -> List[RpnGroupMember]: + """ + :param page: Page number. + :param page_size: Number of rpn v1 group members per page. + :param order_by: Order of the rpn v1 group members. + :param group_id: Filter rpn v1 group members by group ID. + :param project_id: A project ID. + :return: :class:`List[RpnGroupMember] ` + + Usage: + :: + + result = await api.list_rpn_group_members_all( + group_id=1, + ) + """ + + return await fetch_all_pages_async( + type=ListRpnGroupMembersResponse, + key="members", + fetcher=self.list_rpn_group_members, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "group_id": group_id, + "project_id": project_id, + }, + ) + + async def rpn_group_invite( + self, + *, + group_id: int, + server_ids: List[int], + project_id: Optional[str] = None, + ) -> None: + """ + :param group_id: The RPN V1 group ID. + :param server_ids: A collection of external server IDs. + :param project_id: A project ID. + + Usage: + :: + + result = await api.rpn_group_invite( + group_id=1, + server_ids=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv1/groups/{param_group_id}/invite", + body=marshal_RpnV1ApiRpnGroupInviteRequest( + RpnV1ApiRpnGroupInviteRequest( + group_id=group_id, + server_ids=server_ids, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def leave_rpn_group( + self, + *, + group_id: int, + member_ids: List[int], + project_id: Optional[str] = None, + ) -> None: + """ + :param group_id: The RPN V1 group ID. + :param member_ids: A collection of rpn v1 group members IDs. + :param project_id: A project ID. + + Usage: + :: + + result = await api.leave_rpn_group( + group_id=1, + member_ids=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv1/groups/{param_group_id}/leave", + body=marshal_RpnV1ApiLeaveRpnGroupRequest( + RpnV1ApiLeaveRpnGroupRequest( + group_id=group_id, + member_ids=member_ids, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def add_rpn_group_members( + self, + *, + group_id: int, + server_ids: Optional[List[int]] = None, + san_server_ids: Optional[List[int]] = None, + ) -> RpnGroup: + """ + :param group_id: The rpn v1 group ID. + :param server_ids: A collection of rpn v1 capable server IDs. + :param san_server_ids: A collection of rpn v1 capable RPN SAN server IDs. + :return: :class:`RpnGroup ` + + Usage: + :: + + result = await api.add_rpn_group_members( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv1/groups/{param_group_id}/members", + body=marshal_RpnV1ApiAddRpnGroupMembersRequest( + RpnV1ApiAddRpnGroupMembersRequest( + group_id=group_id, + server_ids=server_ids, + san_server_ids=san_server_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnGroup(res.json()) + + async def delete_rpn_group_members( + self, + *, + group_id: int, + member_ids: List[int], + ) -> RpnGroup: + """ + :param group_id: The rpn v1 group ID. + :param member_ids: A collection of rpn v1 group members IDs. + :return: :class:`RpnGroup ` + + Usage: + :: + + result = await api.delete_rpn_group_members( + group_id=1, + member_ids=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpnv1/groups/{param_group_id}/members", + body=marshal_RpnV1ApiDeleteRpnGroupMembersRequest( + RpnV1ApiDeleteRpnGroupMembersRequest( + group_id=group_id, + member_ids=member_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnGroup(res.json()) + + async def list_rpn_capable_servers( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnCapableServersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnCapableServersResponse: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`ListRpnCapableServersResponse ` + + Usage: + :: + + result = await api.list_rpn_capable_servers() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv1/capable-servers", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnCapableServersResponse(res.json()) + + async def list_rpn_capable_servers_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnCapableServersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[Server]: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`List[Server] ` + + Usage: + :: + + result = await api.list_rpn_capable_servers_all() + """ + + return await fetch_all_pages_async( + type=ListRpnCapableServersResponse, + key="servers", + fetcher=self.list_rpn_capable_servers, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def list_rpn_capable_san_servers( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnCapableSanServersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnCapableSanServersResponse: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`ListRpnCapableSanServersResponse ` + + Usage: + :: + + result = await api.list_rpn_capable_san_servers() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv1/capable-san-servers", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnCapableSanServersResponse(res.json()) + + async def list_rpn_capable_san_servers_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnCapableSanServersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnSanServer]: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`List[RpnSanServer] ` + + Usage: + :: + + result = await api.list_rpn_capable_san_servers_all() + """ + + return await fetch_all_pages_async( + type=ListRpnCapableSanServersResponse, + key="san_servers", + fetcher=self.list_rpn_capable_san_servers, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def list_rpn_invites( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnInvitesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnInvitesResponse: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`ListRpnInvitesResponse ` + + Usage: + :: + + result = await api.list_rpn_invites() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv1/invites", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnInvitesResponse(res.json()) + + async def list_rpn_invites_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnInvitesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnGroupMember]: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`List[RpnGroupMember] ` + + Usage: + :: + + result = await api.list_rpn_invites_all() + """ + + return await fetch_all_pages_async( + type=ListRpnInvitesResponse, + key="members", + fetcher=self.list_rpn_invites, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def accept_rpn_invite( + self, + *, + member_id: int, + ) -> None: + """ + :param member_id: The member ID. + + Usage: + :: + + result = await api.accept_rpn_invite( + member_id=1, + ) + """ + + param_member_id = validate_path_param("member_id", member_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv1/invites/{param_member_id}/accept", + ) + + self._throw_on_error(res) + + async def refuse_rpn_invite( + self, + *, + member_id: int, + ) -> None: + """ + :param member_id: The member ID. + + Usage: + :: + + result = await api.refuse_rpn_invite( + member_id=1, + ) + """ + + param_member_id = validate_path_param("member_id", member_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv1/invites/{param_member_id}/refuse", + ) + + self._throw_on_error(res) + + +class DediboxV1RpnV2API(API): + """ + Dedibox Phoenix RPN v2 API. + """ + + async def list_rpn_v2_groups( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2GroupsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnV2GroupsResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v2 groups per page. + :param order_by: Order of the rpn v2 groups. + :param project_id: Filter rpn v2 groups by project ID. + :return: :class:`ListRpnV2GroupsResponse ` + + Usage: + :: + + result = await api.list_rpn_v2_groups() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv2/groups", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnV2GroupsResponse(res.json()) + + async def list_rpn_v2_groups_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2GroupsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnV2Group]: + """ + :param page: Page number. + :param page_size: Number of rpn v2 groups per page. + :param order_by: Order of the rpn v2 groups. + :param project_id: Filter rpn v2 groups by project ID. + :return: :class:`List[RpnV2Group] ` + + Usage: + :: + + result = await api.list_rpn_v2_groups_all() + """ + + return await fetch_all_pages_async( + type=ListRpnV2GroupsResponse, + key="rpn_groups", + fetcher=self.list_rpn_v2_groups, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def list_rpn_v2_members( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2MembersRequestOrderBy] = None, + group_id: int, + type_: Optional[ListRpnV2MembersRequestType] = None, + ) -> ListRpnV2MembersResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v2 group members per page. + :param order_by: Order of the rpn v2 group members. + :param group_id: RPN V2 group ID. + :param type_: Filter members by type. + :return: :class:`ListRpnV2MembersResponse ` + + Usage: + :: + + result = await api.list_rpn_v2_members( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/members", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "type": type_, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnV2MembersResponse(res.json()) + + async def list_rpn_v2_members_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2MembersRequestOrderBy] = None, + group_id: int, + type_: Optional[ListRpnV2MembersRequestType] = None, + ) -> List[RpnV2Member]: + """ + :param page: Page number. + :param page_size: Number of rpn v2 group members per page. + :param order_by: Order of the rpn v2 group members. + :param group_id: RPN V2 group ID. + :param type_: Filter members by type. + :return: :class:`List[RpnV2Member] ` + + Usage: + :: + + result = await api.list_rpn_v2_members_all( + group_id=1, + ) + """ + + return await fetch_all_pages_async( + type=ListRpnV2MembersResponse, + key="members", + fetcher=self.list_rpn_v2_members, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "group_id": group_id, + "type_": type_, + }, + ) + + async def get_rpn_v2_group( + self, + *, + group_id: int, + ) -> RpnV2Group: + """ + :param group_id: RPN V2 group ID. + :return: :class:`RpnV2Group ` + + Usage: + :: + + result = await api.get_rpn_v2_group( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpnv2/groups/{param_group_id}", + ) + + self._throw_on_error(res) + return unmarshal_RpnV2Group(res.json()) + + async def wait_for_rpn_v2_group( + self, + *, + group_id: int, + options: Optional[ + WaitForOptions[RpnV2Group, Union[bool, Awaitable[bool]]] + ] = None, + ) -> RpnV2Group: + """ + :param group_id: RPN V2 group ID. + :return: :class:`RpnV2Group ` + + Usage: + :: + + result = await api.get_rpn_v2_group( + group_id=1, + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in RPN_V2_GROUP_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_rpn_v2_group, + options=options, + args={ + "group_id": group_id, + }, + ) + + async def create_rpn_v2_group( + self, + *, + name: str, + servers: List[int], + project_id: Optional[str] = None, + type_: Optional[RpnV2GroupType] = None, + ) -> RpnV2Group: + """ + :param name: RPN V2 group name. + :param servers: A collection of server IDs. + :param project_id: Project ID of the RPN V2 group. + :param type_: RPN V2 group type (qing / standard). + :return: :class:`RpnV2Group ` + + Usage: + :: + + result = await api.create_rpn_v2_group( + name="example", + servers=[], + ) + """ + + res = self._request( + "POST", + "/dedibox/v1/rpnv2/groups", + body=marshal_RpnV2ApiCreateRpnV2GroupRequest( + RpnV2ApiCreateRpnV2GroupRequest( + name=name, + servers=servers, + project_id=project_id, + type_=type_, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnV2Group(res.json()) + + async def delete_rpn_v2_group( + self, + *, + group_id: int, + ) -> None: + """ + :param group_id: RPN V2 group ID. + + Usage: + :: + + result = await api.delete_rpn_v2_group( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpnv2/groups/{param_group_id}", + ) + + self._throw_on_error(res) + + async def update_rpn_v2_group_name( + self, + *, + group_id: int, + name: Optional[str] = None, + ) -> RpnV2Group: + """ + :param group_id: RPN V2 group ID. + :param name: RPN V2 group name. + :return: :class:`RpnV2Group ` + + Usage: + :: + + result = await api.update_rpn_v2_group_name( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/rpnv2/groups/{param_group_id}", + body=marshal_RpnV2ApiUpdateRpnV2GroupNameRequest( + RpnV2ApiUpdateRpnV2GroupNameRequest( + group_id=group_id, + name=name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnV2Group(res.json()) + + async def add_rpn_v2_members( + self, + *, + group_id: int, + servers: List[int], + ) -> None: + """ + :param group_id: RPN V2 group ID. + :param servers: A collection of server IDs. + + Usage: + :: + + result = await api.add_rpn_v2_members( + group_id=1, + servers=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/members", + body=marshal_RpnV2ApiAddRpnV2MembersRequest( + RpnV2ApiAddRpnV2MembersRequest( + group_id=group_id, + servers=servers, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def delete_rpn_v2_members( + self, + *, + group_id: int, + member_ids: List[int], + ) -> None: + """ + :param group_id: RPN V2 group ID. + :param member_ids: A collection of member IDs. + + Usage: + :: + + result = await api.delete_rpn_v2_members( + group_id=1, + member_ids=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/members", + body=marshal_RpnV2ApiDeleteRpnV2MembersRequest( + RpnV2ApiDeleteRpnV2MembersRequest( + group_id=group_id, + member_ids=member_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def list_rpn_v2_capable_resources( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2CapableResourcesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnV2CapableResourcesResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v2 capable resources per page. + :param order_by: Order of the rpn v2 capable resources. + :param project_id: Filter rpn v2 capable resources by project ID. + :return: :class:`ListRpnV2CapableResourcesResponse ` + + Usage: + :: + + result = await api.list_rpn_v2_capable_resources() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv2/groups/capable", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnV2CapableResourcesResponse(res.json()) + + async def list_rpn_v2_capable_resources_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2CapableResourcesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[Server]: + """ + :param page: Page number. + :param page_size: Number of rpn v2 capable resources per page. + :param order_by: Order of the rpn v2 capable resources. + :param project_id: Filter rpn v2 capable resources by project ID. + :return: :class:`List[Server] ` + + Usage: + :: + + result = await api.list_rpn_v2_capable_resources_all() + """ + + return await fetch_all_pages_async( + type=ListRpnV2CapableResourcesResponse, + key="servers", + fetcher=self.list_rpn_v2_capable_resources, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + async def list_rpn_v2_group_logs( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2GroupLogsRequestOrderBy] = None, + group_id: int, + ) -> ListRpnV2GroupLogsResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v2 group logs per page. + :param order_by: Order of the rpn v2 group logs. + :param group_id: RPN V2 group ID. + :return: :class:`ListRpnV2GroupLogsResponse ` + + Usage: + :: + + result = await api.list_rpn_v2_group_logs( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/logs", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnV2GroupLogsResponse(res.json()) + + async def list_rpn_v2_group_logs_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2GroupLogsRequestOrderBy] = None, + group_id: int, + ) -> List[Log]: + """ + :param page: Page number. + :param page_size: Number of rpn v2 group logs per page. + :param order_by: Order of the rpn v2 group logs. + :param group_id: RPN V2 group ID. + :return: :class:`List[Log] ` + + Usage: + :: + + result = await api.list_rpn_v2_group_logs_all( + group_id=1, + ) + """ + + return await fetch_all_pages_async( + type=ListRpnV2GroupLogsResponse, + key="logs", + fetcher=self.list_rpn_v2_group_logs, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "group_id": group_id, + }, + ) + + async def update_rpn_v2_vlan_for_members( + self, + *, + group_id: int, + member_ids: List[int], + vlan: Optional[int] = None, + ) -> None: + """ + :param group_id: RPN V2 group ID. + :param member_ids: RPN V2 member IDs. + :param vlan: Min: 0. + Max: 3967. + + Usage: + :: + + result = await api.update_rpn_v2_vlan_for_members( + group_id=1, + member_ids=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/vlan", + body=marshal_RpnV2ApiUpdateRpnV2VlanForMembersRequest( + RpnV2ApiUpdateRpnV2VlanForMembersRequest( + group_id=group_id, + member_ids=member_ids, + vlan=vlan, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def enable_rpn_v2_group_compatibility( + self, + *, + group_id: int, + rpnv1_group_id: int, + ) -> None: + """ + :param group_id: RPN V2 group ID. + :param rpnv1_group_id: RPN V1 group ID. + + Usage: + :: + + result = await api.enable_rpn_v2_group_compatibility( + group_id=1, + rpnv1_group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/enable-compatibility", + body=marshal_RpnV2ApiEnableRpnV2GroupCompatibilityRequest( + RpnV2ApiEnableRpnV2GroupCompatibilityRequest( + group_id=group_id, + rpnv1_group_id=rpnv1_group_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def disable_rpn_v2_group_compatibility( + self, + *, + group_id: int, + ) -> None: + """ + :param group_id: RPN V2 group ID. + + Usage: + :: + + result = await api.disable_rpn_v2_group_compatibility( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/disable-compatibility", + body={}, + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/dedibox/v1/content.py b/scaleway-async/scaleway_async/dedibox/v1/content.py new file mode 100644 index 00000000..44306732 --- /dev/null +++ b/scaleway-async/scaleway_async/dedibox/v1/content.py @@ -0,0 +1,86 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + BMCAccessStatus, + IPv6BlockDelegationStatus, + RpnGroupMemberStatus, + RpnSanStatus, + RpnV2GroupStatus, + RpnV2MemberStatus, + ServerInstallStatus, + ServerStatus, + ServiceProvisioningStatus, +) + +BMC_ACCESS_TRANSIENT_STATUSES: List[BMCAccessStatus] = [ + BMCAccessStatus.CREATING, + BMCAccessStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`BMCAccessStatus `. +""" +I_PV6_BLOCK_DELEGATION_TRANSIENT_STATUSES: List[IPv6BlockDelegationStatus] = [ + IPv6BlockDelegationStatus.UPDATING, +] +""" +Lists transient statutes of the enum :class:`IPv6BlockDelegationStatus `. +""" +RPN_GROUP_MEMBER_TRANSIENT_STATUSES: List[RpnGroupMemberStatus] = [ + RpnGroupMemberStatus.CREATING, + RpnGroupMemberStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`RpnGroupMemberStatus `. +""" +RPN_SAN_TRANSIENT_STATUSES: List[RpnSanStatus] = [ + RpnSanStatus.CREATING, + RpnSanStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`RpnSanStatus `. +""" +RPN_V2_GROUP_TRANSIENT_STATUSES: List[RpnV2GroupStatus] = [ + RpnV2GroupStatus.CREATING, + RpnV2GroupStatus.UPDATING, + RpnV2GroupStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`RpnV2GroupStatus `. +""" +RPN_V2_MEMBER_TRANSIENT_STATUSES: List[RpnV2MemberStatus] = [ + RpnV2MemberStatus.CREATING, + RpnV2MemberStatus.UPDATING, + RpnV2MemberStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`RpnV2MemberStatus `. +""" +SERVER_INSTALL_TRANSIENT_STATUSES: List[ServerInstallStatus] = [ + ServerInstallStatus.BOOTING, + ServerInstallStatus.SETTING_UP_RAID, + ServerInstallStatus.PARTITIONING, + ServerInstallStatus.FORMATTING, + ServerInstallStatus.INSTALLING, + ServerInstallStatus.CONFIGURING, + ServerInstallStatus.CONFIGURING_BOOTLOADER, + ServerInstallStatus.REBOOTING, +] +""" +Lists transient statutes of the enum :class:`ServerInstallStatus `. +""" +SERVER_TRANSIENT_STATUSES: List[ServerStatus] = [ + ServerStatus.DELIVERING, + ServerStatus.INSTALLING, +] +""" +Lists transient statutes of the enum :class:`ServerStatus `. +""" +SERVICE_PROVISIONING_TRANSIENT_STATUSES: List[ServiceProvisioningStatus] = [ + ServiceProvisioningStatus.DELIVERING, + ServiceProvisioningStatus.EXPIRING, +] +""" +Lists transient statutes of the enum :class:`ServiceProvisioningStatus `. +""" diff --git a/scaleway-async/scaleway_async/dedibox/v1/marshalling.py b/scaleway-async/scaleway_async/dedibox/v1/marshalling.py new file mode 100644 index 00000000..8bdd9b9b --- /dev/null +++ b/scaleway-async/scaleway_async/dedibox/v1/marshalling.py @@ -0,0 +1,3725 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from .types import ( + OfferServerInfoStock, + PartitionFileSystem, + IP, + CPU, + Disk, + Memory, + PersistentMemory, + RaidController, + OfferAntiDosInfo, + OfferBackupInfo, + OfferBandwidthInfo, + OfferFailoverBlockInfo, + OfferFailoverIpInfo, + OfferLicenseInfo, + OfferRPNInfo, + OfferSANInfo, + OfferServerInfo, + OfferServiceLevelInfo, + OfferStorageInfo, + Offer, + OS, + RpnSan, + RpnGroup, + NetworkInterface, + ServerLocation, + ServerOption, + ServiceLevel, + Server, + RpnV2GroupSubnet, + RpnV2Group, + Service, + FailoverBlock, + FailoverIP, + BMCAccess, + Backup, + CanOrderResponse, + CreateFailoverIPsResponse, + GetIPv6BlockQuotasResponseQuota, + GetIPv6BlockQuotasResponse, + GetRemainingQuotaResponse, + GetRpnStatusResponse, + IPv6Block, + Invoice, + ListFailoverIPsResponse, + ListIPv6BlockSubnetsAvailableResponseSubnet, + ListIPv6BlockSubnetsAvailableResponse, + InvoiceSummary, + ListInvoicesResponse, + RpnSanIpRpnV2Group, + RpnSanIpServer, + RpnSanIp, + ListIpsResponse, + ListOSResponse, + ListOffersResponse, + RefundSummary, + ListRefundsResponse, + RpnSanServer, + ListRpnCapableSanServersResponse, + ListRpnCapableServersResponse, + RpnGroupMember, + ListRpnGroupMembersResponse, + ListRpnGroupsResponse, + ListRpnInvitesResponse, + RpnSanSummary, + ListRpnSansResponse, + RpnServerCapability, + ListRpnServerCapabilitiesResponse, + ListRpnV2CapableResourcesResponse, + RpnV2Member, + Log, + ListRpnV2GroupLogsResponse, + ListRpnV2GroupsResponse, + ListRpnV2MembersResponse, + ServerDisk, + ListServerDisksResponse, + ServerEvent, + ListServerEventsResponse, + ServerSummary, + ListServersResponse, + ListServicesResponse, + ListSubscribableServerOptionsResponse, + RaidArray, + Raid, + Refund, + Rescue, + Partition, + ServerDefaultPartitioning, + ServerInstall, + SubscribeStorageOptionsResponse, + AttachFailoverIPToMacAddressRequest, + AttachFailoverIPsRequest, + CreateFailoverIPsRequest, + CreateServerRequest, + DetachFailoverIPsRequest, + IPv6BlockApiCreateIPv6BlockRequest, + IPv6BlockApiCreateIPv6BlockSubnetRequest, + IPv6BlockApiUpdateIPv6BlockRequest, + InstallPartition, + InstallServerRequest, + RpnSanApiAddIpRequest, + RpnSanApiCreateRpnSanRequest, + RpnSanApiRemoveIpRequest, + RpnV1ApiAddRpnGroupMembersRequest, + RpnV1ApiCreateRpnGroupRequest, + RpnV1ApiDeleteRpnGroupMembersRequest, + RpnV1ApiLeaveRpnGroupRequest, + RpnV1ApiRpnGroupInviteRequest, + RpnV1ApiUpdateRpnGroupNameRequest, + RpnV2ApiAddRpnV2MembersRequest, + RpnV2ApiCreateRpnV2GroupRequest, + RpnV2ApiDeleteRpnV2MembersRequest, + RpnV2ApiEnableRpnV2GroupCompatibilityRequest, + RpnV2ApiUpdateRpnV2GroupNameRequest, + RpnV2ApiUpdateRpnV2VlanForMembersRequest, + StartBMCAccessRequest, + StartRescueRequest, + SubscribeServerOptionRequest, + SubscribeStorageOptionsRequest, + UpdatableRaidArray, + UpdateRaidRequest, + UpdateReverseRequest, + UpdateServerBackupRequest, + UpdateServerRequest, + UpdateServerTagsRequest, +) + + +def unmarshal_IP(data: Any) -> IP: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'IP' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("ip_id", None) + if field is not None: + args["ip_id"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("reverse", None) + if field is not None: + args["reverse"] = field + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + field = data.get("netmask", None) + if field is not None: + args["netmask"] = field + + field = data.get("semantic", None) + if field is not None: + args["semantic"] = field + + field = data.get("gateway", None) + if field is not None: + args["gateway"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + return IP(**args) + + +def unmarshal_CPU(data: Any) -> CPU: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CPU' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("core_count", None) + if field is not None: + args["core_count"] = field + + field = data.get("thread_count", None) + if field is not None: + args["thread_count"] = field + + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + + return CPU(**args) + + +def unmarshal_Disk(data: Any) -> Disk: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Disk' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return Disk(**args) + + +def unmarshal_Memory(data: Any) -> Memory: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Memory' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + + field = data.get("is_ecc", None) + if field is not None: + args["is_ecc"] = field + + return Memory(**args) + + +def unmarshal_PersistentMemory(data: Any) -> PersistentMemory: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PersistentMemory' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = field + + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + + field = data.get("model", None) + if field is not None: + args["model"] = field + + return PersistentMemory(**args) + + +def unmarshal_RaidController(data: Any) -> RaidController: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RaidController' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("model", None) + if field is not None: + args["model"] = field + + field = data.get("raid_level", None) + if field is not None: + args["raid_level"] = field + + return RaidController(**args) + + +def unmarshal_OfferAntiDosInfo(data: Any) -> OfferAntiDosInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferAntiDosInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return OfferAntiDosInfo(**args) + + +def unmarshal_OfferBackupInfo(data: Any) -> OfferBackupInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferBackupInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("size", None) + if field is not None: + args["size"] = field + + return OfferBackupInfo(**args) + + +def unmarshal_OfferBandwidthInfo(data: Any) -> OfferBandwidthInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferBandwidthInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("speed", None) + if field is not None: + args["speed"] = field + + return OfferBandwidthInfo(**args) + + +def unmarshal_OfferFailoverBlockInfo(data: Any) -> OfferFailoverBlockInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferFailoverBlockInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("onetime_fees", None) + if field is not None: + args["onetime_fees"] = unmarshal_Offer(field) + else: + args["onetime_fees"] = None + + return OfferFailoverBlockInfo(**args) + + +def unmarshal_OfferFailoverIpInfo(data: Any) -> OfferFailoverIpInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferFailoverIpInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("onetime_fees", None) + if field is not None: + args["onetime_fees"] = unmarshal_Offer(field) + else: + args["onetime_fees"] = None + + return OfferFailoverIpInfo(**args) + + +def unmarshal_OfferLicenseInfo(data: Any) -> OfferLicenseInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferLicenseInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bound_to_ip", None) + if field is not None: + args["bound_to_ip"] = field + + return OfferLicenseInfo(**args) + + +def unmarshal_OfferRPNInfo(data: Any) -> OfferRPNInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferRPNInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("speed", None) + if field is not None: + args["speed"] = field + + return OfferRPNInfo(**args) + + +def unmarshal_OfferSANInfo(data: Any) -> OfferSANInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferSANInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("ha", None) + if field is not None: + args["ha"] = field + + field = data.get("device_type", None) + if field is not None: + args["device_type"] = field + + return OfferSANInfo(**args) + + +def unmarshal_OfferServerInfo(data: Any) -> OfferServerInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferServerInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bandwidth", None) + if field is not None: + args["bandwidth"] = field + + field = data.get("stock", None) + if field is not None: + args["stock"] = field + + field = data.get("commercial_range", None) + if field is not None: + args["commercial_range"] = field + + field = data.get("disks", None) + if field is not None: + args["disks"] = ( + [unmarshal_Disk(v) for v in field] if field is not None else None + ) + + field = data.get("cpus", None) + if field is not None: + args["cpus"] = [unmarshal_CPU(v) for v in field] if field is not None else None + + field = data.get("memories", None) + if field is not None: + args["memories"] = ( + [unmarshal_Memory(v) for v in field] if field is not None else None + ) + + field = data.get("persistent_memories", None) + if field is not None: + args["persistent_memories"] = ( + [unmarshal_PersistentMemory(v) for v in field] + if field is not None + else None + ) + + field = data.get("raid_controllers", None) + if field is not None: + args["raid_controllers"] = ( + [unmarshal_RaidController(v) for v in field] if field is not None else None + ) + + field = data.get("available_options", None) + if field is not None: + args["available_options"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + field = data.get("connectivity", None) + if field is not None: + args["connectivity"] = field + + field = data.get("stock_by_datacenter", None) + if field is not None: + args["stock_by_datacenter"] = ( + {key: OfferServerInfoStock(value) for key, value in field.items()} + if field is not None + else None + ) + + field = data.get("rpn_version", None) + if field is not None: + args["rpn_version"] = field + else: + args["rpn_version"] = None + + field = data.get("onetime_fees", None) + if field is not None: + args["onetime_fees"] = unmarshal_Offer(field) + else: + args["onetime_fees"] = None + + return OfferServerInfo(**args) + + +def unmarshal_OfferServiceLevelInfo(data: Any) -> OfferServiceLevelInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferServiceLevelInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("support_ticket", None) + if field is not None: + args["support_ticket"] = field + + field = data.get("support_phone", None) + if field is not None: + args["support_phone"] = field + + field = data.get("sales_support", None) + if field is not None: + args["sales_support"] = field + + field = data.get("git", None) + if field is not None: + args["git"] = field + + field = data.get("sla", None) + if field is not None: + args["sla"] = field + + field = data.get("priority_support", None) + if field is not None: + args["priority_support"] = field + + field = data.get("high_rpn_bandwidth", None) + if field is not None: + args["high_rpn_bandwidth"] = field + + field = data.get("customization", None) + if field is not None: + args["customization"] = field + + field = data.get("antidos", None) + if field is not None: + args["antidos"] = field + + field = data.get("extra_failover_quota", None) + if field is not None: + args["extra_failover_quota"] = field + + field = data.get("available_options", None) + if field is not None: + args["available_options"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return OfferServiceLevelInfo(**args) + + +def unmarshal_OfferStorageInfo(data: Any) -> OfferStorageInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferStorageInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("max_quota", None) + if field is not None: + args["max_quota"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + return OfferStorageInfo(**args) + + +def unmarshal_Offer(data: Any) -> Offer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Offer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("catalog", None) + if field is not None: + args["catalog"] = field + + field = data.get("payment_frequency", None) + if field is not None: + args["payment_frequency"] = field + + field = data.get("pricing", None) + if field is not None: + args["pricing"] = unmarshal_Money(field) + else: + args["pricing"] = None + + field = data.get("server_info", None) + if field is not None: + args["server_info"] = unmarshal_OfferServerInfo(field) + else: + args["server_info"] = None + + field = data.get("service_level_info", None) + if field is not None: + args["service_level_info"] = unmarshal_OfferServiceLevelInfo(field) + else: + args["service_level_info"] = None + + field = data.get("rpn_info", None) + if field is not None: + args["rpn_info"] = unmarshal_OfferRPNInfo(field) + else: + args["rpn_info"] = None + + field = data.get("san_info", None) + if field is not None: + args["san_info"] = unmarshal_OfferSANInfo(field) + else: + args["san_info"] = None + + field = data.get("antidos_info", None) + if field is not None: + args["antidos_info"] = unmarshal_OfferAntiDosInfo(field) + else: + args["antidos_info"] = None + + field = data.get("backup_info", None) + if field is not None: + args["backup_info"] = unmarshal_OfferBackupInfo(field) + else: + args["backup_info"] = None + + field = data.get("usb_storage_info", None) + if field is not None: + args["usb_storage_info"] = unmarshal_OfferStorageInfo(field) + else: + args["usb_storage_info"] = None + + field = data.get("storage_info", None) + if field is not None: + args["storage_info"] = unmarshal_OfferStorageInfo(field) + else: + args["storage_info"] = None + + field = data.get("license_info", None) + if field is not None: + args["license_info"] = unmarshal_OfferLicenseInfo(field) + else: + args["license_info"] = None + + field = data.get("failover_ip_info", None) + if field is not None: + args["failover_ip_info"] = unmarshal_OfferFailoverIpInfo(field) + else: + args["failover_ip_info"] = None + + field = data.get("failover_block_info", None) + if field is not None: + args["failover_block_info"] = unmarshal_OfferFailoverBlockInfo(field) + else: + args["failover_block_info"] = None + + field = data.get("bandwidth_info", None) + if field is not None: + args["bandwidth_info"] = unmarshal_OfferBandwidthInfo(field) + else: + args["bandwidth_info"] = None + + return Offer(**args) + + +def unmarshal_OS(data: Any) -> OS: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OS' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("arch", None) + if field is not None: + args["arch"] = field + + field = data.get("allow_custom_partitioning", None) + if field is not None: + args["allow_custom_partitioning"] = field + + field = data.get("allow_ssh_keys", None) + if field is not None: + args["allow_ssh_keys"] = field + + field = data.get("requires_user", None) + if field is not None: + args["requires_user"] = field + + field = data.get("requires_admin_password", None) + if field is not None: + args["requires_admin_password"] = field + + field = data.get("requires_panel_password", None) + if field is not None: + args["requires_panel_password"] = field + + field = data.get("allowed_filesystems", None) + if field is not None: + args["allowed_filesystems"] = ( + [PartitionFileSystem(v) for v in field] if field is not None else None + ) + + field = data.get("requires_license", None) + if field is not None: + args["requires_license"] = field + + field = data.get("license_offers", None) + if field is not None: + args["license_offers"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + field = data.get("display_name", None) + if field is not None: + args["display_name"] = field + + field = data.get("password_regex", None) + if field is not None: + args["password_regex"] = field + + field = data.get("hostname_max_length", None) + if field is not None: + args["hostname_max_length"] = field + + field = data.get("max_partitions", None) + if field is not None: + args["max_partitions"] = field + else: + args["max_partitions"] = None + + field = data.get("panel_password_regex", None) + if field is not None: + args["panel_password_regex"] = field + else: + args["panel_password_regex"] = None + + field = data.get("requires_valid_hostname", None) + if field is not None: + args["requires_valid_hostname"] = field + else: + args["requires_valid_hostname"] = None + + field = data.get("hostname_regex", None) + if field is not None: + args["hostname_regex"] = field + else: + args["hostname_regex"] = None + + field = data.get("released_at", None) + if field is not None: + args["released_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["released_at"] = None + + return OS(**args) + + +def unmarshal_RpnSan(data: Any) -> RpnSan: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSan' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("server_hostname", None) + if field is not None: + args["server_hostname"] = field + + field = data.get("iqn_suffix", None) + if field is not None: + args["iqn_suffix"] = field + + field = data.get("offer_id", None) + if field is not None: + args["offer_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("storage_size", None) + if field is not None: + args["storage_size"] = field + + field = data.get("iqn", None) + if field is not None: + args["iqn"] = field + + field = data.get("rpnv1_compatible", None) + if field is not None: + args["rpnv1_compatible"] = field + + field = data.get("rpnv1_implicit", None) + if field is not None: + args["rpnv1_implicit"] = field + + field = data.get("offer", None) + if field is not None: + args["offer"] = unmarshal_Offer(field) + else: + args["offer"] = None + + field = data.get("delivered_at", None) + if field is not None: + args["delivered_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["delivered_at"] = None + + field = data.get("terminated_at", None) + if field is not None: + args["terminated_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["terminated_at"] = None + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + return RpnSan(**args) + + +def unmarshal_RpnGroup(data: Any) -> RpnGroup: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnGroup' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("active", None) + if field is not None: + args["active"] = field + + field = data.get("owner", None) + if field is not None: + args["owner"] = field + + field = data.get("members_count", None) + if field is not None: + args["members_count"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + return RpnGroup(**args) + + +def unmarshal_NetworkInterface(data: Any) -> NetworkInterface: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NetworkInterface' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("card_id", None) + if field is not None: + args["card_id"] = field + + field = data.get("device_id", None) + if field is not None: + args["device_id"] = field + + field = data.get("mac", None) + if field is not None: + args["mac"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("ips", None) + if field is not None: + args["ips"] = [unmarshal_IP(v) for v in field] if field is not None else None + + return NetworkInterface(**args) + + +def unmarshal_ServerLocation(data: Any) -> ServerLocation: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerLocation' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rack", None) + if field is not None: + args["rack"] = field + + field = data.get("room", None) + if field is not None: + args["room"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + return ServerLocation(**args) + + +def unmarshal_ServerOption(data: Any) -> ServerOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("options", None) + if field is not None: + args["options"] = ( + [unmarshal_ServerOption(v) for v in field] if field is not None else None + ) + + field = data.get("offer", None) + if field is not None: + args["offer"] = unmarshal_Offer(field) + else: + args["offer"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("expired_at", None) + if field is not None: + args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None + + return ServerOption(**args) + + +def unmarshal_ServiceLevel(data: Any) -> ServiceLevel: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServiceLevel' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("offer_id", None) + if field is not None: + args["offer_id"] = field + + field = data.get("level", None) + if field is not None: + args["level"] = field + + return ServiceLevel(**args) + + +def unmarshal_Server(data: Any) -> Server: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Server' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("rebooted_at", None) + if field is not None: + args["rebooted_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["rebooted_at"] = None + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("abuse_contact", None) + if field is not None: + args["abuse_contact"] = field + + field = data.get("interfaces", None) + if field is not None: + args["interfaces"] = ( + [unmarshal_NetworkInterface(v) for v in field] + if field is not None + else None + ) + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("options", None) + if field is not None: + args["options"] = ( + [unmarshal_ServerOption(v) for v in field] if field is not None else None + ) + + field = data.get("has_bmc", None) + if field is not None: + args["has_bmc"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("is_outsourced", None) + if field is not None: + args["is_outsourced"] = field + + field = data.get("ipv6_slaac", None) + if field is not None: + args["ipv6_slaac"] = field + + field = data.get("qinq", None) + if field is not None: + args["qinq"] = field + + field = data.get("is_rpnv2_member", None) + if field is not None: + args["is_rpnv2_member"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("expired_at", None) + if field is not None: + args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None + + field = data.get("offer", None) + if field is not None: + args["offer"] = unmarshal_Offer(field) + else: + args["offer"] = None + + field = data.get("location", None) + if field is not None: + args["location"] = unmarshal_ServerLocation(field) + else: + args["location"] = None + + field = data.get("os", None) + if field is not None: + args["os"] = unmarshal_OS(field) + else: + args["os"] = None + + field = data.get("level", None) + if field is not None: + args["level"] = unmarshal_ServiceLevel(field) + else: + args["level"] = None + + field = data.get("rescue_os", None) + if field is not None: + args["rescue_os"] = unmarshal_OS(field) + else: + args["rescue_os"] = None + + return Server(**args) + + +def unmarshal_RpnV2GroupSubnet(data: Any) -> RpnV2GroupSubnet: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnV2GroupSubnet' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + return RpnV2GroupSubnet(**args) + + +def unmarshal_RpnV2Group(data: Any) -> RpnV2Group: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnV2Group' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("compatible_rpnv1", None) + if field is not None: + args["compatible_rpnv1"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("owner", None) + if field is not None: + args["owner"] = field + + field = data.get("members_count", None) + if field is not None: + args["members_count"] = field + + field = data.get("gateway", None) + if field is not None: + args["gateway"] = field + + field = data.get("subnet", None) + if field is not None: + args["subnet"] = unmarshal_RpnV2GroupSubnet(field) + else: + args["subnet"] = None + + field = data.get("rpnv1_group", None) + if field is not None: + args["rpnv1_group"] = unmarshal_RpnGroup(field) + else: + args["rpnv1_group"] = None + + return RpnV2Group(**args) + + +def unmarshal_Service(data: Any) -> Service: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Service' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("provisioning_status", None) + if field is not None: + args["provisioning_status"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("resource_id", None) + if field is not None: + args["resource_id"] = field + else: + args["resource_id"] = None + + field = data.get("offer", None) + if field is not None: + args["offer"] = unmarshal_Offer(field) + else: + args["offer"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("delivered_at", None) + if field is not None: + args["delivered_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["delivered_at"] = None + + field = data.get("terminated_at", None) + if field is not None: + args["terminated_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["terminated_at"] = None + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + return Service(**args) + + +def unmarshal_FailoverBlock(data: Any) -> FailoverBlock: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'FailoverBlock' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("nameservers", None) + if field is not None: + args["nameservers"] = field + + field = data.get("ip_version", None) + if field is not None: + args["ip_version"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + field = data.get("netmask", None) + if field is not None: + args["netmask"] = field + + field = data.get("gateway_ip", None) + if field is not None: + args["gateway_ip"] = field + + return FailoverBlock(**args) + + +def unmarshal_FailoverIP(data: Any) -> FailoverIP: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'FailoverIP' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("reverse", None) + if field is not None: + args["reverse"] = field + + field = data.get("ip_version", None) + if field is not None: + args["ip_version"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + field = data.get("netmask", None) + if field is not None: + args["netmask"] = field + + field = data.get("gateway_ip", None) + if field is not None: + args["gateway_ip"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("mac", None) + if field is not None: + args["mac"] = field + else: + args["mac"] = None + + field = data.get("server_id", None) + if field is not None: + args["server_id"] = field + else: + args["server_id"] = None + + field = data.get("block", None) + if field is not None: + args["block"] = unmarshal_FailoverBlock(field) + else: + args["block"] = None + + field = data.get("server_zone", None) + if field is not None: + args["server_zone"] = field + else: + args["server_zone"] = None + + return FailoverIP(**args) + + +def unmarshal_BMCAccess(data: Any) -> BMCAccess: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BMCAccess' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("url", None) + if field is not None: + args["url"] = field + + field = data.get("login", None) + if field is not None: + args["login"] = field + + field = data.get("password", None) + if field is not None: + args["password"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + return BMCAccess(**args) + + +def unmarshal_Backup(data: Any) -> Backup: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Backup' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("login", None) + if field is not None: + args["login"] = field + + field = data.get("server", None) + if field is not None: + args["server"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("acl_enabled", None) + if field is not None: + args["acl_enabled"] = field + + field = data.get("autologin", None) + if field is not None: + args["autologin"] = field + + field = data.get("quota_space", None) + if field is not None: + args["quota_space"] = field + + field = data.get("quota_space_used", None) + if field is not None: + args["quota_space_used"] = field + + field = data.get("quota_files", None) + if field is not None: + args["quota_files"] = field + + field = data.get("quota_files_used", None) + if field is not None: + args["quota_files_used"] = field + + return Backup(**args) + + +def unmarshal_CanOrderResponse(data: Any) -> CanOrderResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CanOrderResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("can_order", None) + if field is not None: + args["can_order"] = field + + field = data.get("quota_ok", None) + if field is not None: + args["quota_ok"] = field + + field = data.get("phone_confirmed", None) + if field is not None: + args["phone_confirmed"] = field + + field = data.get("email_confirmed", None) + if field is not None: + args["email_confirmed"] = field + + field = data.get("user_confirmed", None) + if field is not None: + args["user_confirmed"] = field + + field = data.get("payment_mode", None) + if field is not None: + args["payment_mode"] = field + + field = data.get("billing_ok", None) + if field is not None: + args["billing_ok"] = field + + field = data.get("message", None) + if field is not None: + args["message"] = field + else: + args["message"] = None + + return CanOrderResponse(**args) + + +def unmarshal_CreateFailoverIPsResponse(data: Any) -> CreateFailoverIPsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CreateFailoverIPsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("services", None) + if field is not None: + args["services"] = ( + [unmarshal_Service(v) for v in field] if field is not None else None + ) + + return CreateFailoverIPsResponse(**args) + + +def unmarshal_GetIPv6BlockQuotasResponseQuota( + data: Any, +) -> GetIPv6BlockQuotasResponseQuota: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetIPv6BlockQuotasResponseQuota' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("quota", None) + if field is not None: + args["quota"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + return GetIPv6BlockQuotasResponseQuota(**args) + + +def unmarshal_GetIPv6BlockQuotasResponse(data: Any) -> GetIPv6BlockQuotasResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetIPv6BlockQuotasResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("quotas", None) + if field is not None: + args["quotas"] = ( + [unmarshal_GetIPv6BlockQuotasResponseQuota(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return GetIPv6BlockQuotasResponse(**args) + + +def unmarshal_GetRemainingQuotaResponse(data: Any) -> GetRemainingQuotaResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetRemainingQuotaResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("failover_ip_quota", None) + if field is not None: + args["failover_ip_quota"] = field + + field = data.get("failover_ip_remaining_quota", None) + if field is not None: + args["failover_ip_remaining_quota"] = field + + field = data.get("failover_block_quota", None) + if field is not None: + args["failover_block_quota"] = field + + field = data.get("failover_block_remaining_quota", None) + if field is not None: + args["failover_block_remaining_quota"] = field + + return GetRemainingQuotaResponse(**args) + + +def unmarshal_GetRpnStatusResponse(data: Any) -> GetRpnStatusResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetRpnStatusResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("operations_left", None) + if field is not None: + args["operations_left"] = field + else: + args["operations_left"] = None + + return GetRpnStatusResponse(**args) + + +def unmarshal_IPv6Block(data: Any) -> IPv6Block: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'IPv6Block' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("duid", None) + if field is not None: + args["duid"] = field + + field = data.get("nameservers", None) + if field is not None: + args["nameservers"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + field = data.get("subnets", None) + if field is not None: + args["subnets"] = ( + [unmarshal_IPv6Block(v) for v in field] if field is not None else None + ) + + field = data.get("delegation_status", None) + if field is not None: + args["delegation_status"] = field + + return IPv6Block(**args) + + +def unmarshal_Invoice(data: Any) -> Invoice: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Invoice' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("payment_method", None) + if field is not None: + args["payment_method"] = field + + field = data.get("content", None) + if field is not None: + args["content"] = field + + field = data.get("transaction_id", None) + if field is not None: + args["transaction_id"] = field + + field = data.get("total_with_taxes", None) + if field is not None: + args["total_with_taxes"] = unmarshal_Money(field) + else: + args["total_with_taxes"] = None + + field = data.get("total_without_taxes", None) + if field is not None: + args["total_without_taxes"] = unmarshal_Money(field) + else: + args["total_without_taxes"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("paid_at", None) + if field is not None: + args["paid_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["paid_at"] = None + + return Invoice(**args) + + +def unmarshal_ListFailoverIPsResponse(data: Any) -> ListFailoverIPsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListFailoverIPsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("failover_ips", None) + if field is not None: + args["failover_ips"] = ( + [unmarshal_FailoverIP(v) for v in field] if field is not None else None + ) + + return ListFailoverIPsResponse(**args) + + +def unmarshal_ListIPv6BlockSubnetsAvailableResponseSubnet( + data: Any, +) -> ListIPv6BlockSubnetsAvailableResponseSubnet: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListIPv6BlockSubnetsAvailableResponseSubnet' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + return ListIPv6BlockSubnetsAvailableResponseSubnet(**args) + + +def unmarshal_ListIPv6BlockSubnetsAvailableResponse( + data: Any, +) -> ListIPv6BlockSubnetsAvailableResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListIPv6BlockSubnetsAvailableResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("subnet_availables", None) + if field is not None: + args["subnet_availables"] = ( + [unmarshal_ListIPv6BlockSubnetsAvailableResponseSubnet(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListIPv6BlockSubnetsAvailableResponse(**args) + + +def unmarshal_InvoiceSummary(data: Any) -> InvoiceSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InvoiceSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("payment_method", None) + if field is not None: + args["payment_method"] = field + + field = data.get("transaction_id", None) + if field is not None: + args["transaction_id"] = field + + field = data.get("total_with_taxes", None) + if field is not None: + args["total_with_taxes"] = unmarshal_Money(field) + else: + args["total_with_taxes"] = None + + field = data.get("total_without_taxes", None) + if field is not None: + args["total_without_taxes"] = unmarshal_Money(field) + else: + args["total_without_taxes"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("paid_at", None) + if field is not None: + args["paid_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["paid_at"] = None + + return InvoiceSummary(**args) + + +def unmarshal_ListInvoicesResponse(data: Any) -> ListInvoicesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInvoicesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("invoices", None) + if field is not None: + args["invoices"] = ( + [unmarshal_InvoiceSummary(v) for v in field] if field is not None else None + ) + + return ListInvoicesResponse(**args) + + +def unmarshal_RpnSanIpRpnV2Group(data: Any) -> RpnSanIpRpnV2Group: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSanIpRpnV2Group' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + return RpnSanIpRpnV2Group(**args) + + +def unmarshal_RpnSanIpServer(data: Any) -> RpnSanIpServer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSanIpServer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + return RpnSanIpServer(**args) + + +def unmarshal_RpnSanIp(data: Any) -> RpnSanIp: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSanIp' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("server", None) + if field is not None: + args["server"] = unmarshal_RpnSanIpServer(field) + else: + args["server"] = None + + field = data.get("rpnv2_group", None) + if field is not None: + args["rpnv2_group"] = unmarshal_RpnSanIpRpnV2Group(field) + else: + args["rpnv2_group"] = None + + field = data.get("ip", None) + if field is not None: + args["ip"] = unmarshal_IP(field) + else: + args["ip"] = None + + return RpnSanIp(**args) + + +def unmarshal_ListIpsResponse(data: Any) -> ListIpsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListIpsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("ips", None) + if field is not None: + args["ips"] = ( + [unmarshal_RpnSanIp(v) for v in field] if field is not None else None + ) + + return ListIpsResponse(**args) + + +def unmarshal_ListOSResponse(data: Any) -> ListOSResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOSResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("os", None) + if field is not None: + args["os"] = [unmarshal_OS(v) for v in field] if field is not None else None + + return ListOSResponse(**args) + + +def unmarshal_ListOffersResponse(data: Any) -> ListOffersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOffersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offers", None) + if field is not None: + args["offers"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return ListOffersResponse(**args) + + +def unmarshal_RefundSummary(data: Any) -> RefundSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RefundSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("method", None) + if field is not None: + args["method"] = field + + field = data.get("total_with_taxes", None) + if field is not None: + args["total_with_taxes"] = unmarshal_Money(field) + else: + args["total_with_taxes"] = None + + field = data.get("total_without_taxes", None) + if field is not None: + args["total_without_taxes"] = unmarshal_Money(field) + else: + args["total_without_taxes"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("refunded_at", None) + if field is not None: + args["refunded_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["refunded_at"] = None + + return RefundSummary(**args) + + +def unmarshal_ListRefundsResponse(data: Any) -> ListRefundsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRefundsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("refunds", None) + if field is not None: + args["refunds"] = ( + [unmarshal_RefundSummary(v) for v in field] if field is not None else None + ) + + return ListRefundsResponse(**args) + + +def unmarshal_RpnSanServer(data: Any) -> RpnSanServer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSanServer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("sans", None) + if field is not None: + args["sans"] = ( + [unmarshal_RpnSan(v) for v in field] if field is not None else None + ) + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + return RpnSanServer(**args) + + +def unmarshal_ListRpnCapableSanServersResponse( + data: Any, +) -> ListRpnCapableSanServersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnCapableSanServersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("san_servers", None) + if field is not None: + args["san_servers"] = ( + [unmarshal_RpnSanServer(v) for v in field] if field is not None else None + ) + + return ListRpnCapableSanServersResponse(**args) + + +def unmarshal_ListRpnCapableServersResponse(data: Any) -> ListRpnCapableServersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnCapableServersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("servers", None) + if field is not None: + args["servers"] = ( + [unmarshal_Server(v) for v in field] if field is not None else None + ) + + return ListRpnCapableServersResponse(**args) + + +def unmarshal_RpnGroupMember(data: Any) -> RpnGroupMember: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnGroupMember' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("group_id", None) + if field is not None: + args["group_id"] = field + + field = data.get("group_name", None) + if field is not None: + args["group_name"] = field + + field = data.get("group_owner", None) + if field is not None: + args["group_owner"] = field + + field = data.get("owner", None) + if field is not None: + args["owner"] = field + + field = data.get("san_server", None) + if field is not None: + args["san_server"] = unmarshal_RpnSanServer(field) + else: + args["san_server"] = None + + field = data.get("server", None) + if field is not None: + args["server"] = unmarshal_Server(field) + else: + args["server"] = None + + field = data.get("speed", None) + if field is not None: + args["speed"] = field + else: + args["speed"] = None + + return RpnGroupMember(**args) + + +def unmarshal_ListRpnGroupMembersResponse(data: Any) -> ListRpnGroupMembersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnGroupMembersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("members", None) + if field is not None: + args["members"] = ( + [unmarshal_RpnGroupMember(v) for v in field] if field is not None else None + ) + + return ListRpnGroupMembersResponse(**args) + + +def unmarshal_ListRpnGroupsResponse(data: Any) -> ListRpnGroupsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnGroupsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("rpn_groups", None) + if field is not None: + args["rpn_groups"] = ( + [unmarshal_RpnGroup(v) for v in field] if field is not None else None + ) + + return ListRpnGroupsResponse(**args) + + +def unmarshal_ListRpnInvitesResponse(data: Any) -> ListRpnInvitesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnInvitesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("members", None) + if field is not None: + args["members"] = ( + [unmarshal_RpnGroupMember(v) for v in field] if field is not None else None + ) + + return ListRpnInvitesResponse(**args) + + +def unmarshal_RpnSanSummary(data: Any) -> RpnSanSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSanSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("server_hostname", None) + if field is not None: + args["server_hostname"] = field + + field = data.get("iqn_suffix", None) + if field is not None: + args["iqn_suffix"] = field + + field = data.get("offer_id", None) + if field is not None: + args["offer_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("storage_size", None) + if field is not None: + args["storage_size"] = field + + field = data.get("rpnv1_compatible", None) + if field is not None: + args["rpnv1_compatible"] = field + + field = data.get("rpnv1_implicit", None) + if field is not None: + args["rpnv1_implicit"] = field + + field = data.get("delivered_at", None) + if field is not None: + args["delivered_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["delivered_at"] = None + + field = data.get("terminated_at", None) + if field is not None: + args["terminated_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["terminated_at"] = None + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + return RpnSanSummary(**args) + + +def unmarshal_ListRpnSansResponse(data: Any) -> ListRpnSansResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnSansResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("rpn_sans", None) + if field is not None: + args["rpn_sans"] = ( + [unmarshal_RpnSanSummary(v) for v in field] if field is not None else None + ) + + return ListRpnSansResponse(**args) + + +def unmarshal_RpnServerCapability(data: Any) -> RpnServerCapability: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnServerCapability' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("compatible_qinq", None) + if field is not None: + args["compatible_qinq"] = field + + field = data.get("can_join_qinq_group", None) + if field is not None: + args["can_join_qinq_group"] = field + + field = data.get("rpnv1_group_count", None) + if field is not None: + args["rpnv1_group_count"] = field + + field = data.get("rpnv2_group_count", None) + if field is not None: + args["rpnv2_group_count"] = field + + field = data.get("can_join_rpnv2_group", None) + if field is not None: + args["can_join_rpnv2_group"] = field + + field = data.get("ip_address", None) + if field is not None: + args["ip_address"] = field + else: + args["ip_address"] = None + + field = data.get("rpn_version", None) + if field is not None: + args["rpn_version"] = field + else: + args["rpn_version"] = None + + return RpnServerCapability(**args) + + +def unmarshal_ListRpnServerCapabilitiesResponse( + data: Any, +) -> ListRpnServerCapabilitiesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnServerCapabilitiesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("servers", None) + if field is not None: + args["servers"] = ( + [unmarshal_RpnServerCapability(v) for v in field] + if field is not None + else None + ) + + return ListRpnServerCapabilitiesResponse(**args) + + +def unmarshal_ListRpnV2CapableResourcesResponse( + data: Any, +) -> ListRpnV2CapableResourcesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnV2CapableResourcesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("servers", None) + if field is not None: + args["servers"] = ( + [unmarshal_Server(v) for v in field] if field is not None else None + ) + + return ListRpnV2CapableResourcesResponse(**args) + + +def unmarshal_RpnV2Member(data: Any) -> RpnV2Member: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnV2Member' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("vlan", None) + if field is not None: + args["vlan"] = field + + field = data.get("server", None) + if field is not None: + args["server"] = unmarshal_Server(field) + else: + args["server"] = None + + field = data.get("rpnv1_group", None) + if field is not None: + args["rpnv1_group"] = unmarshal_RpnGroup(field) + else: + args["rpnv1_group"] = None + + field = data.get("speed", None) + if field is not None: + args["speed"] = field + else: + args["speed"] = None + + return RpnV2Member(**args) + + +def unmarshal_Log(data: Any) -> Log: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Log' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("action", None) + if field is not None: + args["action"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("group", None) + if field is not None: + args["group"] = unmarshal_RpnV2Group(field) + else: + args["group"] = None + + field = data.get("member", None) + if field is not None: + args["member"] = unmarshal_RpnV2Member(field) + else: + args["member"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("finished_at", None) + if field is not None: + args["finished_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["finished_at"] = None + + return Log(**args) + + +def unmarshal_ListRpnV2GroupLogsResponse(data: Any) -> ListRpnV2GroupLogsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnV2GroupLogsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("logs", None) + if field is not None: + args["logs"] = [unmarshal_Log(v) for v in field] if field is not None else None + + return ListRpnV2GroupLogsResponse(**args) + + +def unmarshal_ListRpnV2GroupsResponse(data: Any) -> ListRpnV2GroupsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnV2GroupsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("rpn_groups", None) + if field is not None: + args["rpn_groups"] = ( + [unmarshal_RpnV2Group(v) for v in field] if field is not None else None + ) + + return ListRpnV2GroupsResponse(**args) + + +def unmarshal_ListRpnV2MembersResponse(data: Any) -> ListRpnV2MembersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnV2MembersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("members", None) + if field is not None: + args["members"] = ( + [unmarshal_RpnV2Member(v) for v in field] if field is not None else None + ) + + return ListRpnV2MembersResponse(**args) + + +def unmarshal_ServerDisk(data: Any) -> ServerDisk: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerDisk' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("connector", None) + if field is not None: + args["connector"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = field + + field = data.get("is_addon", None) + if field is not None: + args["is_addon"] = field + + return ServerDisk(**args) + + +def unmarshal_ListServerDisksResponse(data: Any) -> ListServerDisksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServerDisksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("disks", None) + if field is not None: + args["disks"] = ( + [unmarshal_ServerDisk(v) for v in field] if field is not None else None + ) + + return ListServerDisksResponse(**args) + + +def unmarshal_ServerEvent(data: Any) -> ServerEvent: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerEvent' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("event_id", None) + if field is not None: + args["event_id"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("date", None) + if field is not None: + args["date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["date"] = None + + return ServerEvent(**args) + + +def unmarshal_ListServerEventsResponse(data: Any) -> ListServerEventsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServerEventsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("events", None) + if field is not None: + args["events"] = ( + [unmarshal_ServerEvent(v) for v in field] if field is not None else None + ) + + return ListServerEventsResponse(**args) + + +def unmarshal_ServerSummary(data: Any) -> ServerSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("expired_at", None) + if field is not None: + args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None + + field = data.get("offer_id", None) + if field is not None: + args["offer_id"] = field + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("interfaces", None) + if field is not None: + args["interfaces"] = ( + [unmarshal_NetworkInterface(v) for v in field] + if field is not None + else None + ) + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("is_outsourced", None) + if field is not None: + args["is_outsourced"] = field + + field = data.get("qinq", None) + if field is not None: + args["qinq"] = field + + field = data.get("os_id", None) + if field is not None: + args["os_id"] = field + else: + args["os_id"] = None + + field = data.get("level", None) + if field is not None: + args["level"] = unmarshal_ServiceLevel(field) + else: + args["level"] = None + + field = data.get("rpn_version", None) + if field is not None: + args["rpn_version"] = field + else: + args["rpn_version"] = None + + return ServerSummary(**args) + + +def unmarshal_ListServersResponse(data: Any) -> ListServersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("servers", None) + if field is not None: + args["servers"] = ( + [unmarshal_ServerSummary(v) for v in field] if field is not None else None + ) + + return ListServersResponse(**args) + + +def unmarshal_ListServicesResponse(data: Any) -> ListServicesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServicesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("services", None) + if field is not None: + args["services"] = ( + [unmarshal_Service(v) for v in field] if field is not None else None + ) + + return ListServicesResponse(**args) + + +def unmarshal_ListSubscribableServerOptionsResponse( + data: Any, +) -> ListSubscribableServerOptionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSubscribableServerOptionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("server_options", None) + if field is not None: + args["server_options"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return ListSubscribableServerOptionsResponse(**args) + + +def unmarshal_RaidArray(data: Any) -> RaidArray: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RaidArray' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("raid_level", None) + if field is not None: + args["raid_level"] = field + + field = data.get("disks", None) + if field is not None: + args["disks"] = ( + [unmarshal_ServerDisk(v) for v in field] if field is not None else None + ) + + return RaidArray(**args) + + +def unmarshal_Raid(data: Any) -> Raid: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Raid' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("raid_arrays", None) + if field is not None: + args["raid_arrays"] = ( + [unmarshal_RaidArray(v) for v in field] if field is not None else None + ) + + return Raid(**args) + + +def unmarshal_Refund(data: Any) -> Refund: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Refund' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("method", None) + if field is not None: + args["method"] = field + + field = data.get("content", None) + if field is not None: + args["content"] = field + + field = data.get("total_with_taxes", None) + if field is not None: + args["total_with_taxes"] = unmarshal_Money(field) + else: + args["total_with_taxes"] = None + + field = data.get("total_without_taxes", None) + if field is not None: + args["total_without_taxes"] = unmarshal_Money(field) + else: + args["total_without_taxes"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("refunded_at", None) + if field is not None: + args["refunded_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["refunded_at"] = None + + return Refund(**args) + + +def unmarshal_Rescue(data: Any) -> Rescue: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Rescue' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("os_id", None) + if field is not None: + args["os_id"] = field + + field = data.get("login", None) + if field is not None: + args["login"] = field + + field = data.get("password", None) + if field is not None: + args["password"] = field + + field = data.get("protocol", None) + if field is not None: + args["protocol"] = field + + return Rescue(**args) + + +def unmarshal_Partition(data: Any) -> Partition: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Partition' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("file_system", None) + if field is not None: + args["file_system"] = field + + field = data.get("raid_level", None) + if field is not None: + args["raid_level"] = field + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = field + + field = data.get("connectors", None) + if field is not None: + args["connectors"] = field + + field = data.get("mount_point", None) + if field is not None: + args["mount_point"] = field + else: + args["mount_point"] = None + + return Partition(**args) + + +def unmarshal_ServerDefaultPartitioning(data: Any) -> ServerDefaultPartitioning: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerDefaultPartitioning' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("partitions", None) + if field is not None: + args["partitions"] = ( + [unmarshal_Partition(v) for v in field] if field is not None else None + ) + + return ServerDefaultPartitioning(**args) + + +def unmarshal_ServerInstall(data: Any) -> ServerInstall: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerInstall' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("os_id", None) + if field is not None: + args["os_id"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("partitions", None) + if field is not None: + args["partitions"] = ( + [unmarshal_Partition(v) for v in field] if field is not None else None + ) + + field = data.get("ssh_key_ids", None) + if field is not None: + args["ssh_key_ids"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("user_login", None) + if field is not None: + args["user_login"] = field + else: + args["user_login"] = None + + field = data.get("panel_url", None) + if field is not None: + args["panel_url"] = field + else: + args["panel_url"] = None + + return ServerInstall(**args) + + +def unmarshal_SubscribeStorageOptionsResponse( + data: Any, +) -> SubscribeStorageOptionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SubscribeStorageOptionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("services", None) + if field is not None: + args["services"] = ( + [unmarshal_Service(v) for v in field] if field is not None else None + ) + + return SubscribeStorageOptionsResponse(**args) + + +def marshal_AttachFailoverIPToMacAddressRequest( + request: AttachFailoverIPToMacAddressRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.mac is not None: + output["mac"] = request.mac + + return output + + +def marshal_AttachFailoverIPsRequest( + request: AttachFailoverIPsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.server_id is not None: + output["server_id"] = request.server_id + + if request.fips_ids is not None: + output["fips_ids"] = request.fips_ids + + return output + + +def marshal_CreateFailoverIPsRequest( + request: CreateFailoverIPsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.quantity is not None: + output["quantity"] = request.quantity + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_CreateServerRequest( + request: CreateServerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.server_option_ids is not None: + output["server_option_ids"] = request.server_option_ids + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.datacenter_name is not None: + output["datacenter_name"] = request.datacenter_name + + return output + + +def marshal_DetachFailoverIPsRequest( + request: DetachFailoverIPsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.fips_ids is not None: + output["fips_ids"] = request.fips_ids + + return output + + +def marshal_IPv6BlockApiCreateIPv6BlockRequest( + request: IPv6BlockApiCreateIPv6BlockRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id + + return output + + +def marshal_IPv6BlockApiCreateIPv6BlockSubnetRequest( + request: IPv6BlockApiCreateIPv6BlockSubnetRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.address is not None: + output["address"] = request.address + + if request.cidr is not None: + output["cidr"] = request.cidr + + return output + + +def marshal_IPv6BlockApiUpdateIPv6BlockRequest( + request: IPv6BlockApiUpdateIPv6BlockRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.nameservers is not None: + output["nameservers"] = request.nameservers + + return output + + +def marshal_InstallPartition( + request: InstallPartition, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.file_system is not None: + output["file_system"] = str(request.file_system) + + if request.raid_level is not None: + output["raid_level"] = str(request.raid_level) + + if request.capacity is not None: + output["capacity"] = request.capacity + + if request.connectors is not None: + output["connectors"] = request.connectors + + if request.mount_point is not None: + output["mount_point"] = request.mount_point + + return output + + +def marshal_InstallServerRequest( + request: InstallServerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.os_id is not None: + output["os_id"] = request.os_id + + if request.hostname is not None: + output["hostname"] = request.hostname + + if request.user_login is not None: + output["user_login"] = request.user_login + + if request.user_password is not None: + output["user_password"] = request.user_password + + if request.panel_password is not None: + output["panel_password"] = request.panel_password + + if request.root_password is not None: + output["root_password"] = request.root_password + + if request.partitions is not None: + output["partitions"] = [ + marshal_InstallPartition(item, defaults) for item in request.partitions + ] + + if request.ssh_key_ids is not None: + output["ssh_key_ids"] = request.ssh_key_ids + + if request.license_offer_id is not None: + output["license_offer_id"] = request.license_offer_id + + if request.ip_id is not None: + output["ip_id"] = request.ip_id + + return output + + +def marshal_RpnSanApiAddIpRequest( + request: RpnSanApiAddIpRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip_ids is not None: + output["ip_ids"] = request.ip_ids + + return output + + +def marshal_RpnSanApiCreateRpnSanRequest( + request: RpnSanApiCreateRpnSanRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RpnSanApiRemoveIpRequest( + request: RpnSanApiRemoveIpRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip_ids is not None: + output["ip_ids"] = request.ip_ids + + return output + + +def marshal_RpnV1ApiAddRpnGroupMembersRequest( + request: RpnV1ApiAddRpnGroupMembersRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.server_ids is not None: + output["server_ids"] = request.server_ids + + if request.san_server_ids is not None: + output["san_server_ids"] = request.san_server_ids + + return output + + +def marshal_RpnV1ApiCreateRpnGroupRequest( + request: RpnV1ApiCreateRpnGroupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.server_ids is not None: + output["server_ids"] = request.server_ids + + if request.san_server_ids is not None: + output["san_server_ids"] = request.san_server_ids + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RpnV1ApiDeleteRpnGroupMembersRequest( + request: RpnV1ApiDeleteRpnGroupMembersRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.member_ids is not None: + output["member_ids"] = request.member_ids + + return output + + +def marshal_RpnV1ApiLeaveRpnGroupRequest( + request: RpnV1ApiLeaveRpnGroupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.member_ids is not None: + output["member_ids"] = request.member_ids + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RpnV1ApiRpnGroupInviteRequest( + request: RpnV1ApiRpnGroupInviteRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.server_ids is not None: + output["server_ids"] = request.server_ids + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RpnV1ApiUpdateRpnGroupNameRequest( + request: RpnV1ApiUpdateRpnGroupNameRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + return output + + +def marshal_RpnV2ApiAddRpnV2MembersRequest( + request: RpnV2ApiAddRpnV2MembersRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.servers is not None: + output["servers"] = request.servers + + return output + + +def marshal_RpnV2ApiCreateRpnV2GroupRequest( + request: RpnV2ApiCreateRpnV2GroupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.servers is not None: + output["servers"] = request.servers + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.type_ is not None: + output["type"] = str(request.type_) + + return output + + +def marshal_RpnV2ApiDeleteRpnV2MembersRequest( + request: RpnV2ApiDeleteRpnV2MembersRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.member_ids is not None: + output["member_ids"] = request.member_ids + + return output + + +def marshal_RpnV2ApiEnableRpnV2GroupCompatibilityRequest( + request: RpnV2ApiEnableRpnV2GroupCompatibilityRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.rpnv1_group_id is not None: + output["rpnv1_group_id"] = request.rpnv1_group_id + + return output + + +def marshal_RpnV2ApiUpdateRpnV2GroupNameRequest( + request: RpnV2ApiUpdateRpnV2GroupNameRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + return output + + +def marshal_RpnV2ApiUpdateRpnV2VlanForMembersRequest( + request: RpnV2ApiUpdateRpnV2VlanForMembersRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.member_ids is not None: + output["member_ids"] = request.member_ids + + if request.vlan is not None: + output["vlan"] = request.vlan + + return output + + +def marshal_StartBMCAccessRequest( + request: StartBMCAccessRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip is not None: + output["ip"] = request.ip + + return output + + +def marshal_StartRescueRequest( + request: StartRescueRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.os_id is not None: + output["os_id"] = request.os_id + + return output + + +def marshal_SubscribeServerOptionRequest( + request: SubscribeServerOptionRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.option_id is not None: + output["option_id"] = request.option_id + + return output + + +def marshal_SubscribeStorageOptionsRequest( + request: SubscribeStorageOptionsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.options_ids is not None: + output["options_ids"] = request.options_ids + + return output + + +def marshal_UpdatableRaidArray( + request: UpdatableRaidArray, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.raid_level is not None: + output["raid_level"] = str(request.raid_level) + + if request.disk_ids is not None: + output["disk_ids"] = request.disk_ids + + return output + + +def marshal_UpdateRaidRequest( + request: UpdateRaidRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.raid_arrays is not None: + output["raid_arrays"] = [ + marshal_UpdatableRaidArray(item, defaults) for item in request.raid_arrays + ] + + return output + + +def marshal_UpdateReverseRequest( + request: UpdateReverseRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.reverse is not None: + output["reverse"] = request.reverse + + return output + + +def marshal_UpdateServerBackupRequest( + request: UpdateServerBackupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + if request.autologin is not None: + output["autologin"] = request.autologin + + if request.acl_enabled is not None: + output["acl_enabled"] = request.acl_enabled + + return output + + +def marshal_UpdateServerRequest( + request: UpdateServerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.hostname is not None: + output["hostname"] = request.hostname + + if request.enable_ipv6 is not None: + output["enable_ipv6"] = request.enable_ipv6 + + return output + + +def marshal_UpdateServerTagsRequest( + request: UpdateServerTagsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.tags is not None: + output["tags"] = request.tags + + return output diff --git a/scaleway-async/scaleway_async/dedibox/v1/types.py b/scaleway-async/scaleway_async/dedibox/v1/types.py new file mode 100644 index 00000000..8fba972c --- /dev/null +++ b/scaleway-async/scaleway_async/dedibox/v1/types.py @@ -0,0 +1,4453 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Money, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class AttachFailoverIPToMacAddressRequestMacType(str, Enum, metaclass=StrEnumMeta): + MAC_TYPE_UNKNOWN = "mac_type_unknown" + VMWARE = "vmware" + KVM = "kvm" + XEN = "xen" + + def __str__(self) -> str: + return str(self.value) + + +class BMCAccessStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + CREATING = "creating" + CREATED = "created" + DELETING = "deleting" + + def __str__(self) -> str: + return str(self.value) + + +class BackupStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_BACKUP_STATUS = "unknown_backup_status" + UNINITIALIZED = "uninitialized" + INACTIVE = "inactive" + READY = "ready" + + def __str__(self) -> str: + return str(self.value) + + +class FailoverBlockVersion(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_VERSION = "unknown_version" + IPV4 = "ipv4" + IPV6 = "ipv6" + + def __str__(self) -> str: + return str(self.value) + + +class FailoverIPInterfaceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + NORMAL = "normal" + IPMI = "ipmi" + VIRTUAL = "virtual" + + def __str__(self) -> str: + return str(self.value) + + +class FailoverIPStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + BUSY = "busy" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class FailoverIPVersion(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_VERSION = "unknown_version" + IPV4 = "ipv4" + IPV6 = "ipv6" + + def __str__(self) -> str: + return str(self.value) + + +class GetRpnStatusResponseStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + BUSY = "busy" + OPERATIONAL = "operational" + + def __str__(self) -> str: + return str(self.value) + + +class IPSemantic(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + PROXAD = "proxad" + EXT = "ext" + PUBLIC = "public" + PRIVATE = "private" + IPMI = "ipmi" + ADM = "adm" + REDIRECT = "redirect" + MIGRATION = "migration" + + def __str__(self) -> str: + return str(self.value) + + +class IPStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + BUSY = "busy" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class IPVersion(str, Enum, metaclass=StrEnumMeta): + IPV4 = "ipv4" + IPV6 = "ipv6" + + def __str__(self) -> str: + return str(self.value) + + +class IPv6BlockDelegationStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + UPDATING = "updating" + DONE = "done" + + def __str__(self) -> str: + return str(self.value) + + +class InvoicePaymentMethod(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PAYMENT_METHOD = "unknown_payment_method" + CREDIT_CARD = "credit_card" + AMEX = "amex" + PAYPAL = "paypal" + TRANSFER = "transfer" + DIRECT_DEBIT = "direct_debit" + + def __str__(self) -> str: + return str(self.value) + + +class InvoiceStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_INVOICE_STATUS = "unknown_invoice_status" + UNPAID = "unpaid" + PAID = "paid" + ERRORED = "errored" + + def __str__(self) -> str: + return str(self.value) + + +class ListFailoverIPsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + IP_ASC = "ip_asc" + IP_DESC = "ip_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListInvoicesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListOSRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + RELEASED_AT_ASC = "released_at_asc" + RELEASED_AT_DESC = "released_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListOffersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + PRICE_ASC = "price_asc" + PRICE_DESC = "price_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRefundsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnCapableSanServersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnCapableServersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnGroupMembersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnGroupsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnInvitesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnSansRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnServerCapabilitiesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnV2CapableResourcesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnV2GroupLogsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnV2GroupsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnV2MembersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnV2MembersRequestType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + RPNV1_GROUP = "rpnv1_group" + SERVER = "server" + + def __str__(self) -> str: + return str(self.value) + + +class ListServerDisksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListServerEventsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListServersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListServicesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class LogAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_LOG_ACTION = "unknown_log_action" + GROUP_CREATED = "group_created" + GROUP_DELETED = "group_deleted" + MEMBERS_ADDED = "members_added" + MEMBERS_DELETED = "members_deleted" + DESCRIPTION_UPDATED = "description_updated" + RPNV1_MEMBERS_ADDED = "rpnv1_members_added" + RPNV1_MEMBERS_DELETED = "rpnv1_members_deleted" + VLAN_UPDATED = "vlan_updated" + VLAN_UPDATED_ON_ALL_SERVERS = "vlan_updated_on_all_servers" + + def __str__(self) -> str: + return str(self.value) + + +class LogStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_LOG_STATUS = "unknown_log_status" + SUCCESS = "success" + IN_PROGRESS = "in_progress" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class MemoryType(str, Enum, metaclass=StrEnumMeta): + DDR2 = "ddr2" + DDR3 = "ddr3" + DDR4 = "ddr4" + DDR5 = "ddr5" + + def __str__(self) -> str: + return str(self.value) + + +class NetworkInterfaceInterfaceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + NORMAL = "normal" + IPMI = "ipmi" + VIRTUAL = "virtual" + + def __str__(self) -> str: + return str(self.value) + + +class OSArch(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ARCH = "unknown_arch" + AMD64 = "amd64" + X86 = "x86" + ARM = "arm" + ARM64 = "arm64" + + def __str__(self) -> str: + return str(self.value) + + +class OSType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + SERVER = "server" + VIRTU = "virtu" + PANEL = "panel" + DESKTOP = "desktop" + CUSTOM = "custom" + RESCUE = "rescue" + + def __str__(self) -> str: + return str(self.value) + + +class OfferAntiDosInfoType(str, Enum, metaclass=StrEnumMeta): + MINIMAL = "minimal" + PREVENTIVE = "preventive" + CURATIVE = "curative" + + def __str__(self) -> str: + return str(self.value) + + +class OfferCatalog(str, Enum, metaclass=StrEnumMeta): + ALL = "all" + DEFAULT = "default" + BETA = "beta" + RESELLER = "reseller" + PREMIUM = "premium" + VOLUME = "volume" + ADMIN = "admin" + INACTIVE = "inactive" + + def __str__(self) -> str: + return str(self.value) + + +class OfferPaymentFrequency(str, Enum, metaclass=StrEnumMeta): + MONTHLY = "monthly" + ONESHOT = "oneshot" + + def __str__(self) -> str: + return str(self.value) + + +class OfferSANInfoType(str, Enum, metaclass=StrEnumMeta): + HDD = "hdd" + SSD = "ssd" + + def __str__(self) -> str: + return str(self.value) + + +class OfferServerInfoStock(str, Enum, metaclass=StrEnumMeta): + EMPTY = "empty" + LOW = "low" + AVAILABLE = "available" + + def __str__(self) -> str: + return str(self.value) + + +class PartitionFileSystem(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + EFI = "efi" + SWAP = "swap" + EXT4 = "ext4" + EXT3 = "ext3" + EXT2 = "ext2" + XFS = "xfs" + NTFS = "ntfs" + FAT32 = "fat32" + UFS = "ufs" + + def __str__(self) -> str: + return str(self.value) + + +class PartitionType(str, Enum, metaclass=StrEnumMeta): + PRIMARY = "primary" + EXTENDED = "extended" + LOGICAL = "logical" + + def __str__(self) -> str: + return str(self.value) + + +class RaidArrayRaidLevel(str, Enum, metaclass=StrEnumMeta): + NO_RAID = "no_raid" + RAID0 = "raid0" + RAID1 = "raid1" + RAID5 = "raid5" + RAID6 = "raid6" + RAID10 = "raid10" + + def __str__(self) -> str: + return str(self.value) + + +class RefundMethod(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_REFUND_METHOD = "unknown_refund_method" + CREDIT_CARD = "credit_card" + AMEX = "amex" + PAYPAL = "paypal" + TRANSFER = "transfer" + + def __str__(self) -> str: + return str(self.value) + + +class RefundStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_REFUND_STATUS = "unknown_refund_status" + UNPAID = "unpaid" + PAID = "paid" + ERRORED = "errored" + + def __str__(self) -> str: + return str(self.value) + + +class RescueProtocol(str, Enum, metaclass=StrEnumMeta): + VNC = "vnc" + SSH = "ssh" + + def __str__(self) -> str: + return str(self.value) + + +class RpnGroupMemberStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_RPN_MEMBER_STATUS = "unknown_rpn_member_status" + PENDING_INVITATION = "pending_invitation" + ACTIVE = "active" + CREATING = "creating" + DELETING = "deleting" + DELETED = "deleted" + + def __str__(self) -> str: + return str(self.value) + + +class RpnGroupType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + LOCAL = "local" + SHARED = "shared" + + def __str__(self) -> str: + return str(self.value) + + +class RpnSanIpType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + SERVER_IP = "server_ip" + RPNV2_SUBNET = "rpnv2_subnet" + + def __str__(self) -> str: + return str(self.value) + + +class RpnSanStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + ACTIVE = "active" + DELETING = "deleting" + MAINTENANCE = "maintenance" + + def __str__(self) -> str: + return str(self.value) + + +class RpnV2GroupStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_GROUP_STATUS = "unknown_group_status" + CREATING = "creating" + ACTIVE = "active" + UPDATING = "updating" + DELETING = "deleting" + + def __str__(self) -> str: + return str(self.value) + + +class RpnV2GroupType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + STANDARD = "standard" + QINQ = "qinq" + + def __str__(self) -> str: + return str(self.value) + + +class RpnV2MemberStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_MEMBER_STATUS = "unknown_member_status" + CREATING = "creating" + ACTIVE = "active" + UPDATING = "updating" + DELETING = "deleting" + + def __str__(self) -> str: + return str(self.value) + + +class ServerDiskType(str, Enum, metaclass=StrEnumMeta): + SATA = "sata" + SSD = "ssd" + SAS = "sas" + SSHD = "sshd" + USB = "usb" + NVME = "nvme" + + def __str__(self) -> str: + return str(self.value) + + +class ServerInstallStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + BOOTING = "booting" + SETTING_UP_RAID = "setting_up_raid" + PARTITIONING = "partitioning" + FORMATTING = "formatting" + INSTALLING = "installing" + CONFIGURING = "configuring" + CONFIGURING_BOOTLOADER = "configuring_bootloader" + REBOOTING = "rebooting" + INSTALLED = "installed" + + def __str__(self) -> str: + return str(self.value) + + +class ServerStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + DELIVERING = "delivering" + INSTALLING = "installing" + READY = "ready" + STOPPED = "stopped" + ERROR = "error" + LOCKED = "locked" + RESCUE = "rescue" + BUSY = "busy" + + def __str__(self) -> str: + return str(self.value) + + +class ServiceLevelLevel(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + BASIC = "basic" + BUSINESS = "business" + + def __str__(self) -> str: + return str(self.value) + + +class ServiceProvisioningStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + DELIVERING = "delivering" + READY = "ready" + ERROR = "error" + EXPIRING = "expiring" + EXPIRED = "expired" + + def __str__(self) -> str: + return str(self.value) + + +class ServiceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + SERVICE = "service" + ORDER = "order" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class OfferAntiDosInfo: + type_: OfferAntiDosInfoType + + +@dataclass +class OfferBackupInfo: + size: int + + +@dataclass +class OfferBandwidthInfo: + speed: int + + +@dataclass +class OfferLicenseInfo: + bound_to_ip: bool + + +@dataclass +class OfferRPNInfo: + speed: int + + +@dataclass +class OfferSANInfo: + size: int + """ + SAN size (in bytes). + """ + + ha: bool + """ + High availability offer. + """ + + device_type: OfferSANInfoType + """ + Type of SAN device (hdd / ssd). + """ + + +@dataclass +class OfferStorageInfo: + max_quota: int + + size: int + + +@dataclass +class IP: + ip_id: int + """ + ID of the IP. + """ + + address: str + """ + Address of the IP. + """ + + reverse: str + """ + Reverse IP value. + """ + + version: IPVersion + """ + Version of IP (v4 or v6). + """ + + cidr: int + """ + Classless InterDomain Routing notation of the IP. + """ + + netmask: str + """ + Network mask of IP. + """ + + semantic: IPSemantic + """ + Semantic of IP. + """ + + gateway: str + """ + Gateway of IP. + """ + + status: IPStatus + """ + Status of the IP. + """ + + +@dataclass +class Offer: + id: int + """ + ID of the offer. + """ + + name: str + """ + Name of the offer. + """ + + catalog: OfferCatalog + """ + Catalog of the offer. + """ + + payment_frequency: OfferPaymentFrequency + """ + Payment frequency of the offer. + """ + + pricing: Optional[Money] + """ + Price of the offer. + """ + + server_info: Optional[OfferServerInfo] + + service_level_info: Optional[OfferServiceLevelInfo] + + rpn_info: Optional[OfferRPNInfo] + + san_info: Optional[OfferSANInfo] + + antidos_info: Optional[OfferAntiDosInfo] + + backup_info: Optional[OfferBackupInfo] + + usb_storage_info: Optional[OfferStorageInfo] + + storage_info: Optional[OfferStorageInfo] + + license_info: Optional[OfferLicenseInfo] + + failover_ip_info: Optional[OfferFailoverIpInfo] + + failover_block_info: Optional[OfferFailoverBlockInfo] + + bandwidth_info: Optional[OfferBandwidthInfo] + + +@dataclass +class NetworkInterface: + card_id: int + """ + Card ID of the network interface. + """ + + device_id: int + """ + Device ID of the network interface. + """ + + mac: str + """ + MAC address of the network interface. + """ + + type_: NetworkInterfaceInterfaceType + """ + Network interface type. + """ + + ips: List[IP] + """ + IPs of the network interface. + """ + + +@dataclass +class OS: + id: int + """ + ID of the OS. + """ + + name: str + """ + Name of the OS. + """ + + type_: OSType + """ + Type of the OS. + """ + + version: str + """ + Version of the OS. + """ + + arch: OSArch + """ + Architecture of the OS. + """ + + allow_custom_partitioning: bool + """ + True if the OS allow custom partitioning. + """ + + allow_ssh_keys: bool + """ + True if the OS allow SSH Keys. + """ + + requires_user: bool + """ + True if the OS requires user. + """ + + requires_admin_password: bool + """ + True if the OS requires admin password. + """ + + requires_panel_password: bool + """ + True if the OS requires panel password. + """ + + allowed_filesystems: List[PartitionFileSystem] + """ + True if the OS allow file systems. + """ + + requires_license: bool + """ + True if the OS requires license. + """ + + license_offers: List[Offer] + """ + License offers available with the OS. + """ + + display_name: str + """ + Display name of the OS. + """ + + password_regex: str + """ + Regex used to validate the installation passwords. + """ + + hostname_max_length: int + """ + Hostname max length. + """ + + max_partitions: Optional[int] + """ + Maximum number of partitions which can be created. + """ + + panel_password_regex: Optional[str] + """ + Regex used to validate the panel installation password. + """ + + requires_valid_hostname: Optional[bool] + """ + If both requires_valid_hostname & hostname_regex are set, it means that at least one of the criteria must be valid. + """ + + hostname_regex: Optional[str] + """ + If both requires_valid_hostname & hostname_regex are set, it means that at least one of the criteria must be valid. + """ + + released_at: Optional[datetime] + """ + OS release date. + """ + + +@dataclass +class ServerLocation: + rack: str + + room: str + + datacenter_name: str + + +@dataclass +class ServerOption: + options: List[ServerOption] + + offer: Optional[Offer] + + created_at: Optional[datetime] + + updated_at: Optional[datetime] + + expired_at: Optional[datetime] + + +@dataclass +class ServiceLevel: + offer_id: int + """ + Offer ID of service level. + """ + + level: ServiceLevelLevel + """ + Level type of service level. + """ + + +@dataclass +class RpnSan: + id: int + """ + RPN SAN ID. + """ + + datacenter_name: str + """ + Datacenter location. + """ + + organization_id: str + """ + Organization ID. + """ + + project_id: str + """ + Project ID. + """ + + server_hostname: str + """ + RPN SAN server hostname. + """ + + iqn_suffix: str + """ + IQN suffix. + """ + + offer_id: int + """ + Offer ID. + """ + + created_at: Optional[datetime] + """ + Date of creation of the RPN SAN. + """ + + offer_name: str + """ + Offer description. + """ + + status: RpnSanStatus + """ + Status. + """ + + storage_size: int + """ + RPN SAN storage size. + """ + + iqn: str + + rpnv1_compatible: bool + """ + True if the SAN is compatible with the RPNv1 technology. + """ + + rpnv1_implicit: bool + """ + True if the offer supports the RPNv1 implicitly, false if it must to be added to a group to support RPNv1. + """ + + offer: Optional[Offer] + + delivered_at: Optional[datetime] + """ + RPN SAN delivery date. + """ + + terminated_at: Optional[datetime] + """ + RPN SAN termination date. + """ + + expires_at: Optional[datetime] + """ + RPN SAN expiration date. + """ + + +@dataclass +class RpnGroup: + id: int + """ + Rpn group member ID. + """ + + name: str + """ + Rpn group name. + """ + + type_: RpnGroupType + """ + Rpn group type (local or shared). + """ + + active: bool + """ + Whether the group is active or not. + """ + + owner: str + """ + RPN group owner. + """ + + members_count: int + """ + Total number of members. + """ + + organization_id: str + """ + Rpn group organization ID. + """ + + project_id: str + """ + Rpn group project ID. + """ + + created_at: Optional[datetime] + """ + Rpn group creation date. + """ + + +@dataclass +class RpnV2GroupSubnet: + address: str + + cidr: int + + +@dataclass +class Server: + id: int + """ + ID of the server. + """ + + organization_id: str + """ + Organization ID the server is attached to. + """ + + project_id: str + """ + Project ID the server is attached to. + """ + + hostname: str + """ + Hostname of the server. + """ + + rebooted_at: Optional[datetime] + """ + Date of last reboot of the server. + """ + + status: ServerStatus + """ + Status of the server. + """ + + abuse_contact: str + """ + Abuse contact of the server. + """ + + interfaces: List[NetworkInterface] + """ + Network interfaces of the server. + """ + + zone: ScwZone + """ + The zone in which is the server. + """ + + options: List[ServerOption] + """ + Options subscribe on the server. + """ + + has_bmc: bool + """ + Boolean if the server has a BMC. + """ + + tags: List[str] + """ + Array of customs tags attached to the server. + """ + + is_outsourced: bool + """ + Whether the server is outsourced or not. + """ + + ipv6_slaac: bool + """ + Whether or not you can enable/disable the IPv6. + """ + + qinq: bool + """ + Whether the server is compatible with QinQ. + """ + + is_rpnv2_member: bool + """ + Whether or not the server is already part of an rpnv2 group. + """ + + created_at: Optional[datetime] + """ + Date of creation of the server. + """ + + updated_at: Optional[datetime] + """ + Date of last modification of the server. + """ + + expired_at: Optional[datetime] + """ + Date of release of the server. + """ + + offer: Optional[Offer] + """ + Offer of the server. + """ + + location: Optional[ServerLocation] + """ + Location of the server. + """ + + os: Optional[OS] + """ + OS installed on the server. + """ + + level: Optional[ServiceLevel] + """ + Service level of the server. + """ + + rescue_os: Optional[OS] + """ + Rescue OS of the server. + """ + + +@dataclass +class FailoverBlock: + id: int + """ + ID of the failover block. + """ + + address: str + """ + IP of the failover block. + """ + + nameservers: List[str] + """ + Name servers. + """ + + ip_version: FailoverBlockVersion + """ + IP version of the failover block. + """ + + cidr: int + """ + Classless InterDomain Routing notation of the failover block. + """ + + netmask: str + """ + Netmask of the failover block. + """ + + gateway_ip: str + """ + Gateway IP of the failover block. + """ + + +@dataclass +class RpnSanIpRpnV2Group: + id: int + + name: str + + +@dataclass +class RpnSanIpServer: + id: int + + hostname: str + + datacenter_name: str + + +@dataclass +class RpnSanServer: + id: int + """ + The RPN SAN server ID. + """ + + datacenter_name: str + """ + The RPN SAN server datacenter name. + """ + + hostname: str + """ + The RPN SAN server hostname. + """ + + sans: List[RpnSan] + """ + RPN SANs linked to the RPN SAN server. + """ + + zone: ScwZone + """ + The RPN SAN server zone. + """ + + +@dataclass +class RpnV2Group: + id: int + """ + RPN V2 group ID. + """ + + name: str + """ + RPN V2 group name. + """ + + compatible_rpnv1: bool + """ + Whether or not the RPN V1 compatibility was enabled. + """ + + organization_id: str + """ + Organization ID of the RPN V2 group. + """ + + project_id: str + """ + Project ID of the RPN V2 group. + """ + + type_: RpnV2GroupType + """ + RPN V2 group type (qing / standard). + """ + + status: RpnV2GroupStatus + """ + RPN V2 group status. + """ + + owner: str + """ + RPN V2 group owner. + """ + + members_count: int + """ + Total number of members. + """ + + gateway: str + """ + RPN V2 gateway. + """ + + subnet: Optional[RpnV2GroupSubnet] + """ + RPN V2 subnet. + """ + + rpnv1_group: Optional[RpnGroup] + """ + The RPNv1 group (if the compatibility was enabled). + """ + + +@dataclass +class RpnV2Member: + id: int + """ + RPN V2 member ID. + """ + + status: RpnV2MemberStatus + """ + RPN V2 member status. + """ + + vlan: str + """ + RPN V2 member VLAN. + """ + + speed: Optional[int] + """ + RPN speed. + """ + + server: Optional[Server] + + rpnv1_group: Optional[RpnGroup] + + +@dataclass +class ServerDisk: + id: int + + connector: str + + type_: ServerDiskType + + capacity: int + + is_addon: bool + + +@dataclass +class Service: + id: int + """ + ID of the service. + """ + + provisioning_status: ServiceProvisioningStatus + """ + Provisioning status of the service. + """ + + type_: ServiceType + """ + Service type, either order or service. + """ + + resource_id: Optional[int] + """ + Resource ID of the service. + """ + + offer: Optional[Offer] + """ + Offer of the service. + """ + + created_at: Optional[datetime] + """ + Creation date of the service. + """ + + delivered_at: Optional[datetime] + """ + Delivery date of the service. + """ + + terminated_at: Optional[datetime] + """ + Terminatation date of the service. + """ + + expires_at: Optional[datetime] + """ + Expiration date of the service. + """ + + +@dataclass +class GetIPv6BlockQuotasResponseQuota: + quota: int + + cidr: int + + +@dataclass +class InstallPartition: + file_system: PartitionFileSystem + """ + File system of the installation partition. + """ + + raid_level: RaidArrayRaidLevel + """ + RAID level of the installation partition. + """ + + capacity: int + """ + Capacity of the installation partition. + """ + + connectors: List[str] + """ + Connectors of the installation partition. + """ + + mount_point: Optional[str] + """ + Mount point of the installation partition. + """ + + +@dataclass +class FailoverIP: + id: int + """ + ID of the failover IP. + """ + + address: str + """ + IP of the failover IP. + """ + + reverse: str + """ + Reverse IP value. + """ + + ip_version: FailoverIPVersion + """ + IP version of the failover IP. + """ + + cidr: int + """ + Classless InterDomain Routing notation of the failover IP. + """ + + netmask: str + """ + Netmask of the failover IP. + """ + + gateway_ip: str + """ + Gateway IP of the failover IP. + """ + + status: FailoverIPStatus + """ + Status of the IP failover. + """ + + type_: FailoverIPInterfaceType + """ + The interface type. + """ + + mac: Optional[str] + """ + MAC address of the IP failover. + """ + + server_id: Optional[int] + """ + Server ID linked to the IP failover. + """ + + block: Optional[FailoverBlock] + """ + Block of the IP failover. + """ + + server_zone: Optional[str] + """ + The server zone (if assigned). + """ + + +@dataclass +class ListIPv6BlockSubnetsAvailableResponseSubnet: + address: str + + cidr: int + + +@dataclass +class InvoiceSummary: + id: int + + status: InvoiceStatus + + payment_method: InvoicePaymentMethod + + transaction_id: int + + total_with_taxes: Optional[Money] + + total_without_taxes: Optional[Money] + + created_at: Optional[datetime] + + paid_at: Optional[datetime] + + +@dataclass +class RpnSanIp: + type_: RpnSanIpType + """ + IP type (server | rpnv2_subnet). + """ + + ip: Optional[IP] + """ + An IP object. + """ + + server: Optional[RpnSanIpServer] + + rpnv2_group: Optional[RpnSanIpRpnV2Group] + + +@dataclass +class RefundSummary: + id: int + + status: RefundStatus + + method: RefundMethod + + total_with_taxes: Optional[Money] + + total_without_taxes: Optional[Money] + + created_at: Optional[datetime] + + refunded_at: Optional[datetime] + + +@dataclass +class RpnGroupMember: + id: int + """ + Rpn group member ID. + """ + + status: RpnGroupMemberStatus + """ + RPN group member status. + """ + + group_id: int + """ + RPN group ID. + """ + + group_name: str + """ + RPN group name. + """ + + group_owner: str + """ + RPN group owner. + """ + + owner: str + """ + RPN member owner. + """ + + san_server: Optional[RpnSanServer] + """ + Authorized RPN SAN server. + """ + + server: Optional[Server] + """ + Authorized rpn v1 capable server. + """ + + speed: Optional[int] + """ + RPN speed. + """ + + +@dataclass +class RpnSanSummary: + id: int + """ + RPN SAN ID. + """ + + datacenter_name: str + """ + Datacenter location. + """ + + organization_id: str + """ + Organization ID. + """ + + project_id: str + """ + Project ID. + """ + + server_hostname: str + """ + RPN SAN server hostname. + """ + + iqn_suffix: str + """ + IQN suffix. + """ + + offer_id: int + """ + Offer ID. + """ + + created_at: Optional[datetime] + """ + Date of creation of the RPN SAN. + """ + + offer_name: str + """ + Offer description. + """ + + status: RpnSanStatus + """ + Status. + """ + + storage_size: int + """ + RPN SAN storage size. + """ + + rpnv1_compatible: bool + """ + True if the SAN is compatible with the RPNv1 technology. + """ + + rpnv1_implicit: bool + """ + True if the offer supports the RPNv1 implicitly, false if it must to be added to a group to support RPNv1. + """ + + delivered_at: Optional[datetime] + """ + RPN SAN delivery date. + """ + + terminated_at: Optional[datetime] + """ + RPN SAN termination date. + """ + + expires_at: Optional[datetime] + """ + RPN SAN expiration date. + """ + + +@dataclass +class RpnServerCapability: + id: int + """ + Server ID. + """ + + hostname: str + """ + Server hostname. + """ + + datacenter_name: str + """ + Server datacenter name. + """ + + zone: ScwZone + """ + Server zone. + """ + + compatible_qinq: bool + """ + True if server is compatible with QinQ protocol (rpn v2). + """ + + can_join_qinq_group: bool + """ + True if server can join a QinQ group. + """ + + rpnv1_group_count: int + """ + Times server is linked in a rpnv1 group. + """ + + rpnv2_group_count: int + """ + Times server is linked in a rpnv2 group. + """ + + can_join_rpnv2_group: bool + """ + True if server can join an rpnv2 group. + """ + + ip_address: Optional[str] + """ + Private IP address (if rpn compatiblle). + """ + + rpn_version: Optional[int] + """ + Supported rpn version. + """ + + +@dataclass +class Log: + id: int + """ + RPN V2 log ID. + """ + + action: LogAction + """ + Which action was performed. + """ + + status: LogStatus + """ + Action status. + """ + + group: Optional[RpnV2Group] + """ + RPN V2 group. + """ + + member: Optional[RpnV2Member] + """ + RPN V2 member (if appliable). + """ + + created_at: Optional[datetime] + """ + Creation date. + """ + + finished_at: Optional[datetime] + """ + Completion date. + """ + + +@dataclass +class ServerEvent: + event_id: int + """ + ID of the event. + """ + + description: str + """ + Description of the event. + """ + + date: Optional[datetime] + """ + Date of the event. + """ + + +@dataclass +class ServerSummary: + id: int + """ + ID of the server. + """ + + datacenter_name: str + """ + Datacenter of the server. + """ + + organization_id: str + """ + Organization ID the server is attached to. + """ + + project_id: str + """ + Project ID the server is attached to. + """ + + hostname: str + """ + Hostname of the server. + """ + + created_at: Optional[datetime] + """ + Date of creation of the server. + """ + + updated_at: Optional[datetime] + """ + Date of last modification of the server. + """ + + expired_at: Optional[datetime] + """ + Date of release of the server. + """ + + offer_id: int + """ + Offer ID of the server. + """ + + offer_name: str + """ + Offer name of the server. + """ + + status: ServerStatus + """ + Status of the server. + """ + + interfaces: List[NetworkInterface] + """ + Network interfaces of the server. + """ + + zone: ScwZone + """ + The zone in which is the server. + """ + + is_outsourced: bool + """ + Whether the server is outsourced or not. + """ + + qinq: bool + """ + Whether the server is compatible with QinQ. + """ + + os_id: Optional[int] + """ + OS ID installed on server. + """ + + level: Optional[ServiceLevel] + """ + Service level of the server. + """ + + rpn_version: Optional[int] + """ + Supported RPN version. + """ + + +@dataclass +class CPU: + name: str + """ + Name of CPU. + """ + + core_count: int + """ + Number of cores of the CPU. + """ + + thread_count: int + """ + Number of threads of the CPU. + """ + + frequency: int + """ + Frequency of the CPU. + """ + + +@dataclass +class Disk: + capacity: int + """ + Capacity of the disk. + """ + + type_: ServerDiskType + """ + Type of the disk. + """ + + +@dataclass +class Memory: + capacity: int + """ + Capacity of the memory. + """ + + type_: MemoryType + """ + Type of the memory. + """ + + frequency: int + """ + Frequency of the memory. + """ + + is_ecc: bool + """ + True if the memory is an error-correcting code memory. + """ + + +@dataclass +class PersistentMemory: + capacity: int + """ + Capacity of the persistent memory. + """ + + frequency: int + """ + Frequency of the persistent memory. + """ + + model: str + """ + Model of the persistent memory. + """ + + +@dataclass +class RaidController: + model: str + """ + Model of the RAID controller. + """ + + raid_level: List[str] + """ + RAID level of the RAID controller. + """ + + +@dataclass +class RaidArray: + raid_level: RaidArrayRaidLevel + """ + The RAID level. + """ + + disks: List[ServerDisk] + """ + Disks on the RAID controller. + """ + + +@dataclass +class Partition: + type_: PartitionType + """ + Type of the partition. + """ + + file_system: PartitionFileSystem + """ + File system of the partition. + """ + + raid_level: RaidArrayRaidLevel + """ + Raid level of the partition. + """ + + capacity: int + """ + Capacity of the partition. + """ + + connectors: List[str] + """ + Connectors of the partition. + """ + + mount_point: Optional[str] + """ + Mount point of the partition. + """ + + +@dataclass +class UpdatableRaidArray: + raid_level: RaidArrayRaidLevel + """ + The RAID level. + """ + + disk_ids: List[int] + """ + The list of Disk ID of the updatable RAID. + """ + + +@dataclass +class AttachFailoverIPToMacAddressRequest: + ip_id: int + """ + ID of the failover IP. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + type_: Optional[AttachFailoverIPToMacAddressRequestMacType] + """ + A mac type. + """ + + mac: Optional[str] + """ + A valid mac address (existing or not). + """ + + +@dataclass +class AttachFailoverIPsRequest: + server_id: int + """ + ID of the server. + """ + + fips_ids: List[int] + """ + List of ID of failovers IP to attach. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class BMCAccess: + url: str + """ + URL to access to the server console. + """ + + login: str + """ + The login to use for the BMC (Baseboard Management Controller) access authentification. + """ + + password: str + """ + The password to use for the BMC (Baseboard Management Controller) access authentification. + """ + + status: BMCAccessStatus + """ + Status of the connection. + """ + + expires_at: Optional[datetime] + """ + The date after which the BMC (Baseboard Management Controller) access will be closed. + """ + + +@dataclass +class Backup: + id: int + """ + ID of the backup. + """ + + login: str + """ + Login of the backup. + """ + + server: str + """ + Server of the backup. + """ + + status: BackupStatus + """ + Status of the backup. + """ + + acl_enabled: bool + """ + ACL enable boolean of the backup. + """ + + autologin: bool + """ + Autologin boolean of the backup. + """ + + quota_space: int + """ + Total quota space of the backup. + """ + + quota_space_used: int + """ + Quota space used of the backup. + """ + + quota_files: int + """ + Total quota files of the backup. + """ + + quota_files_used: int + """ + Quota files used of the backup. + """ + + +@dataclass +class BillingApiCanOrderRequest: + project_id: Optional[str] + + +@dataclass +class BillingApiDownloadInvoiceRequest: + invoice_id: int + + +@dataclass +class BillingApiDownloadRefundRequest: + refund_id: int + + +@dataclass +class BillingApiGetInvoiceRequest: + invoice_id: int + + +@dataclass +class BillingApiGetRefundRequest: + refund_id: int + + +@dataclass +class BillingApiListInvoicesRequest: + page: Optional[int] + + page_size: Optional[int] + + order_by: Optional[ListInvoicesRequestOrderBy] + + project_id: Optional[str] + + +@dataclass +class BillingApiListRefundsRequest: + page: Optional[int] + + page_size: Optional[int] + + order_by: Optional[ListRefundsRequestOrderBy] + + project_id: Optional[str] + + +@dataclass +class CanOrderResponse: + can_order: bool + + quota_ok: bool + + phone_confirmed: bool + + email_confirmed: bool + + user_confirmed: bool + + payment_mode: bool + + billing_ok: bool + + message: Optional[str] + + +@dataclass +class CancelServerInstallRequest: + server_id: int + """ + Server ID of the server to cancel install. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class CreateFailoverIPsRequest: + offer_id: int + """ + Failover IP offer ID. + """ + + quantity: int + """ + Quantity. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class CreateFailoverIPsResponse: + total_count: int + + services: List[Service] + + +@dataclass +class CreateServerRequest: + offer_id: int + """ + Offer ID of the new server. + """ + + server_option_ids: List[int] + """ + Server option IDs of the new server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID of the new server. + """ + + datacenter_name: Optional[str] + """ + Datacenter name of the new server. + """ + + +@dataclass +class DeleteFailoverIPRequest: + ip_id: int + """ + ID of the failover IP to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteServerRequest: + server_id: int + """ + Server ID to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteServiceRequest: + service_id: int + """ + ID of the service. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DetachFailoverIPFromMacAddressRequest: + ip_id: int + """ + ID of the failover IP. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DetachFailoverIPsRequest: + fips_ids: List[int] + """ + List of IDs of failovers IP to detach. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetBMCAccessRequest: + server_id: int + """ + ID of the server to get BMC access. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetFailoverIPRequest: + ip_id: int + """ + ID of the failover IP. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetIPv6BlockQuotasResponse: + quotas: List[GetIPv6BlockQuotasResponseQuota] + """ + Quota for each CIDR of IPv6 block. + """ + + total_count: int + """ + Total count of quotas. + """ + + +@dataclass +class GetOSRequest: + os_id: int + """ + ID of the OS. + """ + + server_id: int + """ + ID of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class GetOfferRequest: + offer_id: int + """ + ID of offer. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class GetOrderedServiceRequest: + ordered_service_id: int + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetRaidRequest: + server_id: int + """ + ID of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetRemainingQuotaRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class GetRemainingQuotaResponse: + failover_ip_quota: int + """ + Current failover IP quota. + """ + + failover_ip_remaining_quota: int + """ + Remaining failover IP quota. + """ + + failover_block_quota: int + """ + Current failover block quota. + """ + + failover_block_remaining_quota: int + """ + Remaining failover block quota. + """ + + +@dataclass +class GetRescueRequest: + server_id: int + """ + ID of the server to get rescue. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetRpnStatusResponse: + status: GetRpnStatusResponseStatus + """ + If status = 'operational', you can perform rpn actions in write. + """ + + operations_left: Optional[int] + """ + Number of operations left to perform before being operational. + """ + + +@dataclass +class GetServerBackupRequest: + server_id: int + """ + Server ID of the backup. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetServerDefaultPartitioningRequest: + server_id: int + """ + ID of the server. + """ + + os_id: int + """ + OS ID of the default partitioning. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetServerInstallRequest: + server_id: int + """ + Server ID of the server to install. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetServerRequest: + server_id: int + """ + ID of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetServiceRequest: + service_id: int + """ + ID of the service. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class IPv6Block: + id: int + """ + ID of the IPv6. + """ + + address: str + """ + Address of the IPv6. + """ + + duid: str + """ + DUID of the IPv6. + """ + + nameservers: List[str] + """ + DNS linked to the IPv6. + """ + + cidr: int + """ + Classless InterDomain Routing notation of the IPv6. + """ + + subnets: List[IPv6Block] + """ + All IPv6 subnets. + """ + + delegation_status: IPv6BlockDelegationStatus + """ + The nameservers delegation status. + """ + + +@dataclass +class IPv6BlockApiCreateIPv6BlockRequest: + project_id: Optional[str] + """ + ID of the project. + """ + + +@dataclass +class IPv6BlockApiCreateIPv6BlockSubnetRequest: + block_id: int + """ + ID of the IPv6 block. + """ + + address: str + """ + Address of the IPv6. + """ + + cidr: int + """ + Classless InterDomain Routing notation of the IPv6. + """ + + +@dataclass +class IPv6BlockApiDeleteIPv6BlockRequest: + block_id: int + """ + ID of the IPv6 block to delete. + """ + + +@dataclass +class IPv6BlockApiGetIPv6BlockQuotasRequest: + project_id: Optional[str] + """ + ID of the project. + """ + + +@dataclass +class IPv6BlockApiGetIPv6BlockRequest: + project_id: Optional[str] + """ + ID of the project. + """ + + +@dataclass +class IPv6BlockApiListIPv6BlockSubnetsAvailableRequest: + block_id: int + """ + ID of the IPv6 block. + """ + + +@dataclass +class IPv6BlockApiUpdateIPv6BlockRequest: + block_id: int + """ + ID of the IPv6 block. + """ + + nameservers: Optional[List[str]] + """ + DNS to link to the IPv6. + """ + + +@dataclass +class InstallServerRequest: + server_id: int + """ + Server ID to install. + """ + + os_id: int + """ + OS ID to install on the server. + """ + + hostname: str + """ + Hostname of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + user_login: Optional[str] + """ + User to install on the server. + """ + + user_password: Optional[str] + """ + User password to install on the server. + """ + + panel_password: Optional[str] + """ + Panel password to install on the server. + """ + + root_password: Optional[str] + """ + Root password to install on the server. + """ + + partitions: Optional[List[InstallPartition]] + """ + Partitions to install on the server. + """ + + ssh_key_ids: Optional[List[str]] + """ + SSH key IDs authorized on the server. + """ + + license_offer_id: Optional[int] + """ + Offer ID of license to install on server. + """ + + ip_id: Optional[int] + """ + IP to link at the license to install on server. + """ + + +@dataclass +class Invoice: + id: int + + status: InvoiceStatus + + payment_method: InvoicePaymentMethod + + content: str + + transaction_id: int + + total_with_taxes: Optional[Money] + + total_without_taxes: Optional[Money] + + created_at: Optional[datetime] + + paid_at: Optional[datetime] + + +@dataclass +class ListFailoverIPsRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of failovers IP per page. + """ + + order_by: Optional[ListFailoverIPsRequestOrderBy] + """ + Order of the failovers IP. + """ + + project_id: Optional[str] + """ + Filter failovers IP by project ID. + """ + + search: Optional[str] + """ + Filter failovers IP which matching with this field. + """ + + only_available: Optional[bool] + """ + True: return all failovers IP not attached on server +false: return all failovers IP attached on server. + """ + + +@dataclass +class ListFailoverIPsResponse: + total_count: int + """ + Total count of matching failovers IP. + """ + + failover_ips: List[FailoverIP] + """ + List of failover IPs that match filters. + """ + + +@dataclass +class ListIPv6BlockSubnetsAvailableResponse: + subnet_availables: List[ListIPv6BlockSubnetsAvailableResponseSubnet] + """ + All available address and CIDR available in subnet. + """ + + total_count: int + """ + Total count of available subnets. + """ + + +@dataclass +class ListInvoicesResponse: + total_count: int + + invoices: List[InvoiceSummary] + + +@dataclass +class ListIpsResponse: + total_count: int + """ + Total count of authorized IPs. + """ + + ips: List[RpnSanIp] + """ + List of authorized IPs. + """ + + +@dataclass +class ListOSRequest: + server_id: int + """ + Filter OS by compatible server ID. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of OS per page. + """ + + order_by: Optional[ListOSRequestOrderBy] + """ + Order of the OS. + """ + + type_: Optional[OSType] + """ + Type of the OS. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class ListOSResponse: + total_count: int + """ + Total count of matching OS. + """ + + os: List[OS] + """ + OS that match filters. + """ + + +@dataclass +class ListOffersRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of offer per page. + """ + + order_by: Optional[ListOffersRequestOrderBy] + """ + Order of the offers. + """ + + commercial_range: Optional[str] + """ + Filter on commercial range. + """ + + catalog: Optional[OfferCatalog] + """ + Filter on catalog. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + is_failover_ip: Optional[bool] + """ + Get the current failover IP offer. + """ + + is_failover_block: Optional[bool] + """ + Get the current failover IP block offer. + """ + + sold_in: Optional[List[str]] + """ + Filter offers depending on their datacenter. + """ + + available_only: Optional[bool] + """ + Set this filter to true to only return available offers. + """ + + is_rpn_san: Optional[bool] + """ + Get the RPN SAN offers. + """ + + +@dataclass +class ListOffersResponse: + total_count: int + """ + Total count of matching offers. + """ + + offers: List[Offer] + """ + Offers that match filters. + """ + + +@dataclass +class ListRefundsResponse: + total_count: int + + refunds: List[RefundSummary] + + +@dataclass +class ListRpnCapableSanServersResponse: + total_count: int + """ + Total count of rpn capable san servers. + """ + + san_servers: List[RpnSanServer] + """ + List of san servers. + """ + + +@dataclass +class ListRpnCapableServersResponse: + total_count: int + """ + Total count of rpn capable servers. + """ + + servers: List[Server] + """ + List of servers. + """ + + +@dataclass +class ListRpnGroupMembersResponse: + total_count: int + """ + Total count of rpn v1 group members. + """ + + members: List[RpnGroupMember] + """ + List of rpn v1 group members. + """ + + +@dataclass +class ListRpnGroupsResponse: + total_count: int + """ + Total count of rpn groups. + """ + + rpn_groups: List[RpnGroup] + """ + List of rpn v1 groups. + """ + + +@dataclass +class ListRpnInvitesResponse: + total_count: int + """ + Total count of invites. + """ + + members: List[RpnGroupMember] + """ + List of invites. + """ + + +@dataclass +class ListRpnSansResponse: + total_count: int + """ + Total count of matching RPN SANs. + """ + + rpn_sans: List[RpnSanSummary] + """ + List of RPN SANs that match filters. + """ + + +@dataclass +class ListRpnServerCapabilitiesResponse: + total_count: int + """ + Total count of servers. + """ + + servers: List[RpnServerCapability] + """ + List of servers and their RPN capabilities. + """ + + +@dataclass +class ListRpnV2CapableResourcesResponse: + total_count: int + """ + Total count of matching rpn v2 capable resources. + """ + + servers: List[Server] + """ + List of rpn v2 capable resources that match filters. + """ + + +@dataclass +class ListRpnV2GroupLogsResponse: + total_count: int + """ + Total count of matching rpn v2 logs. + """ + + logs: List[Log] + """ + List of rpn v2 logs that match filters. + """ + + +@dataclass +class ListRpnV2GroupsResponse: + total_count: int + """ + Total count of matching rpn v2 groups. + """ + + rpn_groups: List[RpnV2Group] + """ + List of rpn v2 groups that match filters. + """ + + +@dataclass +class ListRpnV2MembersResponse: + total_count: int + """ + Total count of matching rpn v2 group members. + """ + + members: List[RpnV2Member] + """ + List of rpn v2 group members that match filters. + """ + + +@dataclass +class ListServerDisksRequest: + server_id: int + """ + Server ID of the server disks. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of server disk per page. + """ + + order_by: Optional[ListServerDisksRequestOrderBy] + """ + Order of the server disks. + """ + + +@dataclass +class ListServerDisksResponse: + total_count: int + """ + Total count of matching server disks. + """ + + disks: List[ServerDisk] + """ + Server disks that match filters. + """ + + +@dataclass +class ListServerEventsRequest: + server_id: int + """ + Server ID of the server events. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of server event per page. + """ + + order_by: Optional[ListServerEventsRequestOrderBy] + """ + Order of the server events. + """ + + +@dataclass +class ListServerEventsResponse: + total_count: int + """ + Total count of matching server events. + """ + + events: List[ServerEvent] + """ + Server events that match filters. + """ + + +@dataclass +class ListServersRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of server per page. + """ + + order_by: Optional[ListServersRequestOrderBy] + """ + Order of the servers. + """ + + project_id: Optional[str] + """ + Filter servers by project ID. + """ + + search: Optional[str] + """ + Filter servers by hostname. + """ + + +@dataclass +class ListServersResponse: + total_count: int + """ + Total count of matching servers. + """ + + servers: List[ServerSummary] + """ + Servers that match filters. + """ + + +@dataclass +class ListServicesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of service per page. + """ + + order_by: Optional[ListServicesRequestOrderBy] + """ + Order of the services. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class ListServicesResponse: + total_count: int + """ + Total count of matching services. + """ + + services: List[Service] + """ + Services that match filters. + """ + + +@dataclass +class ListSubscribableServerOptionsRequest: + server_id: int + """ + Server ID of the subscribable server options. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of subscribable server option per page. + """ + + +@dataclass +class ListSubscribableServerOptionsResponse: + total_count: int + """ + Total count of matching subscribable server options. + """ + + server_options: List[Offer] + """ + Server options that match filters. + """ + + +@dataclass +class OfferFailoverBlockInfo: + onetime_fees: Optional[Offer] + + +@dataclass +class OfferFailoverIpInfo: + onetime_fees: Optional[Offer] + + +@dataclass +class OfferServerInfo: + bandwidth: int + + stock: OfferServerInfoStock + + commercial_range: str + + disks: List[Disk] + + cpus: List[CPU] + + memories: List[Memory] + + persistent_memories: List[PersistentMemory] + + raid_controllers: List[RaidController] + + available_options: List[Offer] + + connectivity: int + + stock_by_datacenter: Dict[str, OfferServerInfoStock] + + rpn_version: Optional[int] + + onetime_fees: Optional[Offer] + + +@dataclass +class OfferServiceLevelInfo: + support_ticket: bool + + support_phone: bool + + sales_support: bool + + git: str + + sla: float + + priority_support: bool + + high_rpn_bandwidth: bool + + customization: bool + + antidos: bool + + extra_failover_quota: int + + available_options: List[Offer] + + +@dataclass +class Raid: + raid_arrays: List[RaidArray] + """ + Details about the RAID controller. + """ + + +@dataclass +class RebootServerRequest: + server_id: int + """ + Server ID to reboot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class Refund: + id: int + + status: RefundStatus + + method: RefundMethod + + content: str + + total_with_taxes: Optional[Money] + + total_without_taxes: Optional[Money] + + created_at: Optional[datetime] + + refunded_at: Optional[datetime] + + +@dataclass +class Rescue: + os_id: int + """ + OS ID of the rescue. + """ + + login: str + """ + Login of the rescue. + """ + + password: str + """ + Password of the rescue. + """ + + protocol: RescueProtocol + """ + Protocol of the resuce. + """ + + +@dataclass +class RpnApiGetRpnStatusRequest: + project_id: Optional[str] + """ + A project ID. + """ + + rpnv1_group_id: Optional[int] + """ + An RPN v1 group ID. + """ + + rpnv2_group_id: Optional[int] + """ + An RPN v2 group ID. + """ + + +@dataclass +class RpnApiListRpnServerCapabilitiesRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of servers per page. + """ + + order_by: Optional[ListRpnServerCapabilitiesRequestOrderBy] + """ + Order of the servers. + """ + + project_id: Optional[str] + """ + Filter servers by project ID. + """ + + +@dataclass +class RpnSanApiAddIpRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + ip_ids: List[int] + """ + An array of IP ID. + """ + + +@dataclass +class RpnSanApiCreateRpnSanRequest: + offer_id: int + """ + Offer ID. + """ + + project_id: Optional[str] + """ + Your project ID. + """ + + +@dataclass +class RpnSanApiDeleteRpnSanRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + +@dataclass +class RpnSanApiGetRpnSanRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + +@dataclass +class RpnSanApiListAvailableIpsRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + type_: Optional[RpnSanIpType] + """ + Filter by IP type (server | rpnv2_subnet). + """ + + +@dataclass +class RpnSanApiListIpsRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + type_: Optional[RpnSanIpType] + """ + Filter by IP type (server | rpnv2_subnet). + """ + + +@dataclass +class RpnSanApiListRpnSansRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of RPN SANs per page. + """ + + order_by: Optional[ListRpnSansRequestOrderBy] + """ + Order of the RPN SANs. + """ + + project_id: Optional[str] + """ + Filter RPN SANs by project ID. + """ + + +@dataclass +class RpnSanApiRemoveIpRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + ip_ids: List[int] + """ + An array of IP ID. + """ + + +@dataclass +class RpnV1ApiAcceptRpnInviteRequest: + member_id: int + """ + The member ID. + """ + + +@dataclass +class RpnV1ApiAddRpnGroupMembersRequest: + group_id: int + """ + The rpn v1 group ID. + """ + + server_ids: Optional[List[int]] + """ + A collection of rpn v1 capable server IDs. + """ + + san_server_ids: Optional[List[int]] + """ + A collection of rpn v1 capable RPN SAN server IDs. + """ + + +@dataclass +class RpnV1ApiCreateRpnGroupRequest: + name: str + """ + Rpn v1 group name. + """ + + server_ids: Optional[List[int]] + """ + A collection of rpn v1 capable servers. + """ + + san_server_ids: Optional[List[int]] + """ + A collection of rpn v1 capable rpn sans servers. + """ + + project_id: Optional[str] + """ + A project ID. + """ + + +@dataclass +class RpnV1ApiDeleteRpnGroupMembersRequest: + group_id: int + """ + The rpn v1 group ID. + """ + + member_ids: List[int] + """ + A collection of rpn v1 group members IDs. + """ + + +@dataclass +class RpnV1ApiDeleteRpnGroupRequest: + group_id: int + """ + Rpn v1 group ID. + """ + + +@dataclass +class RpnV1ApiGetRpnGroupRequest: + group_id: int + """ + Rpn v1 group ID. + """ + + +@dataclass +class RpnV1ApiLeaveRpnGroupRequest: + group_id: int + """ + The RPN V1 group ID. + """ + + member_ids: List[int] + """ + A collection of rpn v1 group members IDs. + """ + + project_id: Optional[str] + """ + A project ID. + """ + + +@dataclass +class RpnV1ApiListRpnCapableSanServersRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn capable resources per page. + """ + + order_by: Optional[ListRpnCapableSanServersRequestOrderBy] + """ + Order of the rpn capable resources. + """ + + project_id: Optional[str] + """ + Filter rpn capable resources by project ID. + """ + + +@dataclass +class RpnV1ApiListRpnCapableServersRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn capable resources per page. + """ + + order_by: Optional[ListRpnCapableServersRequestOrderBy] + """ + Order of the rpn capable resources. + """ + + project_id: Optional[str] + """ + Filter rpn capable resources by project ID. + """ + + +@dataclass +class RpnV1ApiListRpnGroupMembersRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v1 group members per page. + """ + + order_by: Optional[ListRpnGroupMembersRequestOrderBy] + """ + Order of the rpn v1 group members. + """ + + group_id: int + """ + Filter rpn v1 group members by group ID. + """ + + project_id: Optional[str] + """ + A project ID. + """ + + +@dataclass +class RpnV1ApiListRpnGroupsRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v1 groups per page. + """ + + order_by: Optional[ListRpnGroupsRequestOrderBy] + """ + Order of the rpn v1 groups. + """ + + project_id: Optional[str] + """ + Filter rpn v1 groups by project ID. + """ + + +@dataclass +class RpnV1ApiListRpnInvitesRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn capable resources per page. + """ + + order_by: Optional[ListRpnInvitesRequestOrderBy] + """ + Order of the rpn capable resources. + """ + + project_id: Optional[str] + """ + Filter rpn capable resources by project ID. + """ + + +@dataclass +class RpnV1ApiRefuseRpnInviteRequest: + member_id: int + """ + The member ID. + """ + + +@dataclass +class RpnV1ApiRpnGroupInviteRequest: + group_id: int + """ + The RPN V1 group ID. + """ + + server_ids: List[int] + """ + A collection of external server IDs. + """ + + project_id: Optional[str] + """ + A project ID. + """ + + +@dataclass +class RpnV1ApiUpdateRpnGroupNameRequest: + group_id: int + """ + Rpn v1 group ID. + """ + + name: Optional[str] + """ + New rpn v1 group name. + """ + + +@dataclass +class RpnV2ApiAddRpnV2MembersRequest: + group_id: int + """ + RPN V2 group ID. + """ + + servers: List[int] + """ + A collection of server IDs. + """ + + +@dataclass +class RpnV2ApiCreateRpnV2GroupRequest: + name: str + """ + RPN V2 group name. + """ + + servers: List[int] + """ + A collection of server IDs. + """ + + project_id: Optional[str] + """ + Project ID of the RPN V2 group. + """ + + type_: Optional[RpnV2GroupType] + """ + RPN V2 group type (qing / standard). + """ + + +@dataclass +class RpnV2ApiDeleteRpnV2GroupRequest: + group_id: int + """ + RPN V2 group ID. + """ + + +@dataclass +class RpnV2ApiDeleteRpnV2MembersRequest: + group_id: int + """ + RPN V2 group ID. + """ + + member_ids: List[int] + """ + A collection of member IDs. + """ + + +@dataclass +class RpnV2ApiDisableRpnV2GroupCompatibilityRequest: + group_id: int + """ + RPN V2 group ID. + """ + + +@dataclass +class RpnV2ApiEnableRpnV2GroupCompatibilityRequest: + group_id: int + """ + RPN V2 group ID. + """ + + rpnv1_group_id: int + """ + RPN V1 group ID. + """ + + +@dataclass +class RpnV2ApiGetRpnV2GroupRequest: + group_id: int + """ + RPN V2 group ID. + """ + + +@dataclass +class RpnV2ApiListRpnV2CapableResourcesRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v2 capable resources per page. + """ + + order_by: Optional[ListRpnV2CapableResourcesRequestOrderBy] + """ + Order of the rpn v2 capable resources. + """ + + project_id: Optional[str] + """ + Filter rpn v2 capable resources by project ID. + """ + + +@dataclass +class RpnV2ApiListRpnV2GroupLogsRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v2 group logs per page. + """ + + order_by: Optional[ListRpnV2GroupLogsRequestOrderBy] + """ + Order of the rpn v2 group logs. + """ + + group_id: int + """ + RPN V2 group ID. + """ + + +@dataclass +class RpnV2ApiListRpnV2GroupsRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v2 groups per page. + """ + + order_by: Optional[ListRpnV2GroupsRequestOrderBy] + """ + Order of the rpn v2 groups. + """ + + project_id: Optional[str] + """ + Filter rpn v2 groups by project ID. + """ + + +@dataclass +class RpnV2ApiListRpnV2MembersRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v2 group members per page. + """ + + order_by: Optional[ListRpnV2MembersRequestOrderBy] + """ + Order of the rpn v2 group members. + """ + + group_id: int + """ + RPN V2 group ID. + """ + + type_: Optional[ListRpnV2MembersRequestType] + """ + Filter members by type. + """ + + +@dataclass +class RpnV2ApiUpdateRpnV2GroupNameRequest: + group_id: int + """ + RPN V2 group ID. + """ + + name: Optional[str] + """ + RPN V2 group name. + """ + + +@dataclass +class RpnV2ApiUpdateRpnV2VlanForMembersRequest: + group_id: int + """ + RPN V2 group ID. + """ + + member_ids: List[int] + """ + RPN V2 member IDs. + """ + + vlan: Optional[int] + """ + Min: 0. +Max: 3967. + """ + + +@dataclass +class ServerDefaultPartitioning: + partitions: List[Partition] + """ + Default partitions. + """ + + +@dataclass +class ServerInstall: + os_id: int + + hostname: str + + partitions: List[Partition] + + ssh_key_ids: List[str] + + status: ServerInstallStatus + + user_login: Optional[str] + + panel_url: Optional[str] + + +@dataclass +class StartBMCAccessRequest: + server_id: int + """ + ID of the server to start the BMC access. + """ + + ip: str + """ + The IP authorized to connect to the given server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StartRescueRequest: + server_id: int + """ + ID of the server to start rescue. + """ + + os_id: int + """ + OS ID to use to start rescue. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StartServerRequest: + server_id: int + """ + Server ID to start. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StopBMCAccessRequest: + server_id: int + """ + ID of the server to stop BMC access. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StopRescueRequest: + server_id: int + """ + ID of the server to stop rescue. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StopServerRequest: + server_id: int + """ + Server ID to stop. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SubscribeServerOptionRequest: + server_id: int + """ + Server ID to subscribe server option. + """ + + option_id: int + """ + Option ID to subscribe. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SubscribeStorageOptionsRequest: + server_id: int + """ + Server ID of the storage options to subscribe. + """ + + options_ids: List[int] + """ + Option IDs of the storage options to subscribe. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SubscribeStorageOptionsResponse: + services: List[Service] + """ + Services subscribe storage options. + """ + + +@dataclass +class UpdateRaidRequest: + server_id: int + """ + ID of the server. + """ + + raid_arrays: List[UpdatableRaidArray] + """ + RAIDs to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class UpdateReverseRequest: + ip_id: int + """ + ID of the IP. + """ + + reverse: str + """ + Reverse to apply on the IP. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class UpdateServerBackupRequest: + server_id: int + """ + Server ID to update backup. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + password: Optional[str] + """ + Password of the server backup. + """ + + autologin: Optional[bool] + """ + Autologin of the server backup. + """ + + acl_enabled: Optional[bool] + """ + Boolean to enable or disable ACL. + """ + + +@dataclass +class UpdateServerRequest: + server_id: int + """ + Server ID to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + hostname: Optional[str] + """ + Hostname of the server to update. + """ + + enable_ipv6: Optional[bool] + """ + Flag to enable or not the IPv6 of server. + """ + + +@dataclass +class UpdateServerTagsRequest: + server_id: int + """ + Server ID to update the tags. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + tags: Optional[List[str]] + """ + Tags of server to update. + """ diff --git a/scaleway-async/scaleway_async/document_db/v1beta1/api.py b/scaleway-async/scaleway_async/document_db/v1beta1/api.py index e502dd35..408a7764 100644 --- a/scaleway-async/scaleway_async/document_db/v1beta1/api.py +++ b/scaleway-async/scaleway_async/document_db/v1beta1/api.py @@ -143,7 +143,9 @@ class DocumentDbV1Beta1API(API): - """ """ + """ + This API allows you to manage your Document Databases. + """ async def list_database_engines( self, diff --git a/scaleway-async/scaleway_async/document_db/v1beta1/marshalling.py b/scaleway-async/scaleway_async/document_db/v1beta1/marshalling.py index 8efeb6af..0ed12b87 100644 --- a/scaleway-async/scaleway_async/document_db/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/document_db/v1beta1/marshalling.py @@ -155,26 +155,38 @@ def unmarshal_Endpoint(data: Any) -> Endpoint: field = data.get("ip", None) if field is not None: args["ip"] = field + else: + args["ip"] = None field = data.get("name", None) if field is not None: args["name"] = field + else: + args["name"] = None field = data.get("private_network", None) if field is not None: args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None field = data.get("load_balancer", None) if field is not None: args["load_balancer"] = unmarshal_EndpointLoadBalancerDetails(field) + else: + args["load_balancer"] = None field = data.get("direct_access", None) if field is not None: args["direct_access"] = unmarshal_EndpointDirectAccessDetails(field) + else: + args["direct_access"] = None field = data.get("hostname", None) if field is not None: args["hostname"] = field + else: + args["hostname"] = None return Endpoint(**args) @@ -198,18 +210,26 @@ def unmarshal_Maintenance(data: Any) -> Maintenance: field = data.get("starts_at", None) if field is not None: args["starts_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["starts_at"] = None field = data.get("stops_at", None) if field is not None: args["stops_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stops_at"] = None field = data.get("closed_at", None) if field is not None: args["closed_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["closed_at"] = None field = data.get("forced_at", None) if field is not None: args["forced_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["forced_at"] = None return Maintenance(**args) @@ -301,14 +321,20 @@ def unmarshal_InstanceLog(data: Any) -> InstanceLog: field = data.get("download_url", None) if field is not None: args["download_url"] = field + else: + args["download_url"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return InstanceLog(**args) @@ -338,6 +364,8 @@ def unmarshal_BackupSchedule(data: Any) -> BackupSchedule: args["next_run_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["next_run_at"] = None return BackupSchedule(**args) @@ -372,10 +400,14 @@ def unmarshal_LogsPolicy(data: Any) -> LogsPolicy: field = data.get("max_age_retention", None) if field is not None: args["max_age_retention"] = field + else: + args["max_age_retention"] = None field = data.get("total_disk_retention", None) if field is not None: args["total_disk_retention"] = field + else: + args["total_disk_retention"] = None return LogsPolicy(**args) @@ -415,7 +447,7 @@ def unmarshal_Volume(data: Any) -> Volume: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -423,7 +455,7 @@ def unmarshal_Volume(data: Any) -> Volume: if field is not None: args["size"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -457,10 +489,14 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None field = data.get("project_id", None) if field is not None: @@ -499,10 +535,14 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("endpoint", None) if field is not None: args["endpoint"] = unmarshal_Endpoint(field) + else: + args["endpoint"] = None field = data.get("backup_schedule", None) if field is not None: args["backup_schedule"] = unmarshal_BackupSchedule(field) + else: + args["backup_schedule"] = None field = data.get("read_replicas", None) if field is not None: @@ -539,6 +579,8 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("logs_policy", None) if field is not None: args["logs_policy"] = unmarshal_LogsPolicy(field) + else: + args["logs_policy"] = None return Instance(**args) @@ -574,11 +616,11 @@ def unmarshal_SnapshotVolumeType(data: Any) -> SnapshotVolumeType: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -624,22 +666,32 @@ def unmarshal_Snapshot(data: Any) -> Snapshot: field = data.get("size", None) if field is not None: args["size"] = field + else: + args["size"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("volume_type", None) if field is not None: args["volume_type"] = unmarshal_SnapshotVolumeType(field) + else: + args["volume_type"] = None return Snapshot(**args) @@ -694,6 +746,8 @@ def unmarshal_ACLRule(data: Any) -> ACLRule: field = data.get("port", None) if field is not None: args["port"] = field + else: + args["port"] = None return ACLRule(**args) @@ -818,26 +872,38 @@ def unmarshal_EngineSetting(data: Any) -> EngineSetting: field = data.get("unit", None) if field is not None: args["unit"] = field + else: + args["unit"] = None field = data.get("string_constraint", None) if field is not None: args["string_constraint"] = field + else: + args["string_constraint"] = None field = data.get("int_min", None) if field is not None: args["int_min"] = field + else: + args["int_min"] = None field = data.get("int_max", None) if field is not None: args["int_max"] = field + else: + args["int_max"] = None field = data.get("float_min", None) if field is not None: args["float_min"] = field + else: + args["float_min"] = None field = data.get("float_max", None) if field is not None: args["float_max"] = field + else: + args["float_max"] = None return EngineSetting(**args) @@ -883,6 +949,8 @@ def unmarshal_EngineVersion(data: Any) -> EngineVersion: args["end_of_life"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["end_of_life"] = None return EngineVersion(**args) @@ -1089,7 +1157,7 @@ def unmarshal_NodeTypeVolumeType(data: Any) -> NodeTypeVolumeType: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -1109,7 +1177,7 @@ def unmarshal_NodeTypeVolumeType(data: Any) -> NodeTypeVolumeType: if field is not None: args["chunk_size"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -1155,10 +1223,14 @@ def unmarshal_NodeType(data: Any) -> NodeType: field = data.get("volume_constraint", None) if field is not None: args["volume_constraint"] = unmarshal_NodeTypeVolumeConstraintSizes(field) + else: + args["volume_constraint"] = None field = data.get("is_bssd_compatible", None) if field is not None: args["is_bssd_compatible"] = field + else: + args["is_bssd_compatible"] = None field = data.get("available_volume_types", None) if field is not None: @@ -1452,9 +1524,7 @@ def marshal_CreateEndpointRequest( output: Dict[str, Any] = {} if request.endpoint_spec is not None: - output["endpoint_spec"] = ( - marshal_EndpointSpec(request.endpoint_spec, defaults), - ) + output["endpoint_spec"] = marshal_EndpointSpec(request.endpoint_spec, defaults) return output @@ -1644,7 +1714,7 @@ def marshal_CreateSnapshotRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -1798,7 +1868,7 @@ def marshal_UpdateInstanceRequest( output["tags"] = request.tags if request.logs_policy is not None: - output["logs_policy"] = (marshal_LogsPolicy(request.logs_policy, defaults),) + output["logs_policy"] = marshal_LogsPolicy(request.logs_policy, defaults) if request.backup_same_region is not None: output["backup_same_region"] = request.backup_same_region @@ -1819,7 +1889,7 @@ def marshal_UpdateSnapshotRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output diff --git a/scaleway-async/scaleway_async/domain/v2beta1/api.py b/scaleway-async/scaleway_async/domain/v2beta1/api.py index 89a37584..3acd1f74 100644 --- a/scaleway-async/scaleway_async/domain/v2beta1/api.py +++ b/scaleway-async/scaleway_async/domain/v2beta1/api.py @@ -170,7 +170,7 @@ class DomainV2Beta1API(API): """ - Manage your domains, DNS zones and records with the Domains and DNS API. + This API allows you to manage your domains, DNS zones and records. """ async def list_dns_zones( @@ -2486,7 +2486,7 @@ async def enable_domain_dnssec( ) -> Domain: """ Update domain DNSSEC. - If your domain has the default Scaleway NS and uses another registrar, you have to update the DS record manually. + If your domain uses another registrar and has the default Scaleway NS, you have to **update the DS record at your registrar**. :param domain: :param ds_record: :return: :class:`Domain ` diff --git a/scaleway-async/scaleway_async/domain/v2beta1/marshalling.py b/scaleway-async/scaleway_async/domain/v2beta1/marshalling.py index c198aad5..00214b0e 100644 --- a/scaleway-async/scaleway_async/domain/v2beta1/marshalling.py +++ b/scaleway-async/scaleway_async/domain/v2beta1/marshalling.py @@ -137,6 +137,8 @@ def unmarshal_ContactExtensionFRAssociationInfo( args["publication_jo"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["publication_jo"] = None return ContactExtensionFRAssociationInfo(**args) @@ -241,24 +243,34 @@ def unmarshal_ContactExtensionFR(data: Any) -> ContactExtensionFR: field = data.get("individual_info", None) if field is not None: args["individual_info"] = unmarshal_ContactExtensionFRIndividualInfo(field) + else: + args["individual_info"] = None field = data.get("duns_info", None) if field is not None: args["duns_info"] = unmarshal_ContactExtensionFRDunsInfo(field) + else: + args["duns_info"] = None field = data.get("association_info", None) if field is not None: args["association_info"] = unmarshal_ContactExtensionFRAssociationInfo(field) + else: + args["association_info"] = None field = data.get("trademark_info", None) if field is not None: args["trademark_info"] = unmarshal_ContactExtensionFRTrademarkInfo(field) + else: + args["trademark_info"] = None field = data.get("code_auth_afnic_info", None) if field is not None: args["code_auth_afnic_info"] = unmarshal_ContactExtensionFRCodeAuthAfnicInfo( field ) + else: + args["code_auth_afnic_info"] = None return ContactExtensionFR(**args) @@ -390,14 +402,20 @@ def unmarshal_Contact(data: Any) -> Contact: args["questions"] = ( [unmarshal_ContactQuestion(v) for v in field] if field is not None else None ) + else: + args["questions"] = None field = data.get("extension_fr", None) if field is not None: args["extension_fr"] = unmarshal_ContactExtensionFR(field) + else: + args["extension_fr"] = None field = data.get("extension_eu", None) if field is not None: args["extension_eu"] = unmarshal_ContactExtensionEU(field) + else: + args["extension_eu"] = None field = data.get("email_status", None) if field is not None: @@ -414,6 +432,8 @@ def unmarshal_Contact(data: Any) -> Contact: field = data.get("extension_nl", None) if field is not None: args["extension_nl"] = unmarshal_ContactExtensionNL(field) + else: + args["extension_nl"] = None return Contact(**args) @@ -463,10 +483,14 @@ def unmarshal_DNSZone(data: Any) -> DNSZone: field = data.get("message", None) if field is not None: args["message"] = field + else: + args["message"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return DNSZone(**args) @@ -529,10 +553,14 @@ def unmarshal_SSLCertificate(data: Any) -> SSLCertificate: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("expired_at", None) if field is not None: args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None return SSLCertificate(**args) @@ -554,6 +582,8 @@ def unmarshal_CheckContactsCompatibilityResponseContactCheckResult( field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None return CheckContactsCompatibilityResponseContactCheckResult(**args) @@ -577,18 +607,24 @@ def unmarshal_CheckContactsCompatibilityResponse( args["owner_check_result"] = ( unmarshal_CheckContactsCompatibilityResponseContactCheckResult(field) ) + else: + args["owner_check_result"] = None field = data.get("administrative_check_result", None) if field is not None: args["administrative_check_result"] = ( unmarshal_CheckContactsCompatibilityResponseContactCheckResult(field) ) + else: + args["administrative_check_result"] = None field = data.get("technical_check_result", None) if field is not None: args["technical_check_result"] = ( unmarshal_CheckContactsCompatibilityResponseContactCheckResult(field) ) + else: + args["technical_check_result"] = None return CheckContactsCompatibilityResponse(**args) @@ -660,7 +696,7 @@ def unmarshal_DSRecordDigest(data: Any) -> DSRecordDigest: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -671,6 +707,8 @@ def unmarshal_DSRecordDigest(data: Any) -> DSRecordDigest: field = data.get("public_key", None) if field is not None: args["public_key"] = unmarshal_DSRecordPublicKey(field) + else: + args["public_key"] = None return DSRecordDigest(**args) @@ -694,10 +732,14 @@ def unmarshal_DSRecord(data: Any) -> DSRecord: field = data.get("digest", None) if field is not None: args["digest"] = unmarshal_DSRecordDigest(field) + else: + args["digest"] = None field = data.get("public_key", None) if field is not None: args["public_key"] = unmarshal_DSRecordPublicKey(field) + else: + args["public_key"] = None return DSRecord(**args) @@ -721,6 +763,8 @@ def unmarshal_TldOffer(data: Any) -> TldOffer: field = data.get("price", None) if field is not None: args["price"] = unmarshal_Money(field) + else: + args["price"] = None return TldOffer(**args) @@ -870,14 +914,20 @@ def unmarshal_Domain(data: Any) -> Domain: field = data.get("dnssec", None) if field is not None: args["dnssec"] = unmarshal_DomainDNSSEC(field) + else: + args["dnssec"] = None field = data.get("expired_at", None) if field is not None: args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("status", None) if field is not None: @@ -902,30 +952,42 @@ def unmarshal_Domain(data: Any) -> Domain: field = data.get("owner_contact", None) if field is not None: args["owner_contact"] = unmarshal_Contact(field) + else: + args["owner_contact"] = None field = data.get("technical_contact", None) if field is not None: args["technical_contact"] = unmarshal_Contact(field) + else: + args["technical_contact"] = None field = data.get("administrative_contact", None) if field is not None: args["administrative_contact"] = unmarshal_Contact(field) + else: + args["administrative_contact"] = None field = data.get("external_domain_registration_status", None) if field is not None: args["external_domain_registration_status"] = ( unmarshal_DomainRegistrationStatusExternalDomain(field) ) + else: + args["external_domain_registration_status"] = None field = data.get("transfer_registration_status", None) if field is not None: args["transfer_registration_status"] = ( unmarshal_DomainRegistrationStatusTransfer(field) ) + else: + args["transfer_registration_status"] = None field = data.get("tld", None) if field is not None: args["tld"] = unmarshal_Tld(field) + else: + args["tld"] = None return Domain(**args) @@ -1062,10 +1124,14 @@ def unmarshal_RecordHTTPServiceConfig(data: Any) -> RecordHTTPServiceConfig: field = data.get("must_contain", None) if field is not None: args["must_contain"] = field + else: + args["must_contain"] = None field = data.get("user_agent", None) if field is not None: args["user_agent"] = field + else: + args["user_agent"] = None return RecordHTTPServiceConfig(**args) @@ -1132,7 +1198,7 @@ def unmarshal_Record(data: Any) -> Record: if field is not None: args["ttl"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -1143,22 +1209,32 @@ def unmarshal_Record(data: Any) -> Record: field = data.get("comment", None) if field is not None: args["comment"] = field + else: + args["comment"] = None field = data.get("geo_ip_config", None) if field is not None: args["geo_ip_config"] = unmarshal_RecordGeoIPConfig(field) + else: + args["geo_ip_config"] = None field = data.get("http_service_config", None) if field is not None: args["http_service_config"] = unmarshal_RecordHTTPServiceConfig(field) + else: + args["http_service_config"] = None field = data.get("weighted_config", None) if field is not None: args["weighted_config"] = unmarshal_RecordWeightedConfig(field) + else: + args["weighted_config"] = None field = data.get("view_config", None) if field is not None: args["view_config"] = unmarshal_RecordViewConfig(field) + else: + args["view_config"] = None return Record(**args) @@ -1175,17 +1251,21 @@ def unmarshal_RecordIdentifier(data: Any) -> RecordIdentifier: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field field = data.get("data", None) if field is not None: args["data"] = field + else: + args["data"] = None field = data.get("ttl", None) if field is not None: args["ttl"] = field + else: + args["ttl"] = None return RecordIdentifier(**args) @@ -1229,10 +1309,14 @@ def unmarshal_RecordChangeDelete(data: Any) -> RecordChangeDelete: field = data.get("id", None) if field is not None: args["id"] = field + else: + args["id"] = None field = data.get("id_fields", None) if field is not None: args["id_fields"] = unmarshal_RecordIdentifier(field) + else: + args["id_fields"] = None return RecordChangeDelete(**args) @@ -1254,10 +1338,14 @@ def unmarshal_RecordChangeSet(data: Any) -> RecordChangeSet: field = data.get("id", None) if field is not None: args["id"] = field + else: + args["id"] = None field = data.get("id_fields", None) if field is not None: args["id_fields"] = unmarshal_RecordIdentifier(field) + else: + args["id_fields"] = None return RecordChangeSet(**args) @@ -1273,18 +1361,26 @@ def unmarshal_RecordChange(data: Any) -> RecordChange: field = data.get("add", None) if field is not None: args["add"] = unmarshal_RecordChangeAdd(field) + else: + args["add"] = None - field = data.get("set_", None) + field = data.get("set", None) if field is not None: args["set_"] = unmarshal_RecordChangeSet(field) + else: + args["set_"] = None field = data.get("delete", None) if field is not None: args["delete"] = unmarshal_RecordChangeDelete(field) + else: + args["delete"] = None field = data.get("clear", None) if field is not None: args["clear"] = unmarshal_RecordChangeClear(field) + else: + args["clear"] = None return RecordChange(**args) @@ -1397,6 +1493,8 @@ def unmarshal_ContactRoles(data: Any) -> ContactRoles: field = data.get("contact", None) if field is not None: args["contact"] = unmarshal_Contact(field) + else: + args["contact"] = None return ContactRoles(**args) @@ -1519,6 +1617,8 @@ def unmarshal_DNSZoneVersion(data: Any) -> DNSZoneVersion: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return DNSZoneVersion(**args) @@ -1625,10 +1725,14 @@ def unmarshal_DomainSummary(data: Any) -> DomainSummary: field = data.get("expired_at", None) if field is not None: args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("status", None) if field is not None: @@ -1647,16 +1751,22 @@ def unmarshal_DomainSummary(data: Any) -> DomainSummary: args["external_domain_registration_status"] = ( unmarshal_DomainRegistrationStatusExternalDomain(field) ) + else: + args["external_domain_registration_status"] = None field = data.get("transfer_registration_status", None) if field is not None: args["transfer_registration_status"] = ( unmarshal_DomainRegistrationStatusTransfer(field) ) + else: + args["transfer_registration_status"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return DomainSummary(**args) @@ -1709,32 +1819,44 @@ def unmarshal_RenewableDomain(data: Any) -> RenewableDomain: field = data.get("renewable_duration_in_years", None) if field is not None: args["renewable_duration_in_years"] = field + else: + args["renewable_duration_in_years"] = None field = data.get("expired_at", None) if field is not None: args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None field = data.get("limit_renew_at", None) if field is not None: args["limit_renew_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["limit_renew_at"] = None field = data.get("limit_redemption_at", None) if field is not None: args["limit_redemption_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["limit_redemption_at"] = None field = data.get("estimated_delete_at", None) if field is not None: args["estimated_delete_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["estimated_delete_at"] = None field = data.get("tld", None) if field is not None: args["tld"] = unmarshal_Tld(field) + else: + args["tld"] = None return RenewableDomain(**args) @@ -1801,7 +1923,7 @@ def unmarshal_Task(data: Any) -> Task: if field is not None: args["organization_id"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -1812,22 +1934,32 @@ def unmarshal_Task(data: Any) -> Task: field = data.get("domain", None) if field is not None: args["domain"] = field + else: + args["domain"] = None field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("message", None) if field is not None: args["message"] = field + else: + args["message"] = None field = data.get("contact_identifier", None) if field is not None: args["contact_identifier"] = field + else: + args["contact_identifier"] = None return Task(**args) @@ -1899,6 +2031,8 @@ def unmarshal_OrderResponse(data: Any) -> OrderResponse: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return OrderResponse(**args) @@ -1949,6 +2083,8 @@ def unmarshal_RegisterExternalDomainResponse( field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return RegisterExternalDomainResponse(**args) @@ -1983,6 +2119,8 @@ def unmarshal_AvailableDomain(data: Any) -> AvailableDomain: field = data.get("tld", None) if field is not None: args["tld"] = unmarshal_Tld(field) + else: + args["tld"] = None return AvailableDomain(**args) @@ -2149,8 +2287,8 @@ def marshal_ImportRawDNSZoneRequestAXFRSource( output["name_server"] = request.name_server if request.tsig_key is not None: - output["tsig_key"] = ( - marshal_ImportRawDNSZoneRequestTsigKey(request.tsig_key, defaults), + output["tsig_key"] = marshal_ImportRawDNSZoneRequestTsigKey( + request.tsig_key, defaults ) return output @@ -2219,7 +2357,7 @@ def marshal_ContactExtensionFRAssociationInfo( output["publication_jo_page"] = request.publication_jo_page if request.publication_jo is not None: - output["publication_jo"] = request.publication_jo + output["publication_jo"] = request.publication_jo.isoformat() return output @@ -2408,21 +2546,21 @@ def marshal_NewContact( ] if request.extension_fr is not None: - output["extension_fr"] = ( - marshal_ContactExtensionFR(request.extension_fr, defaults), + output["extension_fr"] = marshal_ContactExtensionFR( + request.extension_fr, defaults ) if request.extension_eu is not None: - output["extension_eu"] = ( - marshal_ContactExtensionEU(request.extension_eu, defaults), + output["extension_eu"] = marshal_ContactExtensionEU( + request.extension_eu, defaults ) if request.state is not None: output["state"] = request.state if request.extension_nl is not None: - output["extension_nl"] = ( - marshal_ContactExtensionNL(request.extension_nl, defaults), + output["extension_nl"] = marshal_ContactExtensionNL( + request.extension_nl, defaults ) return output @@ -2557,9 +2695,7 @@ def marshal_DSRecordDigest( output["digest"] = request.digest if request.public_key is not None: - output["public_key"] = ( - marshal_DSRecordPublicKey(request.public_key, defaults), - ) + output["public_key"] = marshal_DSRecordPublicKey(request.public_key, defaults) return output @@ -2594,7 +2730,7 @@ def marshal_RegistrarApiEnableDomainDNSSECRequest( output: Dict[str, Any] = {} if request.ds_record is not None: - output["ds_record"] = (marshal_DSRecord(request.ds_record, defaults),) + output["ds_record"] = marshal_DSRecord(request.ds_record, defaults) return output @@ -2780,13 +2916,13 @@ def marshal_RegistrarApiUpdateContactRequest( ] if request.extension_fr is not None: - output["extension_fr"] = ( - marshal_ContactExtensionFR(request.extension_fr, defaults), + output["extension_fr"] = marshal_ContactExtensionFR( + request.extension_fr, defaults ) if request.extension_eu is not None: - output["extension_eu"] = ( - marshal_ContactExtensionEU(request.extension_eu, defaults), + output["extension_eu"] = marshal_ContactExtensionEU( + request.extension_eu, defaults ) if request.whois_opt_in is not None: @@ -2796,8 +2932,8 @@ def marshal_RegistrarApiUpdateContactRequest( output["state"] = request.state if request.extension_nl is not None: - output["extension_nl"] = ( - marshal_ContactExtensionNL(request.extension_nl, defaults), + output["extension_nl"] = marshal_ContactExtensionNL( + request.extension_nl, defaults ) return output diff --git a/scaleway-async/scaleway_async/domain/v2beta1/types.py b/scaleway-async/scaleway_async/domain/v2beta1/types.py index c68cc41a..2b10de0a 100644 --- a/scaleway-async/scaleway_async/domain/v2beta1/types.py +++ b/scaleway-async/scaleway_async/domain/v2beta1/types.py @@ -300,6 +300,8 @@ class RecordType(str, Enum, metaclass=StrEnumMeta): DS = "ds" NAPTR = "naptr" DNAME = "dname" + SVCB = "svcb" + HTTPS = "https" def __str__(self) -> str: return str(self.value) diff --git a/scaleway-async/scaleway_async/edge_services/__init__.py b/scaleway-async/scaleway_async/edge_services/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway-async/scaleway_async/edge_services/v1alpha1/__init__.py b/scaleway-async/scaleway_async/edge_services/v1alpha1/__init__.py new file mode 100644 index 00000000..a69731fd --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1alpha1/__init__.py @@ -0,0 +1,173 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DNSStageType +from .types import LbOriginError +from .types import ListBackendStagesRequestOrderBy +from .types import ListCacheStagesRequestOrderBy +from .types import ListDNSStagesRequestOrderBy +from .types import ListPipelinesRequestOrderBy +from .types import ListPipelinesWithStagesRequestOrderBy +from .types import ListPurgeRequestsRequestOrderBy +from .types import ListTLSStagesRequestOrderBy +from .types import PipelineErrorCode +from .types import PipelineErrorSeverity +from .types import PipelineErrorStage +from .types import PipelineErrorType +from .types import PipelineStatus +from .content import PIPELINE_TRANSIENT_STATUSES +from .types import PlanName +from .types import PurgeRequestStatus +from .content import PURGE_REQUEST_TRANSIENT_STATUSES +from .types import ScalewayLb +from .types import ScalewayLbBackendConfig +from .types import ScalewayS3BackendConfig +from .types import PipelineError +from .types import TLSSecret +from .types import BackendStage +from .types import CacheStage +from .types import DNSStage +from .types import Pipeline +from .types import TLSStage +from .types import CheckPEMChainRequestSecretChain +from .types import PlanDetails +from .types import PlanUsageDetails +from .types import PipelineStages +from .types import PurgeRequest +from .types import TLSSecretsConfig +from .types import CheckDomainRequest +from .types import CheckDomainResponse +from .types import CheckLbOriginRequest +from .types import CheckLbOriginResponse +from .types import CheckPEMChainRequest +from .types import CheckPEMChainResponse +from .types import CreateBackendStageRequest +from .types import CreateCacheStageRequest +from .types import CreateDNSStageRequest +from .types import CreatePipelineRequest +from .types import CreatePurgeRequestRequest +from .types import CreateTLSStageRequest +from .types import DeleteBackendStageRequest +from .types import DeleteCacheStageRequest +from .types import DeleteCurrentPlanRequest +from .types import DeleteDNSStageRequest +from .types import DeletePipelineRequest +from .types import DeleteTLSStageRequest +from .types import GetBackendStageRequest +from .types import GetBillingRequest +from .types import GetBillingResponse +from .types import GetCacheStageRequest +from .types import GetCurrentPlanRequest +from .types import GetDNSStageRequest +from .types import GetPipelineRequest +from .types import GetPurgeRequestRequest +from .types import GetTLSStageRequest +from .types import ListBackendStagesRequest +from .types import ListBackendStagesResponse +from .types import ListCacheStagesRequest +from .types import ListCacheStagesResponse +from .types import ListDNSStagesRequest +from .types import ListDNSStagesResponse +from .types import ListPipelinesRequest +from .types import ListPipelinesResponse +from .types import ListPipelinesWithStagesRequest +from .types import ListPipelinesWithStagesResponse +from .types import ListPlansResponse +from .types import ListPurgeRequestsRequest +from .types import ListPurgeRequestsResponse +from .types import ListTLSStagesRequest +from .types import ListTLSStagesResponse +from .types import Plan +from .types import SelectPlanRequest +from .types import UpdateBackendStageRequest +from .types import UpdateCacheStageRequest +from .types import UpdateDNSStageRequest +from .types import UpdatePipelineRequest +from .types import UpdateTLSStageRequest +from .api import EdgeServicesV1Alpha1API + +__all__ = [ + "DNSStageType", + "LbOriginError", + "ListBackendStagesRequestOrderBy", + "ListCacheStagesRequestOrderBy", + "ListDNSStagesRequestOrderBy", + "ListPipelinesRequestOrderBy", + "ListPipelinesWithStagesRequestOrderBy", + "ListPurgeRequestsRequestOrderBy", + "ListTLSStagesRequestOrderBy", + "PipelineErrorCode", + "PipelineErrorSeverity", + "PipelineErrorStage", + "PipelineErrorType", + "PipelineStatus", + "PIPELINE_TRANSIENT_STATUSES", + "PlanName", + "PurgeRequestStatus", + "PURGE_REQUEST_TRANSIENT_STATUSES", + "ScalewayLb", + "ScalewayLbBackendConfig", + "ScalewayS3BackendConfig", + "PipelineError", + "TLSSecret", + "BackendStage", + "CacheStage", + "DNSStage", + "Pipeline", + "TLSStage", + "CheckPEMChainRequestSecretChain", + "PlanDetails", + "PlanUsageDetails", + "PipelineStages", + "PurgeRequest", + "TLSSecretsConfig", + "CheckDomainRequest", + "CheckDomainResponse", + "CheckLbOriginRequest", + "CheckLbOriginResponse", + "CheckPEMChainRequest", + "CheckPEMChainResponse", + "CreateBackendStageRequest", + "CreateCacheStageRequest", + "CreateDNSStageRequest", + "CreatePipelineRequest", + "CreatePurgeRequestRequest", + "CreateTLSStageRequest", + "DeleteBackendStageRequest", + "DeleteCacheStageRequest", + "DeleteCurrentPlanRequest", + "DeleteDNSStageRequest", + "DeletePipelineRequest", + "DeleteTLSStageRequest", + "GetBackendStageRequest", + "GetBillingRequest", + "GetBillingResponse", + "GetCacheStageRequest", + "GetCurrentPlanRequest", + "GetDNSStageRequest", + "GetPipelineRequest", + "GetPurgeRequestRequest", + "GetTLSStageRequest", + "ListBackendStagesRequest", + "ListBackendStagesResponse", + "ListCacheStagesRequest", + "ListCacheStagesResponse", + "ListDNSStagesRequest", + "ListDNSStagesResponse", + "ListPipelinesRequest", + "ListPipelinesResponse", + "ListPipelinesWithStagesRequest", + "ListPipelinesWithStagesResponse", + "ListPlansResponse", + "ListPurgeRequestsRequest", + "ListPurgeRequestsResponse", + "ListTLSStagesRequest", + "ListTLSStagesResponse", + "Plan", + "SelectPlanRequest", + "UpdateBackendStageRequest", + "UpdateCacheStageRequest", + "UpdateDNSStageRequest", + "UpdatePipelineRequest", + "UpdateTLSStageRequest", + "EdgeServicesV1Alpha1API", +] diff --git a/scaleway-async/scaleway_async/edge_services/v1alpha1/api.py b/scaleway-async/scaleway_async/edge_services/v1alpha1/api.py new file mode 100644 index 00000000..094f79c2 --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1alpha1/api.py @@ -0,0 +1,1827 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + ListBackendStagesRequestOrderBy, + ListCacheStagesRequestOrderBy, + ListDNSStagesRequestOrderBy, + ListPipelinesRequestOrderBy, + ListPipelinesWithStagesRequestOrderBy, + ListPurgeRequestsRequestOrderBy, + ListTLSStagesRequestOrderBy, + PlanName, + BackendStage, + CacheStage, + CheckDomainRequest, + CheckDomainResponse, + CheckLbOriginRequest, + CheckLbOriginResponse, + CheckPEMChainRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainResponse, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateTLSStageRequest, + DNSStage, + GetBillingResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListTLSStagesResponse, + Pipeline, + PipelineStages, + Plan, + PurgeRequest, + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + SelectPlanRequest, + TLSSecret, + TLSSecretsConfig, + TLSStage, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + UpdateTLSStageRequest, +) +from .content import ( + PIPELINE_TRANSIENT_STATUSES, + PURGE_REQUEST_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_BackendStage, + unmarshal_CacheStage, + unmarshal_DNSStage, + unmarshal_Pipeline, + unmarshal_TLSStage, + unmarshal_PurgeRequest, + unmarshal_CheckDomainResponse, + unmarshal_CheckLbOriginResponse, + unmarshal_CheckPEMChainResponse, + unmarshal_GetBillingResponse, + unmarshal_ListBackendStagesResponse, + unmarshal_ListCacheStagesResponse, + unmarshal_ListDNSStagesResponse, + unmarshal_ListPipelinesResponse, + unmarshal_ListPipelinesWithStagesResponse, + unmarshal_ListPlansResponse, + unmarshal_ListPurgeRequestsResponse, + unmarshal_ListTLSStagesResponse, + unmarshal_Plan, + marshal_CheckDomainRequest, + marshal_CheckLbOriginRequest, + marshal_CheckPEMChainRequest, + marshal_CreateBackendStageRequest, + marshal_CreateCacheStageRequest, + marshal_CreateDNSStageRequest, + marshal_CreatePipelineRequest, + marshal_CreatePurgeRequestRequest, + marshal_CreateTLSStageRequest, + marshal_SelectPlanRequest, + marshal_UpdateBackendStageRequest, + marshal_UpdateCacheStageRequest, + marshal_UpdateDNSStageRequest, + marshal_UpdatePipelineRequest, + marshal_UpdateTLSStageRequest, +) + + +class EdgeServicesV1Alpha1API(API): + """ """ + + async def list_pipelines( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> ListPipelinesResponse: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for, only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for, only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for, only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage, only pipelines with a Load Balancer origin will be returned. + :return: :class:`ListPipelinesResponse ` + + Usage: + :: + + result = await api.list_pipelines() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/pipelines", + params={ + "has_backend_stage_lb": has_backend_stage_lb, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesResponse(res.json()) + + async def list_pipelines_all( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> List[Pipeline]: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for, only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for, only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for, only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage, only pipelines with a Load Balancer origin will be returned. + :return: :class:`List[Pipeline] ` + + Usage: + :: + + result = await api.list_pipelines_all() + """ + + return await fetch_all_pages_async( + type=ListPipelinesResponse, + key="pipelines", + fetcher=self.list_pipelines, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + "has_backend_stage_lb": has_backend_stage_lb, + }, + ) + + async def create_pipeline( + self, + *, + name: str, + description: str, + project_id: Optional[str] = None, + dns_stage_id: Optional[str] = None, + ) -> Pipeline: + """ + Create pipeline. + Create a new pipeline. You must specify a `dns_stage_id` to form a stage-chain that goes all the way to the backend stage (origin), so the HTTP request will be processed according to the stages you created. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :param project_id: Project ID in which the pipeline will be created. + :param dns_stage_id: DNS stage ID the pipeline will be attached to. + One-Of ('head'): at most one of 'dns_stage_id' could be set. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.create_pipeline( + name="example", + description="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/pipelines", + body=marshal_CreatePipelineRequest( + CreatePipelineRequest( + name=name, + description=description, + project_id=project_id, + dns_stage_id=dns_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + async def get_pipeline( + self, + *, + pipeline_id: str, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.get_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + async def wait_for_pipeline( + self, + *, + pipeline_id: str, + options: Optional[ + WaitForOptions[Pipeline, Union[bool, Awaitable[bool]]] + ] = None, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.get_pipeline( + pipeline_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in PIPELINE_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_pipeline, + options=options, + args={ + "pipeline_id": pipeline_id, + }, + ) + + async def list_pipelines_with_stages( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> ListPipelinesWithStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`ListPipelinesWithStagesResponse ` + + Usage: + :: + + result = await api.list_pipelines_with_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/pipelines-stages", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesWithStagesResponse(res.json()) + + async def list_pipelines_with_stages_all( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> List[PipelineStages]: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`List[PipelineStages] ` + + Usage: + :: + + result = await api.list_pipelines_with_stages_all() + """ + + return await fetch_all_pages_async( + type=ListPipelinesWithStagesResponse, + key="pipelines", + fetcher=self.list_pipelines_with_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + }, + ) + + async def update_pipeline( + self, + *, + pipeline_id: str, + name: Optional[str] = None, + description: Optional[str] = None, + dns_stage_id: Optional[str] = None, + ) -> Pipeline: + """ + Update pipeline. + Update the parameters of an existing pipeline, specified by its `pipeline_id`. Parameters which can be updated include the `name`, `description` and `dns_stage_id`. + :param pipeline_id: ID of the pipeline to update. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :param dns_stage_id: DNS stage ID the pipeline will be attached to. + One-Of ('head'): at most one of 'dns_stage_id' could be set. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.update_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "PATCH", + f"/edge-services/v1alpha1/pipelines/{param_pipeline_id}", + body=marshal_UpdatePipelineRequest( + UpdatePipelineRequest( + pipeline_id=pipeline_id, + name=name, + description=description, + dns_stage_id=dns_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + async def delete_pipeline( + self, + *, + pipeline_id: str, + ) -> None: + """ + Delete pipeline. + Delete an existing pipeline, specified by its `pipeline_id`. Deleting a pipeline is permanent, and cannot be undone. Note that all stages linked to the pipeline are also deleted. + :param pipeline_id: ID of the pipeline to delete. + + Usage: + :: + + result = await api.delete_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + + async def list_dns_stages( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + fqdn: Optional[str] = None, + ) -> ListDNSStagesResponse: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only DNS stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only DNS stages from this Project will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com), only DNS stages with this FQDN will be returned. + :return: :class:`ListDNSStagesResponse ` + + Usage: + :: + + result = await api.list_dns_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/dns-stages", + params={ + "fqdn": fqdn, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDNSStagesResponse(res.json()) + + async def list_dns_stages_all( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + fqdn: Optional[str] = None, + ) -> List[DNSStage]: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only DNS stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only DNS stages from this Project will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com), only DNS stages with this FQDN will be returned. + :return: :class:`List[DNSStage] ` + + Usage: + :: + + result = await api.list_dns_stages_all() + """ + + return await fetch_all_pages_async( + type=ListDNSStagesResponse, + key="stages", + fetcher=self.list_dns_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "project_id": project_id, + "fqdn": fqdn, + }, + ) + + async def create_dns_stage( + self, + *, + project_id: Optional[str] = None, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> DNSStage: + """ + Create DNS stage. + Create a new DNS stage. You must specify the `fqdns` field to customize the domain endpoint, using a domain you already own. + :param project_id: Project ID in which the DNS stage will be created. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`DNSStage ` + + Usage: + :: + + result = await api.create_dns_stage() + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/dns-stages", + body=marshal_CreateDNSStageRequest( + CreateDNSStageRequest( + project_id=project_id, + fqdns=fqdns, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + async def get_dns_stage( + self, + *, + dns_stage_id: str, + ) -> DNSStage: + """ + Get DNS stage. + Retrieve information about an existing DNS stage, specified by its `dns_stage_id`. Its full details, including FQDNs, are returned in the response object. + :param dns_stage_id: ID of the requested DNS stage. + :return: :class:`DNSStage ` + + Usage: + :: + + result = await api.get_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + async def update_dns_stage( + self, + *, + dns_stage_id: str, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> DNSStage: + """ + Update DNS stage. + Update the parameters of an existing DNS stage, specified by its `dns_stage_id`. + :param dns_stage_id: ID of the DNS stage to update. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`DNSStage ` + + Usage: + :: + + result = await api.update_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1alpha1/dns-stages/{param_dns_stage_id}", + body=marshal_UpdateDNSStageRequest( + UpdateDNSStageRequest( + dns_stage_id=dns_stage_id, + fqdns=fqdns, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + async def delete_dns_stage( + self, + *, + dns_stage_id: str, + ) -> None: + """ + Delete DNS stage. + Delete an existing DNS stage, specified by its `dns_stage_id`. Deleting a DNS stage is permanent, and cannot be undone. + :param dns_stage_id: ID of the DNS stage to delete. + + Usage: + :: + + result = await api.delete_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + + async def list_tls_stages( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> ListTLSStagesResponse: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only TLS stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only TLS stages from this Project will be returned. + :param secret_id: Secret ID to filter for, only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for, only TLS stages with a Secret in this region will be returned. + :return: :class:`ListTLSStagesResponse ` + + Usage: + :: + + result = await api.list_tls_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/tls-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListTLSStagesResponse(res.json()) + + async def list_tls_stages_all( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> List[TLSStage]: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only TLS stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only TLS stages from this Project will be returned. + :param secret_id: Secret ID to filter for, only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for, only TLS stages with a Secret in this region will be returned. + :return: :class:`List[TLSStage] ` + + Usage: + :: + + result = await api.list_tls_stages_all() + """ + + return await fetch_all_pages_async( + type=ListTLSStagesResponse, + key="stages", + fetcher=self.list_tls_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "project_id": project_id, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + async def create_tls_stage( + self, + *, + project_id: Optional[str] = None, + secrets: Optional[List[TLSSecret]] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Create TLS stage. + Create a new TLS stage. You must specify either the `secrets` or `managed_certificate` fields to customize the SSL/TLS certificate of your endpoint. Choose `secrets` if you are using a pre-existing certificate held in Scaleway Secret Manager, or `managed_certificate` to let Scaleway generate and manage a Let's Encrypt certificate for your customized endpoint. + :param project_id: Project ID in which the TLS stage will be created. + :param secrets: Secret (from Scaleway Secret Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = await api.create_tls_stage() + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/tls-stages", + body=marshal_CreateTLSStageRequest( + CreateTLSStageRequest( + project_id=project_id, + secrets=secrets, + managed_certificate=managed_certificate, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + async def get_tls_stage( + self, + *, + tls_stage_id: str, + ) -> TLSStage: + """ + Get TLS stage. + Retrieve information about an existing TLS stage, specified by its `tls_stage_id`. Its full details, including secrets and certificate expiration date are returned in the response object. + :param tls_stage_id: ID of the requested TLS stage. + :return: :class:`TLSStage ` + + Usage: + :: + + result = await api.get_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + async def update_tls_stage( + self, + *, + tls_stage_id: str, + tls_secrets_config: Optional[TLSSecretsConfig] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Update TLS stage. + Update the parameters of an existing TLS stage, specified by its `tls_stage_id`. Both `tls_secrets_config` and `managed_certificate` parameters can be updated. + :param tls_stage_id: ID of the TLS stage to update. + :param tls_secrets_config: Secret (from Scaleway Secret-Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = await api.update_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1alpha1/tls-stages/{param_tls_stage_id}", + body=marshal_UpdateTLSStageRequest( + UpdateTLSStageRequest( + tls_stage_id=tls_stage_id, + tls_secrets_config=tls_secrets_config, + managed_certificate=managed_certificate, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + async def delete_tls_stage( + self, + *, + tls_stage_id: str, + ) -> None: + """ + Delete TLS stage. + Delete an existing TLS stage, specified by its `tls_stage_id`. Deleting a TLS stage is permanent, and cannot be undone. + :param tls_stage_id: ID of the TLS stage to delete. + + Usage: + :: + + result = await api.delete_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + + async def list_cache_stages( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> ListCacheStagesResponse: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only cache stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only cache stages from this Project will be returned. + :return: :class:`ListCacheStagesResponse ` + + Usage: + :: + + result = await api.list_cache_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/cache-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListCacheStagesResponse(res.json()) + + async def list_cache_stages_all( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> List[CacheStage]: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only cache stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only cache stages from this Project will be returned. + :return: :class:`List[CacheStage] ` + + Usage: + :: + + result = await api.list_cache_stages_all() + """ + + return await fetch_all_pages_async( + type=ListCacheStagesResponse, + key="stages", + fetcher=self.list_cache_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "project_id": project_id, + }, + ) + + async def create_cache_stage( + self, + *, + project_id: Optional[str] = None, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Create cache stage. + Create a new cache stage. You must specify the `fallback_ttl` field to customize the TTL of the cache. + :param project_id: Project ID in which the cache stage will be created. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = await api.create_cache_stage() + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/cache-stages", + body=marshal_CreateCacheStageRequest( + CreateCacheStageRequest( + project_id=project_id, + fallback_ttl=fallback_ttl, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + async def get_cache_stage( + self, + *, + cache_stage_id: str, + ) -> CacheStage: + """ + Get cache stage. + Retrieve information about an existing cache stage, specified by its `cache_stage_id`. Its full details, including Time To Live (TTL), are returned in the response object. + :param cache_stage_id: ID of the requested cache stage. + :return: :class:`CacheStage ` + + Usage: + :: + + result = await api.get_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + async def update_cache_stage( + self, + *, + cache_stage_id: str, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Update cache stage. + Update the parameters of an existing cache stage, specified by its `cache_stage_id`. Parameters which can be updated include the `fallback_ttl` and `backend_stage_id`. + :param cache_stage_id: ID of the cache stage to update. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = await api.update_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1alpha1/cache-stages/{param_cache_stage_id}", + body=marshal_UpdateCacheStageRequest( + UpdateCacheStageRequest( + cache_stage_id=cache_stage_id, + fallback_ttl=fallback_ttl, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + async def delete_cache_stage( + self, + *, + cache_stage_id: str, + ) -> None: + """ + Delete cache stage. + Delete an existing cache stage, specified by its `cache_stage_id`. Deleting a cache stage is permanent, and cannot be undone. + :param cache_stage_id: ID of the cache stage to delete. + + Usage: + :: + + result = await api.delete_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + + async def list_backend_stages( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> ListBackendStagesResponse: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only backend stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only backend stages from this Project will be returned. + :param bucket_name: Bucket name to filter for, only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for, only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for, only backend stages with this Load Balancer will be returned. + :return: :class:`ListBackendStagesResponse ` + + Usage: + :: + + result = await api.list_backend_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/backend-stages", + params={ + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBackendStagesResponse(res.json()) + + async def list_backend_stages_all( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> List[BackendStage]: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only backend stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only backend stages from this Project will be returned. + :param bucket_name: Bucket name to filter for, only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for, only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for, only backend stages with this Load Balancer will be returned. + :return: :class:`List[BackendStage] ` + + Usage: + :: + + result = await api.list_backend_stages_all() + """ + + return await fetch_all_pages_async( + type=ListBackendStagesResponse, + key="stages", + fetcher=self.list_backend_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "project_id": project_id, + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + }, + ) + + async def create_backend_stage( + self, + *, + project_id: Optional[str] = None, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + ) -> BackendStage: + """ + Create backend stage. + Create a new backend stage. You must specify either a `scaleway_s3` (for a Scaleway Object Storage bucket) or `scaleway_lb` (for a Scaleway Load Balancer) field to configure the origin. + :param project_id: Project ID in which the backend stage will be created. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :return: :class:`BackendStage ` + + Usage: + :: + + result = await api.create_backend_stage() + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/backend-stages", + body=marshal_CreateBackendStageRequest( + CreateBackendStageRequest( + project_id=project_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + async def get_backend_stage( + self, + *, + backend_stage_id: str, + ) -> BackendStage: + """ + Get backend stage. + Retrieve information about an existing backend stage, specified by its `backend_stage_id`. Its full details, including `scaleway_s3` or `scaleway_lb`, are returned in the response object. + :param backend_stage_id: ID of the requested backend stage. + :return: :class:`BackendStage ` + + Usage: + :: + + result = await api.get_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + async def update_backend_stage( + self, + *, + backend_stage_id: str, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + ) -> BackendStage: + """ + Update backend stage. + Update the parameters of an existing backend stage, specified by its `backend_stage_id`. + :param backend_stage_id: ID of the backend stage to update. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :return: :class:`BackendStage ` + + Usage: + :: + + result = await api.update_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "PATCH", + f"/edge-services/v1alpha1/backend-stages/{param_backend_stage_id}", + body=marshal_UpdateBackendStageRequest( + UpdateBackendStageRequest( + backend_stage_id=backend_stage_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + async def delete_backend_stage( + self, + *, + backend_stage_id: str, + ) -> None: + """ + Delete backend stage. + Delete an existing backend stage, specified by its `backend_stage_id`. Deleting a backend stage is permanent, and cannot be undone. + :param backend_stage_id: ID of the backend stage to delete. + + Usage: + :: + + result = await api.delete_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + + async def check_domain( + self, + *, + fqdn: str, + cname: str, + project_id: Optional[str] = None, + ) -> CheckDomainResponse: + """ + :param fqdn: + :param cname: + :param project_id: + :return: :class:`CheckDomainResponse ` + + Usage: + :: + + result = await api.check_domain( + fqdn="example", + cname="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/check-domain", + body=marshal_CheckDomainRequest( + CheckDomainRequest( + fqdn=fqdn, + cname=cname, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckDomainResponse(res.json()) + + async def check_pem_chain( + self, + *, + fqdn: str, + project_id: Optional[str] = None, + secret: Optional[CheckPEMChainRequestSecretChain] = None, + raw: Optional[str] = None, + ) -> CheckPEMChainResponse: + """ + :param fqdn: + :param project_id: + :param secret: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :param raw: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :return: :class:`CheckPEMChainResponse ` + + Usage: + :: + + result = await api.check_pem_chain( + fqdn="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/check-pem-chain", + body=marshal_CheckPEMChainRequest( + CheckPEMChainRequest( + fqdn=fqdn, + project_id=project_id, + secret=secret, + raw=raw, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckPEMChainResponse(res.json()) + + async def list_purge_requests( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> ListPurgeRequestsResponse: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for, only purge requests from this Project will be returned. + :param project_id: Project ID to filter for, only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for, only purge requests from this pipeline will be returned. + :return: :class:`ListPurgeRequestsResponse ` + + Usage: + :: + + result = await api.list_purge_requests() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/purge-requests", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPurgeRequestsResponse(res.json()) + + async def list_purge_requests_all( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> List[PurgeRequest]: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for, only purge requests from this Project will be returned. + :param project_id: Project ID to filter for, only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for, only purge requests from this pipeline will be returned. + :return: :class:`List[PurgeRequest] ` + + Usage: + :: + + result = await api.list_purge_requests_all() + """ + + return await fetch_all_pages_async( + type=ListPurgeRequestsResponse, + key="purge_requests", + fetcher=self.list_purge_requests, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "pipeline_id": pipeline_id, + }, + ) + + async def create_purge_request( + self, + *, + pipeline_id: str, + assets: Optional[List[str]] = None, + all: Optional[bool] = None, + ) -> PurgeRequest: + """ + Create purge request. + Create a new purge request. You must specify either the `all` field (to purge all content) or a list of `assets` (to define the precise assets to purge). + :param pipeline_id: Pipeline ID in which the purge request will be created. + :param assets: List of asserts to purge. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :param all: Defines whether to purge all content. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = await api.create_purge_request( + pipeline_id="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/purge-requests", + body=marshal_CreatePurgeRequestRequest( + CreatePurgeRequestRequest( + pipeline_id=pipeline_id, + assets=assets, + all=all, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + async def get_purge_request( + self, + *, + purge_request_id: str, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = await api.get_purge_request( + purge_request_id="example", + ) + """ + + param_purge_request_id = validate_path_param( + "purge_request_id", purge_request_id + ) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/purge-requests/{param_purge_request_id}", + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + async def wait_for_purge_request( + self, + *, + purge_request_id: str, + options: Optional[ + WaitForOptions[PurgeRequest, Union[bool, Awaitable[bool]]] + ] = None, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = await api.get_purge_request( + purge_request_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in PURGE_REQUEST_TRANSIENT_STATUSES + ) + + return await wait_for_resource_async( + fetcher=self.get_purge_request, + options=options, + args={ + "purge_request_id": purge_request_id, + }, + ) + + async def check_lb_origin( + self, + *, + lb: Optional[ScalewayLb] = None, + ) -> CheckLbOriginResponse: + """ + :param lb: + :return: :class:`CheckLbOriginResponse ` + + Usage: + :: + + result = await api.check_lb_origin() + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/check-lb-origin", + body=marshal_CheckLbOriginRequest( + CheckLbOriginRequest( + lb=lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckLbOriginResponse(res.json()) + + async def list_plans( + self, + ) -> ListPlansResponse: + """ + + :return: :class:`ListPlansResponse ` + + Usage: + :: + + result = await api.list_plans() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/plans", + ) + + self._throw_on_error(res) + return unmarshal_ListPlansResponse(res.json()) + + async def select_plan( + self, + *, + project_id: Optional[str] = None, + plan_name: Optional[PlanName] = None, + ) -> Plan: + """ + :param project_id: + :param plan_name: + :return: :class:`Plan ` + + Usage: + :: + + result = await api.select_plan() + """ + + res = self._request( + "PATCH", + "/edge-services/v1alpha1/current-plan", + body=marshal_SelectPlanRequest( + SelectPlanRequest( + project_id=project_id, + plan_name=plan_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + async def get_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> Plan: + """ + :param project_id: + :return: :class:`Plan ` + + Usage: + :: + + result = await api.get_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + async def delete_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> None: + """ + :param project_id: + + Usage: + :: + + result = await api.delete_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + + async def get_billing( + self, + *, + project_id: Optional[str] = None, + ) -> GetBillingResponse: + """ + Gives information on the currently selected Edge Services subscription plan, resource usage and associated billing information for this calendar month (including whether consumption falls within or exceeds the currently selected subscription plan.). + :param project_id: + :return: :class:`GetBillingResponse ` + + Usage: + :: + + result = await api.get_billing() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/billing/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_GetBillingResponse(res.json()) diff --git a/scaleway-async/scaleway_async/edge_services/v1alpha1/content.py b/scaleway-async/scaleway_async/edge_services/v1alpha1/content.py new file mode 100644 index 00000000..ad1b5e0e --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1alpha1/content.py @@ -0,0 +1,21 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + PipelineStatus, + PurgeRequestStatus, +) + +PIPELINE_TRANSIENT_STATUSES: List[PipelineStatus] = [ + PipelineStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PipelineStatus `. +""" +PURGE_REQUEST_TRANSIENT_STATUSES: List[PurgeRequestStatus] = [ + PurgeRequestStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PurgeRequestStatus `. +""" diff --git a/scaleway-async/scaleway_async/edge_services/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/edge_services/v1alpha1/marshalling.py new file mode 100644 index 00000000..f9145ff0 --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1alpha1/marshalling.py @@ -0,0 +1,1334 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + BackendStage, + CacheStage, + DNSStage, + PipelineError, + Pipeline, + TLSSecret, + TLSStage, + PipelineStages, + PurgeRequest, + CheckDomainResponse, + CheckLbOriginResponse, + CheckPEMChainResponse, + PlanDetails, + PlanUsageDetails, + GetBillingResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListTLSStagesResponse, + Plan, + CheckDomainRequest, + CheckLbOriginRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainRequest, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateTLSStageRequest, + SelectPlanRequest, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + TLSSecretsConfig, + UpdateTLSStageRequest, +) + + +def unmarshal_ScalewayLb(data: Any) -> ScalewayLb: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLb' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("frontend_id", None) + if field is not None: + args["frontend_id"] = field + + field = data.get("is_ssl", None) + if field is not None: + args["is_ssl"] = field + else: + args["is_ssl"] = None + + field = data.get("domain_name", None) + if field is not None: + args["domain_name"] = field + else: + args["domain_name"] = None + + return ScalewayLb(**args) + + +def unmarshal_ScalewayLbBackendConfig(data: Any) -> ScalewayLbBackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLbBackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("lbs", None) + if field is not None: + args["lbs"] = ( + [unmarshal_ScalewayLb(v) for v in field] if field is not None else None + ) + + return ScalewayLbBackendConfig(**args) + + +def unmarshal_ScalewayS3BackendConfig(data: Any) -> ScalewayS3BackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayS3BackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bucket_name", None) + if field is not None: + args["bucket_name"] = field + else: + args["bucket_name"] = None + + field = data.get("bucket_region", None) + if field is not None: + args["bucket_region"] = field + else: + args["bucket_region"] = None + + field = data.get("is_website", None) + if field is not None: + args["is_website"] = field + else: + args["is_website"] = None + + return ScalewayS3BackendConfig(**args) + + +def unmarshal_BackendStage(data: Any) -> BackendStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BackendStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + else: + args["pipeline_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("scaleway_s3", None) + if field is not None: + args["scaleway_s3"] = unmarshal_ScalewayS3BackendConfig(field) + else: + args["scaleway_s3"] = None + + field = data.get("scaleway_lb", None) + if field is not None: + args["scaleway_lb"] = unmarshal_ScalewayLbBackendConfig(field) + else: + args["scaleway_lb"] = None + + return BackendStage(**args) + + +def unmarshal_CacheStage(data: Any) -> CacheStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CacheStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + else: + args["pipeline_id"] = None + + field = data.get("fallback_ttl", None) + if field is not None: + args["fallback_ttl"] = field + else: + args["fallback_ttl"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return CacheStage(**args) + + +def unmarshal_DNSStage(data: Any) -> DNSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DNSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("fqdns", None) + if field is not None: + args["fqdns"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + else: + args["pipeline_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("tls_stage_id", None) + if field is not None: + args["tls_stage_id"] = field + else: + args["tls_stage_id"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return DNSStage(**args) + + +def unmarshal_PipelineError(data: Any) -> PipelineError: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineError' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stage", None) + if field is not None: + args["stage"] = field + + field = data.get("code", None) + if field is not None: + args["code"] = field + + field = data.get("severity", None) + if field is not None: + args["severity"] = field + + field = data.get("message", None) + if field is not None: + args["message"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return PipelineError(**args) + + +def unmarshal_Pipeline(data: Any) -> Pipeline: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pipeline' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("errors", None) + if field is not None: + args["errors"] = ( + [unmarshal_PipelineError(v) for v in field] if field is not None else None + ) + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("dns_stage_id", None) + if field is not None: + args["dns_stage_id"] = field + else: + args["dns_stage_id"] = None + + return Pipeline(**args) + + +def unmarshal_TLSSecret(data: Any) -> TLSSecret: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSSecret' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secret_id", None) + if field is not None: + args["secret_id"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + return TLSSecret(**args) + + +def unmarshal_TLSStage(data: Any) -> TLSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("secrets", None) + if field is not None: + args["secrets"] = ( + [unmarshal_TLSSecret(v) for v in field] if field is not None else None + ) + + field = data.get("managed_certificate", None) + if field is not None: + args["managed_certificate"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + else: + args["pipeline_id"] = None + + field = data.get("certificate_expires_at", None) + if field is not None: + args["certificate_expires_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["certificate_expires_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return TLSStage(**args) + + +def unmarshal_PipelineStages(data: Any) -> PipelineStages: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineStages' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stages", None) + if field is not None: + args["dns_stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("tls_stages", None) + if field is not None: + args["tls_stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("cache_stages", None) + if field is not None: + args["cache_stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("backend_stages", None) + if field is not None: + args["backend_stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("pipeline", None) + if field is not None: + args["pipeline"] = unmarshal_Pipeline(field) + else: + args["pipeline"] = None + + return PipelineStages(**args) + + +def unmarshal_PurgeRequest(data: Any) -> PurgeRequest: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PurgeRequest' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("assets", None) + if field is not None: + args["assets"] = field + else: + args["assets"] = None + + field = data.get("all", None) + if field is not None: + args["all"] = field + else: + args["all"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return PurgeRequest(**args) + + +def unmarshal_CheckDomainResponse(data: Any) -> CheckDomainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckDomainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckDomainResponse(**args) + + +def unmarshal_CheckLbOriginResponse(data: Any) -> CheckLbOriginResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckLbOriginResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + field = data.get("error_type", None) + if field is not None: + args["error_type"] = field + + return CheckLbOriginResponse(**args) + + +def unmarshal_CheckPEMChainResponse(data: Any) -> CheckPEMChainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckPEMChainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckPEMChainResponse(**args) + + +def unmarshal_PlanDetails(data: Any) -> PlanDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + field = data.get("package_gb", None) + if field is not None: + args["package_gb"] = field + + field = data.get("pipeline_limit", None) + if field is not None: + args["pipeline_limit"] = field + + field = data.get("waf_requests", None) + if field is not None: + args["waf_requests"] = field + + return PlanDetails(**args) + + +def unmarshal_PlanUsageDetails(data: Any) -> PlanUsageDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanUsageDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + return PlanUsageDetails(**args) + + +def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetBillingResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("current_plan", None) + if field is not None: + args["current_plan"] = unmarshal_PlanDetails(field) + else: + args["current_plan"] = None + + field = data.get("pipeline_number", None) + if field is not None: + args["pipeline_number"] = field + + field = data.get("current_plan_cache_usage", None) + if field is not None: + args["current_plan_cache_usage"] = field + + field = data.get("extra_cache_usage", None) + if field is not None: + args["extra_cache_usage"] = field + + field = data.get("current_plan_waf_usage", None) + if field is not None: + args["current_plan_waf_usage"] = field + + field = data.get("extra_waf_usage", None) + if field is not None: + args["extra_waf_usage"] = field + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + field = data.get("extra_pipelines_cost", None) + if field is not None: + args["extra_pipelines_cost"] = unmarshal_Money(field) + else: + args["extra_pipelines_cost"] = None + + field = data.get("plans_usage_details", None) + if field is not None: + args["plans_usage_details"] = ( + {key: unmarshal_PlanUsageDetails(value) for key, value in field.items()} + if field is not None + else None + ) + + field = data.get("extra_cache_cost", None) + if field is not None: + args["extra_cache_cost"] = unmarshal_Money(field) + else: + args["extra_cache_cost"] = None + + field = data.get("extra_waf_cost", None) + if field is not None: + args["extra_waf_cost"] = unmarshal_Money(field) + else: + args["extra_waf_cost"] = None + + field = data.get("waf_add_on", None) + if field is not None: + args["waf_add_on"] = unmarshal_Money(field) + else: + args["waf_add_on"] = None + + field = data.get("total_cost", None) + if field is not None: + args["total_cost"] = unmarshal_Money(field) + else: + args["total_cost"] = None + + return GetBillingResponse(**args) + + +def unmarshal_ListBackendStagesResponse(data: Any) -> ListBackendStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListBackendStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListBackendStagesResponse(**args) + + +def unmarshal_ListCacheStagesResponse(data: Any) -> ListCacheStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListCacheStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListCacheStagesResponse(**args) + + +def unmarshal_ListDNSStagesResponse(data: Any) -> ListDNSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDNSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDNSStagesResponse(**args) + + +def unmarshal_ListPipelinesResponse(data: Any) -> ListPipelinesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_Pipeline(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesResponse(**args) + + +def unmarshal_ListPipelinesWithStagesResponse( + data: Any, +) -> ListPipelinesWithStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesWithStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_PipelineStages(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesWithStagesResponse(**args) + + +def unmarshal_ListPlansResponse(data: Any) -> ListPlansResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPlansResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("plans", None) + if field is not None: + args["plans"] = ( + [unmarshal_PlanDetails(v) for v in field] if field is not None else None + ) + + return ListPlansResponse(**args) + + +def unmarshal_ListPurgeRequestsResponse(data: Any) -> ListPurgeRequestsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPurgeRequestsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("purge_requests", None) + if field is not None: + args["purge_requests"] = ( + [unmarshal_PurgeRequest(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPurgeRequestsResponse(**args) + + +def unmarshal_ListTLSStagesResponse(data: Any) -> ListTLSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListTLSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListTLSStagesResponse(**args) + + +def unmarshal_Plan(data: Any) -> Plan: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Plan' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + return Plan(**args) + + +def marshal_CheckDomainRequest( + request: CheckDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.cname is not None: + output["cname"] = request.cname + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLb( + request: ScalewayLb, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.id is not None: + output["id"] = request.id + + if request.zone is not None: + output["zone"] = request.zone or defaults.default_zone + + if request.frontend_id is not None: + output["frontend_id"] = request.frontend_id + + if request.is_ssl is not None: + output["is_ssl"] = request.is_ssl + + if request.domain_name is not None: + output["domain_name"] = request.domain_name + + return output + + +def marshal_CheckLbOriginRequest( + request: CheckLbOriginRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lb is not None: + output["lb"] = marshal_ScalewayLb(request.lb, defaults) + + return output + + +def marshal_CheckPEMChainRequestSecretChain( + request: CheckPEMChainRequestSecretChain, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.secret_region is not None: + output["secret_region"] = request.secret_region + + return output + + +def marshal_CheckPEMChainRequest( + request: CheckPEMChainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("secret", request.secret), + OneOfPossibility("raw", request.raw), + ] + ), + ) + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLbBackendConfig( + request: ScalewayLbBackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lbs is not None: + output["lbs"] = [marshal_ScalewayLb(item, defaults) for item in request.lbs] + + return output + + +def marshal_ScalewayS3BackendConfig( + request: ScalewayS3BackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket_name is not None: + output["bucket_name"] = request.bucket_name + + if request.bucket_region is not None: + output["bucket_region"] = request.bucket_region + + if request.is_website is not None: + output["is_website"] = request.is_website + + return output + + +def marshal_CreateBackendStageRequest( + request: CreateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_CreateCacheStageRequest( + request: CreateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_CreateDNSStageRequest( + request: CreateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_CreatePipelineRequest( + request: CreatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("dns_stage_id", request.dns_stage_id), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_CreatePurgeRequestRequest( + request: CreatePurgeRequestRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("assets", request.assets), + OneOfPossibility("all", request.all), + ] + ), + ) + + if request.pipeline_id is not None: + output["pipeline_id"] = request.pipeline_id + + return output + + +def marshal_TLSSecret( + request: TLSSecret, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.region is not None: + output["region"] = request.region or defaults.default_region + + return output + + +def marshal_CreateTLSStageRequest( + request: CreateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.secrets is not None: + output["secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.secrets + ] + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output + + +def marshal_SelectPlanRequest( + request: SelectPlanRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.plan_name is not None: + output["plan_name"] = str(request.plan_name) + + return output + + +def marshal_UpdateBackendStageRequest( + request: UpdateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + return output + + +def marshal_UpdateCacheStageRequest( + request: UpdateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_UpdateDNSStageRequest( + request: UpdateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_UpdatePipelineRequest( + request: UpdatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("dns_stage_id", request.dns_stage_id), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + return output + + +def marshal_TLSSecretsConfig( + request: TLSSecretsConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.tls_secrets is not None: + output["tls_secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.tls_secrets + ] + + return output + + +def marshal_UpdateTLSStageRequest( + request: UpdateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.tls_secrets_config is not None: + output["tls_secrets_config"] = marshal_TLSSecretsConfig( + request.tls_secrets_config, defaults + ) + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output diff --git a/scaleway-async/scaleway_async/edge_services/v1alpha1/types.py b/scaleway-async/scaleway_async/edge_services/v1alpha1/types.py new file mode 100644 index 00000000..a4121656 --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1alpha1/types.py @@ -0,0 +1,1302 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Money, + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DNSStageType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + AUTO = "auto" + MANAGED = "managed" + CUSTOM = "custom" + + def __str__(self) -> str: + return str(self.value) + + +class LbOriginError(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + TIMEOUT = "timeout" + CONNECTION_REFUSED = "connection_refused" + TLS_ERROR = "tls_error" + + def __str__(self) -> str: + return str(self.value) + + +class ListBackendStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListCacheStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListDNSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesWithStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPurgeRequestsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListTLSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorCode(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_CODE = "unknown_code" + DNS_INVALID_FORMAT = "dns_invalid_format" + DNS_INVALID_TLD = "dns_invalid_tld" + DNS_FORBIDDEN_ROOT_DOMAIN = "dns_forbidden_root_domain" + DNS_FORBIDDEN_SCW_CLOUD = "dns_forbidden_scw_cloud" + DNS_DOMAIN_DONT_EXIST = "dns_domain_dont_exist" + DNS_CNAME_DONT_EXIST = "dns_cname_dont_exist" + DNS_CNAME_RESOLVE = "dns_cname_resolve" + DNS_FQDN_ALREADY_EXISTS = "dns_fqdn_already_exists" + DNS_FQDN_ALREADY_IN_USE = "dns_fqdn_already_in_use" + TLS_CERT_DELETED = "tls_cert_deleted" + TLS_CERT_DISABLED = "tls_cert_disabled" + TLS_CERT_EXPIRED = "tls_cert_expired" + TLS_CERT_INVALID_FORMAT = "tls_cert_invalid_format" + TLS_CERT_MISSING = "tls_cert_missing" + TLS_CHAIN_ORDER = "tls_chain_order" + TLS_KEY_INVALID_FORMAT = "tls_key_invalid_format" + TLS_KEY_MISSING = "tls_key_missing" + TLS_KEY_TOO_MANY = "tls_key_too_many" + TLS_MANAGED_DOMAIN_RATE_LIMIT = "tls_managed_domain_rate_limit" + TLS_MANAGED_INTERNAL = "tls_managed_internal" + TLS_PAIR_MISMATCH = "tls_pair_mismatch" + TLS_ROOT_INCONSISTENT = "tls_root_inconsistent" + TLS_ROOT_INCORRECT = "tls_root_incorrect" + TLS_ROOT_MISSING = "tls_root_missing" + TLS_SAN_MISMATCH = "tls_san_mismatch" + TLS_SELF_SIGNED = "tls_self_signed" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorSeverity(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SEVERITY = "unknown_severity" + WARNING = "warning" + CRITICAL = "critical" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorStage(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STAGE = "unknown_stage" + DNS = "dns" + TLS = "tls" + CACHE = "cache" + BACKEND = "backend" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + RUNTIME = "runtime" + CONFIG = "config" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + ERROR = "error" + PENDING = "pending" + WARNING = "warning" + + def __str__(self) -> str: + return str(self.value) + + +class PlanName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + STARTER = "starter" + PROFESSIONAL = "professional" + ADVANCED = "advanced" + + def __str__(self) -> str: + return str(self.value) + + +class PurgeRequestStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DONE = "done" + ERROR = "error" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ScalewayLb: + id: str + """ + ID of the Load Balancer. + """ + + zone: ScwZone + """ + Zone of the Load Balancer. + """ + + frontend_id: str + """ + ID of the frontend linked to the Load Balancer. + """ + + is_ssl: Optional[bool] + """ + Defines whether the Load Balancer's frontend handles SSL connections. + """ + + domain_name: Optional[str] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to use in HTTP requests sent towards your Load Balancer. + """ + + +@dataclass +class ScalewayLbBackendConfig: + lbs: List[ScalewayLb] + """ + Load Balancer information. + """ + + +@dataclass +class ScalewayS3BackendConfig: + bucket_name: Optional[str] + """ + Name of the Bucket. + """ + + bucket_region: Optional[str] + """ + Region of the Bucket. + """ + + is_website: Optional[bool] + """ + Defines whether the bucket website feature is enabled. + """ + + +@dataclass +class PipelineError: + stage: PipelineErrorStage + + code: PipelineErrorCode + + severity: PipelineErrorSeverity + + message: str + + type_: PipelineErrorType + + +@dataclass +class TLSSecret: + secret_id: str + """ + ID of the Secret. + """ + + region: ScwRegion + """ + Region of the Secret. + """ + + +@dataclass +class BackendStage: + id: str + """ + ID of the backend stage. + """ + + project_id: str + """ + Project ID of the backend stage. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID the backend stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the backend stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the backend stage was last updated. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CacheStage: + id: str + """ + ID of the cache stage. + """ + + project_id: str + """ + Project ID of the cache stage. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID the cache stage belongs to. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + created_at: Optional[datetime] + """ + Date the cache stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the cache stage was last updated. + """ + + backend_stage_id: Optional[str] + + +@dataclass +class DNSStage: + id: str + """ + ID of the DNS stage. + """ + + fqdns: List[str] + """ + List of Fully Qualified Domain Names attached to the stage. + """ + + type_: DNSStageType + """ + Type of the stage. + """ + + project_id: str + """ + Project ID of the DNS stage. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID the DNS stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the DNS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the DNS stage was last updated. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class Pipeline: + id: str + """ + ID of the pipeline. + """ + + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + status: PipelineStatus + """ + Status of the pipeline. + """ + + errors: List[PipelineError] + """ + Errors of the pipeline. + """ + + project_id: str + """ + Project ID of the pipeline. + """ + + organization_id: str + """ + Organization ID of the pipeline. + """ + + created_at: Optional[datetime] + """ + Date the pipeline was created. + """ + + updated_at: Optional[datetime] + """ + Date the pipeline was last updated. + """ + + dns_stage_id: Optional[str] + + +@dataclass +class TLSStage: + id: str + """ + ID of the TLS stage. + """ + + secrets: List[TLSSecret] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: bool + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + project_id: str + """ + Project ID of the TLS stage. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID the TLS stage belongs to. + """ + + certificate_expires_at: Optional[datetime] + """ + Expiration date of the certificate. + """ + + created_at: Optional[datetime] + """ + Date the TLS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the TLS stage was last updated. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class CheckPEMChainRequestSecretChain: + secret_id: str + + secret_region: str + + +@dataclass +class PlanDetails: + plan_name: PlanName + """ + Subscription plan name. + """ + + package_gb: int + """ + Amount of egress data from cache included in subscription plan. + """ + + pipeline_limit: int + """ + Number of pipelines included in subscription plan. + """ + + waf_requests: int + """ + Number of WAF requests included in subscription plan. + """ + + +@dataclass +class PlanUsageDetails: + plan_cost: Optional[Money] + """ + Cost to date (this month) for the corresponding Edge Services subscription plan. + """ + + +@dataclass +class PipelineStages: + dns_stages: List[DNSStage] + + tls_stages: List[TLSStage] + + cache_stages: List[CacheStage] + + backend_stages: List[BackendStage] + + pipeline: Optional[Pipeline] + + +@dataclass +class PurgeRequest: + id: str + """ + ID of the purge request. + """ + + pipeline_id: str + """ + Pipeline ID the purge request belongs to. + """ + + status: PurgeRequestStatus + """ + Status of the purge request. + """ + + created_at: Optional[datetime] + """ + Date the purge request was created. + """ + + updated_at: Optional[datetime] + """ + Date the purge request was last updated. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class TLSSecretsConfig: + tls_secrets: List[TLSSecret] + """ + Secret information (from Secret Manager). + """ + + +@dataclass +class CheckDomainRequest: + fqdn: str + + cname: str + + project_id: Optional[str] + + +@dataclass +class CheckDomainResponse: + is_valid: bool + + +@dataclass +class CheckLbOriginRequest: + lb: Optional[ScalewayLb] + + +@dataclass +class CheckLbOriginResponse: + is_valid: bool + + error_type: LbOriginError + + +@dataclass +class CheckPEMChainRequest: + fqdn: str + + project_id: Optional[str] + + secret: Optional[CheckPEMChainRequestSecretChain] + + raw: Optional[str] + + +@dataclass +class CheckPEMChainResponse: + is_valid: bool + + +@dataclass +class CreateBackendStageRequest: + project_id: Optional[str] + """ + Project ID in which the backend stage will be created. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CreateCacheStageRequest: + project_id: Optional[str] + """ + Project ID in which the cache stage will be created. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + backend_stage_id: Optional[str] + + +@dataclass +class CreateDNSStageRequest: + project_id: Optional[str] + """ + Project ID in which the DNS stage will be created. + """ + + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class CreatePipelineRequest: + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + project_id: Optional[str] + """ + Project ID in which the pipeline will be created. + """ + + dns_stage_id: Optional[str] + + +@dataclass +class CreatePurgeRequestRequest: + pipeline_id: str + """ + Pipeline ID in which the purge request will be created. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class CreateTLSStageRequest: + project_id: Optional[str] + """ + Project ID in which the TLS stage will be created. + """ + + secrets: Optional[List[TLSSecret]] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class DeleteBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to delete. + """ + + +@dataclass +class DeleteCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to delete. + """ + + +@dataclass +class DeleteCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class DeleteDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to delete. + """ + + +@dataclass +class DeletePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to delete. + """ + + +@dataclass +class DeleteTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to delete. + """ + + +@dataclass +class GetBackendStageRequest: + backend_stage_id: str + """ + ID of the requested backend stage. + """ + + +@dataclass +class GetBillingRequest: + project_id: Optional[str] + + +@dataclass +class GetBillingResponse: + current_plan: Optional[PlanDetails] + """ + Information on the currently-selected, active Edge Services subscription plan. + """ + + pipeline_number: int + """ + Total number of pipelines currently configured. + """ + + current_plan_cache_usage: int + """ + Total amount of data egressed from the cache in gigabytes from the beginning of the month, for the active subscription plan. + """ + + extra_cache_usage: int + """ + Total amount of extra data egressed from cache in gigabytes from the beginning of the month, not included in the subscription plans. + """ + + current_plan_waf_usage: int + """ + Total number of requests processed by the WAF since the beginning of the current month, for the active subscription plan. + """ + + extra_waf_usage: int + """ + Total number of extra requests processed by the WAF from the beginning of the month, not included in the subscription plans. + """ + + plan_cost: Optional[Money] + """ + Cost to date (this month) for Edge Service subscription plans. This comprises the pro-rata cost of the current subscription plan, and any previous subscription plans that were active earlier in the month. + """ + + extra_pipelines_cost: Optional[Money] + """ + Cost to date (this month) of pipelines not included in the subscription plans. + """ + + plans_usage_details: Dict[str, PlanUsageDetails] + """ + Detailed costs and usage for all Edge Services subscription plans that were activated during the month. + """ + + extra_cache_cost: Optional[Money] + """ + Cost to date (this month) of the data egressed from the cache that is not included in the subscription plans. + """ + + extra_waf_cost: Optional[Money] + """ + Cost to date (this month) of the extra requests processed by the WAF that were not included in the subscription plans. + """ + + waf_add_on: Optional[Money] + """ + Cost of activating WAF add-on (where subscription plan does not include WAF). + """ + + total_cost: Optional[Money] + """ + Total cost to date (this month) of all Edge Services resources including active subscription plan, previously active plans, extra pipelines and extra egress cache data. + """ + + +@dataclass +class GetCacheStageRequest: + cache_stage_id: str + """ + ID of the requested cache stage. + """ + + +@dataclass +class GetCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class GetDNSStageRequest: + dns_stage_id: str + """ + ID of the requested DNS stage. + """ + + +@dataclass +class GetPipelineRequest: + pipeline_id: str + """ + ID of the requested pipeline. + """ + + +@dataclass +class GetPurgeRequestRequest: + purge_request_id: str + """ + ID of the requested purge request. + """ + + +@dataclass +class GetTLSStageRequest: + tls_stage_id: str + """ + ID of the requested TLS stage. + """ + + +@dataclass +class ListBackendStagesRequest: + order_by: Optional[ListBackendStagesRequestOrderBy] + """ + Sort order of backend stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of backend stages to return per page. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for, only backend stages from this pipeline will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only backend stages from this Project will be returned. + """ + + bucket_name: Optional[str] + """ + Bucket name to filter for, only backend stages from this Bucket will be returned. + """ + + bucket_region: Optional[str] + """ + Bucket region to filter for, only backend stages with buckets in this region will be returned. + """ + + lb_id: Optional[str] + """ + Load Balancer ID to filter for, only backend stages with this Load Balancer will be returned. + """ + + +@dataclass +class ListBackendStagesResponse: + stages: List[BackendStage] + """ + Paginated list of backend stages. + """ + + total_count: int + """ + Count of all backend stages matching the requested criteria. + """ + + +@dataclass +class ListCacheStagesRequest: + order_by: Optional[ListCacheStagesRequestOrderBy] + """ + Sort order of cache stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of cache stages to return per page. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for, only cache stages from this pipeline will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only cache stages from this Project will be returned. + """ + + +@dataclass +class ListCacheStagesResponse: + stages: List[CacheStage] + """ + Paginated list of cache stages. + """ + + total_count: int + """ + Count of all cache stages matching the requested criteria. + """ + + +@dataclass +class ListDNSStagesRequest: + order_by: Optional[ListDNSStagesRequestOrderBy] + """ + Sort order of DNS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of DNS stages to return per page. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for, only DNS stages from this pipeline will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only DNS stages from this Project will be returned. + """ + + fqdn: Optional[str] + """ + Fully Qualified Domain Name to filter for (in the format subdomain.example.com), only DNS stages with this FQDN will be returned. + """ + + +@dataclass +class ListDNSStagesResponse: + stages: List[DNSStage] + """ + Paginated list of DNS stages. + """ + + total_count: int + """ + Count of all DNS stages matching the requested criteria. + """ + + +@dataclass +class ListPipelinesRequest: + order_by: Optional[ListPipelinesRequestOrderBy] + """ + Sort order of pipelines in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of pipelines to return per page. + """ + + name: Optional[str] + """ + Pipeline name to filter for, only pipelines with this string within their name will be returned. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for, only pipelines from this Organization will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only pipelines from this Project will be returned. + """ + + has_backend_stage_lb: Optional[bool] + """ + Filter on backend stage, only pipelines with a Load Balancer origin will be returned. + """ + + +@dataclass +class ListPipelinesResponse: + pipelines: List[Pipeline] + """ + Paginated list of pipelines. + """ + + total_count: int + """ + Count of all pipelines matching the requested criteria. + """ + + +@dataclass +class ListPipelinesWithStagesRequest: + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + name: Optional[str] + + organization_id: Optional[str] + + project_id: Optional[str] + + +@dataclass +class ListPipelinesWithStagesResponse: + pipelines: List[PipelineStages] + + total_count: int + + +@dataclass +class ListPlansResponse: + total_count: int + + plans: List[PlanDetails] + + +@dataclass +class ListPurgeRequestsRequest: + order_by: Optional[ListPurgeRequestsRequestOrderBy] + """ + Sort order of purge requests in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of purge requests to return per page. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for, only purge requests from this Project will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only purge requests from this Project will be returned. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for, only purge requests from this pipeline will be returned. + """ + + +@dataclass +class ListPurgeRequestsResponse: + purge_requests: List[PurgeRequest] + """ + Paginated list of purge requests. + """ + + total_count: int + """ + Count of all purge requests matching the requested criteria. + """ + + +@dataclass +class ListTLSStagesRequest: + order_by: Optional[ListTLSStagesRequestOrderBy] + """ + Sort order of TLS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of TLS stages to return per page. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for, only TLS stages from this pipeline will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only TLS stages from this Project will be returned. + """ + + secret_id: Optional[str] + """ + Secret ID to filter for, only TLS stages with this Secret ID will be returned. + """ + + secret_region: Optional[str] + """ + Secret region to filter for, only TLS stages with a Secret in this region will be returned. + """ + + +@dataclass +class ListTLSStagesResponse: + stages: List[TLSStage] + """ + Paginated list of TLS stages. + """ + + total_count: int + """ + Count of all TLS stages matching the requested criteria. + """ + + +@dataclass +class Plan: + plan_name: PlanName + + +@dataclass +class SelectPlanRequest: + project_id: Optional[str] + + plan_name: Optional[PlanName] + + +@dataclass +class UpdateBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to update. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class UpdateCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to update. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + backend_stage_id: Optional[str] + + +@dataclass +class UpdateDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to update. + """ + + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class UpdatePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + name: Optional[str] + """ + Name of the pipeline. + """ + + description: Optional[str] + """ + Description of the pipeline. + """ + + dns_stage_id: Optional[str] + + +@dataclass +class UpdateTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to update. + """ + + tls_secrets_config: Optional[TLSSecretsConfig] + """ + Secret (from Scaleway Secret-Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/__init__.py b/scaleway-async/scaleway_async/edge_services/v1beta1/__init__.py new file mode 100644 index 00000000..c441b4ae --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/__init__.py @@ -0,0 +1,257 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DNSStageType +from .types import LbOriginError +from .types import ListBackendStagesRequestOrderBy +from .types import ListCacheStagesRequestOrderBy +from .types import ListDNSStagesRequestOrderBy +from .types import ListPipelinesRequestOrderBy +from .types import ListPipelinesWithStagesRequestOrderBy +from .types import ListPurgeRequestsRequestOrderBy +from .types import ListRouteStagesRequestOrderBy +from .types import ListTLSStagesRequestOrderBy +from .types import ListWafStagesRequestOrderBy +from .types import PipelineErrorCode +from .types import PipelineErrorSeverity +from .types import PipelineErrorStage +from .types import PipelineErrorType +from .types import PipelineStatus +from .content import PIPELINE_TRANSIENT_STATUSES +from .types import PlanName +from .types import PurgeRequestStatus +from .content import PURGE_REQUEST_TRANSIENT_STATUSES +from .types import RuleHttpMatchMethodFilter +from .types import RuleHttpMatchPathFilterPathFilterType +from .types import SearchBackendStagesRequestOrderBy +from .types import SearchWafStagesRequestOrderBy +from .types import WafStageMode +from .types import ScalewayLb +from .types import RuleHttpMatchPathFilter +from .types import ScalewayLbBackendConfig +from .types import ScalewayS3BackendConfig +from .types import PipelineError +from .types import TLSSecret +from .types import RuleHttpMatch +from .types import BackendStage +from .types import CacheStage +from .types import DNSStage +from .types import Pipeline +from .types import RouteStage +from .types import TLSStage +from .types import WafStage +from .types import SetRouteRulesRequestRouteRule +from .types import RouteRule +from .types import CheckPEMChainRequestSecretChain +from .types import PlanDetails +from .types import PlanUsageDetails +from .types import HeadStageResponseHeadStage +from .types import ListHeadStagesResponseHeadStage +from .types import PipelineStages +from .types import PurgeRequest +from .types import SetHeadStageRequestAddNewHeadStage +from .types import SetHeadStageRequestRemoveHeadStage +from .types import SetHeadStageRequestSwapHeadStage +from .types import TLSSecretsConfig +from .types import AddRouteRulesRequest +from .types import AddRouteRulesResponse +from .types import CheckDomainRequest +from .types import CheckDomainResponse +from .types import CheckLbOriginRequest +from .types import CheckLbOriginResponse +from .types import CheckPEMChainRequest +from .types import CheckPEMChainResponse +from .types import CreateBackendStageRequest +from .types import CreateCacheStageRequest +from .types import CreateDNSStageRequest +from .types import CreatePipelineRequest +from .types import CreatePurgeRequestRequest +from .types import CreateRouteStageRequest +from .types import CreateTLSStageRequest +from .types import CreateWafStageRequest +from .types import DeleteBackendStageRequest +from .types import DeleteCacheStageRequest +from .types import DeleteCurrentPlanRequest +from .types import DeleteDNSStageRequest +from .types import DeletePipelineRequest +from .types import DeleteRouteStageRequest +from .types import DeleteTLSStageRequest +from .types import DeleteWafStageRequest +from .types import GetBackendStageRequest +from .types import GetBillingRequest +from .types import GetBillingResponse +from .types import GetCacheStageRequest +from .types import GetCurrentPlanRequest +from .types import GetDNSStageRequest +from .types import GetPipelineRequest +from .types import GetPurgeRequestRequest +from .types import GetRouteStageRequest +from .types import GetTLSStageRequest +from .types import GetWafStageRequest +from .types import HeadStageResponse +from .types import ListBackendStagesRequest +from .types import ListBackendStagesResponse +from .types import ListCacheStagesRequest +from .types import ListCacheStagesResponse +from .types import ListDNSStagesRequest +from .types import ListDNSStagesResponse +from .types import ListHeadStagesRequest +from .types import ListHeadStagesResponse +from .types import ListPipelinesRequest +from .types import ListPipelinesResponse +from .types import ListPipelinesWithStagesRequest +from .types import ListPipelinesWithStagesResponse +from .types import ListPlansResponse +from .types import ListPurgeRequestsRequest +from .types import ListPurgeRequestsResponse +from .types import ListRouteRulesRequest +from .types import ListRouteRulesResponse +from .types import ListRouteStagesRequest +from .types import ListRouteStagesResponse +from .types import ListTLSStagesRequest +from .types import ListTLSStagesResponse +from .types import ListWafStagesRequest +from .types import ListWafStagesResponse +from .types import Plan +from .types import SearchBackendStagesRequest +from .types import SearchWafStagesRequest +from .types import SelectPlanRequest +from .types import SetHeadStageRequest +from .types import SetRouteRulesRequest +from .types import SetRouteRulesResponse +from .types import UpdateBackendStageRequest +from .types import UpdateCacheStageRequest +from .types import UpdateDNSStageRequest +from .types import UpdatePipelineRequest +from .types import UpdateRouteStageRequest +from .types import UpdateTLSStageRequest +from .types import UpdateWafStageRequest +from .api import EdgeServicesV1Beta1API + +__all__ = [ + "DNSStageType", + "LbOriginError", + "ListBackendStagesRequestOrderBy", + "ListCacheStagesRequestOrderBy", + "ListDNSStagesRequestOrderBy", + "ListPipelinesRequestOrderBy", + "ListPipelinesWithStagesRequestOrderBy", + "ListPurgeRequestsRequestOrderBy", + "ListRouteStagesRequestOrderBy", + "ListTLSStagesRequestOrderBy", + "ListWafStagesRequestOrderBy", + "PipelineErrorCode", + "PipelineErrorSeverity", + "PipelineErrorStage", + "PipelineErrorType", + "PipelineStatus", + "PIPELINE_TRANSIENT_STATUSES", + "PlanName", + "PurgeRequestStatus", + "PURGE_REQUEST_TRANSIENT_STATUSES", + "RuleHttpMatchMethodFilter", + "RuleHttpMatchPathFilterPathFilterType", + "SearchBackendStagesRequestOrderBy", + "SearchWafStagesRequestOrderBy", + "WafStageMode", + "ScalewayLb", + "RuleHttpMatchPathFilter", + "ScalewayLbBackendConfig", + "ScalewayS3BackendConfig", + "PipelineError", + "TLSSecret", + "RuleHttpMatch", + "BackendStage", + "CacheStage", + "DNSStage", + "Pipeline", + "RouteStage", + "TLSStage", + "WafStage", + "SetRouteRulesRequestRouteRule", + "RouteRule", + "CheckPEMChainRequestSecretChain", + "PlanDetails", + "PlanUsageDetails", + "HeadStageResponseHeadStage", + "ListHeadStagesResponseHeadStage", + "PipelineStages", + "PurgeRequest", + "SetHeadStageRequestAddNewHeadStage", + "SetHeadStageRequestRemoveHeadStage", + "SetHeadStageRequestSwapHeadStage", + "TLSSecretsConfig", + "AddRouteRulesRequest", + "AddRouteRulesResponse", + "CheckDomainRequest", + "CheckDomainResponse", + "CheckLbOriginRequest", + "CheckLbOriginResponse", + "CheckPEMChainRequest", + "CheckPEMChainResponse", + "CreateBackendStageRequest", + "CreateCacheStageRequest", + "CreateDNSStageRequest", + "CreatePipelineRequest", + "CreatePurgeRequestRequest", + "CreateRouteStageRequest", + "CreateTLSStageRequest", + "CreateWafStageRequest", + "DeleteBackendStageRequest", + "DeleteCacheStageRequest", + "DeleteCurrentPlanRequest", + "DeleteDNSStageRequest", + "DeletePipelineRequest", + "DeleteRouteStageRequest", + "DeleteTLSStageRequest", + "DeleteWafStageRequest", + "GetBackendStageRequest", + "GetBillingRequest", + "GetBillingResponse", + "GetCacheStageRequest", + "GetCurrentPlanRequest", + "GetDNSStageRequest", + "GetPipelineRequest", + "GetPurgeRequestRequest", + "GetRouteStageRequest", + "GetTLSStageRequest", + "GetWafStageRequest", + "HeadStageResponse", + "ListBackendStagesRequest", + "ListBackendStagesResponse", + "ListCacheStagesRequest", + "ListCacheStagesResponse", + "ListDNSStagesRequest", + "ListDNSStagesResponse", + "ListHeadStagesRequest", + "ListHeadStagesResponse", + "ListPipelinesRequest", + "ListPipelinesResponse", + "ListPipelinesWithStagesRequest", + "ListPipelinesWithStagesResponse", + "ListPlansResponse", + "ListPurgeRequestsRequest", + "ListPurgeRequestsResponse", + "ListRouteRulesRequest", + "ListRouteRulesResponse", + "ListRouteStagesRequest", + "ListRouteStagesResponse", + "ListTLSStagesRequest", + "ListTLSStagesResponse", + "ListWafStagesRequest", + "ListWafStagesResponse", + "Plan", + "SearchBackendStagesRequest", + "SearchWafStagesRequest", + "SelectPlanRequest", + "SetHeadStageRequest", + "SetRouteRulesRequest", + "SetRouteRulesResponse", + "UpdateBackendStageRequest", + "UpdateCacheStageRequest", + "UpdateDNSStageRequest", + "UpdatePipelineRequest", + "UpdateRouteStageRequest", + "UpdateTLSStageRequest", + "UpdateWafStageRequest", + "EdgeServicesV1Beta1API", +] diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/api.py b/scaleway-async/scaleway_async/edge_services/v1beta1/api.py new file mode 100644 index 00000000..d28be38e --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/api.py @@ -0,0 +1,2650 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + ListBackendStagesRequestOrderBy, + ListCacheStagesRequestOrderBy, + ListDNSStagesRequestOrderBy, + ListPipelinesRequestOrderBy, + ListPipelinesWithStagesRequestOrderBy, + ListPurgeRequestsRequestOrderBy, + ListRouteStagesRequestOrderBy, + ListTLSStagesRequestOrderBy, + ListWafStagesRequestOrderBy, + PlanName, + SearchBackendStagesRequestOrderBy, + SearchWafStagesRequestOrderBy, + WafStageMode, + AddRouteRulesRequest, + AddRouteRulesResponse, + BackendStage, + CacheStage, + CheckDomainRequest, + CheckDomainResponse, + CheckLbOriginRequest, + CheckLbOriginResponse, + CheckPEMChainRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainResponse, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateRouteStageRequest, + CreateTLSStageRequest, + CreateWafStageRequest, + DNSStage, + GetBillingResponse, + HeadStageResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListHeadStagesResponse, + ListHeadStagesResponseHeadStage, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListRouteRulesResponse, + ListRouteStagesResponse, + ListTLSStagesResponse, + ListWafStagesResponse, + Pipeline, + PipelineStages, + Plan, + PurgeRequest, + RouteStage, + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + SelectPlanRequest, + SetHeadStageRequest, + SetHeadStageRequestAddNewHeadStage, + SetHeadStageRequestRemoveHeadStage, + SetHeadStageRequestSwapHeadStage, + SetRouteRulesRequest, + SetRouteRulesRequestRouteRule, + SetRouteRulesResponse, + TLSSecret, + TLSSecretsConfig, + TLSStage, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + UpdateRouteStageRequest, + UpdateTLSStageRequest, + UpdateWafStageRequest, + WafStage, +) +from .content import ( + PIPELINE_TRANSIENT_STATUSES, + PURGE_REQUEST_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_BackendStage, + unmarshal_CacheStage, + unmarshal_DNSStage, + unmarshal_Pipeline, + unmarshal_RouteStage, + unmarshal_TLSStage, + unmarshal_WafStage, + unmarshal_PurgeRequest, + unmarshal_AddRouteRulesResponse, + unmarshal_CheckDomainResponse, + unmarshal_CheckLbOriginResponse, + unmarshal_CheckPEMChainResponse, + unmarshal_GetBillingResponse, + unmarshal_HeadStageResponse, + unmarshal_ListBackendStagesResponse, + unmarshal_ListCacheStagesResponse, + unmarshal_ListDNSStagesResponse, + unmarshal_ListHeadStagesResponse, + unmarshal_ListPipelinesResponse, + unmarshal_ListPipelinesWithStagesResponse, + unmarshal_ListPlansResponse, + unmarshal_ListPurgeRequestsResponse, + unmarshal_ListRouteRulesResponse, + unmarshal_ListRouteStagesResponse, + unmarshal_ListTLSStagesResponse, + unmarshal_ListWafStagesResponse, + unmarshal_Plan, + unmarshal_SetRouteRulesResponse, + marshal_AddRouteRulesRequest, + marshal_CheckDomainRequest, + marshal_CheckLbOriginRequest, + marshal_CheckPEMChainRequest, + marshal_CreateBackendStageRequest, + marshal_CreateCacheStageRequest, + marshal_CreateDNSStageRequest, + marshal_CreatePipelineRequest, + marshal_CreatePurgeRequestRequest, + marshal_CreateRouteStageRequest, + marshal_CreateTLSStageRequest, + marshal_CreateWafStageRequest, + marshal_SelectPlanRequest, + marshal_SetHeadStageRequest, + marshal_SetRouteRulesRequest, + marshal_UpdateBackendStageRequest, + marshal_UpdateCacheStageRequest, + marshal_UpdateDNSStageRequest, + marshal_UpdatePipelineRequest, + marshal_UpdateRouteStageRequest, + marshal_UpdateTLSStageRequest, + marshal_UpdateWafStageRequest, +) + + +class EdgeServicesV1Beta1API(API): + """ """ + + async def list_pipelines( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> ListPipelinesResponse: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for. Only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for. Only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for. Only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + :return: :class:`ListPipelinesResponse ` + + Usage: + :: + + result = await api.list_pipelines() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/pipelines", + params={ + "has_backend_stage_lb": has_backend_stage_lb, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesResponse(res.json()) + + async def list_pipelines_all( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> List[Pipeline]: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for. Only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for. Only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for. Only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + :return: :class:`List[Pipeline] ` + + Usage: + :: + + result = await api.list_pipelines_all() + """ + + return await fetch_all_pages_async( + type=ListPipelinesResponse, + key="pipelines", + fetcher=self.list_pipelines, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + "has_backend_stage_lb": has_backend_stage_lb, + }, + ) + + async def create_pipeline( + self, + *, + name: str, + description: str, + project_id: Optional[str] = None, + ) -> Pipeline: + """ + Create pipeline. + Create a new pipeline. You must specify a `dns_stage_id` to form a stage-chain that goes all the way to the backend stage (origin), so the HTTP request will be processed according to the stages you created. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :param project_id: Project ID in which the pipeline will be created. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.create_pipeline( + name="example", + description="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/pipelines", + body=marshal_CreatePipelineRequest( + CreatePipelineRequest( + name=name, + description=description, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + async def get_pipeline( + self, + *, + pipeline_id: str, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.get_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + async def wait_for_pipeline( + self, + *, + pipeline_id: str, + options: Optional[ + WaitForOptions[Pipeline, Union[bool, Awaitable[bool]]] + ] = None, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.get_pipeline( + pipeline_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in PIPELINE_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_pipeline, + options=options, + args={ + "pipeline_id": pipeline_id, + }, + ) + + async def list_pipelines_with_stages( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> ListPipelinesWithStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`ListPipelinesWithStagesResponse ` + + Usage: + :: + + result = await api.list_pipelines_with_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/pipelines-stages", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesWithStagesResponse(res.json()) + + async def list_pipelines_with_stages_all( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> List[PipelineStages]: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`List[PipelineStages] ` + + Usage: + :: + + result = await api.list_pipelines_with_stages_all() + """ + + return await fetch_all_pages_async( + type=ListPipelinesWithStagesResponse, + key="pipelines", + fetcher=self.list_pipelines_with_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + }, + ) + + async def update_pipeline( + self, + *, + pipeline_id: str, + name: Optional[str] = None, + description: Optional[str] = None, + ) -> Pipeline: + """ + Update pipeline. + Update the parameters of an existing pipeline, specified by its `pipeline_id`. Parameters which can be updated include the `name`, `description` and `dns_stage_id`. + :param pipeline_id: ID of the pipeline to update. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = await api.update_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + body=marshal_UpdatePipelineRequest( + UpdatePipelineRequest( + pipeline_id=pipeline_id, + name=name, + description=description, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + async def delete_pipeline( + self, + *, + pipeline_id: str, + ) -> None: + """ + Delete pipeline. + Delete an existing pipeline, specified by its `pipeline_id`. Deleting a pipeline is permanent, and cannot be undone. Note that all stages linked to the pipeline are also deleted. + :param pipeline_id: ID of the pipeline to delete. + + Usage: + :: + + result = await api.delete_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + + async def list_head_stages( + self, + *, + pipeline_id: str, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListHeadStagesResponse: + """ + :param pipeline_id: ID of the pipeline to update. + :param page: Page number to return, from the paginated results. + :param page_size: Number of head stages to return per page. + :return: :class:`ListHeadStagesResponse ` + + Usage: + :: + + result = await api.list_head_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/head-stages", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListHeadStagesResponse(res.json()) + + async def list_head_stages_all( + self, + *, + pipeline_id: str, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[ListHeadStagesResponseHeadStage]: + """ + :param pipeline_id: ID of the pipeline to update. + :param page: Page number to return, from the paginated results. + :param page_size: Number of head stages to return per page. + :return: :class:`List[ListHeadStagesResponseHeadStage] ` + + Usage: + :: + + result = await api.list_head_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListHeadStagesResponse, + key="head_stages", + fetcher=self.list_head_stages, + args={ + "pipeline_id": pipeline_id, + "page": page, + "page_size": page_size, + }, + ) + + async def set_head_stage( + self, + *, + pipeline_id: str, + add_new_head_stage: Optional[SetHeadStageRequestAddNewHeadStage] = None, + remove_head_stage: Optional[SetHeadStageRequestRemoveHeadStage] = None, + swap_head_stage: Optional[SetHeadStageRequestSwapHeadStage] = None, + ) -> HeadStageResponse: + """ + Configure a entry point to your pipeline. You must specify a `head stage` to form a stage-chain that goes all the way to the backend stage (origin), so the HTTP request will be processed according to the stages you created. + You must specify either a `add_new_head_stage` (to add a new head stage), `remove_head_stage` (to remove a head stage) or `swap_head_stage` (to replace a head stage). + :param pipeline_id: ID of the pipeline to update. + :param add_new_head_stage: Add a new head stage. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :param remove_head_stage: Remove a head stage. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :param swap_head_stage: Replace a head stage with a new one. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :return: :class:`HeadStageResponse ` + + Usage: + :: + + result = await api.set_head_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/set-head-stage", + body=marshal_SetHeadStageRequest( + SetHeadStageRequest( + pipeline_id=pipeline_id, + add_new_head_stage=add_new_head_stage, + remove_head_stage=remove_head_stage, + swap_head_stage=swap_head_stage, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_HeadStageResponse(res.json()) + + async def list_dns_stages( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + fqdn: Optional[str] = None, + ) -> ListDNSStagesResponse: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + :return: :class:`ListDNSStagesResponse ` + + Usage: + :: + + result = await api.list_dns_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/dns-stages", + params={ + "fqdn": fqdn, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDNSStagesResponse(res.json()) + + async def list_dns_stages_all( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + fqdn: Optional[str] = None, + ) -> List[DNSStage]: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + :return: :class:`List[DNSStage] ` + + Usage: + :: + + result = await api.list_dns_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListDNSStagesResponse, + key="stages", + fetcher=self.list_dns_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "fqdn": fqdn, + }, + ) + + async def create_dns_stage( + self, + *, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + ) -> DNSStage: + """ + Create DNS stage. + Create a new DNS stage. You must specify the `fqdns` field to customize the domain endpoint, using a domain you already own. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param pipeline_id: Pipeline ID the DNS stage belongs to. + :return: :class:`DNSStage ` + + Usage: + :: + + result = await api.create_dns_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/dns-stages", + body=marshal_CreateDNSStageRequest( + CreateDNSStageRequest( + fqdns=fqdns, + pipeline_id=pipeline_id, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + async def get_dns_stage( + self, + *, + dns_stage_id: str, + ) -> DNSStage: + """ + Get DNS stage. + Retrieve information about an existing DNS stage, specified by its `dns_stage_id`. Its full details, including FQDNs, are returned in the response object. + :param dns_stage_id: ID of the requested DNS stage. + :return: :class:`DNSStage ` + + Usage: + :: + + result = await api.get_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + async def update_dns_stage( + self, + *, + dns_stage_id: str, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> DNSStage: + """ + Update DNS stage. + Update the parameters of an existing DNS stage, specified by its `dns_stage_id`. + :param dns_stage_id: ID of the DNS stage to update. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`DNSStage ` + + Usage: + :: + + result = await api.update_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + body=marshal_UpdateDNSStageRequest( + UpdateDNSStageRequest( + dns_stage_id=dns_stage_id, + fqdns=fqdns, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + async def delete_dns_stage( + self, + *, + dns_stage_id: str, + ) -> None: + """ + Delete DNS stage. + Delete an existing DNS stage, specified by its `dns_stage_id`. Deleting a DNS stage is permanent, and cannot be undone. + :param dns_stage_id: ID of the DNS stage to delete. + + Usage: + :: + + result = await api.delete_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + + async def list_tls_stages( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> ListTLSStagesResponse: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + :param secret_id: Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + :return: :class:`ListTLSStagesResponse ` + + Usage: + :: + + result = await api.list_tls_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/tls-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListTLSStagesResponse(res.json()) + + async def list_tls_stages_all( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> List[TLSStage]: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + :param secret_id: Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + :return: :class:`List[TLSStage] ` + + Usage: + :: + + result = await api.list_tls_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListTLSStagesResponse, + key="stages", + fetcher=self.list_tls_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + async def create_tls_stage( + self, + *, + secrets: Optional[List[TLSSecret]] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + route_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Create TLS stage. + Create a new TLS stage. You must specify either the `secrets` or `managed_certificate` fields to customize the SSL/TLS certificate of your endpoint. Choose `secrets` if you are using a pre-existing certificate held in Scaleway Secret Manager, or `managed_certificate` to let Scaleway generate and manage a Let's Encrypt certificate for your customized endpoint. + :param secrets: Secret (from Scaleway Secret Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param pipeline_id: Pipeline ID the TLS stage belongs to. + :param route_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = await api.create_tls_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/tls-stages", + body=marshal_CreateTLSStageRequest( + CreateTLSStageRequest( + secrets=secrets, + managed_certificate=managed_certificate, + pipeline_id=pipeline_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + async def get_tls_stage( + self, + *, + tls_stage_id: str, + ) -> TLSStage: + """ + Get TLS stage. + Retrieve information about an existing TLS stage, specified by its `tls_stage_id`. Its full details, including secrets and certificate expiration date are returned in the response object. + :param tls_stage_id: ID of the requested TLS stage. + :return: :class:`TLSStage ` + + Usage: + :: + + result = await api.get_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + async def update_tls_stage( + self, + *, + tls_stage_id: str, + tls_secrets_config: Optional[TLSSecretsConfig] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Update TLS stage. + Update the parameters of an existing TLS stage, specified by its `tls_stage_id`. Both `tls_secrets_config` and `managed_certificate` parameters can be updated. + :param tls_stage_id: ID of the TLS stage to update. + :param tls_secrets_config: Secret (from Scaleway Secret-Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = await api.update_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + body=marshal_UpdateTLSStageRequest( + UpdateTLSStageRequest( + tls_stage_id=tls_stage_id, + tls_secrets_config=tls_secrets_config, + managed_certificate=managed_certificate, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + async def delete_tls_stage( + self, + *, + tls_stage_id: str, + ) -> None: + """ + Delete TLS stage. + Delete an existing TLS stage, specified by its `tls_stage_id`. Deleting a TLS stage is permanent, and cannot be undone. + :param tls_stage_id: ID of the TLS stage to delete. + + Usage: + :: + + result = await api.delete_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + + async def list_cache_stages( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListCacheStagesResponse: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + :return: :class:`ListCacheStagesResponse ` + + Usage: + :: + + result = await api.list_cache_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/cache-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListCacheStagesResponse(res.json()) + + async def list_cache_stages_all( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[CacheStage]: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + :return: :class:`List[CacheStage] ` + + Usage: + :: + + result = await api.list_cache_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListCacheStagesResponse, + key="stages", + fetcher=self.list_cache_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + async def create_cache_stage( + self, + *, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + waf_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Create cache stage. + Create a new cache stage. You must specify the `fallback_ttl` field to customize the TTL of the cache. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param pipeline_id: Pipeline ID the Cache stage belongs to. + :param waf_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = await api.create_cache_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/cache-stages", + body=marshal_CreateCacheStageRequest( + CreateCacheStageRequest( + fallback_ttl=fallback_ttl, + pipeline_id=pipeline_id, + backend_stage_id=backend_stage_id, + waf_stage_id=waf_stage_id, + route_stage_id=route_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + async def get_cache_stage( + self, + *, + cache_stage_id: str, + ) -> CacheStage: + """ + Get cache stage. + Retrieve information about an existing cache stage, specified by its `cache_stage_id`. Its full details, including Time To Live (TTL), are returned in the response object. + :param cache_stage_id: ID of the requested cache stage. + :return: :class:`CacheStage ` + + Usage: + :: + + result = await api.get_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + async def update_cache_stage( + self, + *, + cache_stage_id: str, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Update cache stage. + Update the parameters of an existing cache stage, specified by its `cache_stage_id`. Parameters which can be updated include the `fallback_ttl` and `backend_stage_id`. + :param cache_stage_id: ID of the cache stage to update. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = await api.update_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + body=marshal_UpdateCacheStageRequest( + UpdateCacheStageRequest( + cache_stage_id=cache_stage_id, + fallback_ttl=fallback_ttl, + backend_stage_id=backend_stage_id, + waf_stage_id=waf_stage_id, + route_stage_id=route_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + async def delete_cache_stage( + self, + *, + cache_stage_id: str, + ) -> None: + """ + Delete cache stage. + Delete an existing cache stage, specified by its `cache_stage_id`. Deleting a cache stage is permanent, and cannot be undone. + :param cache_stage_id: ID of the cache stage to delete. + + Usage: + :: + + result = await api.delete_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + + async def list_backend_stages( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> ListBackendStagesResponse: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + :param bucket_name: Bucket name to filter for. Only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for. Only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + :return: :class:`ListBackendStagesResponse ` + + Usage: + :: + + result = await api.list_backend_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/backend-stages", + params={ + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBackendStagesResponse(res.json()) + + async def list_backend_stages_all( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> List[BackendStage]: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + :param bucket_name: Bucket name to filter for. Only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for. Only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + :return: :class:`List[BackendStage] ` + + Usage: + :: + + result = await api.list_backend_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListBackendStagesResponse, + key="stages", + fetcher=self.list_backend_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + }, + ) + + async def create_backend_stage( + self, + *, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + pipeline_id: str, + ) -> BackendStage: + """ + Create backend stage. + Create a new backend stage. You must specify either a `scaleway_s3` (for a Scaleway Object Storage bucket) or `scaleway_lb` (for a Scaleway Load Balancer) field to configure the origin. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param pipeline_id: Pipeline ID the Backend stage belongs to. + :return: :class:`BackendStage ` + + Usage: + :: + + result = await api.create_backend_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/backend-stages", + body=marshal_CreateBackendStageRequest( + CreateBackendStageRequest( + pipeline_id=pipeline_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + async def get_backend_stage( + self, + *, + backend_stage_id: str, + ) -> BackendStage: + """ + Get backend stage. + Retrieve information about an existing backend stage, specified by its `backend_stage_id`. Its full details, including `scaleway_s3` or `scaleway_lb`, are returned in the response object. + :param backend_stage_id: ID of the requested backend stage. + :return: :class:`BackendStage ` + + Usage: + :: + + result = await api.get_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + async def update_backend_stage( + self, + *, + backend_stage_id: str, + pipeline_id: str, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + ) -> BackendStage: + """ + Update backend stage. + Update the parameters of an existing backend stage, specified by its `backend_stage_id`. + :param backend_stage_id: ID of the backend stage to update. + :param pipeline_id: Pipeline ID the Backend stage belongs to. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :return: :class:`BackendStage ` + + Usage: + :: + + result = await api.update_backend_stage( + backend_stage_id="example", + pipeline_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + body=marshal_UpdateBackendStageRequest( + UpdateBackendStageRequest( + backend_stage_id=backend_stage_id, + pipeline_id=pipeline_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + async def delete_backend_stage( + self, + *, + backend_stage_id: str, + ) -> None: + """ + Delete backend stage. + Delete an existing backend stage, specified by its `backend_stage_id`. Deleting a backend stage is permanent, and cannot be undone. + :param backend_stage_id: ID of the backend stage to delete. + + Usage: + :: + + result = await api.delete_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + + async def search_backend_stages( + self, + *, + order_by: Optional[SearchBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> ListBackendStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param project_id: + :param bucket_name: + :param bucket_region: + :param lb_id: + :return: :class:`ListBackendStagesResponse ` + + Usage: + :: + + result = await api.search_backend_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/search-backend-stages", + params={ + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBackendStagesResponse(res.json()) + + async def list_waf_stages( + self, + *, + order_by: Optional[ListWafStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListWafStagesResponse: + """ + List WAF stages. + List all WAF stages, for a Scaleway Organization or Scaleway Project. By default, the WAF stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of WAF stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of WAF stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + :return: :class:`ListWafStagesResponse ` + + Usage: + :: + + result = await api.list_waf_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/waf-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWafStagesResponse(res.json()) + + async def list_waf_stages_all( + self, + *, + order_by: Optional[ListWafStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[WafStage]: + """ + List WAF stages. + List all WAF stages, for a Scaleway Organization or Scaleway Project. By default, the WAF stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of WAF stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of WAF stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + :return: :class:`List[WafStage] ` + + Usage: + :: + + result = await api.list_waf_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListWafStagesResponse, + key="stages", + fetcher=self.list_waf_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + async def create_waf_stage( + self, + *, + pipeline_id: str, + paranoia_level: int, + mode: Optional[WafStageMode] = None, + backend_stage_id: Optional[str] = None, + ) -> WafStage: + """ + Create WAF stage. + Create a new WAF stage. You must specify the `mode` and `paranoia_level` fields to customize the WAF. + :param pipeline_id: Pipeline ID the WAF stage belongs to. + :param paranoia_level: Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + :param mode: Mode defining WAF behavior (`disable`/`log_only`/`enable`). + :param backend_stage_id: ID of the backend stage to forward requests to after the WAF stage. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`WafStage ` + + Usage: + :: + + result = await api.create_waf_stage( + pipeline_id="example", + paranoia_level=1, + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/waf-stages", + body=marshal_CreateWafStageRequest( + CreateWafStageRequest( + pipeline_id=pipeline_id, + paranoia_level=paranoia_level, + mode=mode, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + async def get_waf_stage( + self, + *, + waf_stage_id: str, + ) -> WafStage: + """ + Get WAF stage. + Retrieve information about an existing WAF stage, specified by its `waf_stage_id`. Its full details are returned in the response object. + :param waf_stage_id: ID of the requested WAF stage. + :return: :class:`WafStage ` + + Usage: + :: + + result = await api.get_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + async def update_waf_stage( + self, + *, + waf_stage_id: str, + mode: Optional[WafStageMode] = None, + paranoia_level: Optional[int] = None, + backend_stage_id: Optional[str] = None, + ) -> WafStage: + """ + Update WAF stage. + Update the parameters of an existing WAF stage, specified by its `waf_stage_id`. Both `mode` and `paranoia_level` parameters can be updated. + :param waf_stage_id: ID of the WAF stage to update. + :param mode: Mode defining WAF behavior (`disable`/`log_only`/`enable`). + :param paranoia_level: Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + :param backend_stage_id: ID of the backend stage to forward requests to after the WAF stage. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`WafStage ` + + Usage: + :: + + result = await api.update_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + body=marshal_UpdateWafStageRequest( + UpdateWafStageRequest( + waf_stage_id=waf_stage_id, + mode=mode, + paranoia_level=paranoia_level, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + async def delete_waf_stage( + self, + *, + waf_stage_id: str, + ) -> None: + """ + Delete WAF stage. + Delete an existing WAF stage, specified by its `waf_stage_id`. Deleting a WAF stage is permanent, and cannot be undone. + :param waf_stage_id: ID of the WAF stage to delete. + + Usage: + :: + + result = await api.delete_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + ) + + self._throw_on_error(res) + + async def search_waf_stages( + self, + *, + order_by: Optional[SearchWafStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> ListWafStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param project_id: + :return: :class:`ListWafStagesResponse ` + + Usage: + :: + + result = await api.search_waf_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/search-waf-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWafStagesResponse(res.json()) + + async def list_route_stages( + self, + *, + order_by: Optional[ListRouteStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListRouteStagesResponse: + """ + List route stages. + List all route stages, for a given pipeline. By default, the route stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of route stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of route stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only route stages from this pipeline will be returned. + :return: :class:`ListRouteStagesResponse ` + + Usage: + :: + + result = await api.list_route_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/route-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRouteStagesResponse(res.json()) + + async def list_route_stages_all( + self, + *, + order_by: Optional[ListRouteStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[RouteStage]: + """ + List route stages. + List all route stages, for a given pipeline. By default, the route stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of route stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of route stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only route stages from this pipeline will be returned. + :return: :class:`List[RouteStage] ` + + Usage: + :: + + result = await api.list_route_stages_all( + pipeline_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListRouteStagesResponse, + key="stages", + fetcher=self.list_route_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + async def create_route_stage( + self, + *, + pipeline_id: str, + waf_stage_id: Optional[str] = None, + ) -> RouteStage: + """ + Create route stage. + Create a new route stage. You must specify the `waf_stage_id` field to customize the route. + :param pipeline_id: Pipeline ID the route stage belongs to. + :param waf_stage_id: ID of the WAF stage HTTP requests should be forwarded to when no rules are matched. + One-Of ('next'): at most one of 'waf_stage_id' could be set. + :return: :class:`RouteStage ` + + Usage: + :: + + result = await api.create_route_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/route-stages", + body=marshal_CreateRouteStageRequest( + CreateRouteStageRequest( + pipeline_id=pipeline_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + async def get_route_stage( + self, + *, + route_stage_id: str, + ) -> RouteStage: + """ + Get route stage. + Retrieve information about an existing route stage, specified by its `route_stage_id`. The summary of the route stage (without route rules) is returned in the response object. + :param route_stage_id: ID of the requested route stage. + :return: :class:`RouteStage ` + + Usage: + :: + + result = await api.get_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + async def update_route_stage( + self, + *, + route_stage_id: str, + waf_stage_id: Optional[str] = None, + ) -> RouteStage: + """ + Update route stage. + Update the parameters of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param waf_stage_id: ID of the WAF stage HTTP requests should be forwarded to when no rules are matched. + One-Of ('next'): at most one of 'waf_stage_id' could be set. + :return: :class:`RouteStage ` + + Usage: + :: + + result = await api.update_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + body=marshal_UpdateRouteStageRequest( + UpdateRouteStageRequest( + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + async def delete_route_stage( + self, + *, + route_stage_id: str, + ) -> None: + """ + Delete route stage. + Delete an existing route stage, specified by its `route_stage_id`. Deleting a route stage is permanent, and cannot be undone. + :param route_stage_id: ID of the route stage to delete. + + Usage: + :: + + result = await api.delete_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + ) + + self._throw_on_error(res) + + async def list_route_rules( + self, + *, + route_stage_id: str, + ) -> ListRouteRulesResponse: + """ + List route rules. + List all route rules of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: Route stage ID to filter for. Only route rules from this route stage will be returned. + :return: :class:`ListRouteRulesResponse ` + + Usage: + :: + + result = await api.list_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", + ) + + self._throw_on_error(res) + return unmarshal_ListRouteRulesResponse(res.json()) + + async def set_route_rules( + self, + *, + route_stage_id: str, + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] = None, + ) -> SetRouteRulesResponse: + """ + Set route rules. + Set the rules of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param route_rules: List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + :return: :class:`SetRouteRulesResponse ` + + Usage: + :: + + result = await api.set_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "PUT", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", + body=marshal_SetRouteRulesRequest( + SetRouteRulesRequest( + route_stage_id=route_stage_id, + route_rules=route_rules, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetRouteRulesResponse(res.json()) + + async def add_route_rules( + self, + *, + route_stage_id: str, + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] = None, + after_position: Optional[int] = None, + before_position: Optional[int] = None, + ) -> AddRouteRulesResponse: + """ + Add route rules. + Add route rules to an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param route_rules: List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + :param after_position: Add rules after the given position. + One-Of ('position'): at most one of 'after_position', 'before_position' could be set. + :param before_position: Add rules before the given position. + One-Of ('position'): at most one of 'after_position', 'before_position' could be set. + :return: :class:`AddRouteRulesResponse ` + + Usage: + :: + + result = await api.add_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", + body=marshal_AddRouteRulesRequest( + AddRouteRulesRequest( + route_stage_id=route_stage_id, + route_rules=route_rules, + after_position=after_position, + before_position=before_position, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AddRouteRulesResponse(res.json()) + + async def check_domain( + self, + *, + fqdn: str, + cname: str, + project_id: Optional[str] = None, + ) -> CheckDomainResponse: + """ + :param fqdn: + :param cname: + :param project_id: + :return: :class:`CheckDomainResponse ` + + Usage: + :: + + result = await api.check_domain( + fqdn="example", + cname="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-domain", + body=marshal_CheckDomainRequest( + CheckDomainRequest( + fqdn=fqdn, + cname=cname, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckDomainResponse(res.json()) + + async def check_pem_chain( + self, + *, + fqdn: str, + project_id: Optional[str] = None, + secret: Optional[CheckPEMChainRequestSecretChain] = None, + raw: Optional[str] = None, + ) -> CheckPEMChainResponse: + """ + :param fqdn: + :param project_id: + :param secret: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :param raw: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :return: :class:`CheckPEMChainResponse ` + + Usage: + :: + + result = await api.check_pem_chain( + fqdn="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-pem-chain", + body=marshal_CheckPEMChainRequest( + CheckPEMChainRequest( + fqdn=fqdn, + project_id=project_id, + secret=secret, + raw=raw, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckPEMChainResponse(res.json()) + + async def list_purge_requests( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> ListPurgeRequestsResponse: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for. Only purge requests from this Project will be returned. + :param project_id: Project ID to filter for. Only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + :return: :class:`ListPurgeRequestsResponse ` + + Usage: + :: + + result = await api.list_purge_requests() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/purge-requests", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPurgeRequestsResponse(res.json()) + + async def list_purge_requests_all( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> List[PurgeRequest]: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for. Only purge requests from this Project will be returned. + :param project_id: Project ID to filter for. Only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + :return: :class:`List[PurgeRequest] ` + + Usage: + :: + + result = await api.list_purge_requests_all() + """ + + return await fetch_all_pages_async( + type=ListPurgeRequestsResponse, + key="purge_requests", + fetcher=self.list_purge_requests, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "pipeline_id": pipeline_id, + }, + ) + + async def create_purge_request( + self, + *, + pipeline_id: str, + assets: Optional[List[str]] = None, + all: Optional[bool] = None, + ) -> PurgeRequest: + """ + Create purge request. + Create a new purge request. You must specify either the `all` field (to purge all content) or a list of `assets` (to define the precise assets to purge). + :param pipeline_id: Pipeline ID in which the purge request will be created. + :param assets: List of asserts to purge. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :param all: Defines whether to purge all content. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = await api.create_purge_request( + pipeline_id="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/purge-requests", + body=marshal_CreatePurgeRequestRequest( + CreatePurgeRequestRequest( + pipeline_id=pipeline_id, + assets=assets, + all=all, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + async def get_purge_request( + self, + *, + purge_request_id: str, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = await api.get_purge_request( + purge_request_id="example", + ) + """ + + param_purge_request_id = validate_path_param( + "purge_request_id", purge_request_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/purge-requests/{param_purge_request_id}", + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + async def wait_for_purge_request( + self, + *, + purge_request_id: str, + options: Optional[ + WaitForOptions[PurgeRequest, Union[bool, Awaitable[bool]]] + ] = None, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = await api.get_purge_request( + purge_request_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in PURGE_REQUEST_TRANSIENT_STATUSES + ) + + return await wait_for_resource_async( + fetcher=self.get_purge_request, + options=options, + args={ + "purge_request_id": purge_request_id, + }, + ) + + async def check_lb_origin( + self, + *, + lb: Optional[ScalewayLb] = None, + ) -> CheckLbOriginResponse: + """ + :param lb: + :return: :class:`CheckLbOriginResponse ` + + Usage: + :: + + result = await api.check_lb_origin() + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-lb-origin", + body=marshal_CheckLbOriginRequest( + CheckLbOriginRequest( + lb=lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckLbOriginResponse(res.json()) + + async def list_plans( + self, + ) -> ListPlansResponse: + """ + + :return: :class:`ListPlansResponse ` + + Usage: + :: + + result = await api.list_plans() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/plans", + ) + + self._throw_on_error(res) + return unmarshal_ListPlansResponse(res.json()) + + async def select_plan( + self, + *, + project_id: Optional[str] = None, + plan_name: Optional[PlanName] = None, + ) -> Plan: + """ + :param project_id: + :param plan_name: + :return: :class:`Plan ` + + Usage: + :: + + result = await api.select_plan() + """ + + res = self._request( + "PATCH", + "/edge-services/v1beta1/current-plan", + body=marshal_SelectPlanRequest( + SelectPlanRequest( + project_id=project_id, + plan_name=plan_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + async def get_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> Plan: + """ + :param project_id: + :return: :class:`Plan ` + + Usage: + :: + + result = await api.get_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + async def delete_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> None: + """ + :param project_id: + + Usage: + :: + + result = await api.delete_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + + async def get_billing( + self, + *, + project_id: Optional[str] = None, + ) -> GetBillingResponse: + """ + Gives information on the currently selected Edge Services subscription plan, resource usage and associated billing information for this calendar month (including whether consumption falls within or exceeds the currently selected subscription plan.). + :param project_id: + :return: :class:`GetBillingResponse ` + + Usage: + :: + + result = await api.get_billing() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/billing/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_GetBillingResponse(res.json()) diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/content.py b/scaleway-async/scaleway_async/edge_services/v1beta1/content.py new file mode 100644 index 00000000..ad1b5e0e --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/content.py @@ -0,0 +1,21 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + PipelineStatus, + PurgeRequestStatus, +) + +PIPELINE_TRANSIENT_STATUSES: List[PipelineStatus] = [ + PipelineStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PipelineStatus `. +""" +PURGE_REQUEST_TRANSIENT_STATUSES: List[PurgeRequestStatus] = [ + PurgeRequestStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PurgeRequestStatus `. +""" diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/marshalling.py b/scaleway-async/scaleway_async/edge_services/v1beta1/marshalling.py new file mode 100644 index 00000000..b01c7d7c --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/marshalling.py @@ -0,0 +1,1901 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + RuleHttpMatchMethodFilter, + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + BackendStage, + CacheStage, + DNSStage, + PipelineError, + Pipeline, + RouteStage, + TLSSecret, + TLSStage, + WafStage, + PipelineStages, + PurgeRequest, + RuleHttpMatchPathFilter, + RuleHttpMatch, + RouteRule, + AddRouteRulesResponse, + CheckDomainResponse, + CheckLbOriginResponse, + CheckPEMChainResponse, + PlanDetails, + PlanUsageDetails, + GetBillingResponse, + HeadStageResponseHeadStage, + HeadStageResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListHeadStagesResponseHeadStage, + ListHeadStagesResponse, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListRouteRulesResponse, + ListRouteStagesResponse, + ListTLSStagesResponse, + ListWafStagesResponse, + Plan, + SetRouteRulesResponse, + SetRouteRulesRequestRouteRule, + AddRouteRulesRequest, + CheckDomainRequest, + CheckLbOriginRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainRequest, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateRouteStageRequest, + CreateTLSStageRequest, + CreateWafStageRequest, + SelectPlanRequest, + SetHeadStageRequestAddNewHeadStage, + SetHeadStageRequestRemoveHeadStage, + SetHeadStageRequestSwapHeadStage, + SetHeadStageRequest, + SetRouteRulesRequest, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + UpdateRouteStageRequest, + TLSSecretsConfig, + UpdateTLSStageRequest, + UpdateWafStageRequest, +) + + +def unmarshal_ScalewayLb(data: Any) -> ScalewayLb: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLb' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("frontend_id", None) + if field is not None: + args["frontend_id"] = field + + field = data.get("is_ssl", None) + if field is not None: + args["is_ssl"] = field + else: + args["is_ssl"] = None + + field = data.get("domain_name", None) + if field is not None: + args["domain_name"] = field + else: + args["domain_name"] = None + + return ScalewayLb(**args) + + +def unmarshal_ScalewayLbBackendConfig(data: Any) -> ScalewayLbBackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLbBackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("lbs", None) + if field is not None: + args["lbs"] = ( + [unmarshal_ScalewayLb(v) for v in field] if field is not None else None + ) + + return ScalewayLbBackendConfig(**args) + + +def unmarshal_ScalewayS3BackendConfig(data: Any) -> ScalewayS3BackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayS3BackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bucket_name", None) + if field is not None: + args["bucket_name"] = field + else: + args["bucket_name"] = None + + field = data.get("bucket_region", None) + if field is not None: + args["bucket_region"] = field + else: + args["bucket_region"] = None + + field = data.get("is_website", None) + if field is not None: + args["is_website"] = field + else: + args["is_website"] = None + + return ScalewayS3BackendConfig(**args) + + +def unmarshal_BackendStage(data: Any) -> BackendStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BackendStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("scaleway_s3", None) + if field is not None: + args["scaleway_s3"] = unmarshal_ScalewayS3BackendConfig(field) + else: + args["scaleway_s3"] = None + + field = data.get("scaleway_lb", None) + if field is not None: + args["scaleway_lb"] = unmarshal_ScalewayLbBackendConfig(field) + else: + args["scaleway_lb"] = None + + return BackendStage(**args) + + +def unmarshal_CacheStage(data: Any) -> CacheStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CacheStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("fallback_ttl", None) + if field is not None: + args["fallback_ttl"] = field + else: + args["fallback_ttl"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + else: + args["route_stage_id"] = None + + return CacheStage(**args) + + +def unmarshal_DNSStage(data: Any) -> DNSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DNSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("fqdns", None) + if field is not None: + args["fqdns"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("tls_stage_id", None) + if field is not None: + args["tls_stage_id"] = field + else: + args["tls_stage_id"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return DNSStage(**args) + + +def unmarshal_PipelineError(data: Any) -> PipelineError: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineError' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stage", None) + if field is not None: + args["stage"] = field + + field = data.get("code", None) + if field is not None: + args["code"] = field + + field = data.get("severity", None) + if field is not None: + args["severity"] = field + + field = data.get("message", None) + if field is not None: + args["message"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return PipelineError(**args) + + +def unmarshal_Pipeline(data: Any) -> Pipeline: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pipeline' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("errors", None) + if field is not None: + args["errors"] = ( + [unmarshal_PipelineError(v) for v in field] if field is not None else None + ) + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Pipeline(**args) + + +def unmarshal_RouteStage(data: Any) -> RouteStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RouteStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return RouteStage(**args) + + +def unmarshal_TLSSecret(data: Any) -> TLSSecret: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSSecret' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secret_id", None) + if field is not None: + args["secret_id"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + return TLSSecret(**args) + + +def unmarshal_TLSStage(data: Any) -> TLSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("secrets", None) + if field is not None: + args["secrets"] = ( + [unmarshal_TLSSecret(v) for v in field] if field is not None else None + ) + + field = data.get("managed_certificate", None) + if field is not None: + args["managed_certificate"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("certificate_expires_at", None) + if field is not None: + args["certificate_expires_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["certificate_expires_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + else: + args["route_stage_id"] = None + + return TLSStage(**args) + + +def unmarshal_WafStage(data: Any) -> WafStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'WafStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("mode", None) + if field is not None: + args["mode"] = field + + field = data.get("paranoia_level", None) + if field is not None: + args["paranoia_level"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return WafStage(**args) + + +def unmarshal_PipelineStages(data: Any) -> PipelineStages: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineStages' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stages", None) + if field is not None: + args["dns_stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("tls_stages", None) + if field is not None: + args["tls_stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("cache_stages", None) + if field is not None: + args["cache_stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("backend_stages", None) + if field is not None: + args["backend_stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("waf_stages", None) + if field is not None: + args["waf_stages"] = ( + [unmarshal_WafStage(v) for v in field] if field is not None else None + ) + + field = data.get("route_stages", None) + if field is not None: + args["route_stages"] = ( + [unmarshal_RouteStage(v) for v in field] if field is not None else None + ) + + field = data.get("pipeline", None) + if field is not None: + args["pipeline"] = unmarshal_Pipeline(field) + else: + args["pipeline"] = None + + return PipelineStages(**args) + + +def unmarshal_PurgeRequest(data: Any) -> PurgeRequest: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PurgeRequest' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("assets", None) + if field is not None: + args["assets"] = field + else: + args["assets"] = None + + field = data.get("all", None) + if field is not None: + args["all"] = field + else: + args["all"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return PurgeRequest(**args) + + +def unmarshal_RuleHttpMatchPathFilter(data: Any) -> RuleHttpMatchPathFilter: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RuleHttpMatchPathFilter' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("path_filter_type", None) + if field is not None: + args["path_filter_type"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + return RuleHttpMatchPathFilter(**args) + + +def unmarshal_RuleHttpMatch(data: Any) -> RuleHttpMatch: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RuleHttpMatch' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("method_filters", None) + if field is not None: + args["method_filters"] = ( + [RuleHttpMatchMethodFilter(v) for v in field] if field is not None else None + ) + + field = data.get("path_filter", None) + if field is not None: + args["path_filter"] = unmarshal_RuleHttpMatchPathFilter(field) + else: + args["path_filter"] = None + + return RuleHttpMatch(**args) + + +def unmarshal_RouteRule(data: Any) -> RouteRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RouteRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("position", None) + if field is not None: + args["position"] = field + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + + field = data.get("rule_http_match", None) + if field is not None: + args["rule_http_match"] = unmarshal_RuleHttpMatch(field) + else: + args["rule_http_match"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return RouteRule(**args) + + +def unmarshal_AddRouteRulesResponse(data: Any) -> AddRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AddRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return AddRouteRulesResponse(**args) + + +def unmarshal_CheckDomainResponse(data: Any) -> CheckDomainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckDomainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckDomainResponse(**args) + + +def unmarshal_CheckLbOriginResponse(data: Any) -> CheckLbOriginResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckLbOriginResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + field = data.get("error_type", None) + if field is not None: + args["error_type"] = field + + return CheckLbOriginResponse(**args) + + +def unmarshal_CheckPEMChainResponse(data: Any) -> CheckPEMChainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckPEMChainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckPEMChainResponse(**args) + + +def unmarshal_PlanDetails(data: Any) -> PlanDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + field = data.get("package_gb", None) + if field is not None: + args["package_gb"] = field + + field = data.get("pipeline_limit", None) + if field is not None: + args["pipeline_limit"] = field + + field = data.get("waf_requests", None) + if field is not None: + args["waf_requests"] = field + + return PlanDetails(**args) + + +def unmarshal_PlanUsageDetails(data: Any) -> PlanUsageDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanUsageDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + return PlanUsageDetails(**args) + + +def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetBillingResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("current_plan", None) + if field is not None: + args["current_plan"] = unmarshal_PlanDetails(field) + else: + args["current_plan"] = None + + field = data.get("pipeline_number", None) + if field is not None: + args["pipeline_number"] = field + + field = data.get("current_plan_cache_usage", None) + if field is not None: + args["current_plan_cache_usage"] = field + + field = data.get("extra_cache_usage", None) + if field is not None: + args["extra_cache_usage"] = field + + field = data.get("current_plan_waf_usage", None) + if field is not None: + args["current_plan_waf_usage"] = field + + field = data.get("extra_waf_usage", None) + if field is not None: + args["extra_waf_usage"] = field + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + field = data.get("extra_pipelines_cost", None) + if field is not None: + args["extra_pipelines_cost"] = unmarshal_Money(field) + else: + args["extra_pipelines_cost"] = None + + field = data.get("plans_usage_details", None) + if field is not None: + args["plans_usage_details"] = ( + {key: unmarshal_PlanUsageDetails(value) for key, value in field.items()} + if field is not None + else None + ) + + field = data.get("extra_cache_cost", None) + if field is not None: + args["extra_cache_cost"] = unmarshal_Money(field) + else: + args["extra_cache_cost"] = None + + field = data.get("extra_waf_cost", None) + if field is not None: + args["extra_waf_cost"] = unmarshal_Money(field) + else: + args["extra_waf_cost"] = None + + field = data.get("waf_add_on", None) + if field is not None: + args["waf_add_on"] = unmarshal_Money(field) + else: + args["waf_add_on"] = None + + field = data.get("total_cost", None) + if field is not None: + args["total_cost"] = unmarshal_Money(field) + else: + args["total_cost"] = None + + return GetBillingResponse(**args) + + +def unmarshal_HeadStageResponseHeadStage(data: Any) -> HeadStageResponseHeadStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HeadStageResponseHeadStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stage_id", None) + if field is not None: + args["dns_stage_id"] = field + else: + args["dns_stage_id"] = None + + return HeadStageResponseHeadStage(**args) + + +def unmarshal_HeadStageResponse(data: Any) -> HeadStageResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HeadStageResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("head_stage", None) + if field is not None: + args["head_stage"] = unmarshal_HeadStageResponseHeadStage(field) + else: + args["head_stage"] = None + + return HeadStageResponse(**args) + + +def unmarshal_ListBackendStagesResponse(data: Any) -> ListBackendStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListBackendStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListBackendStagesResponse(**args) + + +def unmarshal_ListCacheStagesResponse(data: Any) -> ListCacheStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListCacheStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListCacheStagesResponse(**args) + + +def unmarshal_ListDNSStagesResponse(data: Any) -> ListDNSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDNSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDNSStagesResponse(**args) + + +def unmarshal_ListHeadStagesResponseHeadStage( + data: Any, +) -> ListHeadStagesResponseHeadStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListHeadStagesResponseHeadStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stage_id", None) + if field is not None: + args["dns_stage_id"] = field + else: + args["dns_stage_id"] = None + + return ListHeadStagesResponseHeadStage(**args) + + +def unmarshal_ListHeadStagesResponse(data: Any) -> ListHeadStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListHeadStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("head_stages", None) + if field is not None: + args["head_stages"] = ( + [unmarshal_ListHeadStagesResponseHeadStage(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListHeadStagesResponse(**args) + + +def unmarshal_ListPipelinesResponse(data: Any) -> ListPipelinesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_Pipeline(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesResponse(**args) + + +def unmarshal_ListPipelinesWithStagesResponse( + data: Any, +) -> ListPipelinesWithStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesWithStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_PipelineStages(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesWithStagesResponse(**args) + + +def unmarshal_ListPlansResponse(data: Any) -> ListPlansResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPlansResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("plans", None) + if field is not None: + args["plans"] = ( + [unmarshal_PlanDetails(v) for v in field] if field is not None else None + ) + + return ListPlansResponse(**args) + + +def unmarshal_ListPurgeRequestsResponse(data: Any) -> ListPurgeRequestsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPurgeRequestsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("purge_requests", None) + if field is not None: + args["purge_requests"] = ( + [unmarshal_PurgeRequest(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPurgeRequestsResponse(**args) + + +def unmarshal_ListRouteRulesResponse(data: Any) -> ListRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return ListRouteRulesResponse(**args) + + +def unmarshal_ListRouteStagesResponse(data: Any) -> ListRouteStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRouteStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_RouteStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListRouteStagesResponse(**args) + + +def unmarshal_ListTLSStagesResponse(data: Any) -> ListTLSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListTLSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListTLSStagesResponse(**args) + + +def unmarshal_ListWafStagesResponse(data: Any) -> ListWafStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListWafStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_WafStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListWafStagesResponse(**args) + + +def unmarshal_Plan(data: Any) -> Plan: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Plan' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + return Plan(**args) + + +def unmarshal_SetRouteRulesResponse(data: Any) -> SetRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return SetRouteRulesResponse(**args) + + +def marshal_RuleHttpMatchPathFilter( + request: RuleHttpMatchPathFilter, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.path_filter_type is not None: + output["path_filter_type"] = str(request.path_filter_type) + + if request.value is not None: + output["value"] = request.value + + return output + + +def marshal_RuleHttpMatch( + request: RuleHttpMatch, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.method_filters is not None: + output["method_filters"] = [str(item) for item in request.method_filters] + + if request.path_filter is not None: + output["path_filter"] = marshal_RuleHttpMatchPathFilter( + request.path_filter, defaults + ) + + return output + + +def marshal_SetRouteRulesRequestRouteRule( + request: SetRouteRulesRequestRouteRule, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("rule_http_match", request.rule_http_match), + ] + ), + ) + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + return output + + +def marshal_AddRouteRulesRequest( + request: AddRouteRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("after_position", request.after_position), + OneOfPossibility("before_position", request.before_position), + ] + ), + ) + + if request.route_rules is not None: + output["route_rules"] = [ + marshal_SetRouteRulesRequestRouteRule(item, defaults) + for item in request.route_rules + ] + + return output + + +def marshal_CheckDomainRequest( + request: CheckDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.cname is not None: + output["cname"] = request.cname + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLb( + request: ScalewayLb, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.id is not None: + output["id"] = request.id + + if request.zone is not None: + output["zone"] = request.zone or defaults.default_zone + + if request.frontend_id is not None: + output["frontend_id"] = request.frontend_id + + if request.is_ssl is not None: + output["is_ssl"] = request.is_ssl + + if request.domain_name is not None: + output["domain_name"] = request.domain_name + + return output + + +def marshal_CheckLbOriginRequest( + request: CheckLbOriginRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lb is not None: + output["lb"] = marshal_ScalewayLb(request.lb, defaults) + + return output + + +def marshal_CheckPEMChainRequestSecretChain( + request: CheckPEMChainRequestSecretChain, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.secret_region is not None: + output["secret_region"] = request.secret_region + + return output + + +def marshal_CheckPEMChainRequest( + request: CheckPEMChainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("secret", request.secret), + OneOfPossibility("raw", request.raw), + ] + ), + ) + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLbBackendConfig( + request: ScalewayLbBackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lbs is not None: + output["lbs"] = [marshal_ScalewayLb(item, defaults) for item in request.lbs] + + return output + + +def marshal_ScalewayS3BackendConfig( + request: ScalewayS3BackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket_name is not None: + output["bucket_name"] = request.bucket_name + + if request.bucket_region is not None: + output["bucket_region"] = request.bucket_region + + if request.is_website is not None: + output["is_website"] = request.is_website + + return output + + +def marshal_CreateBackendStageRequest( + request: CreateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + return output + + +def marshal_CreateCacheStageRequest( + request: CreateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + ] + ), + ) + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_CreateDNSStageRequest( + request: CreateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_CreatePipelineRequest( + request: CreatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_CreatePurgeRequestRequest( + request: CreatePurgeRequestRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("assets", request.assets), + OneOfPossibility("all", request.all), + ] + ), + ) + + if request.pipeline_id is not None: + output["pipeline_id"] = request.pipeline_id + + return output + + +def marshal_CreateRouteStageRequest( + request: CreateRouteStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + return output + + +def marshal_TLSSecret( + request: TLSSecret, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.region is not None: + output["region"] = request.region or defaults.default_region + + return output + + +def marshal_CreateTLSStageRequest( + request: CreateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + if request.secrets is not None: + output["secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.secrets + ] + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output + + +def marshal_CreateWafStageRequest( + request: CreateWafStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.paranoia_level is not None: + output["paranoia_level"] = request.paranoia_level + + if request.mode is not None: + output["mode"] = str(request.mode) + + return output + + +def marshal_SelectPlanRequest( + request: SelectPlanRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.plan_name is not None: + output["plan_name"] = str(request.plan_name) + + return output + + +def marshal_SetHeadStageRequestAddNewHeadStage( + request: SetHeadStageRequestAddNewHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.new_stage_id is not None: + output["new_stage_id"] = request.new_stage_id + + return output + + +def marshal_SetHeadStageRequestRemoveHeadStage( + request: SetHeadStageRequestRemoveHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.remove_stage_id is not None: + output["remove_stage_id"] = request.remove_stage_id + + return output + + +def marshal_SetHeadStageRequestSwapHeadStage( + request: SetHeadStageRequestSwapHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.new_stage_id is not None: + output["new_stage_id"] = request.new_stage_id + + if request.current_stage_id is not None: + output["current_stage_id"] = request.current_stage_id + + return output + + +def marshal_SetHeadStageRequest( + request: SetHeadStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("add_new_head_stage", request.add_new_head_stage), + OneOfPossibility("remove_head_stage", request.remove_head_stage), + OneOfPossibility("swap_head_stage", request.swap_head_stage), + ] + ), + ) + + return output + + +def marshal_SetRouteRulesRequest( + request: SetRouteRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.route_rules is not None: + output["route_rules"] = [ + marshal_SetRouteRulesRequestRouteRule(item, defaults) + for item in request.route_rules + ] + + return output + + +def marshal_UpdateBackendStageRequest( + request: UpdateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + if request.pipeline_id is not None: + output["pipeline_id"] = request.pipeline_id + + return output + + +def marshal_UpdateCacheStageRequest( + request: UpdateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + ] + ), + ) + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_UpdateDNSStageRequest( + request: UpdateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_UpdatePipelineRequest( + request: UpdatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + return output + + +def marshal_UpdateRouteStageRequest( + request: UpdateRouteStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + return output + + +def marshal_TLSSecretsConfig( + request: TLSSecretsConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.tls_secrets is not None: + output["tls_secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.tls_secrets + ] + + return output + + +def marshal_UpdateTLSStageRequest( + request: UpdateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + if request.tls_secrets_config is not None: + output["tls_secrets_config"] = marshal_TLSSecretsConfig( + request.tls_secrets_config, defaults + ) + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output + + +def marshal_UpdateWafStageRequest( + request: UpdateWafStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.mode is not None: + output["mode"] = str(request.mode) + + if request.paranoia_level is not None: + output["paranoia_level"] = request.paranoia_level + + return output diff --git a/scaleway-async/scaleway_async/edge_services/v1beta1/types.py b/scaleway-async/scaleway_async/edge_services/v1beta1/types.py new file mode 100644 index 00000000..5172a74a --- /dev/null +++ b/scaleway-async/scaleway_async/edge_services/v1beta1/types.py @@ -0,0 +1,1800 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Money, + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DNSStageType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + AUTO = "auto" + MANAGED = "managed" + CUSTOM = "custom" + + def __str__(self) -> str: + return str(self.value) + + +class LbOriginError(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + TIMEOUT = "timeout" + CONNECTION_REFUSED = "connection_refused" + TLS_ERROR = "tls_error" + + def __str__(self) -> str: + return str(self.value) + + +class ListBackendStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListCacheStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListDNSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesWithStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPurgeRequestsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRouteStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListTLSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListWafStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorCode(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_CODE = "unknown_code" + DNS_INVALID_FORMAT = "dns_invalid_format" + DNS_INVALID_TLD = "dns_invalid_tld" + DNS_FORBIDDEN_ROOT_DOMAIN = "dns_forbidden_root_domain" + DNS_FORBIDDEN_SCW_CLOUD = "dns_forbidden_scw_cloud" + DNS_DOMAIN_DONT_EXIST = "dns_domain_dont_exist" + DNS_CNAME_DONT_EXIST = "dns_cname_dont_exist" + DNS_CNAME_RESOLVE = "dns_cname_resolve" + DNS_FQDN_ALREADY_EXISTS = "dns_fqdn_already_exists" + DNS_FQDN_ALREADY_IN_USE = "dns_fqdn_already_in_use" + TLS_CERT_DELETED = "tls_cert_deleted" + TLS_CERT_DISABLED = "tls_cert_disabled" + TLS_CERT_EXPIRED = "tls_cert_expired" + TLS_CERT_INVALID_FORMAT = "tls_cert_invalid_format" + TLS_CERT_MISSING = "tls_cert_missing" + TLS_CHAIN_ORDER = "tls_chain_order" + TLS_KEY_INVALID_FORMAT = "tls_key_invalid_format" + TLS_KEY_MISSING = "tls_key_missing" + TLS_KEY_TOO_MANY = "tls_key_too_many" + TLS_MANAGED_DOMAIN_RATE_LIMIT = "tls_managed_domain_rate_limit" + TLS_MANAGED_INTERNAL = "tls_managed_internal" + TLS_PAIR_MISMATCH = "tls_pair_mismatch" + TLS_ROOT_INCONSISTENT = "tls_root_inconsistent" + TLS_ROOT_INCORRECT = "tls_root_incorrect" + TLS_ROOT_MISSING = "tls_root_missing" + TLS_SAN_MISMATCH = "tls_san_mismatch" + TLS_SELF_SIGNED = "tls_self_signed" + PIPELINE_INVALID_WORKFLOW = "pipeline_invalid_workflow" + PIPELINE_MISSING_HEAD_STAGE = "pipeline_missing_head_stage" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorSeverity(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SEVERITY = "unknown_severity" + WARNING = "warning" + CRITICAL = "critical" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorStage(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STAGE = "unknown_stage" + DNS = "dns" + TLS = "tls" + CACHE = "cache" + BACKEND = "backend" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + RUNTIME = "runtime" + CONFIG = "config" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + ERROR = "error" + PENDING = "pending" + WARNING = "warning" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class PlanName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + STARTER = "starter" + PROFESSIONAL = "professional" + ADVANCED = "advanced" + + def __str__(self) -> str: + return str(self.value) + + +class PurgeRequestStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DONE = "done" + ERROR = "error" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) + + +class RuleHttpMatchMethodFilter(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_METHOD_FILTER = "unknown_method_filter" + GET = "get" + POST = "post" + PUT = "put" + PATCH = "patch" + DELETE = "delete" + HEAD = "head" + OPTIONS = "options" + + def __str__(self) -> str: + return str(self.value) + + +class RuleHttpMatchPathFilterPathFilterType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PATH_FILTER = "unknown_path_filter" + REGEX = "regex" + + def __str__(self) -> str: + return str(self.value) + + +class SearchBackendStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class SearchWafStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class WafStageMode(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_MODE = "unknown_mode" + DISABLE = "disable" + LOG_ONLY = "log_only" + ENABLE = "enable" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ScalewayLb: + id: str + """ + ID of the Load Balancer. + """ + + zone: ScwZone + """ + Zone of the Load Balancer. + """ + + frontend_id: str + """ + ID of the frontend linked to the Load Balancer. + """ + + is_ssl: Optional[bool] + """ + Defines whether the Load Balancer's frontend handles SSL connections. + """ + + domain_name: Optional[str] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to use in HTTP requests sent towards your Load Balancer. + """ + + +@dataclass +class RuleHttpMatchPathFilter: + path_filter_type: RuleHttpMatchPathFilterPathFilterType + """ + Type of filter to match for the HTTP URL path. For now, all path filters must be written in regex and use the `regex` type. + """ + + value: str + """ + Value to be matched for the HTTP URL path. + """ + + +@dataclass +class ScalewayLbBackendConfig: + lbs: List[ScalewayLb] + """ + Load Balancer information. + """ + + +@dataclass +class ScalewayS3BackendConfig: + bucket_name: Optional[str] + """ + Name of the Bucket. + """ + + bucket_region: Optional[str] + """ + Region of the Bucket. + """ + + is_website: Optional[bool] + """ + Defines whether the bucket website feature is enabled. + """ + + +@dataclass +class PipelineError: + stage: PipelineErrorStage + + code: PipelineErrorCode + + severity: PipelineErrorSeverity + + message: str + + type_: PipelineErrorType + + +@dataclass +class TLSSecret: + secret_id: str + """ + ID of the Secret. + """ + + region: ScwRegion + """ + Region of the Secret. + """ + + +@dataclass +class RuleHttpMatch: + method_filters: List[RuleHttpMatchMethodFilter] + """ + HTTP methods to filter for. A request using any of these methods will be considered to match the rule. Possible values are `get`, `post`, `put`, `patch`, `delete`, `head`, `options`. All methods will match if none is provided. + """ + + path_filter: Optional[RuleHttpMatchPathFilter] + """ + HTTP URL path to filter for. A request whose path matches the given filter will be considered to match the rule. All paths will match if none is provided. + """ + + +@dataclass +class BackendStage: + id: str + """ + ID of the backend stage. + """ + + pipeline_id: str + """ + Pipeline ID the backend stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the backend stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the backend stage was last updated. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CacheStage: + id: str + """ + ID of the cache stage. + """ + + pipeline_id: str + """ + Pipeline ID the cache stage belongs to. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + created_at: Optional[datetime] + """ + Date the cache stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the cache stage was last updated. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class DNSStage: + id: str + """ + ID of the DNS stage. + """ + + fqdns: List[str] + """ + List of Fully Qualified Domain Names attached to the stage. + """ + + type_: DNSStageType + """ + Type of the stage. + """ + + pipeline_id: str + """ + Pipeline ID the DNS stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the DNS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the DNS stage was last updated. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class Pipeline: + id: str + """ + ID of the pipeline. + """ + + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + status: PipelineStatus + """ + Status of the pipeline. + """ + + errors: List[PipelineError] + """ + Errors of the pipeline. + """ + + project_id: str + """ + Project ID of the pipeline. + """ + + organization_id: str + """ + Organization ID of the pipeline. + """ + + created_at: Optional[datetime] + """ + Date the pipeline was created. + """ + + updated_at: Optional[datetime] + """ + Date the pipeline was last updated. + """ + + +@dataclass +class RouteStage: + id: str + """ + ID of the route stage. + """ + + pipeline_id: str + """ + Pipeline ID the route stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the route stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the route stage was last updated. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class TLSStage: + id: str + """ + ID of the TLS stage. + """ + + secrets: List[TLSSecret] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: bool + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + pipeline_id: str + """ + Pipeline ID the TLS stage belongs to. + """ + + certificate_expires_at: Optional[datetime] + """ + Expiration date of the certificate. + """ + + created_at: Optional[datetime] + """ + Date the TLS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the TLS stage was last updated. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class WafStage: + id: str + """ + ID of the WAF stage. + """ + + pipeline_id: str + """ + Pipeline ID the WAF stage belongs to. + """ + + mode: WafStageMode + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + paranoia_level: int + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + created_at: Optional[datetime] + """ + Date the WAF stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the WAF stage was last updated. + """ + + backend_stage_id: Optional[str] + + +@dataclass +class SetRouteRulesRequestRouteRule: + rule_http_match: Optional[RuleHttpMatch] + + backend_stage_id: Optional[str] + + +@dataclass +class RouteRule: + position: int + """ + Position of the rule which determines the order of processing within the route stage. + """ + + route_stage_id: str + """ + Route stage ID the route rule belongs to. + """ + + rule_http_match: Optional[RuleHttpMatch] + + backend_stage_id: Optional[str] + + +@dataclass +class CheckPEMChainRequestSecretChain: + secret_id: str + + secret_region: str + + +@dataclass +class PlanDetails: + plan_name: PlanName + """ + Subscription plan name. + """ + + package_gb: int + """ + Amount of egress data from cache included in subscription plan. + """ + + pipeline_limit: int + """ + Number of pipelines included in subscription plan. + """ + + waf_requests: int + """ + Number of WAF requests included in subscription plan. + """ + + +@dataclass +class PlanUsageDetails: + plan_cost: Optional[Money] + """ + Cost to date (this month) for the corresponding Edge Services subscription plan. + """ + + +@dataclass +class HeadStageResponseHeadStage: + dns_stage_id: Optional[str] + + +@dataclass +class ListHeadStagesResponseHeadStage: + dns_stage_id: Optional[str] + + +@dataclass +class PipelineStages: + dns_stages: List[DNSStage] + + tls_stages: List[TLSStage] + + cache_stages: List[CacheStage] + + backend_stages: List[BackendStage] + + waf_stages: List[WafStage] + + route_stages: List[RouteStage] + + pipeline: Optional[Pipeline] + + +@dataclass +class PurgeRequest: + id: str + """ + ID of the purge request. + """ + + pipeline_id: str + """ + Pipeline ID the purge request belongs to. + """ + + status: PurgeRequestStatus + """ + Status of the purge request. + """ + + created_at: Optional[datetime] + """ + Date the purge request was created. + """ + + updated_at: Optional[datetime] + """ + Date the purge request was last updated. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class SetHeadStageRequestAddNewHeadStage: + new_stage_id: str + + +@dataclass +class SetHeadStageRequestRemoveHeadStage: + remove_stage_id: str + + +@dataclass +class SetHeadStageRequestSwapHeadStage: + new_stage_id: str + + current_stage_id: str + + +@dataclass +class TLSSecretsConfig: + tls_secrets: List[TLSSecret] + """ + Secret information (from Secret Manager). + """ + + +@dataclass +class AddRouteRulesRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + after_position: Optional[int] + + before_position: Optional[int] + + +@dataclass +class AddRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class CheckDomainRequest: + fqdn: str + + cname: str + + project_id: Optional[str] + + +@dataclass +class CheckDomainResponse: + is_valid: bool + + +@dataclass +class CheckLbOriginRequest: + lb: Optional[ScalewayLb] + + +@dataclass +class CheckLbOriginResponse: + is_valid: bool + + error_type: LbOriginError + + +@dataclass +class CheckPEMChainRequest: + fqdn: str + + project_id: Optional[str] + + secret: Optional[CheckPEMChainRequestSecretChain] + + raw: Optional[str] + + +@dataclass +class CheckPEMChainResponse: + is_valid: bool + + +@dataclass +class CreateBackendStageRequest: + pipeline_id: str + """ + Pipeline ID the Backend stage belongs to. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CreateCacheStageRequest: + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + pipeline_id: str + """ + Pipeline ID the Cache stage belongs to. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class CreateDNSStageRequest: + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + """ + + pipeline_id: str + """ + Pipeline ID the DNS stage belongs to. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class CreatePipelineRequest: + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + project_id: Optional[str] + """ + Project ID in which the pipeline will be created. + """ + + +@dataclass +class CreatePurgeRequestRequest: + pipeline_id: str + """ + Pipeline ID in which the purge request will be created. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class CreateRouteStageRequest: + pipeline_id: str + """ + Pipeline ID the route stage belongs to. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class CreateTLSStageRequest: + secrets: Optional[List[TLSSecret]] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + pipeline_id: str + """ + Pipeline ID the TLS stage belongs to. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + route_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + +@dataclass +class CreateWafStageRequest: + pipeline_id: str + """ + Pipeline ID the WAF stage belongs to. + """ + + paranoia_level: int + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + mode: Optional[WafStageMode] + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + backend_stage_id: Optional[str] + + +@dataclass +class DeleteBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to delete. + """ + + +@dataclass +class DeleteCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to delete. + """ + + +@dataclass +class DeleteCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class DeleteDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to delete. + """ + + +@dataclass +class DeletePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to delete. + """ + + +@dataclass +class DeleteRouteStageRequest: + route_stage_id: str + """ + ID of the route stage to delete. + """ + + +@dataclass +class DeleteTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to delete. + """ + + +@dataclass +class DeleteWafStageRequest: + waf_stage_id: str + """ + ID of the WAF stage to delete. + """ + + +@dataclass +class GetBackendStageRequest: + backend_stage_id: str + """ + ID of the requested backend stage. + """ + + +@dataclass +class GetBillingRequest: + project_id: Optional[str] + + +@dataclass +class GetBillingResponse: + current_plan: Optional[PlanDetails] + """ + Information on the currently-selected, active Edge Services subscription plan. + """ + + pipeline_number: int + """ + Total number of pipelines currently configured. + """ + + current_plan_cache_usage: int + """ + Total amount of data egressed from the cache in gigabytes from the beginning of the month, for the active subscription plan. + """ + + extra_cache_usage: int + """ + Total amount of extra data egressed from cache in gigabytes from the beginning of the month, not included in the subscription plans. + """ + + current_plan_waf_usage: int + """ + Total number of requests processed by the WAF since the beginning of the current month, for the active subscription plan. + """ + + extra_waf_usage: int + """ + Total number of extra requests processed by the WAF from the beginning of the month, not included in the subscription plans. + """ + + plan_cost: Optional[Money] + """ + Cost to date (this month) for Edge Service subscription plans. This comprises the pro-rata cost of the current subscription plan, and any previous subscription plans that were active earlier in the month. + """ + + extra_pipelines_cost: Optional[Money] + """ + Cost to date (this month) of pipelines not included in the subscription plans. + """ + + plans_usage_details: Dict[str, PlanUsageDetails] + """ + Detailed costs and usage for all Edge Services subscription plans that were activated during the month. + """ + + extra_cache_cost: Optional[Money] + """ + Cost to date (this month) of the data egressed from the cache that is not included in the subscription plans. + """ + + extra_waf_cost: Optional[Money] + """ + Cost to date (this month) of the extra requests processed by the WAF that were not included in the subscription plans. + """ + + waf_add_on: Optional[Money] + """ + Cost of activating WAF add-on (where subscription plan does not include WAF). + """ + + total_cost: Optional[Money] + """ + Total cost to date (this month) of all Edge Services resources including active subscription plan, previously active plans, extra pipelines and extra egress cache data. + """ + + +@dataclass +class GetCacheStageRequest: + cache_stage_id: str + """ + ID of the requested cache stage. + """ + + +@dataclass +class GetCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class GetDNSStageRequest: + dns_stage_id: str + """ + ID of the requested DNS stage. + """ + + +@dataclass +class GetPipelineRequest: + pipeline_id: str + """ + ID of the requested pipeline. + """ + + +@dataclass +class GetPurgeRequestRequest: + purge_request_id: str + """ + ID of the requested purge request. + """ + + +@dataclass +class GetRouteStageRequest: + route_stage_id: str + """ + ID of the requested route stage. + """ + + +@dataclass +class GetTLSStageRequest: + tls_stage_id: str + """ + ID of the requested TLS stage. + """ + + +@dataclass +class GetWafStageRequest: + waf_stage_id: str + """ + ID of the requested WAF stage. + """ + + +@dataclass +class HeadStageResponse: + head_stage: Optional[HeadStageResponseHeadStage] + """ + Modified or created head stage. + """ + + +@dataclass +class ListBackendStagesRequest: + order_by: Optional[ListBackendStagesRequestOrderBy] + """ + Sort order of backend stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of backend stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + """ + + bucket_name: Optional[str] + """ + Bucket name to filter for. Only backend stages from this Bucket will be returned. + """ + + bucket_region: Optional[str] + """ + Bucket region to filter for. Only backend stages with buckets in this region will be returned. + """ + + lb_id: Optional[str] + """ + Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + """ + + +@dataclass +class ListBackendStagesResponse: + stages: List[BackendStage] + """ + Paginated list of backend stages. + """ + + total_count: int + """ + Count of all backend stages matching the requested criteria. + """ + + +@dataclass +class ListCacheStagesRequest: + order_by: Optional[ListCacheStagesRequestOrderBy] + """ + Sort order of cache stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of cache stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + """ + + +@dataclass +class ListCacheStagesResponse: + stages: List[CacheStage] + """ + Paginated list of cache stages. + """ + + total_count: int + """ + Count of all cache stages matching the requested criteria. + """ + + +@dataclass +class ListDNSStagesRequest: + order_by: Optional[ListDNSStagesRequestOrderBy] + """ + Sort order of DNS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of DNS stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + """ + + fqdn: Optional[str] + """ + Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + """ + + +@dataclass +class ListDNSStagesResponse: + stages: List[DNSStage] + """ + Paginated list of DNS stages. + """ + + total_count: int + """ + Count of all DNS stages matching the requested criteria. + """ + + +@dataclass +class ListHeadStagesRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of head stages to return per page. + """ + + +@dataclass +class ListHeadStagesResponse: + head_stages: List[ListHeadStagesResponseHeadStage] + """ + Number of head stages to return per page. + """ + + total_count: int + """ + Count of all head stages matching the requested pipeline_id. + """ + + +@dataclass +class ListPipelinesRequest: + order_by: Optional[ListPipelinesRequestOrderBy] + """ + Sort order of pipelines in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of pipelines to return per page. + """ + + name: Optional[str] + """ + Pipeline name to filter for. Only pipelines with this string within their name will be returned. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. Only pipelines from this Organization will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for. Only pipelines from this Project will be returned. + """ + + has_backend_stage_lb: Optional[bool] + """ + Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + """ + + +@dataclass +class ListPipelinesResponse: + pipelines: List[Pipeline] + """ + Paginated list of pipelines. + """ + + total_count: int + """ + Count of all pipelines matching the requested criteria. + """ + + +@dataclass +class ListPipelinesWithStagesRequest: + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + name: Optional[str] + + organization_id: Optional[str] + + project_id: Optional[str] + + +@dataclass +class ListPipelinesWithStagesResponse: + pipelines: List[PipelineStages] + + total_count: int + + +@dataclass +class ListPlansResponse: + total_count: int + + plans: List[PlanDetails] + + +@dataclass +class ListPurgeRequestsRequest: + order_by: Optional[ListPurgeRequestsRequestOrderBy] + """ + Sort order of purge requests in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of purge requests to return per page. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. Only purge requests from this Project will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for. Only purge requests from this Project will be returned. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + """ + + +@dataclass +class ListPurgeRequestsResponse: + purge_requests: List[PurgeRequest] + """ + Paginated list of purge requests. + """ + + total_count: int + """ + Count of all purge requests matching the requested criteria. + """ + + +@dataclass +class ListRouteRulesRequest: + route_stage_id: str + """ + Route stage ID to filter for. Only route rules from this route stage will be returned. + """ + + +@dataclass +class ListRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class ListRouteStagesRequest: + order_by: Optional[ListRouteStagesRequestOrderBy] + """ + Sort order of route stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of route stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only route stages from this pipeline will be returned. + """ + + +@dataclass +class ListRouteStagesResponse: + stages: List[RouteStage] + """ + Paginated list of summarized route stages. + """ + + total_count: int + """ + Count of all route stages matching the requested criteria. + """ + + +@dataclass +class ListTLSStagesRequest: + order_by: Optional[ListTLSStagesRequestOrderBy] + """ + Sort order of TLS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of TLS stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + """ + + secret_id: Optional[str] + """ + Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + """ + + secret_region: Optional[str] + """ + Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + """ + + +@dataclass +class ListTLSStagesResponse: + stages: List[TLSStage] + """ + Paginated list of TLS stages. + """ + + total_count: int + """ + Count of all TLS stages matching the requested criteria. + """ + + +@dataclass +class ListWafStagesRequest: + order_by: Optional[ListWafStagesRequestOrderBy] + """ + Sort order of WAF stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of WAF stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + """ + + +@dataclass +class ListWafStagesResponse: + stages: List[WafStage] + """ + Paginated list of WAF stages. + """ + + total_count: int + """ + Count of all WAF stages matching the requested criteria. + """ + + +@dataclass +class Plan: + plan_name: PlanName + + +@dataclass +class SearchBackendStagesRequest: + order_by: Optional[SearchBackendStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + project_id: Optional[str] + + bucket_name: Optional[str] + + bucket_region: Optional[str] + + lb_id: Optional[str] + + +@dataclass +class SearchWafStagesRequest: + order_by: Optional[SearchWafStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + project_id: Optional[str] + + +@dataclass +class SelectPlanRequest: + project_id: Optional[str] + + plan_name: Optional[PlanName] + + +@dataclass +class SetHeadStageRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + add_new_head_stage: Optional[SetHeadStageRequestAddNewHeadStage] + + remove_head_stage: Optional[SetHeadStageRequestRemoveHeadStage] + + swap_head_stage: Optional[SetHeadStageRequestSwapHeadStage] + + +@dataclass +class SetRouteRulesRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class SetRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class UpdateBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to update. + """ + + pipeline_id: str + """ + Pipeline ID the Backend stage belongs to. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class UpdateCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to update. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class UpdateDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to update. + """ + + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class UpdatePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + name: Optional[str] + """ + Name of the pipeline. + """ + + description: Optional[str] + """ + Description of the pipeline. + """ + + +@dataclass +class UpdateRouteStageRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class UpdateTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to update. + """ + + tls_secrets_config: Optional[TLSSecretsConfig] + """ + Secret (from Scaleway Secret-Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + route_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + +@dataclass +class UpdateWafStageRequest: + waf_stage_id: str + """ + ID of the WAF stage to update. + """ + + mode: Optional[WafStageMode] + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + paranoia_level: Optional[int] + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + backend_stage_id: Optional[str] diff --git a/scaleway-async/scaleway_async/file/__init__.py b/scaleway-async/scaleway_async/file/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway-async/scaleway_async/file/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway-async/scaleway_async/file/v1alpha1/__init__.py b/scaleway-async/scaleway_async/file/v1alpha1/__init__.py new file mode 100644 index 00000000..05c3dbdf --- /dev/null +++ b/scaleway-async/scaleway_async/file/v1alpha1/__init__.py @@ -0,0 +1,35 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import AttachmentResourceType +from .types import FileSystemStatus +from .content import FILE_SYSTEM_TRANSIENT_STATUSES +from .types import ListFileSystemsRequestOrderBy +from .types import Attachment +from .types import FileSystem +from .types import CreateFileSystemRequest +from .types import DeleteFileSystemRequest +from .types import GetFileSystemRequest +from .types import ListAttachmentsRequest +from .types import ListAttachmentsResponse +from .types import ListFileSystemsRequest +from .types import ListFileSystemsResponse +from .types import UpdateFileSystemRequest +from .api import FileV1Alpha1API + +__all__ = [ + "AttachmentResourceType", + "FileSystemStatus", + "FILE_SYSTEM_TRANSIENT_STATUSES", + "ListFileSystemsRequestOrderBy", + "Attachment", + "FileSystem", + "CreateFileSystemRequest", + "DeleteFileSystemRequest", + "GetFileSystemRequest", + "ListAttachmentsRequest", + "ListAttachmentsResponse", + "ListFileSystemsRequest", + "ListFileSystemsResponse", + "UpdateFileSystemRequest", + "FileV1Alpha1API", +] diff --git a/scaleway-async/scaleway_async/file/v1alpha1/api.py b/scaleway-async/scaleway_async/file/v1alpha1/api.py new file mode 100644 index 00000000..876e5a9a --- /dev/null +++ b/scaleway-async/scaleway_async/file/v1alpha1/api.py @@ -0,0 +1,436 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + AttachmentResourceType, + ListFileSystemsRequestOrderBy, + Attachment, + CreateFileSystemRequest, + FileSystem, + ListAttachmentsResponse, + ListFileSystemsResponse, + UpdateFileSystemRequest, +) +from .content import ( + FILE_SYSTEM_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_FileSystem, + unmarshal_ListAttachmentsResponse, + unmarshal_ListFileSystemsResponse, + marshal_CreateFileSystemRequest, + marshal_UpdateFileSystemRequest, +) + + +class FileV1Alpha1API(API): + """ + This API allows you to manage your File Storage resources. + """ + + async def get_file_system( + self, + *, + filesystem_id: str, + region: Optional[ScwRegion] = None, + ) -> FileSystem: + """ + Get filesystem details. + Retrieve all properties and current status of a specific filesystem identified by its ID. + :param filesystem_id: UUID of the filesystem. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`FileSystem ` + + Usage: + :: + + result = await api.get_file_system( + filesystem_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_filesystem_id = validate_path_param("filesystem_id", filesystem_id) + + res = self._request( + "GET", + f"/file/v1alpha1/regions/{param_region}/filesystems/{param_filesystem_id}", + ) + + self._throw_on_error(res) + return unmarshal_FileSystem(res.json()) + + async def wait_for_file_system( + self, + *, + filesystem_id: str, + region: Optional[ScwRegion] = None, + options: Optional[ + WaitForOptions[FileSystem, Union[bool, Awaitable[bool]]] + ] = None, + ) -> FileSystem: + """ + Get filesystem details. + Retrieve all properties and current status of a specific filesystem identified by its ID. + :param filesystem_id: UUID of the filesystem. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`FileSystem ` + + Usage: + :: + + result = await api.get_file_system( + filesystem_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in FILE_SYSTEM_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_file_system, + options=options, + args={ + "filesystem_id": filesystem_id, + "region": region, + }, + ) + + async def list_file_systems( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListFileSystemsRequestOrderBy] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListFileSystemsResponse: + """ + List all filesystems. + Retrieve all filesystems in the specified region. By default, the filesystems listed are ordered by creation date in ascending order. This can be modified using the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by project ID. + :param page: Page number (starting at 1). + :param page_size: Number of entries per page (default: 20, max: 100). + :param name: Filter the returned filesystems by their names. + :param tags: Filter by tags. Only filesystems with one or more matching tags will be returned. + :return: :class:`ListFileSystemsResponse ` + + Usage: + :: + + result = await api.list_file_systems() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/file/v1alpha1/regions/{param_region}/filesystems", + params={ + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListFileSystemsResponse(res.json()) + + async def list_file_systems_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListFileSystemsRequestOrderBy] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[FileSystem]: + """ + List all filesystems. + Retrieve all filesystems in the specified region. By default, the filesystems listed are ordered by creation date in ascending order. This can be modified using the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by project ID. + :param page: Page number (starting at 1). + :param page_size: Number of entries per page (default: 20, max: 100). + :param name: Filter the returned filesystems by their names. + :param tags: Filter by tags. Only filesystems with one or more matching tags will be returned. + :return: :class:`List[FileSystem] ` + + Usage: + :: + + result = await api.list_file_systems_all() + """ + + return await fetch_all_pages_async( + type=ListFileSystemsResponse, + key="filesystems", + fetcher=self.list_file_systems, + args={ + "region": region, + "order_by": order_by, + "project_id": project_id, + "page": page, + "page_size": page_size, + "name": name, + "tags": tags, + }, + ) + + async def list_attachments( + self, + *, + region: Optional[ScwRegion] = None, + filesystem_id: Optional[str] = None, + resource_id: Optional[str] = None, + resource_type: Optional[AttachmentResourceType] = None, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListAttachmentsResponse: + """ + List filesystems attachments. + List all existing attachments in a specified region. + By default, the attachments listed are ordered by creation date in ascending order. This can be modified using the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param filesystem_id: UUID of the File Storage volume. + :param resource_id: Filter by resource ID. + :param resource_type: Filter by resource type. + :param zone: Filter by resource zone. + :param page: Page number (starting at 1). + :param page_size: Number of entries per page (default: 20, max: 100). + :return: :class:`ListAttachmentsResponse ` + + Usage: + :: + + result = await api.list_attachments() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/file/v1alpha1/regions/{param_region}/attachments", + params={ + "filesystem_id": filesystem_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "resource_id": resource_id, + "resource_type": resource_type, + "zone": zone or self.client.default_zone, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListAttachmentsResponse(res.json()) + + async def list_attachments_all( + self, + *, + region: Optional[ScwRegion] = None, + filesystem_id: Optional[str] = None, + resource_id: Optional[str] = None, + resource_type: Optional[AttachmentResourceType] = None, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[Attachment]: + """ + List filesystems attachments. + List all existing attachments in a specified region. + By default, the attachments listed are ordered by creation date in ascending order. This can be modified using the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param filesystem_id: UUID of the File Storage volume. + :param resource_id: Filter by resource ID. + :param resource_type: Filter by resource type. + :param zone: Filter by resource zone. + :param page: Page number (starting at 1). + :param page_size: Number of entries per page (default: 20, max: 100). + :return: :class:`List[Attachment] ` + + Usage: + :: + + result = await api.list_attachments_all() + """ + + return await fetch_all_pages_async( + type=ListAttachmentsResponse, + key="attachments", + fetcher=self.list_attachments, + args={ + "region": region, + "filesystem_id": filesystem_id, + "resource_id": resource_id, + "resource_type": resource_type, + "zone": zone, + "page": page, + "page_size": page_size, + }, + ) + + async def create_file_system( + self, + *, + name: str, + size: int, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> FileSystem: + """ + Create a new filesystem. + To create a new filesystem, you must specify a name, a size, and a project ID. + :param name: Name of the filesystem. + :param size: Must be compliant with the minimum (100 GB) and maximum (10 TB) allowed size. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: UUID of the project the filesystem belongs to. + :param tags: List of tags assigned to the filesystem. + :return: :class:`FileSystem ` + + Usage: + :: + + result = await api.create_file_system( + name="example", + size=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/file/v1alpha1/regions/{param_region}/filesystems", + body=marshal_CreateFileSystemRequest( + CreateFileSystemRequest( + name=name, + size=size, + region=region, + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_FileSystem(res.json()) + + async def delete_file_system( + self, + *, + filesystem_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a detached filesystem. + You must specify the `filesystem_id` of the filesystem you want to delete. + :param filesystem_id: UUID of the filesystem. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_file_system( + filesystem_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_filesystem_id = validate_path_param("filesystem_id", filesystem_id) + + res = self._request( + "DELETE", + f"/file/v1alpha1/regions/{param_region}/filesystems/{param_filesystem_id}", + ) + + self._throw_on_error(res) + + async def update_file_system( + self, + *, + filesystem_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + size: Optional[int] = None, + tags: Optional[List[str]] = None, + ) -> FileSystem: + """ + Update filesystem properties. + Update the technical details of a filesystem, such as its name, tags or its new size. + :param filesystem_id: UUID of the filesystem. + :param region: Region to target. If none is passed will use default region from the config. + :param name: When defined, is the new name of the filesystem. + :param size: Size in bytes, with a granularity of 100 GB (10^11 bytes). + Must be compliant with the minimum (100 GB) and maximum (10 TB) allowed size. + :param tags: List of tags assigned to the filesystem. + :return: :class:`FileSystem ` + + Usage: + :: + + result = await api.update_file_system( + filesystem_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_filesystem_id = validate_path_param("filesystem_id", filesystem_id) + + res = self._request( + "PATCH", + f"/file/v1alpha1/regions/{param_region}/filesystems/{param_filesystem_id}", + body=marshal_UpdateFileSystemRequest( + UpdateFileSystemRequest( + filesystem_id=filesystem_id, + region=region, + name=name, + size=size, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_FileSystem(res.json()) diff --git a/scaleway-async/scaleway_async/file/v1alpha1/content.py b/scaleway-async/scaleway_async/file/v1alpha1/content.py new file mode 100644 index 00000000..c6a422b4 --- /dev/null +++ b/scaleway-async/scaleway_async/file/v1alpha1/content.py @@ -0,0 +1,15 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + FileSystemStatus, +) + +FILE_SYSTEM_TRANSIENT_STATUSES: List[FileSystemStatus] = [ + FileSystemStatus.CREATING, + FileSystemStatus.UPDATING, +] +""" +Lists transient statutes of the enum :class:`FileSystemStatus `. +""" diff --git a/scaleway-async/scaleway_async/file/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/file/v1alpha1/marshalling.py new file mode 100644 index 00000000..e9b6d39d --- /dev/null +++ b/scaleway-async/scaleway_async/file/v1alpha1/marshalling.py @@ -0,0 +1,188 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from .types import ( + FileSystem, + Attachment, + ListAttachmentsResponse, + ListFileSystemsResponse, + CreateFileSystemRequest, + UpdateFileSystemRequest, +) + + +def unmarshal_FileSystem(data: Any) -> FileSystem: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'FileSystem' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("number_of_attachments", None) + if field is not None: + args["number_of_attachments"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return FileSystem(**args) + + +def unmarshal_Attachment(data: Any) -> Attachment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Attachment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("filesystem_id", None) + if field is not None: + args["filesystem_id"] = field + + field = data.get("resource_id", None) + if field is not None: + args["resource_id"] = field + + field = data.get("resource_type", None) + if field is not None: + args["resource_type"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + return Attachment(**args) + + +def unmarshal_ListAttachmentsResponse(data: Any) -> ListAttachmentsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListAttachmentsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("attachments", None) + if field is not None: + args["attachments"] = ( + [unmarshal_Attachment(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListAttachmentsResponse(**args) + + +def unmarshal_ListFileSystemsResponse(data: Any) -> ListFileSystemsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListFileSystemsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("filesystems", None) + if field is not None: + args["filesystems"] = ( + [unmarshal_FileSystem(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListFileSystemsResponse(**args) + + +def marshal_CreateFileSystemRequest( + request: CreateFileSystemRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.size is not None: + output["size"] = request.size + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_UpdateFileSystemRequest( + request: UpdateFileSystemRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.size is not None: + output["size"] = request.size + + if request.tags is not None: + output["tags"] = request.tags + + return output diff --git a/scaleway-async/scaleway_async/file/v1alpha1/types.py b/scaleway-async/scaleway_async/file/v1alpha1/types.py new file mode 100644 index 00000000..04f5973a --- /dev/null +++ b/scaleway-async/scaleway_async/file/v1alpha1/types.py @@ -0,0 +1,356 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class AttachmentResourceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_RESOURCE_TYPE = "unknown_resource_type" + INSTANCE_SERVER = "instance_server" + + def __str__(self) -> str: + return str(self.value) + + +class FileSystemStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + AVAILABLE = "available" + ERROR = "error" + CREATING = "creating" + UPDATING = "updating" + + def __str__(self) -> str: + return str(self.value) + + +class ListFileSystemsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class Attachment: + """ + Represents an attachment between a filesystem and a resource. + """ + + id: str + """ + UUID of the attachment. + """ + + filesystem_id: str + """ + UUID of the filesystem. + """ + + resource_id: str + """ + UUID of the attached resource. + """ + + resource_type: AttachmentResourceType + """ + The type of the attached resource. + """ + + zone: Optional[ScwZone] + """ + The zone where the resource is located. + """ + + +@dataclass +class FileSystem: + """ + Represents a filesystem resource and its properties. + """ + + id: str + """ + UUID of the filesystem. + """ + + name: str + """ + Name of the filesystem. + """ + + size: int + """ + Filesystem size in bytes. + """ + + status: FileSystemStatus + """ + Current status of the filesystem (e.g. creating, available, ...). + """ + + project_id: str + """ + UUID of the project to which the filesystem belongs. + """ + + organization_id: str + """ + UUID of the organization to which the filesystem belongs. + """ + + tags: List[str] + """ + List of tags assigned to the filesystem. + """ + + number_of_attachments: int + """ + The current number of attachments (mounts) that the filesystem has. + """ + + region: ScwRegion + """ + Region where the filesystem is located. + """ + + created_at: Optional[datetime] + """ + Creation date of the filesystem. + """ + + updated_at: Optional[datetime] + """ + Last update date of the properties of the filesystem. + """ + + +@dataclass +class CreateFileSystemRequest: + """ + Request to create a new filesystem. + """ + + name: str + """ + Name of the filesystem. + """ + + size: int + """ + Must be compliant with the minimum (100 GB) and maximum (10 TB) allowed size. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + UUID of the project the filesystem belongs to. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the filesystem. + """ + + +@dataclass +class DeleteFileSystemRequest: + """ + Request to delete a specific filesystem. + """ + + filesystem_id: str + """ + UUID of the filesystem. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetFileSystemRequest: + """ + Request to retrieve a specific filesystem. + """ + + filesystem_id: str + """ + UUID of the filesystem. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListAttachmentsRequest: + """ + Request to list filesystem attachments with filtering and pagination options. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + filesystem_id: Optional[str] + """ + UUID of the File Storage volume. + """ + + resource_id: Optional[str] + """ + Filter by resource ID. + """ + + resource_type: Optional[AttachmentResourceType] + """ + Filter by resource type. + """ + + zone: Optional[ScwZone] + """ + Filter by resource zone. + """ + + page: Optional[int] + """ + Page number (starting at 1). + """ + + page_size: Optional[int] + """ + Number of entries per page (default: 20, max: 100). + """ + + +@dataclass +class ListAttachmentsResponse: + """ + Response containing a list of filesystem attachments and total count. + """ + + attachments: List[Attachment] + """ + List of filesystem attachments matching the request criteria. + """ + + total_count: int + """ + Total number of filesystem attachments matching the criteria. + """ + + +@dataclass +class ListFileSystemsRequest: + """ + Request to list filesystems with filtering and pagination options. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListFileSystemsRequestOrderBy] + """ + Criteria to use when ordering the list. + """ + + project_id: Optional[str] + """ + Filter by project ID. + """ + + page: Optional[int] + """ + Page number (starting at 1). + """ + + page_size: Optional[int] + """ + Number of entries per page (default: 20, max: 100). + """ + + name: Optional[str] + """ + Filter the returned filesystems by their names. + """ + + tags: Optional[List[str]] + """ + Filter by tags. Only filesystems with one or more matching tags will be returned. + """ + + +@dataclass +class ListFileSystemsResponse: + """ + Response containing a list of filesystems and total count. + """ + + filesystems: List[FileSystem] + """ + List of filesystems matching the request criteria. + """ + + total_count: int + """ + Total number of filesystems matching the criteria. + """ + + +@dataclass +class UpdateFileSystemRequest: + """ + Request to update a specific filesystem. + """ + + filesystem_id: str + """ + UUID of the filesystem. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + When defined, is the new name of the filesystem. + """ + + size: Optional[int] + """ + Size in bytes, with a granularity of 100 GB (10^11 bytes). +Must be compliant with the minimum (100 GB) and maximum (10 TB) allowed size. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the filesystem. + """ diff --git a/scaleway-async/scaleway_async/flexibleip/v1alpha1/api.py b/scaleway-async/scaleway_async/flexibleip/v1alpha1/api.py index bd4bf31e..4cb04208 100644 --- a/scaleway-async/scaleway_async/flexibleip/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/flexibleip/v1alpha1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, @@ -49,7 +49,7 @@ class FlexibleipV1Alpha1API(API): """ - Elastic Metal - Flexible IP API. + This API allows you to manage your Elastic Metal servers' flexible public IP addresses. """ async def create_flexible_ip( @@ -57,7 +57,7 @@ async def create_flexible_ip( *, description: str, is_ipv6: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, server_id: Optional[str] = None, @@ -110,7 +110,7 @@ async def get_flexible_ip( self, *, fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> FlexibleIP: """ Get an existing flexible IP. @@ -142,7 +142,7 @@ async def wait_for_flexible_ip( self, *, fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[ WaitForOptions[FlexibleIP, Union[bool, Awaitable[bool]]] ] = None, @@ -180,7 +180,7 @@ async def wait_for_flexible_ip( async def list_flexible_i_ps( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListFlexibleIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -234,7 +234,7 @@ async def list_flexible_i_ps( async def list_flexible_i_ps_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListFlexibleIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -285,7 +285,7 @@ async def update_flexible_ip( self, *, fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, reverse: Optional[str] = None, @@ -333,7 +333,7 @@ async def delete_flexible_ip( self, *, fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an existing flexible IP. @@ -364,7 +364,7 @@ async def attach_flexible_ip( *, fips_ids: List[str], server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> AttachFlexibleIPsResponse: """ Attach an existing flexible IP to a server. @@ -405,7 +405,7 @@ async def detach_flexible_ip( self, *, fips_ids: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> DetachFlexibleIPsResponse: """ Detach an existing flexible IP from a server. @@ -444,7 +444,7 @@ async def generate_mac_addr( *, fip_id: str, mac_type: MACAddressType, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> FlexibleIP: """ Generate a virtual MAC address on an existing flexible IP. @@ -487,7 +487,7 @@ async def duplicate_mac_addr( *, fip_id: str, duplicate_from_fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> FlexibleIP: """ Duplicate a virtual MAC address to another flexible IP. @@ -530,7 +530,7 @@ async def move_mac_addr( *, fip_id: str, dst_fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> FlexibleIP: """ Relocate an existing virtual MAC address to a different flexible IP. @@ -572,7 +572,7 @@ async def delete_mac_addr( self, *, fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Detach a given virtual MAC address from an existing flexible IP. diff --git a/scaleway-async/scaleway_async/flexibleip/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/flexibleip/v1alpha1/marshalling.py index 5f44ed7d..6f754d00 100644 --- a/scaleway-async/scaleway_async/flexibleip/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/flexibleip/v1alpha1/marshalling.py @@ -52,10 +52,14 @@ def unmarshal_MACAddress(data: Any) -> MACAddress: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return MACAddress(**args) @@ -99,6 +103,8 @@ def unmarshal_FlexibleIP(data: Any) -> FlexibleIP: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("reverse", None) if field is not None: @@ -111,14 +117,20 @@ def unmarshal_FlexibleIP(data: Any) -> FlexibleIP: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("mac_address", None) if field is not None: args["mac_address"] = unmarshal_MACAddress(field) + else: + args["mac_address"] = None field = data.get("server_id", None) if field is not None: args["server_id"] = field + else: + args["server_id"] = None return FlexibleIP(**args) diff --git a/scaleway-async/scaleway_async/flexibleip/v1alpha1/types.py b/scaleway-async/scaleway_async/flexibleip/v1alpha1/types.py index 36ce0fce..623c8c4e 100644 --- a/scaleway-async/scaleway_async/flexibleip/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/flexibleip/v1alpha1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -80,7 +80,7 @@ class MACAddress: Status of virtual MAC. """ - zone: Zone + zone: ScwZone """ MAC address IP Availability Zone. """ @@ -148,7 +148,7 @@ class FlexibleIP: Reverse DNS value. """ - zone: Zone + zone: ScwZone """ Availability Zone of the flexible IP. """ @@ -181,7 +181,7 @@ class AttachFlexibleIPRequest: ID of the server on which to attach the flexible IPs. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -212,7 +212,7 @@ class CreateFlexibleIPRequest: Defines whether the flexible IP has an IPv6 address. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -245,7 +245,7 @@ class DeleteFlexibleIPRequest: ID of the flexible IP to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -258,7 +258,7 @@ class DeleteMACAddrRequest: If the flexible IP belongs to a MAC group, the MAC will be removed from both the MAC group and flexible IP. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -271,7 +271,7 @@ class DetachFlexibleIPRequest: List of flexible IP IDs to detach from a server. Multiple IDs can be provided. Note that flexible IPs must belong to the same MAC group. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -302,7 +302,7 @@ class DuplicateMACAddrRequest: Note that flexible IPs need to be attached to the same server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -320,7 +320,7 @@ class GenerateMACAddrRequest: TODO. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -333,7 +333,7 @@ class GetFlexibleIPRequest: ID of the flexible IP. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -341,7 +341,7 @@ class GetFlexibleIPRequest: @dataclass class ListFlexibleIPsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -406,7 +406,7 @@ class MoveMACAddrRequest: dst_fip_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -419,7 +419,7 @@ class UpdateFlexibleIPRequest: ID of the flexible IP to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway-async/scaleway_async/function/v1beta1/__init__.py b/scaleway-async/scaleway_async/function/v1beta1/__init__.py index b6e5acf9..2b9481aa 100644 --- a/scaleway-async/scaleway_async/function/v1beta1/__init__.py +++ b/scaleway-async/scaleway_async/function/v1beta1/__init__.py @@ -7,6 +7,7 @@ from .types import FunctionHttpOption from .types import FunctionPrivacy from .types import FunctionRuntime +from .types import FunctionSandbox from .types import FunctionStatus from .content import FUNCTION_TRANSIENT_STATUSES from .types import ListCronsRequestOrderBy @@ -61,7 +62,6 @@ from .types import GetNamespaceRequest from .types import GetTokenRequest from .types import GetTriggerRequest -from .types import IssueJWTRequest from .types import ListCronsRequest from .types import ListCronsResponse from .types import ListDomainsRequest @@ -91,6 +91,7 @@ "FunctionHttpOption", "FunctionPrivacy", "FunctionRuntime", + "FunctionSandbox", "FunctionStatus", "FUNCTION_TRANSIENT_STATUSES", "ListCronsRequestOrderBy", @@ -145,7 +146,6 @@ "GetNamespaceRequest", "GetTokenRequest", "GetTriggerRequest", - "IssueJWTRequest", "ListCronsRequest", "ListCronsResponse", "ListDomainsRequest", diff --git a/scaleway-async/scaleway_async/function/v1beta1/api.py b/scaleway-async/scaleway_async/function/v1beta1/api.py index 41e8de76..0b28ea66 100644 --- a/scaleway-async/scaleway_async/function/v1beta1/api.py +++ b/scaleway-async/scaleway_async/function/v1beta1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( OneOfPossibility, @@ -21,6 +21,7 @@ FunctionHttpOption, FunctionPrivacy, FunctionRuntime, + FunctionSandbox, ListCronsRequestOrderBy, ListDomainsRequestOrderBy, ListFunctionsRequestOrderBy, @@ -96,12 +97,14 @@ class FunctionV1Beta1API(API): - """ """ + """ + This API allows you to manage your Serverless Functions. + """ async def list_namespaces( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -151,7 +154,7 @@ async def list_namespaces( async def list_namespaces_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -196,7 +199,7 @@ async def get_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Get a namespace. @@ -230,7 +233,7 @@ async def wait_for_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[Namespace, Union[bool, Awaitable[bool]]] ] = None, @@ -268,12 +271,13 @@ async def wait_for_namespace( async def create_namespace( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, environment_variables: Optional[Dict[str, str]] = None, project_id: Optional[str] = None, description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, + tags: Optional[List[str]] = None, ) -> Namespace: """ Create a new namespace. @@ -284,6 +288,7 @@ async def create_namespace( :param project_id: UUID of the project in which the namespace will be created. :param description: Description of the namespace. :param secret_environment_variables: Secret environment variables of the namespace. + :param tags: Tags of the Serverless Function Namespace. :return: :class:`Namespace ` Usage: @@ -307,6 +312,7 @@ async def create_namespace( project_id=project_id, description=description, secret_environment_variables=secret_environment_variables, + tags=tags, ), self.client, ), @@ -319,10 +325,11 @@ async def update_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, environment_variables: Optional[Dict[str, str]] = None, description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, + tags: Optional[List[str]] = None, ) -> Namespace: """ Update an existing namespace. @@ -332,6 +339,7 @@ async def update_namespace( :param environment_variables: Environment variables of the namespace. :param description: Description of the namespace. :param secret_environment_variables: Secret environment variables of the namespace. + :param tags: Tags of the Serverless Function Namespace. :return: :class:`Namespace ` Usage: @@ -357,6 +365,7 @@ async def update_namespace( environment_variables=environment_variables, description=description, secret_environment_variables=secret_environment_variables, + tags=tags, ), self.client, ), @@ -369,7 +378,7 @@ async def delete_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Delete an existing namespace. @@ -403,7 +412,7 @@ async def list_functions( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListFunctionsRequestOrderBy] = None, @@ -419,7 +428,7 @@ async def list_functions( :param page_size: Number of functions per page. :param order_by: Order of the functions. :param name: Name of the function. - :param organization_id: UUID of the Organziation the function belongs to. + :param organization_id: UUID of the Organization the function belongs to. :param project_id: UUID of the Project the function belongs to. :return: :class:`ListFunctionsResponse ` @@ -457,7 +466,7 @@ async def list_functions_all( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListFunctionsRequestOrderBy] = None, @@ -473,7 +482,7 @@ async def list_functions_all( :param page_size: Number of functions per page. :param order_by: Order of the functions. :param name: Name of the function. - :param organization_id: UUID of the Organziation the function belongs to. + :param organization_id: UUID of the Organization the function belongs to. :param project_id: UUID of the Project the function belongs to. :return: :class:`List[Function] ` @@ -505,7 +514,7 @@ async def get_function( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Function: """ Get a function. @@ -539,7 +548,7 @@ async def wait_for_function( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[Function, Union[bool, Awaitable[bool]]] ] = None, @@ -578,7 +587,7 @@ async def create_function( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, environment_variables: Optional[Dict[str, str]] = None, min_scale: Optional[int] = None, @@ -591,6 +600,8 @@ async def create_function( description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, http_option: Optional[FunctionHttpOption] = None, + sandbox: Optional[FunctionSandbox] = None, + tags: Optional[List[str]] = None, ) -> Function: """ Create a new function. @@ -599,7 +610,7 @@ async def create_function( :param region: Region to target. If none is passed will use default region from the config. :param name: Name of the function to create. :param environment_variables: Environment variables of the function. - :param min_scale: Minumum number of instances to scale the function to. + :param min_scale: Minimum number of instances to scale the function to. :param max_scale: Maximum number of instances to scale the function to. :param runtime: Runtime to use with the function. :param memory_limit: Memory limit of the function in MB. @@ -611,6 +622,8 @@ async def create_function( :param http_option: Possible values: - redirected: Responds to HTTP request with a 301 redirect to ask the clients to use HTTPS. - enabled: Serve both HTTP and HTTPS traffic. + :param sandbox: Execution environment of the function. + :param tags: Tags of the Serverless Function. :return: :class:`Function ` Usage: @@ -644,6 +657,8 @@ async def create_function( description=description, secret_environment_variables=secret_environment_variables, http_option=http_option, + sandbox=sandbox, + tags=tags, ), self.client, ), @@ -656,7 +671,7 @@ async def update_function( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, environment_variables: Optional[Dict[str, str]] = None, min_scale: Optional[int] = None, max_scale: Optional[int] = None, @@ -669,6 +684,8 @@ async def update_function( description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, http_option: Optional[FunctionHttpOption] = None, + sandbox: Optional[FunctionSandbox] = None, + tags: Optional[List[str]] = None, ) -> Function: """ Update an existing function. @@ -676,7 +693,7 @@ async def update_function( :param function_id: UUID of the function to update. :param region: Region to target. If none is passed will use default region from the config. :param environment_variables: Environment variables of the function to update. - :param min_scale: Minumum number of instances to scale the function to. + :param min_scale: Minimum number of instances to scale the function to. :param max_scale: Maximum number of instances to scale the function to. :param runtime: Runtime to use with the function. :param memory_limit: Memory limit of the function in MB. @@ -689,6 +706,8 @@ async def update_function( :param http_option: Possible values: - redirected: Responds to HTTP request with a 301 redirect to ask the clients to use HTTPS. - enabled: Serve both HTTP and HTTPS traffic. + :param sandbox: Execution environment of the function. + :param tags: Tags of the Serverless Function. :return: :class:`Function ` Usage: @@ -723,6 +742,8 @@ async def update_function( description=description, secret_environment_variables=secret_environment_variables, http_option=http_option, + sandbox=sandbox, + tags=tags, ), self.client, ), @@ -735,7 +756,7 @@ async def delete_function( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Function: """ Delete a function. @@ -769,7 +790,7 @@ async def deploy_function( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Function: """ Deploy a function. @@ -803,7 +824,7 @@ async def deploy_function( async def list_function_runtimes( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListFunctionRuntimesResponse: """ List function runtimes. @@ -834,7 +855,7 @@ async def get_function_upload_url( *, function_id: str, content_length: int, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> UploadURL: """ Get an upload URL of a function. @@ -873,12 +894,12 @@ async def get_function_download_url( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DownloadURL: """ Get a download URL of a function. Get a download URL for a function associated with the specified ID. - :param function_id: UUID of the function to get the the download URL for. + :param function_id: UUID of the function to get the download URL for. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`DownloadURL ` @@ -907,7 +928,7 @@ async def list_crons( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListCronsRequestOrderBy] = None, @@ -952,7 +973,7 @@ async def list_crons_all( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListCronsRequestOrderBy] = None, @@ -992,7 +1013,7 @@ async def get_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cron: """ Get a cron. @@ -1026,7 +1047,7 @@ async def wait_for_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Cron, Union[bool, Awaitable[bool]]]] = None, ) -> Cron: """ @@ -1064,7 +1085,7 @@ async def create_cron( *, function_id: str, schedule: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, args: Optional[Dict[str, Any]] = None, name: Optional[str] = None, ) -> Cron: @@ -1113,7 +1134,7 @@ async def update_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, function_id: Optional[str] = None, schedule: Optional[str] = None, args: Optional[Dict[str, Any]] = None, @@ -1166,7 +1187,7 @@ async def delete_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cron: """ Delete an existing cron. @@ -1200,7 +1221,7 @@ async def list_domains( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDomainsRequestOrderBy] = None, @@ -1208,7 +1229,7 @@ async def list_domains( """ List all domain name bindings. List all domain name bindings in a specified region. - :param function_id: UUID of the function the domain is assoicated with. + :param function_id: UUID of the function the domain is associated with. :param region: Region to target. If none is passed will use default region from the config. :param page: Page number. :param page_size: Number of domains per page. @@ -1245,7 +1266,7 @@ async def list_domains_all( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDomainsRequestOrderBy] = None, @@ -1253,7 +1274,7 @@ async def list_domains_all( """ List all domain name bindings. List all domain name bindings in a specified region. - :param function_id: UUID of the function the domain is assoicated with. + :param function_id: UUID of the function the domain is associated with. :param region: Region to target. If none is passed will use default region from the config. :param page: Page number. :param page_size: Number of domains per page. @@ -1285,7 +1306,7 @@ async def get_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Get a domain name binding. @@ -1319,7 +1340,7 @@ async def wait_for_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Domain, Union[bool, Awaitable[bool]]]] = None, ) -> Domain: """ @@ -1357,7 +1378,7 @@ async def create_domain( *, hostname: str, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Create a domain name binding. @@ -1400,7 +1421,7 @@ async def delete_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Delete a domain name binding. @@ -1430,57 +1451,10 @@ async def delete_domain( self._throw_on_error(res) return unmarshal_Domain(res.json()) - async def issue_jwt( - self, - *, - region: Optional[Region] = None, - function_id: Optional[str] = None, - namespace_id: Optional[str] = None, - expires_at: Optional[datetime] = None, - ) -> Token: - """ - Create a JWT token. - Deprecated in favor of CreateToken. - :param region: Region to target. If none is passed will use default region from the config. - :param function_id: - One-Of ('scope'): at most one of 'function_id', 'namespace_id' could be set. - :param namespace_id: - One-Of ('scope'): at most one of 'function_id', 'namespace_id' could be set. - :param expires_at: - :return: :class:`Token ` - :deprecated - - Usage: - :: - - result = await api.issue_jwt() - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - - res = self._request( - "GET", - f"/functions/v1beta1/regions/{param_region}/issue-jwt", - params={ - "expires_at": expires_at, - **resolve_one_of( - [ - OneOfPossibility("function_id", function_id), - OneOfPossibility("namespace_id", namespace_id), - ] - ), - }, - ) - - self._throw_on_error(res) - return unmarshal_Token(res.json()) - async def create_token( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, function_id: Optional[str] = None, namespace_id: Optional[str] = None, description: Optional[str] = None, @@ -1529,7 +1503,7 @@ async def get_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Token: """ Get a token. @@ -1562,7 +1536,7 @@ async def wait_for_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Token, Union[bool, Awaitable[bool]]]] = None, ) -> Token: """ @@ -1597,7 +1571,7 @@ async def wait_for_token( async def list_tokens( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTokensRequestOrderBy] = None, @@ -1610,7 +1584,7 @@ async def list_tokens( :param page: Page number. :param page_size: Number of tokens per page. :param order_by: Sort order for the tokens. - :param function_id: UUID of the function the token is assoicated with. + :param function_id: UUID of the function the token is associated with. :param namespace_id: UUID of the namespace the token is associated with. :return: :class:`ListTokensResponse ` @@ -1642,7 +1616,7 @@ async def list_tokens( async def list_tokens_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTokensRequestOrderBy] = None, @@ -1655,7 +1629,7 @@ async def list_tokens_all( :param page: Page number. :param page_size: Number of tokens per page. :param order_by: Sort order for the tokens. - :param function_id: UUID of the function the token is assoicated with. + :param function_id: UUID of the function the token is associated with. :param namespace_id: UUID of the namespace the token is associated with. :return: :class:`List[Token] ` @@ -1683,7 +1657,7 @@ async def delete_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Token: """ Delete a token. @@ -1717,7 +1691,7 @@ async def create_trigger( *, name: str, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, scw_sqs_config: Optional[CreateTriggerRequestMnqSqsClientConfig] = None, scw_nats_config: Optional[CreateTriggerRequestMnqNatsClientConfig] = None, @@ -1775,7 +1749,7 @@ async def get_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Trigger: """ Get a trigger. @@ -1809,7 +1783,7 @@ async def wait_for_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Trigger, Union[bool, Awaitable[bool]]]] = None, ) -> Trigger: """ @@ -1845,7 +1819,7 @@ async def wait_for_trigger( async def list_triggers( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTriggersRequestOrderBy] = None, @@ -1901,7 +1875,7 @@ async def list_triggers( async def list_triggers_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTriggersRequestOrderBy] = None, @@ -1949,7 +1923,7 @@ async def update_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, description: Optional[str] = None, sqs_config: Optional[UpdateTriggerRequestSqsClientConfig] = None, @@ -2000,7 +1974,7 @@ async def delete_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Trigger: """ Delete a trigger. diff --git a/scaleway-async/scaleway_async/function/v1beta1/marshalling.py b/scaleway-async/scaleway_async/function/v1beta1/marshalling.py index 34ff2d4d..d3cb71cd 100644 --- a/scaleway-async/scaleway_async/function/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/function/v1beta1/marshalling.py @@ -79,6 +79,8 @@ def unmarshal_Cron(data: Any) -> Cron: field = data.get("args", None) if field is not None: args["args"] = field + else: + args["args"] = None return Cron(**args) @@ -114,6 +116,8 @@ def unmarshal_Domain(data: Any) -> Domain: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None return Domain(**args) @@ -205,6 +209,30 @@ def unmarshal_Function(data: Any) -> Function: else None ) + field = data.get("timeout", None) + if field is not None: + args["timeout"] = field + else: + args["timeout"] = None + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + else: + args["error_message"] = None + + field = data.get("build_message", None) + if field is not None: + args["build_message"] = field + else: + args["build_message"] = None + + field = data.get("description", None) + if field is not None: + args["description"] = field + else: + args["description"] = None + field = data.get("region", None) if field is not None: args["region"] = field @@ -217,21 +245,31 @@ def unmarshal_Function(data: Any) -> Function: if field is not None: args["runtime_message"] = field - field = data.get("timeout", None) + field = data.get("sandbox", None) if field is not None: - args["timeout"] = field + args["sandbox"] = field - field = data.get("error_message", None) + field = data.get("tags", None) if field is not None: - args["error_message"] = field + args["tags"] = field - field = data.get("build_message", None) + field = data.get("created_at", None) if field is not None: - args["build_message"] = field + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None - field = data.get("description", None) + field = data.get("updated_at", None) if field is not None: - args["description"] = field + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("ready_at", None) + if field is not None: + args["ready_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["ready_at"] = None return Function(**args) @@ -288,13 +326,33 @@ def unmarshal_Namespace(data: Any) -> Namespace: if field is not None: args["region"] = field + field = data.get("tags", None) + if field is not None: + args["tags"] = field + field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Namespace(**args) @@ -322,22 +380,32 @@ def unmarshal_Token(data: Any) -> Token: field = data.get("function_id", None) if field is not None: args["function_id"] = field + else: + args["function_id"] = None field = data.get("namespace_id", None) if field is not None: args["namespace_id"] = field + else: + args["namespace_id"] = None field = data.get("public_key", None) if field is not None: args["public_key"] = field + else: + args["public_key"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None return Token(**args) @@ -369,6 +437,8 @@ def unmarshal_TriggerMnqNatsClientConfig(data: Any) -> TriggerMnqNatsClientConfi field = data.get("mnq_credential_id", None) if field is not None: args["mnq_credential_id"] = field + else: + args["mnq_credential_id"] = None return TriggerMnqNatsClientConfig(**args) @@ -396,6 +466,8 @@ def unmarshal_TriggerMnqSqsClientConfig(data: Any) -> TriggerMnqSqsClientConfig: field = data.get("mnq_credential_id", None) if field is not None: args["mnq_credential_id"] = field + else: + args["mnq_credential_id"] = None return TriggerMnqSqsClientConfig(**args) @@ -462,18 +534,26 @@ def unmarshal_Trigger(data: Any) -> Trigger: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("scw_sqs_config", None) if field is not None: args["scw_sqs_config"] = unmarshal_TriggerMnqSqsClientConfig(field) + else: + args["scw_sqs_config"] = None field = data.get("scw_nats_config", None) if field is not None: args["scw_nats_config"] = unmarshal_TriggerMnqNatsClientConfig(field) + else: + args["scw_nats_config"] = None field = data.get("sqs_config", None) if field is not None: args["sqs_config"] = unmarshal_TriggerSqsClientConfig(field) + else: + args["sqs_config"] = None return Trigger(**args) @@ -813,6 +893,12 @@ def marshal_CreateFunctionRequest( if request.http_option is not None: output["http_option"] = str(request.http_option) + if request.sandbox is not None: + output["sandbox"] = str(request.sandbox) + + if request.tags is not None: + output["tags"] = request.tags + return output @@ -840,6 +926,9 @@ def marshal_CreateNamespaceRequest( for item in request.secret_environment_variables ] + if request.tags is not None: + output["tags"] = request.tags + return output @@ -861,7 +950,7 @@ def marshal_CreateTokenRequest( output["description"] = request.description if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -1019,6 +1108,12 @@ def marshal_UpdateFunctionRequest( if request.http_option is not None: output["http_option"] = str(request.http_option) + if request.sandbox is not None: + output["sandbox"] = str(request.sandbox) + + if request.tags is not None: + output["tags"] = request.tags + return output @@ -1040,6 +1135,9 @@ def marshal_UpdateNamespaceRequest( for item in request.secret_environment_variables ] + if request.tags is not None: + output["tags"] = request.tags + return output diff --git a/scaleway-async/scaleway_async/function/v1beta1/types.py b/scaleway-async/scaleway_async/function/v1beta1/types.py index 9da2784b..1e3b8220 100644 --- a/scaleway-async/scaleway_async/function/v1beta1/types.py +++ b/scaleway-async/scaleway_async/function/v1beta1/types.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -84,6 +84,25 @@ class FunctionRuntime(str, Enum, metaclass=StrEnumMeta): GO120 = "go120" NODE20 = "node20" GO121 = "go121" + NODE22 = "node22" + PYTHON312 = "python312" + PHP83 = "php83" + GO122 = "go122" + RUST179 = "rust179" + GO123 = "go123" + GO124 = "go124" + PYTHON313 = "python313" + RUST185 = "rust185" + PHP84 = "php84" + + def __str__(self) -> str: + return str(self.value) + + +class FunctionSandbox(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SANDBOX = "unknown_sandbox" + V1 = "v1" + V2 = "v2" def __str__(self) -> str: return str(self.value) @@ -505,7 +524,27 @@ class Function: Secret environment variables of the function. """ - region: Region + timeout: Optional[str] + """ + Request processing time limit for the function. + """ + + error_message: Optional[str] + """ + Error message if the function is in "error" state. + """ + + build_message: Optional[str] + """ + Description of the current build step. + """ + + description: Optional[str] + """ + Description of the function. + """ + + region: ScwRegion """ Region in which the function is deployed. """ @@ -519,24 +558,29 @@ class Function: runtime_message: str - timeout: Optional[str] + sandbox: FunctionSandbox """ - Request processing time limit for the function. + Execution environment of the function. """ - error_message: Optional[str] + tags: List[str] """ - Error message if the function is in "error" state. + List of tags applied to the Serverless Function. """ - build_message: Optional[str] + created_at: Optional[datetime] """ - Description of the current build step. + Creation date of the function. """ - description: Optional[str] + updated_at: Optional[datetime] """ - Description of the function. + Last update date of the function. + """ + + ready_at: Optional[datetime] + """ + Last date when the function was successfully deployed and set to ready. """ @@ -587,11 +631,16 @@ class Namespace: Secret environment variables of the namespace. """ - region: Region + region: ScwRegion """ Region in which the namespace is located. """ + tags: List[str] + """ + List of tags applied to the Serverless Function Namespace. + """ + error_message: Optional[str] """ Error message if the namespace is in "error" state. @@ -602,6 +651,16 @@ class Namespace: Description of the namespace. """ + created_at: Optional[datetime] + """ + Creation date of the namespace. + """ + + updated_at: Optional[datetime] + """ + Last update date of the namespace. + """ + @dataclass class Token: @@ -703,7 +762,7 @@ class CreateCronRequest: Schedule of the cron in UNIX cron format. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -731,7 +790,7 @@ class CreateDomainRequest: UUID of the function to associate the domain with. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -744,7 +803,7 @@ class CreateFunctionRequest: UUID of the namespace the function will be created in. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -761,7 +820,7 @@ class CreateFunctionRequest: min_scale: Optional[int] """ - Minumum number of instances to scale the function to. + Minimum number of instances to scale the function to. """ max_scale: Optional[int] @@ -808,10 +867,20 @@ class CreateFunctionRequest: - enabled: Serve both HTTP and HTTPS traffic. """ + sandbox: Optional[FunctionSandbox] + """ + Execution environment of the function. + """ + + tags: Optional[List[str]] + """ + Tags of the Serverless Function. + """ + @dataclass class CreateNamespaceRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -838,10 +907,15 @@ class CreateNamespaceRequest: Secret environment variables of the namespace. """ + tags: Optional[List[str]] + """ + Tags of the Serverless Function Namespace. + """ + @dataclass class CreateTokenRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -873,7 +947,7 @@ class CreateTriggerRequest: ID of the function to trigger. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -897,7 +971,7 @@ class DeleteCronRequest: UUID of the cron to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -910,7 +984,7 @@ class DeleteDomainRequest: UUID of the domain to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -923,7 +997,7 @@ class DeleteFunctionRequest: UUID of the function to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -936,7 +1010,7 @@ class DeleteNamespaceRequest: UUID of the namespace. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -949,7 +1023,7 @@ class DeleteTokenRequest: UUID of the token to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -962,7 +1036,7 @@ class DeleteTriggerRequest: ID of the trigger to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -975,7 +1049,7 @@ class DeployFunctionRequest: UUID of the function to deploy. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -995,7 +1069,7 @@ class GetCronRequest: UUID of the cron to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1008,7 +1082,7 @@ class GetDomainRequest: UUID of the domain to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1018,10 +1092,10 @@ class GetDomainRequest: class GetFunctionDownloadURLRequest: function_id: str """ - UUID of the function to get the the download URL for. + UUID of the function to get the download URL for. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1034,7 +1108,7 @@ class GetFunctionRequest: UUID of the function. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1052,7 +1126,7 @@ class GetFunctionUploadURLRequest: Size of the archive to upload in bytes. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1065,7 +1139,7 @@ class GetNamespaceRequest: UUID of the namespace. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1078,7 +1152,7 @@ class GetTokenRequest: UUID of the token to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1091,26 +1165,12 @@ class GetTriggerRequest: ID of the trigger to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ -@dataclass -class IssueJWTRequest: - region: Optional[Region] - """ - Region to target. If none is passed will use default region from the config. - """ - - expires_at: Optional[datetime] - - function_id: Optional[str] - - namespace_id: Optional[str] - - @dataclass class ListCronsRequest: function_id: str @@ -1118,7 +1178,7 @@ class ListCronsRequest: UUID of the function. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1156,10 +1216,10 @@ class ListCronsResponse: class ListDomainsRequest: function_id: str """ - UUID of the function the domain is assoicated with. + UUID of the function the domain is associated with. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1195,7 +1255,7 @@ class ListDomainsResponse: @dataclass class ListFunctionRuntimesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1221,7 +1281,7 @@ class ListFunctionsRequest: UUID of the namespace the function belongs to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1248,7 +1308,7 @@ class ListFunctionsRequest: organization_id: Optional[str] """ - UUID of the Organziation the function belongs to. + UUID of the Organization the function belongs to. """ project_id: Optional[str] @@ -1272,7 +1332,7 @@ class ListFunctionsResponse: @dataclass class ListNamespacesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1320,7 +1380,7 @@ class ListNamespacesResponse: @dataclass class ListTokensRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1342,7 +1402,7 @@ class ListTokensRequest: function_id: Optional[str] """ - UUID of the function the token is assoicated with. + UUID of the function the token is associated with. """ namespace_id: Optional[str] @@ -1360,7 +1420,7 @@ class ListTokensResponse: @dataclass class ListTriggersRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1407,7 +1467,7 @@ class UpdateCronRequest: UUID of the cron to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1440,7 +1500,7 @@ class UpdateFunctionRequest: UUID of the function to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1452,7 +1512,7 @@ class UpdateFunctionRequest: min_scale: Optional[int] """ - Minumum number of instances to scale the function to. + Minimum number of instances to scale the function to. """ max_scale: Optional[int] @@ -1507,6 +1567,16 @@ class UpdateFunctionRequest: - enabled: Serve both HTTP and HTTPS traffic. """ + sandbox: Optional[FunctionSandbox] + """ + Execution environment of the function. + """ + + tags: Optional[List[str]] + """ + Tags of the Serverless Function. + """ + @dataclass class UpdateNamespaceRequest: @@ -1515,7 +1585,7 @@ class UpdateNamespaceRequest: UUID of the namespapce. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1535,6 +1605,11 @@ class UpdateNamespaceRequest: Secret environment variables of the namespace. """ + tags: Optional[List[str]] + """ + Tags of the Serverless Function Namespace. + """ + @dataclass class UpdateTriggerRequest: @@ -1543,7 +1618,7 @@ class UpdateTriggerRequest: ID of the trigger to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py b/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py index cc30cf04..a2f0c4b1 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/__init__.py @@ -1,6 +1,7 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. from .types import BearerType +from .types import GracePeriodType from .types import ListAPIKeysRequestOrderBy from .types import ListApplicationsRequestOrderBy from .types import ListGroupsRequestOrderBy @@ -11,15 +12,22 @@ from .types import ListQuotaRequestOrderBy from .types import ListSSHKeysRequestOrderBy from .types import ListUsersRequestOrderBy +from .types import LocalityType from .types import LogAction from .types import LogResourceType from .types import PermissionSetScopeType from .types import UserStatus from .types import UserType -from .types import RuleSpecs +from .types import ConnectionConnectedOrganization +from .types import ConnectionConnectedUser +from .types import QuotumLimit from .types import JWT +from .types import RuleSpecs +from .types import CreateUserRequestMember +from .types import Connection from .types import APIKey from .types import Application +from .types import GracePeriod from .types import Group from .types import Log from .types import PermissionSet @@ -37,6 +45,7 @@ from .types import CreateJWTRequest from .types import CreatePolicyRequest from .types import CreateSSHKeyRequest +from .types import CreateUserMFAOTPRequest from .types import CreateUserRequest from .types import DeleteAPIKeyRequest from .types import DeleteApplicationRequest @@ -44,6 +53,7 @@ from .types import DeleteJWTRequest from .types import DeletePolicyRequest from .types import DeleteSSHKeyRequest +from .types import DeleteUserMFAOTPRequest from .types import DeleteUserRequest from .types import EncodedJWT from .types import GetAPIKeyRequest @@ -51,14 +61,19 @@ from .types import GetGroupRequest from .types import GetJWTRequest from .types import GetLogRequest +from .types import GetOrganizationSecuritySettingsRequest from .types import GetPolicyRequest from .types import GetQuotumRequest from .types import GetSSHKeyRequest +from .types import GetUserConnectionsRequest +from .types import GetUserConnectionsResponse from .types import GetUserRequest from .types import ListAPIKeysRequest from .types import ListAPIKeysResponse from .types import ListApplicationsRequest from .types import ListApplicationsResponse +from .types import ListGracePeriodsRequest +from .types import ListGracePeriodsResponse from .types import ListGroupsRequest from .types import ListGroupsResponse from .types import ListJWTsRequest @@ -77,20 +92,31 @@ from .types import ListSSHKeysResponse from .types import ListUsersRequest from .types import ListUsersResponse +from .types import LockUserRequest +from .types import MFAOTP +from .types import MigrateOrganizationGuestsRequest +from .types import OrganizationSecuritySettings from .types import RemoveGroupMemberRequest from .types import SetGroupMembersRequest from .types import SetRulesRequest from .types import SetRulesResponse +from .types import UnlockUserRequest from .types import UpdateAPIKeyRequest from .types import UpdateApplicationRequest from .types import UpdateGroupRequest +from .types import UpdateOrganizationSecuritySettingsRequest from .types import UpdatePolicyRequest from .types import UpdateSSHKeyRequest +from .types import UpdateUserPasswordRequest from .types import UpdateUserRequest +from .types import UpdateUserUsernameRequest +from .types import ValidateUserMFAOTPRequest +from .types import ValidateUserMFAOTPResponse from .api import IamV1Alpha1API __all__ = [ "BearerType", + "GracePeriodType", "ListAPIKeysRequestOrderBy", "ListApplicationsRequestOrderBy", "ListGroupsRequestOrderBy", @@ -101,15 +127,22 @@ "ListQuotaRequestOrderBy", "ListSSHKeysRequestOrderBy", "ListUsersRequestOrderBy", + "LocalityType", "LogAction", "LogResourceType", "PermissionSetScopeType", "UserStatus", "UserType", - "RuleSpecs", + "ConnectionConnectedOrganization", + "ConnectionConnectedUser", + "QuotumLimit", "JWT", + "RuleSpecs", + "CreateUserRequestMember", + "Connection", "APIKey", "Application", + "GracePeriod", "Group", "Log", "PermissionSet", @@ -127,6 +160,7 @@ "CreateJWTRequest", "CreatePolicyRequest", "CreateSSHKeyRequest", + "CreateUserMFAOTPRequest", "CreateUserRequest", "DeleteAPIKeyRequest", "DeleteApplicationRequest", @@ -134,6 +168,7 @@ "DeleteJWTRequest", "DeletePolicyRequest", "DeleteSSHKeyRequest", + "DeleteUserMFAOTPRequest", "DeleteUserRequest", "EncodedJWT", "GetAPIKeyRequest", @@ -141,14 +176,19 @@ "GetGroupRequest", "GetJWTRequest", "GetLogRequest", + "GetOrganizationSecuritySettingsRequest", "GetPolicyRequest", "GetQuotumRequest", "GetSSHKeyRequest", + "GetUserConnectionsRequest", + "GetUserConnectionsResponse", "GetUserRequest", "ListAPIKeysRequest", "ListAPIKeysResponse", "ListApplicationsRequest", "ListApplicationsResponse", + "ListGracePeriodsRequest", + "ListGracePeriodsResponse", "ListGroupsRequest", "ListGroupsResponse", "ListJWTsRequest", @@ -167,15 +207,25 @@ "ListSSHKeysResponse", "ListUsersRequest", "ListUsersResponse", + "LockUserRequest", + "MFAOTP", + "MigrateOrganizationGuestsRequest", + "OrganizationSecuritySettings", "RemoveGroupMemberRequest", "SetGroupMembersRequest", "SetRulesRequest", "SetRulesResponse", + "UnlockUserRequest", "UpdateAPIKeyRequest", "UpdateApplicationRequest", "UpdateGroupRequest", + "UpdateOrganizationSecuritySettingsRequest", "UpdatePolicyRequest", "UpdateSSHKeyRequest", + "UpdateUserPasswordRequest", "UpdateUserRequest", + "UpdateUserUsernameRequest", + "ValidateUserMFAOTPRequest", + "ValidateUserMFAOTPResponse", "IamV1Alpha1API", ] diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/api.py b/scaleway-async/scaleway_async/iam/v1alpha1/api.py index fd9af234..2c279086 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/api.py @@ -26,6 +26,7 @@ ListUsersRequestOrderBy, LogAction, LogResourceType, + UserType, APIKey, AddGroupMemberRequest, AddGroupMembersRequest, @@ -37,11 +38,14 @@ CreatePolicyRequest, CreateSSHKeyRequest, CreateUserRequest, + CreateUserRequestMember, EncodedJWT, + GetUserConnectionsResponse, Group, JWT, ListAPIKeysResponse, ListApplicationsResponse, + ListGracePeriodsResponse, ListGroupsResponse, ListJWTsResponse, ListLogsResponse, @@ -52,6 +56,8 @@ ListSSHKeysResponse, ListUsersResponse, Log, + MFAOTP, + OrganizationSecuritySettings, PermissionSet, Policy, Quotum, @@ -65,10 +71,15 @@ UpdateAPIKeyRequest, UpdateApplicationRequest, UpdateGroupRequest, + UpdateOrganizationSecuritySettingsRequest, UpdatePolicyRequest, UpdateSSHKeyRequest, + UpdateUserPasswordRequest, UpdateUserRequest, + UpdateUserUsernameRequest, User, + ValidateUserMFAOTPRequest, + ValidateUserMFAOTPResponse, ) from .marshalling import ( unmarshal_JWT, @@ -81,8 +92,10 @@ unmarshal_SSHKey, unmarshal_User, unmarshal_EncodedJWT, + unmarshal_GetUserConnectionsResponse, unmarshal_ListAPIKeysResponse, unmarshal_ListApplicationsResponse, + unmarshal_ListGracePeriodsResponse, unmarshal_ListGroupsResponse, unmarshal_ListJWTsResponse, unmarshal_ListLogsResponse, @@ -92,7 +105,10 @@ unmarshal_ListRulesResponse, unmarshal_ListSSHKeysResponse, unmarshal_ListUsersResponse, + unmarshal_MFAOTP, + unmarshal_OrganizationSecuritySettings, unmarshal_SetRulesResponse, + unmarshal_ValidateUserMFAOTPResponse, marshal_AddGroupMemberRequest, marshal_AddGroupMembersRequest, marshal_CreateAPIKeyRequest, @@ -108,15 +124,19 @@ marshal_UpdateAPIKeyRequest, marshal_UpdateApplicationRequest, marshal_UpdateGroupRequest, + marshal_UpdateOrganizationSecuritySettingsRequest, marshal_UpdatePolicyRequest, marshal_UpdateSSHKeyRequest, + marshal_UpdateUserPasswordRequest, marshal_UpdateUserRequest, + marshal_UpdateUserUsernameRequest, + marshal_ValidateUserMFAOTPRequest, ) class IamV1Alpha1API(API): """ - IAM API. + This API allows you to manage Identity and Access Management (IAM) across your Scaleway Organizations, Projects and resources. """ async def list_ssh_keys( @@ -356,6 +376,7 @@ async def list_users( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, + type_: Optional[UserType] = None, ) -> ListUsersResponse: """ List users of an Organization. @@ -367,6 +388,7 @@ async def list_users( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. + :param type_: Filter by user type. :return: :class:`ListUsersResponse ` Usage: @@ -386,6 +408,7 @@ async def list_users( "page": page, "page_size": page_size or self.client.default_page_size, "tag": tag, + "type": type_, "user_ids": user_ids, }, ) @@ -403,6 +426,7 @@ async def list_users_all( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, + type_: Optional[UserType] = None, ) -> List[User]: """ List users of an Organization. @@ -414,6 +438,7 @@ async def list_users_all( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. + :param type_: Filter by user type. :return: :class:`List[User] ` Usage: @@ -434,6 +459,7 @@ async def list_users_all( "user_ids": user_ids, "mfa": mfa, "tag": tag, + "type_": type_, }, ) @@ -471,12 +497,22 @@ async def update_user( *, user_id: str, tags: Optional[List[str]] = None, + email: Optional[str] = None, + first_name: Optional[str] = None, + last_name: Optional[str] = None, + phone_number: Optional[str] = None, + locale: Optional[str] = None, ) -> User: """ Update a user. Update the parameters of a user, including `tags`. :param user_id: ID of the user to update. :param tags: New tags for the user (maximum of 10 tags). + :param email: IAM member email. + :param first_name: IAM member first name. + :param last_name: IAM member last name. + :param phone_number: IAM member phone number. + :param locale: IAM member locale. :return: :class:`User ` Usage: @@ -496,6 +532,11 @@ async def update_user( UpdateUserRequest( user_id=user_id, tags=tags, + email=email, + first_name=first_name, + last_name=last_name, + phone_number=phone_number, + locale=locale, ), self.client, ), @@ -534,24 +575,26 @@ async def delete_user( async def create_user( self, *, - email: str, organization_id: Optional[str] = None, + email: Optional[str] = None, tags: Optional[List[str]] = None, + member: Optional[CreateUserRequestMember] = None, ) -> User: """ Create a new user. - Create a new user. You must define the `organization_id` and the `email` in your request. - :param email: Email of the user. + Create a new user. You must define the `organization_id` in your request. If you are adding a member, enter the member's details. If you are adding a guest, you must define the `email` and not add the member attribute. :param organization_id: ID of the Organization. + :param email: Email of the user. + One-Of ('type'): at most one of 'email', 'member' could be set. :param tags: Tags associated with the user. + :param member: Details of IAM member. + One-Of ('type'): at most one of 'email', 'member' could be set. :return: :class:`User ` Usage: :: - result = await api.create_user( - email="example", - ) + result = await api.create_user() """ res = self._request( @@ -559,9 +602,86 @@ async def create_user( "/iam/v1alpha1/users", body=marshal_CreateUserRequest( CreateUserRequest( - email=email, organization_id=organization_id, tags=tags, + email=email, + member=member, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + async def update_user_username( + self, + *, + user_id: str, + username: str, + ) -> User: + """ + Update an user's username. + :param user_id: ID of the user to update. + :param username: The new username. + :return: :class:`User ` + + Usage: + :: + + result = await api.update_user_username( + user_id="example", + username="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/update-username", + body=marshal_UpdateUserUsernameRequest( + UpdateUserUsernameRequest( + user_id=user_id, + username=username, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + async def update_user_password( + self, + *, + user_id: str, + password: str, + ) -> User: + """ + Update an user's password. + :param user_id: ID of the user to update. + :param password: The new password. + :return: :class:`User ` + + Usage: + :: + + result = await api.update_user_password( + user_id="example", + password="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/update-password", + body=marshal_UpdateUserPasswordRequest( + UpdateUserPasswordRequest( + user_id=user_id, + password=password, ), self.client, ), @@ -570,6 +690,214 @@ async def create_user( self._throw_on_error(res) return unmarshal_User(res.json()) + async def create_user_mfaotp( + self, + *, + user_id: str, + ) -> MFAOTP: + """ + Create a MFA OTP. + :param user_id: User ID of the MFA OTP. + :return: :class:`MFAOTP ` + + Usage: + :: + + result = await api.create_user_mfaotp( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/mfa-otp", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_MFAOTP(res.json()) + + async def validate_user_mfaotp( + self, + *, + user_id: str, + one_time_password: str, + ) -> ValidateUserMFAOTPResponse: + """ + Validate a MFA OTP. + :param user_id: User ID of the MFA OTP. + :param one_time_password: A password generated using the OTP. + :return: :class:`ValidateUserMFAOTPResponse ` + + Usage: + :: + + result = await api.validate_user_mfaotp( + user_id="example", + one_time_password="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/validate-mfa-otp", + body=marshal_ValidateUserMFAOTPRequest( + ValidateUserMFAOTPRequest( + user_id=user_id, + one_time_password=one_time_password, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ValidateUserMFAOTPResponse(res.json()) + + async def delete_user_mfaotp( + self, + *, + user_id: str, + ) -> None: + """ + Delete a MFA OTP. + :param user_id: User ID of the MFA OTP. + + Usage: + :: + + result = await api.delete_user_mfaotp( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "DELETE", + f"/iam/v1alpha1/users/{param_user_id}/mfa-otp", + body={}, + ) + + self._throw_on_error(res) + + async def lock_user( + self, + *, + user_id: str, + ) -> User: + """ + Lock a member. + Lock a member. A locked member cannot log in or use API keys until the locked status is removed. + :param user_id: ID of the user to lock. + :return: :class:`User ` + + Usage: + :: + + result = await api.lock_user( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/lock", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + async def unlock_user( + self, + *, + user_id: str, + ) -> User: + """ + Unlock a member. + :param user_id: ID of the user to unlock. + :return: :class:`User ` + + Usage: + :: + + result = await api.unlock_user( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/unlock", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + async def list_grace_periods( + self, + *, + user_id: Optional[str] = None, + ) -> ListGracePeriodsResponse: + """ + List grace periods of a member. + List the grace periods of a member. + :param user_id: ID of the user to list grace periods for. + :return: :class:`ListGracePeriodsResponse ` + + Usage: + :: + + result = await api.list_grace_periods() + """ + + res = self._request( + "GET", + "/iam/v1alpha1/grace-periods", + params={ + "user_id": user_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListGracePeriodsResponse(res.json()) + + async def get_user_connections( + self, + *, + user_id: str, + ) -> GetUserConnectionsResponse: + """ + :param user_id: ID of the user to list connections for. + :return: :class:`GetUserConnectionsResponse ` + + Usage: + :: + + result = await api.get_user_connections( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "GET", + f"/iam/v1alpha1/users/{param_user_id}/connections", + ) + + self._throw_on_error(res) + return unmarshal_GetUserConnectionsResponse(res.json()) + async def list_applications( self, *, @@ -961,7 +1289,7 @@ async def get_group( ) -> Group: """ Get a group. - Retrive information about a given group, specified by the `group_id` parameter. The group's full details, including `user_ids` and `application_ids` are returned in the response. + Retrieve information about a given group, specified by the `group_id` parameter. The group's full details, including `user_ids` and `application_ids` are returned in the response. :param group_id: ID of the group. :return: :class:`Group ` @@ -1079,7 +1407,7 @@ async def add_group_member( ) -> Group: """ Add a user or an application to a group. - Add a user or an application to a group. You can specify a `user_id` and and `application_id` in the body of your request. Note that you can only add one of each per request. + Add a user or an application to a group. You can specify a `user_id` and `application_id` in the body of your request. Note that you can only add one of each per request. :param group_id: ID of the group. :param user_id: ID of the user to add. One-Of ('member'): at most one of 'user_id', 'application_id' could be set. @@ -1163,7 +1491,7 @@ async def remove_group_member( ) -> Group: """ Remove a user or an application from a group. - Remove a user or an application from a group. You can specify a `user_id` and and `application_id` in the body of your request. Note that you can only remove one of each per request. Removing a user from a group means that any permissions given to them via the group (i.e. from an attached policy) will no longer apply. Be sure you want to remove these permissions from the user before proceeding. + Remove a user or an application from a group. You can specify a `user_id` and `application_id` in the body of your request. Note that you can only remove one of each per request. Removing a user from a group means that any permissions given to them via the group (i.e. from an attached policy) will no longer apply. Be sure you want to remove these permissions from the user before proceeding. :param group_id: ID of the group. :param user_id: ID of the user to remove. One-Of ('member'): at most one of 'user_id', 'application_id' could be set. @@ -1878,7 +2206,7 @@ async def create_api_key( ) -> APIKey: """ Create an API key. - Create an API key. You must specify the `application_id` or the `user_id` and the description. You can also specify the `default_project_id` which is the Project ID of your preferred Project, to use with Object Storage. The `access_key` and `secret_key` values are returned in the response. Note that he secret key is only showed once. Make sure that you copy and store both keys somewhere safe. + Create an API key. You must specify the `application_id` or the `user_id` and the description. You can also specify the `default_project_id`, which is the Project ID of your preferred Project, to use with Object Storage. The `access_key` and `secret_key` values are returned in the response. Note that the secret key is only shown once. Make sure that you copy and store both keys somewhere safe. :param description: Description of the API key (max length is 200 characters). :param application_id: ID of the application. One-Of ('bearer'): at most one of 'application_id', 'user_id' could be set. @@ -1921,7 +2249,7 @@ async def get_api_key( ) -> APIKey: """ Get an API key. - Retrive information about an API key, specified by the `access_key` parameter. The API key's details, including either the `user_id` or `application_id` of its bearer are returned in the response. Note that the string value for the `secret_key` is nullable, and therefore is not displayed in the response. The `secret_key` value is only displayed upon API key creation. + Retrieve information about an API key, specified by the `access_key` parameter. The API key's details, including either the `user_id` or `application_id` of its bearer are returned in the response. Note that the string value for the `secret_key` is nullable, and therefore is not displayed in the response. The `secret_key` value is only displayed upon API key creation. :param access_key: Access key to search for. :return: :class:`APIKey ` @@ -2018,6 +2346,7 @@ async def list_quota( page_size: Optional[int] = None, page: Optional[int] = None, organization_id: Optional[str] = None, + quotum_names: Optional[List[str]] = None, ) -> ListQuotaResponse: """ List all quotas in the Organization. @@ -2026,6 +2355,7 @@ async def list_quota( :param page_size: Number of results per page. Value must be between 1 and 100. :param page: Page number. Value must be greater than 1. :param organization_id: Filter by Organization ID. + :param quotum_names: List of quotum names to filter from. :return: :class:`ListQuotaResponse ` Usage: @@ -2043,6 +2373,7 @@ async def list_quota( or self.client.default_organization_id, "page": page, "page_size": page_size or self.client.default_page_size, + "quotum_names": quotum_names, }, ) @@ -2056,6 +2387,7 @@ async def list_quota_all( page_size: Optional[int] = None, page: Optional[int] = None, organization_id: Optional[str] = None, + quotum_names: Optional[List[str]] = None, ) -> List[Quotum]: """ List all quotas in the Organization. @@ -2064,6 +2396,7 @@ async def list_quota_all( :param page_size: Number of results per page. Value must be between 1 and 100. :param page: Page number. Value must be greater than 1. :param organization_id: Filter by Organization ID. + :param quotum_names: List of quotum names to filter from. :return: :class:`List[Quotum] ` Usage: @@ -2081,6 +2414,7 @@ async def list_quota_all( "page_size": page_size, "page": page, "organization_id": organization_id, + "quotum_names": quotum_names, }, ) @@ -2122,16 +2456,16 @@ async def get_quotum( async def list_jw_ts( self, *, + audience_id: str, order_by: Optional[ListJWTsRequestOrderBy] = None, - audience_id: Optional[str] = None, page_size: Optional[int] = None, page: Optional[int] = None, expired: Optional[bool] = None, ) -> ListJWTsResponse: """ List JWTs. - :param order_by: Criteria for sorting results. :param audience_id: ID of the user to search. + :param order_by: Criteria for sorting results. :param page_size: Number of results per page. Value must be between 1 and 100. :param page: Page number. Value must be greater to 1. :param expired: Filter out expired JWTs or not. @@ -2140,7 +2474,9 @@ async def list_jw_ts( Usage: :: - result = await api.list_jw_ts() + result = await api.list_jw_ts( + audience_id="example", + ) """ res = self._request( @@ -2161,16 +2497,16 @@ async def list_jw_ts( async def list_jw_ts_all( self, *, + audience_id: str, order_by: Optional[ListJWTsRequestOrderBy] = None, - audience_id: Optional[str] = None, page_size: Optional[int] = None, page: Optional[int] = None, expired: Optional[bool] = None, ) -> List[JWT]: """ List JWTs. - :param order_by: Criteria for sorting results. :param audience_id: ID of the user to search. + :param order_by: Criteria for sorting results. :param page_size: Number of results per page. Value must be between 1 and 100. :param page: Page number. Value must be greater to 1. :param expired: Filter out expired JWTs or not. @@ -2179,7 +2515,9 @@ async def list_jw_ts_all( Usage: :: - result = await api.list_jw_ts_all() + result = await api.list_jw_ts_all( + audience_id="example", + ) """ return await fetch_all_pages_async( @@ -2187,8 +2525,8 @@ async def list_jw_ts_all( key="jwts", fetcher=self.list_jw_ts, args={ - "order_by": order_by, "audience_id": audience_id, + "order_by": order_by, "page_size": page_size, "page": page, "expired": expired, @@ -2416,3 +2754,101 @@ async def get_log( self._throw_on_error(res) return unmarshal_Log(res.json()) + + async def get_organization_security_settings( + self, + *, + organization_id: Optional[str] = None, + ) -> OrganizationSecuritySettings: + """ + Get security settings of an Organization. + Retrieve information about the security settings of an Organization, specified by the `organization_id` parameter. + :param organization_id: ID of the Organization. + :return: :class:`OrganizationSecuritySettings ` + + Usage: + :: + + result = await api.get_organization_security_settings() + """ + + param_organization_id = validate_path_param( + "organization_id", organization_id or self.client.default_organization_id + ) + + res = self._request( + "GET", + f"/iam/v1alpha1/organizations/{param_organization_id}/security-settings", + ) + + self._throw_on_error(res) + return unmarshal_OrganizationSecuritySettings(res.json()) + + async def update_organization_security_settings( + self, + *, + organization_id: Optional[str] = None, + enforce_password_renewal: Optional[bool] = None, + grace_period_duration: Optional[str] = None, + login_attempts_before_locked: Optional[int] = None, + ) -> OrganizationSecuritySettings: + """ + Update the security settings of an Organization. + :param organization_id: ID of the Organization. + :param enforce_password_renewal: Defines whether password renewal is enforced during first login. + :param grace_period_duration: Duration of the grace period to renew password or enable MFA. + :param login_attempts_before_locked: Number of login attempts before the account is locked. + :return: :class:`OrganizationSecuritySettings ` + + Usage: + :: + + result = await api.update_organization_security_settings() + """ + + param_organization_id = validate_path_param( + "organization_id", organization_id or self.client.default_organization_id + ) + + res = self._request( + "PATCH", + f"/iam/v1alpha1/organizations/{param_organization_id}/security-settings", + body=marshal_UpdateOrganizationSecuritySettingsRequest( + UpdateOrganizationSecuritySettingsRequest( + organization_id=organization_id, + enforce_password_renewal=enforce_password_renewal, + grace_period_duration=grace_period_duration, + login_attempts_before_locked=login_attempts_before_locked, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_OrganizationSecuritySettings(res.json()) + + async def migrate_organization_guests( + self, + *, + organization_id: Optional[str] = None, + ) -> None: + """ + Migrate the organization's guests to IAM members. + :param organization_id: ID of the Organization. + + Usage: + :: + + result = await api.migrate_organization_guests() + """ + + param_organization_id = validate_path_param( + "organization_id", organization_id or self.client.default_organization_id + ) + + res = self._request( + "POST", + f"/iam/v1alpha1/organizations/{param_organization_id}/migrate-guests", + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py index 83f6650e..3bdb9e46 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/marshalling.py @@ -16,12 +16,19 @@ Group, Log, Policy, + QuotumLimit, Quotum, SSHKey, User, EncodedJWT, + ConnectionConnectedOrganization, + ConnectionConnectedUser, + Connection, + GetUserConnectionsResponse, ListAPIKeysResponse, ListApplicationsResponse, + GracePeriod, + ListGracePeriodsResponse, ListGroupsResponse, ListJWTsResponse, ListLogsResponse, @@ -33,7 +40,10 @@ ListRulesResponse, ListSSHKeysResponse, ListUsersResponse, + MFAOTP, + OrganizationSecuritySettings, SetRulesResponse, + ValidateUserMFAOTPResponse, AddGroupMemberRequest, AddGroupMembersRequest, CreateAPIKeyRequest, @@ -43,6 +53,7 @@ RuleSpecs, CreatePolicyRequest, CreateSSHKeyRequest, + CreateUserRequestMember, CreateUserRequest, RemoveGroupMemberRequest, SetGroupMembersRequest, @@ -50,9 +61,13 @@ UpdateAPIKeyRequest, UpdateApplicationRequest, UpdateGroupRequest, + UpdateOrganizationSecuritySettingsRequest, UpdatePolicyRequest, UpdateSSHKeyRequest, + UpdateUserPasswordRequest, UpdateUserRequest, + UpdateUserUsernameRequest, + ValidateUserMFAOTPRequest, ) @@ -87,14 +102,20 @@ def unmarshal_JWT(data: Any) -> JWT: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None return JWT(**args) @@ -119,37 +140,57 @@ def unmarshal_APIKey(data: Any) -> APIKey: if field is not None: args["default_project_id"] = field + field = data.get("secret_key", None) + if field is not None: + args["secret_key"] = field + else: + args["secret_key"] = None + + field = data.get("application_id", None) + if field is not None: + args["application_id"] = field + else: + args["application_id"] = None + field = data.get("editable", None) if field is not None: args["editable"] = field - field = data.get("creation_ip", None) + field = data.get("deletable", None) if field is not None: - args["creation_ip"] = field + args["deletable"] = field - field = data.get("secret_key", None) + field = data.get("managed", None) if field is not None: - args["secret_key"] = field + args["managed"] = field - field = data.get("application_id", None) + field = data.get("creation_ip", None) if field is not None: - args["application_id"] = field + args["creation_ip"] = field field = data.get("user_id", None) if field is not None: args["user_id"] = field + else: + args["user_id"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None return APIKey(**args) @@ -182,6 +223,14 @@ def unmarshal_Application(data: Any) -> Application: if field is not None: args["editable"] = field + field = data.get("deletable", None) + if field is not None: + args["deletable"] = field + + field = data.get("managed", None) + if field is not None: + args["managed"] = field + field = data.get("nb_api_keys", None) if field is not None: args["nb_api_keys"] = field @@ -193,10 +242,14 @@ def unmarshal_Application(data: Any) -> Application: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Application(**args) @@ -237,13 +290,29 @@ def unmarshal_Group(data: Any) -> Group: if field is not None: args["tags"] = field + field = data.get("editable", None) + if field is not None: + args["editable"] = field + + field = data.get("deletable", None) + if field is not None: + args["deletable"] = field + + field = data.get("managed", None) + if field is not None: + args["managed"] = field + field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Group(**args) @@ -291,6 +360,8 @@ def unmarshal_Log(data: Any) -> Log: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return Log(**args) @@ -319,17 +390,17 @@ def unmarshal_Policy(data: Any) -> Policy: if field is not None: args["organization_id"] = field - field = data.get("created_at", None) + field = data.get("editable", None) if field is not None: - args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + args["editable"] = field - field = data.get("updated_at", None) + field = data.get("deletable", None) if field is not None: - args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + args["deletable"] = field - field = data.get("editable", None) + field = data.get("managed", None) if field is not None: - args["editable"] = field + args["managed"] = field field = data.get("nb_rules", None) if field is not None: @@ -343,6 +414,18 @@ def unmarshal_Policy(data: Any) -> Policy: if field is not None: args["nb_permission_sets"] = field + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + field = data.get("tags", None) if field is not None: args["tags"] = field @@ -350,22 +433,71 @@ def unmarshal_Policy(data: Any) -> Policy: field = data.get("user_id", None) if field is not None: args["user_id"] = field + else: + args["user_id"] = None field = data.get("group_id", None) if field is not None: args["group_id"] = field + else: + args["group_id"] = None field = data.get("application_id", None) if field is not None: args["application_id"] = field + else: + args["application_id"] = None field = data.get("no_principal", None) if field is not None: args["no_principal"] = field + else: + args["no_principal"] = None return Policy(**args) +def unmarshal_QuotumLimit(data: Any) -> QuotumLimit: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QuotumLimit' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("global", None) + if field is not None: + args["global_"] = field + else: + args["global_"] = None + + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("limit", None) + if field is not None: + args["limit"] = field + else: + args["limit"] = None + + field = data.get("unlimited", None) + if field is not None: + args["unlimited"] = field + else: + args["unlimited"] = None + + return QuotumLimit(**args) + + def unmarshal_Quotum(data: Any) -> Quotum: if not isinstance(data, dict): raise TypeError( @@ -378,13 +510,39 @@ def unmarshal_Quotum(data: Any) -> Quotum: if field is not None: args["name"] = field + field = data.get("pretty_name", None) + if field is not None: + args["pretty_name"] = field + + field = data.get("unit", None) + if field is not None: + args["unit"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("locality_type", None) + if field is not None: + args["locality_type"] = field + + field = data.get("limits", None) + if field is not None: + args["limits"] = ( + [unmarshal_QuotumLimit(v) for v in field] if field is not None else None + ) + field = data.get("limit", None) if field is not None: args["limit"] = field + else: + args["limit"] = None field = data.get("unlimited", None) if field is not None: args["unlimited"] = field + else: + args["unlimited"] = None return Quotum(**args) @@ -428,10 +586,14 @@ def unmarshal_SSHKey(data: Any) -> SSHKey: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return SSHKey(**args) @@ -452,6 +614,26 @@ def unmarshal_User(data: Any) -> User: if field is not None: args["email"] = field + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("first_name", None) + if field is not None: + args["first_name"] = field + + field = data.get("last_name", None) + if field is not None: + args["last_name"] = field + + field = data.get("phone_number", None) + if field is not None: + args["phone_number"] = field + + field = data.get("locale", None) + if field is not None: + args["locale"] = field + field = data.get("organization_id", None) if field is not None: args["organization_id"] = field @@ -460,7 +642,27 @@ def unmarshal_User(data: Any) -> User: if field is not None: args["deletable"] = field - field = data.get("type_", None) + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("last_login_at", None) + if field is not None: + args["last_login_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["last_login_at"] = None + + field = data.get("type", None) if field is not None: args["type_"] = field @@ -468,10 +670,6 @@ def unmarshal_User(data: Any) -> User: if field is not None: args["status"] = field - field = data.get("created_at", None) - if field is not None: - args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field - field = data.get("mfa", None) if field is not None: args["mfa"] = field @@ -484,19 +682,15 @@ def unmarshal_User(data: Any) -> User: if field is not None: args["tags"] = field - field = data.get("updated_at", None) - if field is not None: - args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field - - field = data.get("last_login_at", None) + field = data.get("locked", None) if field is not None: - args["last_login_at"] = ( - parser.isoparse(field) if isinstance(field, str) else field - ) + args["locked"] = field field = data.get("two_factor_enabled", None) if field is not None: args["two_factor_enabled"] = field + else: + args["two_factor_enabled"] = None return User(**args) @@ -520,10 +714,100 @@ def unmarshal_EncodedJWT(data: Any) -> EncodedJWT: field = data.get("jwt", None) if field is not None: args["jwt"] = unmarshal_JWT(field) + else: + args["jwt"] = None return EncodedJWT(**args) +def unmarshal_ConnectionConnectedOrganization( + data: Any, +) -> ConnectionConnectedOrganization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ConnectionConnectedOrganization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("locked", None) + if field is not None: + args["locked"] = field + + return ConnectionConnectedOrganization(**args) + + +def unmarshal_ConnectionConnectedUser(data: Any) -> ConnectionConnectedUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ConnectionConnectedUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return ConnectionConnectedUser(**args) + + +def unmarshal_Connection(data: Any) -> Connection: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Connection' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("organization", None) + if field is not None: + args["organization"] = unmarshal_ConnectionConnectedOrganization(field) + else: + args["organization"] = None + + field = data.get("user", None) + if field is not None: + args["user"] = unmarshal_ConnectionConnectedUser(field) + else: + args["user"] = None + + return Connection(**args) + + +def unmarshal_GetUserConnectionsResponse(data: Any) -> GetUserConnectionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetUserConnectionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("connections", None) + if field is not None: + args["connections"] = ( + [unmarshal_Connection(v) for v in field] if field is not None else None + ) + + return GetUserConnectionsResponse(**args) + + def unmarshal_ListAPIKeysResponse(data: Any) -> ListAPIKeysResponse: if not isinstance(data, dict): raise TypeError( @@ -566,6 +850,50 @@ def unmarshal_ListApplicationsResponse(data: Any) -> ListApplicationsResponse: return ListApplicationsResponse(**args) +def unmarshal_GracePeriod(data: Any) -> GracePeriod: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GracePeriod' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + return GracePeriod(**args) + + +def unmarshal_ListGracePeriodsResponse(data: Any) -> ListGracePeriodsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGracePeriodsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("grace_periods", None) + if field is not None: + args["grace_periods"] = ( + [unmarshal_GracePeriod(v) for v in field] if field is not None else None + ) + + return ListGracePeriodsResponse(**args) + + def unmarshal_ListGroupsResponse(data: Any) -> ListGroupsResponse: if not isinstance(data, dict): raise TypeError( @@ -652,6 +980,8 @@ def unmarshal_PermissionSet(data: Any) -> PermissionSet: field = data.get("categories", None) if field is not None: args["categories"] = field + else: + args["categories"] = None return PermissionSet(**args) @@ -735,21 +1065,33 @@ def unmarshal_Rule(data: Any) -> Rule: if field is not None: args["permission_sets_scope_type"] = field + field = data.get("condition", None) + if field is not None: + args["condition"] = field + field = data.get("permission_set_names", None) if field is not None: args["permission_set_names"] = field + else: + args["permission_set_names"] = None field = data.get("project_ids", None) if field is not None: args["project_ids"] = field + else: + args["project_ids"] = None field = data.get("organization_id", None) if field is not None: args["organization_id"] = field + else: + args["organization_id"] = None field = data.get("account_root_user_id", None) if field is not None: args["account_root_user_id"] = field + else: + args["account_root_user_id"] = None return Rule(**args) @@ -817,6 +1159,46 @@ def unmarshal_ListUsersResponse(data: Any) -> ListUsersResponse: return ListUsersResponse(**args) +def unmarshal_MFAOTP(data: Any) -> MFAOTP: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'MFAOTP' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secret", None) + if field is not None: + args["secret"] = field + + return MFAOTP(**args) + + +def unmarshal_OrganizationSecuritySettings(data: Any) -> OrganizationSecuritySettings: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OrganizationSecuritySettings' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enforce_password_renewal", None) + if field is not None: + args["enforce_password_renewal"] = field + + field = data.get("login_attempts_before_locked", None) + if field is not None: + args["login_attempts_before_locked"] = field + + field = data.get("grace_period_duration", None) + if field is not None: + args["grace_period_duration"] = field + else: + args["grace_period_duration"] = None + + return OrganizationSecuritySettings(**args) + + def unmarshal_SetRulesResponse(data: Any) -> SetRulesResponse: if not isinstance(data, dict): raise TypeError( @@ -834,6 +1216,21 @@ def unmarshal_SetRulesResponse(data: Any) -> SetRulesResponse: return SetRulesResponse(**args) +def unmarshal_ValidateUserMFAOTPResponse(data: Any) -> ValidateUserMFAOTPResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ValidateUserMFAOTPResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("recovery_codes", None) + if field is not None: + args["recovery_codes"] = field + + return ValidateUserMFAOTPResponse(**args) + + def marshal_AddGroupMemberRequest( request: AddGroupMemberRequest, defaults: ProfileDefaults, @@ -884,7 +1281,7 @@ def marshal_CreateAPIKeyRequest( output["description"] = request.description if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() if request.default_project_id is not None: output["default_project_id"] = request.default_project_id @@ -971,6 +1368,9 @@ def marshal_RuleSpecs( ), ) + if request.condition is not None: + output["condition"] = request.condition + if request.permission_set_names is not None: output["permission_set_names"] = request.permission_set_names @@ -1031,8 +1431,8 @@ def marshal_CreateSSHKeyRequest( return output -def marshal_CreateUserRequest( - request: CreateUserRequest, +def marshal_CreateUserRequestMember( + request: CreateUserRequestMember, defaults: ProfileDefaults, ) -> Dict[str, Any]: output: Dict[str, Any] = {} @@ -1040,6 +1440,47 @@ def marshal_CreateUserRequest( if request.email is not None: output["email"] = request.email + if request.send_password_email is not None: + output["send_password_email"] = request.send_password_email + + if request.send_welcome_email is not None: + output["send_welcome_email"] = request.send_welcome_email + + if request.username is not None: + output["username"] = request.username + + if request.password is not None: + output["password"] = request.password + + if request.first_name is not None: + output["first_name"] = request.first_name + + if request.last_name is not None: + output["last_name"] = request.last_name + + if request.phone_number is not None: + output["phone_number"] = request.phone_number + + if request.locale is not None: + output["locale"] = request.locale + + return output + + +def marshal_CreateUserRequest( + request: CreateUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("email", request.email), + OneOfPossibility("member", request.member), + ] + ), + ) + if request.organization_id is not None: output["organization_id"] = ( request.organization_id or defaults.default_organization_id @@ -1149,6 +1590,24 @@ def marshal_UpdateGroupRequest( return output +def marshal_UpdateOrganizationSecuritySettingsRequest( + request: UpdateOrganizationSecuritySettingsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.enforce_password_renewal is not None: + output["enforce_password_renewal"] = request.enforce_password_renewal + + if request.grace_period_duration is not None: + output["grace_period_duration"] = request.grace_period_duration + + if request.login_attempts_before_locked is not None: + output["login_attempts_before_locked"] = request.login_attempts_before_locked + + return output + + def marshal_UpdatePolicyRequest( request: UpdatePolicyRequest, defaults: ProfileDefaults, @@ -1192,6 +1651,18 @@ def marshal_UpdateSSHKeyRequest( return output +def marshal_UpdateUserPasswordRequest( + request: UpdateUserPasswordRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + return output + + def marshal_UpdateUserRequest( request: UpdateUserRequest, defaults: ProfileDefaults, @@ -1201,4 +1672,43 @@ def marshal_UpdateUserRequest( if request.tags is not None: output["tags"] = request.tags + if request.email is not None: + output["email"] = request.email + + if request.first_name is not None: + output["first_name"] = request.first_name + + if request.last_name is not None: + output["last_name"] = request.last_name + + if request.phone_number is not None: + output["phone_number"] = request.phone_number + + if request.locale is not None: + output["locale"] = request.locale + + return output + + +def marshal_UpdateUserUsernameRequest( + request: UpdateUserUsernameRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + return output + + +def marshal_ValidateUserMFAOTPRequest( + request: ValidateUserMFAOTPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.one_time_password is not None: + output["one_time_password"] = request.one_time_password + return output diff --git a/scaleway-async/scaleway_async/iam/v1alpha1/types.py b/scaleway-async/scaleway_async/iam/v1alpha1/types.py index 000c6d97..a3cd107d 100644 --- a/scaleway-async/scaleway_async/iam/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/iam/v1alpha1/types.py @@ -7,6 +7,10 @@ from enum import Enum from typing import List, Optional +from scaleway_core.bridge import ( + Region as ScwRegion, + Zone as ScwZone, +) from scaleway_core.utils import ( StrEnumMeta, ) @@ -21,6 +25,15 @@ def __str__(self) -> str: return str(self.value) +class GracePeriodType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_GRACE_PERIOD_TYPE = "unknown_grace_period_type" + UPDATE_PASSWORD = "update_password" + SET_MFA = "set_mfa" + + def __str__(self) -> str: + return str(self.value) + + class ListAPIKeysRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -126,6 +139,17 @@ class ListUsersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): EMAIL_DESC = "email_desc" LAST_LOGIN_ASC = "last_login_asc" LAST_LOGIN_DESC = "last_login_desc" + USERNAME_ASC = "username_asc" + USERNAME_DESC = "username_desc" + + def __str__(self) -> str: + return str(self.value) + + +class LocalityType(str, Enum, metaclass=StrEnumMeta): + GLOBAL = "global" + REGION = "region" + ZONE = "zone" def __str__(self) -> str: return str(self.value) @@ -176,21 +200,41 @@ class UserType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_TYPE = "unknown_type" GUEST = "guest" OWNER = "owner" + MEMBER = "member" def __str__(self) -> str: return str(self.value) @dataclass -class RuleSpecs: - permission_set_names: Optional[List[str]] - """ - Names of permission sets bound to the rule. - """ +class ConnectionConnectedOrganization: + id: str - project_ids: Optional[List[str]] + name: str - organization_id: Optional[str] + locked: bool + + +@dataclass +class ConnectionConnectedUser: + id: str + + username: str + + type_: UserType + + +@dataclass +class QuotumLimit: + global_: Optional[bool] + + region: Optional[ScwRegion] + + zone: Optional[ScwZone] + + limit: Optional[int] + + unlimited: Optional[bool] @dataclass @@ -236,6 +280,84 @@ class JWT: """ +@dataclass +class RuleSpecs: + condition: str + """ + Condition expression to evaluate. + """ + + permission_set_names: Optional[List[str]] + """ + Names of permission sets bound to the rule. + """ + + project_ids: Optional[List[str]] + + organization_id: Optional[str] + + +@dataclass +class CreateUserRequestMember: + email: str + """ + Email of the user to create. + """ + + send_password_email: bool + """ + Whether or not to send an email containing the member's password. + """ + + send_welcome_email: bool + """ + Whether or not to send a welcome email that includes onboarding information. + """ + + username: str + """ + The member's username. + """ + + password: str + """ + The member's password. + """ + + first_name: str + """ + The member's first name. + """ + + last_name: str + """ + The member's last name. + """ + + phone_number: str + """ + The member's phone number. + """ + + locale: str + """ + The member's locale. + """ + + +@dataclass +class Connection: + organization: Optional[ConnectionConnectedOrganization] + """ + Information about the connected organization. + """ + + user: Optional[ConnectionConnectedUser] + """ + Information about the connected user. + """ + + @dataclass class APIKey: access_key: str @@ -258,6 +380,16 @@ class APIKey: Defines whether or not the API key is editable. """ + deletable: bool + """ + Defines whether or not the API key is deletable. + """ + + managed: bool + """ + Defines whether or not the API key is managed. + """ + creation_ip: str """ IP address of the device that created the API key. @@ -315,6 +447,16 @@ class Application: Defines whether or not the application is editable. """ + deletable: bool + """ + Defines whether or not the application is deletable. + """ + + managed: bool + """ + Defines whether or not the application is managed. + """ + nb_api_keys: int """ Number of API keys attributed to the application. @@ -336,6 +478,24 @@ class Application: """ +@dataclass +class GracePeriod: + type_: GracePeriodType + """ + Type of grace period. + """ + + created_at: Optional[datetime] + """ + Date and time the grace period was created. + """ + + expires_at: Optional[datetime] + """ + Date and time the grace period expires. + """ + + @dataclass class Group: id: str @@ -373,6 +533,21 @@ class Group: Tags associated to the group. """ + editable: bool + """ + Defines whether or not the group is editable. + """ + + deletable: bool + """ + Defines whether or not the group is deletable. + """ + + managed: bool + """ + Defines whether or not the group is managed. + """ + created_at: Optional[datetime] """ Date and time of group creation. @@ -482,11 +657,31 @@ class Policy: Organization ID of the policy. """ + created_at: Optional[datetime] + """ + Date and time of policy creation. + """ + + updated_at: Optional[datetime] + """ + Date and time of last policy update. + """ + editable: bool """ Defines whether or not a policy is editable. """ + deletable: bool + """ + Defines whether or not a policy is deletable. + """ + + managed: bool + """ + Defines whether or not a policy is managed. + """ + nb_rules: int """ Number of rules of the policy. @@ -507,16 +702,6 @@ class Policy: Tags associated with the policy. """ - created_at: Optional[datetime] - """ - Date and time of policy creation. - """ - - updated_at: Optional[datetime] - """ - Date and time of last policy update. - """ - user_id: Optional[str] group_id: Optional[str] @@ -533,6 +718,31 @@ class Quotum: Name of the quota. """ + pretty_name: str + """ + A human-readable name for the quota. + """ + + unit: str + """ + The unit in which the quota is expressed. + """ + + description: str + """ + Details about the quota. + """ + + locality_type: LocalityType + """ + Whether this quotum is applied on at the zone level, region level, or globally. + """ + + limits: List[QuotumLimit] + """ + Limits per locality. + """ + limit: Optional[int] unlimited: Optional[bool] @@ -550,6 +760,11 @@ class Rule: Permission_set_names have the same scope_type. """ + condition: str + """ + Condition expression to evaluate. + """ + permission_set_names: Optional[List[str]] """ Names of permission sets bound to the rule. @@ -622,6 +837,31 @@ class User: Email of user. """ + username: str + """ + User identifier unique to the Organization. + """ + + first_name: str + """ + First name of the user. + """ + + last_name: str + """ + Last name of the user. + """ + + phone_number: str + """ + Phone number of the user. + """ + + locale: str + """ + Locale of the user. + """ + organization_id: str """ ID of the Organization. @@ -632,6 +872,21 @@ class User: Deletion status of user. Owners cannot be deleted. """ + created_at: Optional[datetime] + """ + Date user was created. + """ + + updated_at: Optional[datetime] + """ + Date of last user update. + """ + + last_login_at: Optional[datetime] + """ + Date of the last login. + """ + type_: UserType """ Type of user. @@ -642,11 +897,6 @@ class User: Status of user invitation. """ - created_at: Optional[datetime] - """ - Date user was created. - """ - mfa: bool """ Defines whether MFA is enabled. @@ -662,14 +912,9 @@ class User: Tags associated with the user. """ - updated_at: Optional[datetime] - """ - Date of last user update. - """ - - last_login_at: Optional[datetime] + locked: bool """ - Date of the last login. + Defines whether the user is locked. """ two_factor_enabled: Optional[bool] @@ -849,12 +1094,15 @@ class CreateSSHKeyRequest: @dataclass -class CreateUserRequest: - email: str +class CreateUserMFAOTPRequest: + user_id: str """ - Email of the user. + User ID of the MFA OTP. """ + +@dataclass +class CreateUserRequest: organization_id: Optional[str] """ ID of the Organization. @@ -865,6 +1113,10 @@ class CreateUserRequest: Tags associated with the user. """ + email: Optional[str] + + member: Optional[CreateUserRequestMember] + @dataclass class DeleteAPIKeyRequest: @@ -911,6 +1163,14 @@ class DeleteSSHKeyRequest: ssh_key_id: str +@dataclass +class DeleteUserMFAOTPRequest: + user_id: str + """ + User ID of the MFA OTP. + """ + + @dataclass class DeleteUserRequest: user_id: str @@ -977,6 +1237,14 @@ class GetLogRequest: """ +@dataclass +class GetOrganizationSecuritySettingsRequest: + organization_id: Optional[str] + """ + ID of the Organization. + """ + + @dataclass class GetPolicyRequest: policy_id: str @@ -1006,6 +1274,22 @@ class GetSSHKeyRequest: """ +@dataclass +class GetUserConnectionsRequest: + user_id: str + """ + ID of the user to list connections for. + """ + + +@dataclass +class GetUserConnectionsResponse: + connections: List[Connection] + """ + List of connections. + """ + + @dataclass class GetUserRequest: user_id: str @@ -1145,6 +1429,22 @@ class ListApplicationsResponse: """ +@dataclass +class ListGracePeriodsRequest: + user_id: Optional[str] + """ + ID of the user to list grace periods for. + """ + + +@dataclass +class ListGracePeriodsResponse: + grace_periods: List[GracePeriod] + """ + List of grace periods. + """ + + @dataclass class ListGroupsRequest: order_by: Optional[ListGroupsRequestOrderBy] @@ -1208,14 +1508,14 @@ class ListGroupsResponse: @dataclass class ListJWTsRequest: - order_by: Optional[ListJWTsRequestOrderBy] + audience_id: str """ - Criteria for sorting results. + ID of the user to search. """ - audience_id: Optional[str] + order_by: Optional[ListJWTsRequestOrderBy] """ - ID of the user to search. + Criteria for sorting results. """ page_size: Optional[int] @@ -1436,6 +1736,11 @@ class ListQuotaRequest: Filter by Organization ID. """ + quotum_names: Optional[List[str]] + """ + List of quotum names to filter from. + """ + @dataclass class ListQuotaResponse: @@ -1569,6 +1874,11 @@ class ListUsersRequest: Filter by tags containing a given string. """ + type_: Optional[UserType] + """ + Filter by user type. + """ + @dataclass class ListUsersResponse: @@ -1583,6 +1893,45 @@ class ListUsersResponse: """ +@dataclass +class LockUserRequest: + user_id: str + """ + ID of the user to lock. + """ + + +@dataclass +class MFAOTP: + secret: str + + +@dataclass +class MigrateOrganizationGuestsRequest: + organization_id: Optional[str] + """ + ID of the Organization. + """ + + +@dataclass +class OrganizationSecuritySettings: + enforce_password_renewal: bool + """ + Defines whether password renewal is enforced during first login. + """ + + login_attempts_before_locked: int + """ + Number of login attempts before the account is locked. + """ + + grace_period_duration: Optional[str] + """ + Duration of the grace period to renew password or enable MFA. + """ + + @dataclass class RemoveGroupMemberRequest: group_id: str @@ -1625,6 +1974,14 @@ class SetRulesResponse: """ +@dataclass +class UnlockUserRequest: + user_id: str + """ + ID of the user to unlock. + """ + + @dataclass class UpdateAPIKeyRequest: access_key: str @@ -1689,6 +2046,29 @@ class UpdateGroupRequest: """ +@dataclass +class UpdateOrganizationSecuritySettingsRequest: + organization_id: Optional[str] + """ + ID of the Organization. + """ + + enforce_password_renewal: Optional[bool] + """ + Defines whether password renewal is enforced during first login. + """ + + grace_period_duration: Optional[str] + """ + Duration of the grace period to renew password or enable MFA. + """ + + login_attempts_before_locked: Optional[int] + """ + Number of login attempts before the account is locked. + """ + + @dataclass class UpdatePolicyRequest: policy_id: str @@ -1735,6 +2115,19 @@ class UpdateSSHKeyRequest: """ +@dataclass +class UpdateUserPasswordRequest: + user_id: str + """ + ID of the user to update. + """ + + password: str + """ + The new password. + """ + + @dataclass class UpdateUserRequest: user_id: str @@ -1746,3 +2139,62 @@ class UpdateUserRequest: """ New tags for the user (maximum of 10 tags). """ + + email: Optional[str] + """ + IAM member email. + """ + + first_name: Optional[str] + """ + IAM member first name. + """ + + last_name: Optional[str] + """ + IAM member last name. + """ + + phone_number: Optional[str] + """ + IAM member phone number. + """ + + locale: Optional[str] + """ + IAM member locale. + """ + + +@dataclass +class UpdateUserUsernameRequest: + user_id: str + """ + ID of the user to update. + """ + + username: str + """ + The new username. + """ + + +@dataclass +class ValidateUserMFAOTPRequest: + user_id: str + """ + User ID of the MFA OTP. + """ + + one_time_password: str + """ + A password generated using the OTP. + """ + + +@dataclass +class ValidateUserMFAOTPResponse: + recovery_codes: List[str] + """ + List of recovery codes usable for this OTP method. + """ diff --git a/scaleway-async/scaleway_async/inference/__init__.py b/scaleway-async/scaleway_async/inference/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway-async/scaleway_async/inference/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway-async/scaleway_async/inference/v1/__init__.py b/scaleway-async/scaleway_async/inference/v1/__init__.py new file mode 100644 index 00000000..526e0c63 --- /dev/null +++ b/scaleway-async/scaleway_async/inference/v1/__init__.py @@ -0,0 +1,79 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DeploymentStatus +from .content import DEPLOYMENT_TRANSIENT_STATUSES +from .types import ListDeploymentsRequestOrderBy +from .types import ListModelsRequestOrderBy +from .types import ModelStatus +from .content import MODEL_TRANSIENT_STATUSES +from .types import NodeTypeStock +from .types import ModelSupportedQuantization +from .types import EndpointPrivateNetworkDetails +from .types import EndpointPublicNetworkDetails +from .types import ModelSupportedNode +from .types import DeploymentQuantization +from .types import Endpoint +from .types import ModelSupportInfo +from .types import EndpointSpec +from .types import ModelSource +from .types import Deployment +from .types import Model +from .types import NodeType +from .types import CreateDeploymentRequest +from .types import CreateEndpointRequest +from .types import CreateModelRequest +from .types import DeleteDeploymentRequest +from .types import DeleteEndpointRequest +from .types import DeleteModelRequest +from .types import GetDeploymentCertificateRequest +from .types import GetDeploymentRequest +from .types import GetModelRequest +from .types import ListDeploymentsRequest +from .types import ListDeploymentsResponse +from .types import ListModelsRequest +from .types import ListModelsResponse +from .types import ListNodeTypesRequest +from .types import ListNodeTypesResponse +from .types import UpdateDeploymentRequest +from .types import UpdateEndpointRequest +from .api import InferenceV1API + +__all__ = [ + "DeploymentStatus", + "DEPLOYMENT_TRANSIENT_STATUSES", + "ListDeploymentsRequestOrderBy", + "ListModelsRequestOrderBy", + "ModelStatus", + "MODEL_TRANSIENT_STATUSES", + "NodeTypeStock", + "ModelSupportedQuantization", + "EndpointPrivateNetworkDetails", + "EndpointPublicNetworkDetails", + "ModelSupportedNode", + "DeploymentQuantization", + "Endpoint", + "ModelSupportInfo", + "EndpointSpec", + "ModelSource", + "Deployment", + "Model", + "NodeType", + "CreateDeploymentRequest", + "CreateEndpointRequest", + "CreateModelRequest", + "DeleteDeploymentRequest", + "DeleteEndpointRequest", + "DeleteModelRequest", + "GetDeploymentCertificateRequest", + "GetDeploymentRequest", + "GetModelRequest", + "ListDeploymentsRequest", + "ListDeploymentsResponse", + "ListModelsRequest", + "ListModelsResponse", + "ListNodeTypesRequest", + "ListNodeTypesResponse", + "UpdateDeploymentRequest", + "UpdateEndpointRequest", + "InferenceV1API", +] diff --git a/scaleway-async/scaleway_async/inference/v1/api.py b/scaleway-async/scaleway_async/inference/v1/api.py new file mode 100644 index 00000000..e6d86e58 --- /dev/null +++ b/scaleway-async/scaleway_async/inference/v1/api.py @@ -0,0 +1,873 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, + ScwFile, + unmarshal_ScwFile, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + ListDeploymentsRequestOrderBy, + ListModelsRequestOrderBy, + CreateDeploymentRequest, + CreateEndpointRequest, + CreateModelRequest, + Deployment, + DeploymentQuantization, + Endpoint, + EndpointSpec, + ListDeploymentsResponse, + ListModelsResponse, + ListNodeTypesResponse, + Model, + ModelSource, + NodeType, + UpdateDeploymentRequest, + UpdateEndpointRequest, +) +from .content import ( + DEPLOYMENT_TRANSIENT_STATUSES, + MODEL_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_Endpoint, + unmarshal_Deployment, + unmarshal_Model, + unmarshal_ListDeploymentsResponse, + unmarshal_ListModelsResponse, + unmarshal_ListNodeTypesResponse, + marshal_CreateDeploymentRequest, + marshal_CreateEndpointRequest, + marshal_CreateModelRequest, + marshal_UpdateDeploymentRequest, + marshal_UpdateEndpointRequest, +) + + +class InferenceV1API(API): + """ + This API allows you to handle your Managed Inference services. + """ + + async def list_deployments( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDeploymentsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListDeploymentsResponse: + """ + List inference deployments. + List all your inference deployments. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of deployments to return per page. + :param order_by: Order in which to return results. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param name: Filter by deployment name. + :param tags: Filter by tags. + :return: :class:`ListDeploymentsResponse ` + + Usage: + :: + + result = await api.list_deployments() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDeploymentsResponse(res.json()) + + async def list_deployments_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDeploymentsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Deployment]: + """ + List inference deployments. + List all your inference deployments. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of deployments to return per page. + :param order_by: Order in which to return results. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param name: Filter by deployment name. + :param tags: Filter by tags. + :return: :class:`List[Deployment] ` + + Usage: + :: + + result = await api.list_deployments_all() + """ + + return await fetch_all_pages_async( + type=ListDeploymentsResponse, + key="deployments", + fetcher=self.list_deployments, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "name": name, + "tags": tags, + }, + ) + + async def get_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> Deployment: + """ + Get a deployment. + Get the deployment for the given ID. + :param deployment_id: ID of the deployment to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = await api.get_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + async def wait_for_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + options: Optional[ + WaitForOptions[Deployment, Union[bool, Awaitable[bool]]] + ] = None, + ) -> Deployment: + """ + Get a deployment. + Get the deployment for the given ID. + :param deployment_id: ID of the deployment to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = await api.get_deployment( + deployment_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in DEPLOYMENT_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_deployment, + options=options, + args={ + "deployment_id": deployment_id, + "region": region, + }, + ) + + async def create_deployment( + self, + *, + model_id: str, + node_type_name: str, + endpoints: List[EndpointSpec], + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + accept_eula: Optional[bool] = None, + tags: Optional[List[str]] = None, + min_size: Optional[int] = None, + max_size: Optional[int] = None, + quantization: Optional[DeploymentQuantization] = None, + ) -> Deployment: + """ + Create a deployment. + Create a new inference deployment related to a specific model. + :param model_id: ID of the model to use. + :param node_type_name: Name of the node type to use. + :param endpoints: List of endpoints to create. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the deployment. + :param project_id: ID of the Project to create the deployment in. + :param accept_eula: If the model has an EULA, you must accept it before proceeding. + The terms of the EULA can be retrieved using the `GetModelEula` API call. + :param tags: List of tags to apply to the deployment. + :param min_size: Defines the minimum size of the pool. + :param max_size: Defines the maximum size of the pool. + :param quantization: Quantization settings to apply to this deployment. + :return: :class:`Deployment ` + + Usage: + :: + + result = await api.create_deployment( + model_id="example", + node_type_name="example", + endpoints=[], + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/deployments", + body=marshal_CreateDeploymentRequest( + CreateDeploymentRequest( + model_id=model_id, + node_type_name=node_type_name, + endpoints=endpoints, + region=region, + name=name or random_name(prefix="inference"), + project_id=project_id, + accept_eula=accept_eula, + tags=tags, + min_size=min_size, + max_size=max_size, + quantization=quantization, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + async def update_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + min_size: Optional[int] = None, + max_size: Optional[int] = None, + model_id: Optional[str] = None, + quantization: Optional[DeploymentQuantization] = None, + ) -> Deployment: + """ + Update a deployment. + Update an existing inference deployment. + :param deployment_id: ID of the deployment to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the deployment. + :param tags: List of tags to apply to the deployment. + :param min_size: Defines the new minimum size of the pool. + :param max_size: Defines the new maximum size of the pool. + :param model_id: Id of the model to set to the deployment. + :param quantization: Quantization to use to the deployment. + :return: :class:`Deployment ` + + Usage: + :: + + result = await api.update_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "PATCH", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + body=marshal_UpdateDeploymentRequest( + UpdateDeploymentRequest( + deployment_id=deployment_id, + region=region, + name=name, + tags=tags, + min_size=min_size, + max_size=max_size, + model_id=model_id, + quantization=quantization, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + async def delete_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> Deployment: + """ + Delete a deployment. + Delete an existing inference deployment. + :param deployment_id: ID of the deployment to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = await api.delete_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + async def get_deployment_certificate( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> ScwFile: + """ + Get the CA certificate. + Get the CA certificate used for the deployment of private endpoints. + The CA certificate will be returned as a PEM file. + :param deployment_id: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ScwFile ` + + Usage: + :: + + result = await api.get_deployment_certificate( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}/certificate", + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + async def create_endpoint( + self, + *, + deployment_id: str, + endpoint: EndpointSpec, + region: Optional[ScwRegion] = None, + ) -> Endpoint: + """ + Create an endpoint. + Create a new Endpoint related to a specific deployment. + :param deployment_id: ID of the deployment to create the endpoint for. + :param endpoint: Specification of the endpoint. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Endpoint ` + + Usage: + :: + + result = await api.create_endpoint( + deployment_id="example", + endpoint=EndpointSpec(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/endpoints", + body=marshal_CreateEndpointRequest( + CreateEndpointRequest( + deployment_id=deployment_id, + endpoint=endpoint, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Endpoint(res.json()) + + async def update_endpoint( + self, + *, + endpoint_id: str, + region: Optional[ScwRegion] = None, + disable_auth: Optional[bool] = None, + ) -> Endpoint: + """ + Update an endpoint. + Update an existing Endpoint. + :param endpoint_id: ID of the endpoint to update. + :param region: Region to target. If none is passed will use default region from the config. + :param disable_auth: By default, deployments are protected by IAM authentication. + When setting this field to true, the authentication will be disabled. + :return: :class:`Endpoint ` + + Usage: + :: + + result = await api.update_endpoint( + endpoint_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_endpoint_id = validate_path_param("endpoint_id", endpoint_id) + + res = self._request( + "PATCH", + f"/inference/v1/regions/{param_region}/endpoints/{param_endpoint_id}", + body=marshal_UpdateEndpointRequest( + UpdateEndpointRequest( + endpoint_id=endpoint_id, + region=region, + disable_auth=disable_auth, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Endpoint(res.json()) + + async def delete_endpoint( + self, + *, + endpoint_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete an endpoint. + Delete an existing Endpoint. + :param endpoint_id: ID of the endpoint to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_endpoint( + endpoint_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_endpoint_id = validate_path_param("endpoint_id", endpoint_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/endpoints/{param_endpoint_id}", + ) + + self._throw_on_error(res) + + async def list_models( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListModelsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListModelsResponse: + """ + List models. + List all available models. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of models to return per page. + :param project_id: Filter by Project ID. + :param name: Filter by model name. + :param tags: Filter by tags. + :return: :class:`ListModelsResponse ` + + Usage: + :: + + result = await api.list_models() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/models", + params={ + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListModelsResponse(res.json()) + + async def list_models_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListModelsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Model]: + """ + List models. + List all available models. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of models to return per page. + :param project_id: Filter by Project ID. + :param name: Filter by model name. + :param tags: Filter by tags. + :return: :class:`List[Model] ` + + Usage: + :: + + result = await api.list_models_all() + """ + + return await fetch_all_pages_async( + type=ListModelsResponse, + key="models", + fetcher=self.list_models, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "name": name, + "tags": tags, + }, + ) + + async def get_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + ) -> Model: + """ + Get a model. + Get the model for the given ID. + :param model_id: ID of the model to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Model ` + + Usage: + :: + + result = await api.get_model( + model_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_model_id = validate_path_param("model_id", model_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/models/{param_model_id}", + ) + + self._throw_on_error(res) + return unmarshal_Model(res.json()) + + async def wait_for_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Model, Union[bool, Awaitable[bool]]]] = None, + ) -> Model: + """ + Get a model. + Get the model for the given ID. + :param model_id: ID of the model to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Model ` + + Usage: + :: + + result = await api.get_model( + model_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in MODEL_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_model, + options=options, + args={ + "model_id": model_id, + "region": region, + }, + ) + + async def create_model( + self, + *, + source: ModelSource, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + ) -> Model: + """ + Import a model. + Import a new model to your model library. + :param source: Where to import the model from. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the model. + :param project_id: ID of the Project to import the model in. + :return: :class:`Model ` + + Usage: + :: + + result = await api.create_model( + source=ModelSource(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/models", + body=marshal_CreateModelRequest( + CreateModelRequest( + source=source, + region=region, + name=name or random_name(prefix="model"), + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Model(res.json()) + + async def delete_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a model. + Delete an existing model from your model library. + :param model_id: ID of the model to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_model( + model_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_model_id = validate_path_param("model_id", model_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/models/{param_model_id}", + ) + + self._throw_on_error(res) + + async def list_node_types( + self, + *, + include_disabled_types: bool, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListNodeTypesResponse: + """ + List available node types. + List all available node types. By default, the node types returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param include_disabled_types: Include disabled node types in the response. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of node types to return per page. + :return: :class:`ListNodeTypesResponse ` + + Usage: + :: + + result = await api.list_node_types( + include_disabled_types=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/node-types", + params={ + "include_disabled_types": include_disabled_types, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListNodeTypesResponse(res.json()) + + async def list_node_types_all( + self, + *, + include_disabled_types: bool, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[NodeType]: + """ + List available node types. + List all available node types. By default, the node types returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param include_disabled_types: Include disabled node types in the response. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of node types to return per page. + :return: :class:`List[NodeType] ` + + Usage: + :: + + result = await api.list_node_types_all( + include_disabled_types=False, + ) + """ + + return await fetch_all_pages_async( + type=ListNodeTypesResponse, + key="node_types", + fetcher=self.list_node_types, + args={ + "include_disabled_types": include_disabled_types, + "region": region, + "page": page, + "page_size": page_size, + }, + ) diff --git a/scaleway-async/scaleway_async/inference/v1/content.py b/scaleway-async/scaleway_async/inference/v1/content.py new file mode 100644 index 00000000..887e0b7e --- /dev/null +++ b/scaleway-async/scaleway_async/inference/v1/content.py @@ -0,0 +1,24 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + DeploymentStatus, + ModelStatus, +) + +DEPLOYMENT_TRANSIENT_STATUSES: List[DeploymentStatus] = [ + DeploymentStatus.CREATING, + DeploymentStatus.DEPLOYING, + DeploymentStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`DeploymentStatus `. +""" +MODEL_TRANSIENT_STATUSES: List[ModelStatus] = [ + ModelStatus.PREPARING, + ModelStatus.DOWNLOADING, +] +""" +Lists transient statutes of the enum :class:`ModelStatus `. +""" diff --git a/scaleway-async/scaleway_async/inference/v1/marshalling.py b/scaleway-async/scaleway_async/inference/v1/marshalling.py new file mode 100644 index 00000000..59057723 --- /dev/null +++ b/scaleway-async/scaleway_async/inference/v1/marshalling.py @@ -0,0 +1,655 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + EndpointPrivateNetworkDetails, + EndpointPublicNetworkDetails, + Endpoint, + ModelSupportedQuantization, + ModelSupportedNode, + ModelSupportInfo, + DeploymentQuantization, + Deployment, + Model, + ListDeploymentsResponse, + ListModelsResponse, + NodeType, + ListNodeTypesResponse, + EndpointSpec, + CreateDeploymentRequest, + CreateEndpointRequest, + ModelSource, + CreateModelRequest, + UpdateDeploymentRequest, + UpdateEndpointRequest, +) + + +def unmarshal_EndpointPrivateNetworkDetails(data: Any) -> EndpointPrivateNetworkDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPrivateNetworkDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + return EndpointPrivateNetworkDetails(**args) + + +def unmarshal_EndpointPublicNetworkDetails(data: Any) -> EndpointPublicNetworkDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPublicNetworkDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return EndpointPublicNetworkDetails(**args) + + +def unmarshal_Endpoint(data: Any) -> Endpoint: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Endpoint' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("url", None) + if field is not None: + args["url"] = field + + field = data.get("disable_auth", None) + if field is not None: + args["disable_auth"] = field + + field = data.get("public_network", None) + if field is not None: + args["public_network"] = unmarshal_EndpointPublicNetworkDetails(field) + else: + args["public_network"] = None + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None + + return Endpoint(**args) + + +def unmarshal_ModelSupportedQuantization(data: Any) -> ModelSupportedQuantization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportedQuantization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("quantization_bits", None) + if field is not None: + args["quantization_bits"] = field + + field = data.get("allowed", None) + if field is not None: + args["allowed"] = field + + field = data.get("max_context_size", None) + if field is not None: + args["max_context_size"] = field + + return ModelSupportedQuantization(**args) + + +def unmarshal_ModelSupportedNode(data: Any) -> ModelSupportedNode: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportedNode' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_type_name", None) + if field is not None: + args["node_type_name"] = field + + field = data.get("quantizations", None) + if field is not None: + args["quantizations"] = ( + [unmarshal_ModelSupportedQuantization(v) for v in field] + if field is not None + else None + ) + + return ModelSupportedNode(**args) + + +def unmarshal_ModelSupportInfo(data: Any) -> ModelSupportInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("nodes", None) + if field is not None: + args["nodes"] = ( + [unmarshal_ModelSupportedNode(v) for v in field] + if field is not None + else None + ) + + return ModelSupportInfo(**args) + + +def unmarshal_DeploymentQuantization(data: Any) -> DeploymentQuantization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DeploymentQuantization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bits", None) + if field is not None: + args["bits"] = field + + return DeploymentQuantization(**args) + + +def unmarshal_Deployment(data: Any) -> Deployment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Deployment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("node_type_name", None) + if field is not None: + args["node_type_name"] = field + + field = data.get("endpoints", None) + if field is not None: + args["endpoints"] = ( + [unmarshal_Endpoint(v) for v in field] if field is not None else None + ) + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("min_size", None) + if field is not None: + args["min_size"] = field + + field = data.get("max_size", None) + if field is not None: + args["max_size"] = field + + field = data.get("model_id", None) + if field is not None: + args["model_id"] = field + + field = data.get("model_name", None) + if field is not None: + args["model_name"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + else: + args["error_message"] = None + + field = data.get("quantization", None) + if field is not None: + args["quantization"] = unmarshal_DeploymentQuantization(field) + else: + args["quantization"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Deployment(**args) + + +def unmarshal_Model(data: Any) -> Model: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Model' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("has_eula", None) + if field is not None: + args["has_eula"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("nodes_support", None) + if field is not None: + args["nodes_support"] = ( + [unmarshal_ModelSupportInfo(v) for v in field] + if field is not None + else None + ) + + field = data.get("parameter_size_bits", None) + if field is not None: + args["parameter_size_bits"] = field + + field = data.get("size_bytes", None) + if field is not None: + args["size_bytes"] = field + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + else: + args["error_message"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Model(**args) + + +def unmarshal_ListDeploymentsResponse(data: Any) -> ListDeploymentsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDeploymentsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("deployments", None) + if field is not None: + args["deployments"] = ( + [unmarshal_Deployment(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDeploymentsResponse(**args) + + +def unmarshal_ListModelsResponse(data: Any) -> ListModelsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListModelsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("models", None) + if field is not None: + args["models"] = ( + [unmarshal_Model(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListModelsResponse(**args) + + +def unmarshal_NodeType(data: Any) -> NodeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("stock_status", None) + if field is not None: + args["stock_status"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("vcpus", None) + if field is not None: + args["vcpus"] = field + + field = data.get("memory", None) + if field is not None: + args["memory"] = field + + field = data.get("vram", None) + if field is not None: + args["vram"] = field + + field = data.get("disabled", None) + if field is not None: + args["disabled"] = field + + field = data.get("beta", None) + if field is not None: + args["beta"] = field + + field = data.get("gpus", None) + if field is not None: + args["gpus"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return NodeType(**args) + + +def unmarshal_ListNodeTypesResponse(data: Any) -> ListNodeTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListNodeTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_types", None) + if field is not None: + args["node_types"] = ( + [unmarshal_NodeType(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListNodeTypesResponse(**args) + + +def marshal_EndpointPrivateNetworkDetails( + request: EndpointPrivateNetworkDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + return output + + +def marshal_EndpointPublicNetworkDetails( + request: EndpointPublicNetworkDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_DeploymentQuantization( + request: DeploymentQuantization, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bits is not None: + output["bits"] = request.bits + + return output + + +def marshal_EndpointSpec( + request: EndpointSpec, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("public_network", request.public_network), + OneOfPossibility("private_network", request.private_network), + ] + ), + ) + + if request.disable_auth is not None: + output["disable_auth"] = request.disable_auth + + return output + + +def marshal_CreateDeploymentRequest( + request: CreateDeploymentRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.model_id is not None: + output["model_id"] = request.model_id + + if request.node_type_name is not None: + output["node_type_name"] = request.node_type_name + + if request.endpoints is not None: + output["endpoints"] = [ + marshal_EndpointSpec(item, defaults) for item in request.endpoints + ] + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.accept_eula is not None: + output["accept_eula"] = request.accept_eula + + if request.tags is not None: + output["tags"] = request.tags + + if request.min_size is not None: + output["min_size"] = request.min_size + + if request.max_size is not None: + output["max_size"] = request.max_size + + if request.quantization is not None: + output["quantization"] = marshal_DeploymentQuantization( + request.quantization, defaults + ) + + return output + + +def marshal_CreateEndpointRequest( + request: CreateEndpointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.deployment_id is not None: + output["deployment_id"] = request.deployment_id + + if request.endpoint is not None: + output["endpoint"] = marshal_EndpointSpec(request.endpoint, defaults) + + return output + + +def marshal_ModelSource( + request: ModelSource, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("secret", request.secret), + ] + ), + ) + + if request.url is not None: + output["url"] = request.url + + return output + + +def marshal_CreateModelRequest( + request: CreateModelRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.source is not None: + output["source"] = marshal_ModelSource(request.source, defaults) + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_UpdateDeploymentRequest( + request: UpdateDeploymentRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.min_size is not None: + output["min_size"] = request.min_size + + if request.max_size is not None: + output["max_size"] = request.max_size + + if request.model_id is not None: + output["model_id"] = request.model_id + + if request.quantization is not None: + output["quantization"] = marshal_DeploymentQuantization( + request.quantization, defaults + ) + + return output + + +def marshal_UpdateEndpointRequest( + request: UpdateEndpointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.disable_auth is not None: + output["disable_auth"] = request.disable_auth + + return output diff --git a/scaleway-async/scaleway_async/inference/v1/types.py b/scaleway-async/scaleway_async/inference/v1/types.py new file mode 100644 index 00000000..a4246cb0 --- /dev/null +++ b/scaleway-async/scaleway_async/inference/v1/types.py @@ -0,0 +1,775 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DeploymentStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + DEPLOYING = "deploying" + READY = "ready" + ERROR = "error" + DELETING = "deleting" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class ListDeploymentsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListModelsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + DISPLAY_RANK_ASC = "display_rank_asc" + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ModelStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + PREPARING = "preparing" + DOWNLOADING = "downloading" + READY = "ready" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class NodeTypeStock(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STOCK = "unknown_stock" + LOW_STOCK = "low_stock" + OUT_OF_STOCK = "out_of_stock" + AVAILABLE = "available" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ModelSupportedQuantization: + quantization_bits: int + """ + Number of bits for this supported quantization. + """ + + allowed: bool + """ + Tells whether this quantization is allowed for this node type. + """ + + max_context_size: int + """ + Maximum inference context size available for this node type and quantization. + """ + + +@dataclass +class EndpointPrivateNetworkDetails: + private_network_id: str + + +@dataclass +class EndpointPublicNetworkDetails: + pass + + +@dataclass +class ModelSupportedNode: + node_type_name: str + """ + Supported node type. + """ + + quantizations: List[ModelSupportedQuantization] + """ + Supported quantizations. + """ + + +@dataclass +class DeploymentQuantization: + bits: int + """ + The number of bits each model parameter should be quantized to. The quantization method is chosen based on this value. + """ + + +@dataclass +class Endpoint: + id: str + """ + Unique identifier. + """ + + url: str + """ + For private endpoints, the URL will be accessible only from the Private Network. +In addition, private endpoints will expose a CA certificate that can be used to verify the server's identity. +This CA certificate can be retrieved using the `GetDeploymentCertificate` API call. + """ + + disable_auth: bool + """ + Defines whether the authentication is disabled. + """ + + public_network: Optional[EndpointPublicNetworkDetails] + + private_network: Optional[EndpointPrivateNetworkDetails] + + +@dataclass +class ModelSupportInfo: + nodes: List[ModelSupportedNode] + """ + List of supported node types. + """ + + +@dataclass +class EndpointSpec: + disable_auth: bool + """ + By default, deployments are protected by IAM authentication. +When setting this field to true, the authentication will be disabled. + """ + + public_network: Optional[EndpointPublicNetworkDetails] + + private_network: Optional[EndpointPrivateNetworkDetails] + + +@dataclass +class ModelSource: + url: str + + secret: Optional[str] + + +@dataclass +class Deployment: + id: str + """ + Unique identifier. + """ + + name: str + """ + Name of the deployment. + """ + + project_id: str + """ + Project ID. + """ + + status: DeploymentStatus + """ + Status of the deployment. + """ + + tags: List[str] + """ + List of tags applied to the deployment. + """ + + node_type_name: str + """ + Node type of the deployment. + """ + + endpoints: List[Endpoint] + """ + List of endpoints. + """ + + size: int + """ + Current size of the pool. + """ + + min_size: int + """ + Defines the minimum size of the pool. + """ + + max_size: int + """ + Defines the maximum size of the pool. + """ + + model_id: str + """ + ID of the model used for the deployment. + """ + + model_name: str + """ + Name of the deployed model. + """ + + region: ScwRegion + """ + Region of the deployment. + """ + + error_message: Optional[str] + """ + Displays information if your deployment is in error state. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization parameters for this deployment. + """ + + created_at: Optional[datetime] + """ + Creation date of the deployment. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the deployment. + """ + + +@dataclass +class Model: + id: str + """ + Unique identifier. + """ + + name: str + """ + Unique Name identifier. + """ + + project_id: str + """ + Project ID. + """ + + tags: List[str] + """ + List of tags applied to the model. + """ + + status: ModelStatus + """ + Status of the model. + """ + + description: str + """ + Purpose of the model. + """ + + has_eula: bool + """ + Defines whether the model has an end user license agreement. + """ + + region: ScwRegion + """ + Region of the model. + """ + + nodes_support: List[ModelSupportInfo] + """ + Supported nodes types with quantization options and context lengths. + """ + + parameter_size_bits: int + """ + Size, in bits, of the model parameters. + """ + + size_bytes: int + """ + Total size, in bytes, of the model files. + """ + + error_message: Optional[str] + """ + Displays information if your model is in error state. + """ + + created_at: Optional[datetime] + """ + Creation date of the model. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the model. + """ + + +@dataclass +class NodeType: + name: str + """ + Name of the node type. + """ + + stock_status: NodeTypeStock + """ + Current stock status for the node type. + """ + + description: str + """ + Current specs of the offer. + """ + + vcpus: int + """ + Number of virtual CPUs. + """ + + memory: int + """ + Quantity of RAM. + """ + + vram: int + """ + Quantity of GPU RAM. + """ + + disabled: bool + """ + The node type is currently disabled. + """ + + beta: bool + """ + The node type is currently in beta. + """ + + gpus: int + """ + Number of GPUs. + """ + + region: ScwRegion + """ + Region of the node type. + """ + + created_at: Optional[datetime] + """ + Creation date of the node type. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the node type. + """ + + +@dataclass +class CreateDeploymentRequest: + model_id: str + """ + ID of the model to use. + """ + + node_type_name: str + """ + Name of the node type to use. + """ + + endpoints: List[EndpointSpec] + """ + List of endpoints to create. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the deployment. + """ + + project_id: Optional[str] + """ + ID of the Project to create the deployment in. + """ + + accept_eula: Optional[bool] + """ + If the model has an EULA, you must accept it before proceeding. +The terms of the EULA can be retrieved using the `GetModelEula` API call. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the deployment. + """ + + min_size: Optional[int] + """ + Defines the minimum size of the pool. + """ + + max_size: Optional[int] + """ + Defines the maximum size of the pool. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization settings to apply to this deployment. + """ + + +@dataclass +class CreateEndpointRequest: + deployment_id: str + """ + ID of the deployment to create the endpoint for. + """ + + endpoint: EndpointSpec + """ + Specification of the endpoint. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateModelRequest: + source: ModelSource + """ + Where to import the model from. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the model. + """ + + project_id: Optional[str] + """ + ID of the Project to import the model in. + """ + + +@dataclass +class DeleteDeploymentRequest: + deployment_id: str + """ + ID of the deployment to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteEndpointRequest: + endpoint_id: str + """ + ID of the endpoint to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteModelRequest: + model_id: str + """ + ID of the model to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDeploymentCertificateRequest: + deployment_id: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDeploymentRequest: + deployment_id: str + """ + ID of the deployment to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetModelRequest: + model_id: str + """ + ID of the model to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListDeploymentsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of deployments to return per page. + """ + + order_by: Optional[ListDeploymentsRequestOrderBy] + """ + Order in which to return results. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + name: Optional[str] + """ + Filter by deployment name. + """ + + tags: Optional[List[str]] + """ + Filter by tags. + """ + + +@dataclass +class ListDeploymentsResponse: + deployments: List[Deployment] + """ + List of deployments on the current page. + """ + + total_count: int + """ + Total number of deployments. + """ + + +@dataclass +class ListModelsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListModelsRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of models to return per page. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + name: Optional[str] + """ + Filter by model name. + """ + + tags: Optional[List[str]] + """ + Filter by tags. + """ + + +@dataclass +class ListModelsResponse: + models: List[Model] + """ + List of models on the current page. + """ + + total_count: int + """ + Total number of models. + """ + + +@dataclass +class ListNodeTypesRequest: + include_disabled_types: bool + """ + Include disabled node types in the response. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of node types to return per page. + """ + + +@dataclass +class ListNodeTypesResponse: + node_types: List[NodeType] + """ + List of node types. + """ + + total_count: int + """ + Total number of node types. + """ + + +@dataclass +class UpdateDeploymentRequest: + deployment_id: str + """ + ID of the deployment to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the deployment. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the deployment. + """ + + min_size: Optional[int] + """ + Defines the new minimum size of the pool. + """ + + max_size: Optional[int] + """ + Defines the new maximum size of the pool. + """ + + model_id: Optional[str] + """ + Id of the model to set to the deployment. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization to use to the deployment. + """ + + +@dataclass +class UpdateEndpointRequest: + endpoint_id: str + """ + ID of the endpoint to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + disable_auth: Optional[bool] + """ + By default, deployments are protected by IAM authentication. +When setting this field to true, the authentication will be disabled. + """ diff --git a/scaleway-async/scaleway_async/llm_inference/v1beta1/__init__.py b/scaleway-async/scaleway_async/inference/v1beta1/__init__.py similarity index 97% rename from scaleway-async/scaleway_async/llm_inference/v1beta1/__init__.py rename to scaleway-async/scaleway_async/inference/v1beta1/__init__.py index e78f7a95..b542f359 100644 --- a/scaleway-async/scaleway_async/llm_inference/v1beta1/__init__.py +++ b/scaleway-async/scaleway_async/inference/v1beta1/__init__.py @@ -41,7 +41,7 @@ from .types import SetDeploymentACLRulesResponse from .types import UpdateDeploymentRequest from .types import UpdateEndpointRequest -from .api import LlmInferenceV1Beta1API +from .api import InferenceV1Beta1API __all__ = [ "DeploymentStatus", @@ -85,5 +85,5 @@ "SetDeploymentACLRulesResponse", "UpdateDeploymentRequest", "UpdateEndpointRequest", - "LlmInferenceV1Beta1API", + "InferenceV1Beta1API", ] diff --git a/scaleway-async/scaleway_async/llm_inference/v1beta1/api.py b/scaleway-async/scaleway_async/inference/v1beta1/api.py similarity index 91% rename from scaleway-async/scaleway_async/llm_inference/v1beta1/api.py rename to scaleway-async/scaleway_async/inference/v1beta1/api.py index 7dca0abc..e35e9ae1 100644 --- a/scaleway-async/scaleway_async/llm_inference/v1beta1/api.py +++ b/scaleway-async/scaleway_async/inference/v1beta1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ScwFile, unmarshal_ScwFile, ) @@ -63,13 +63,15 @@ ) -class LlmInferenceV1Beta1API(API): - """ """ +class InferenceV1Beta1API(API): + """ + This API allows you to manage your Inference services. + """ async def list_deployments( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDeploymentsRequestOrderBy] = None, @@ -103,7 +105,7 @@ async def list_deployments( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/deployments", + f"/inference/v1beta1/regions/{param_region}/deployments", params={ "name": name, "order_by": order_by, @@ -122,7 +124,7 @@ async def list_deployments( async def list_deployments_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDeploymentsRequestOrderBy] = None, @@ -170,7 +172,7 @@ async def get_deployment( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Deployment: """ Get a deployment. @@ -194,7 +196,7 @@ async def get_deployment( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", ) self._throw_on_error(res) @@ -204,7 +206,7 @@ async def wait_for_deployment( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[Deployment, Union[bool, Awaitable[bool]]] ] = None, @@ -245,7 +247,7 @@ async def create_deployment( model_name: str, node_type: str, endpoints: List[EndpointSpec], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, project_id: Optional[str] = None, accept_eula: Optional[bool] = None, @@ -285,14 +287,14 @@ async def create_deployment( res = self._request( "POST", - f"/llm-inference/v1beta1/regions/{param_region}/deployments", + f"/inference/v1beta1/regions/{param_region}/deployments", body=marshal_CreateDeploymentRequest( CreateDeploymentRequest( model_name=model_name, node_type=node_type, endpoints=endpoints, region=region, - name=name or random_name(prefix="llm"), + name=name or random_name(prefix="inference"), project_id=project_id, accept_eula=accept_eula, tags=tags, @@ -310,7 +312,7 @@ async def update_deployment( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, min_size: Optional[int] = None, @@ -342,7 +344,7 @@ async def update_deployment( res = self._request( "PATCH", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", body=marshal_UpdateDeploymentRequest( UpdateDeploymentRequest( deployment_id=deployment_id, @@ -363,7 +365,7 @@ async def delete_deployment( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Deployment: """ Delete a deployment. @@ -387,7 +389,7 @@ async def delete_deployment( res = self._request( "DELETE", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", ) self._throw_on_error(res) @@ -397,7 +399,7 @@ async def get_deployment_certificate( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ScwFile: """ Get the CA certificate. @@ -422,7 +424,7 @@ async def get_deployment_certificate( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/certificate", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/certificate", ) self._throw_on_error(res) @@ -433,7 +435,7 @@ async def create_endpoint( *, deployment_id: str, endpoint: EndpointSpec, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Endpoint: """ Create an endpoint. @@ -458,7 +460,7 @@ async def create_endpoint( res = self._request( "POST", - f"/llm-inference/v1beta1/regions/{param_region}/endpoints", + f"/inference/v1beta1/regions/{param_region}/endpoints", body=marshal_CreateEndpointRequest( CreateEndpointRequest( deployment_id=deployment_id, @@ -476,7 +478,7 @@ async def update_endpoint( self, *, endpoint_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, disable_auth: Optional[bool] = None, ) -> Endpoint: """ @@ -484,7 +486,7 @@ async def update_endpoint( Update an existing Endpoint. :param endpoint_id: ID of the endpoint to update. :param region: Region to target. If none is passed will use default region from the config. - :param disable_auth: By default, LLM deployments are protected by IAM authentication. + :param disable_auth: By default, deployments are protected by IAM authentication. When setting this field to true, the authentication will be disabled. :return: :class:`Endpoint ` @@ -503,7 +505,7 @@ async def update_endpoint( res = self._request( "PATCH", - f"/llm-inference/v1beta1/regions/{param_region}/endpoints/{param_endpoint_id}", + f"/inference/v1beta1/regions/{param_region}/endpoints/{param_endpoint_id}", body=marshal_UpdateEndpointRequest( UpdateEndpointRequest( endpoint_id=endpoint_id, @@ -521,7 +523,7 @@ async def delete_endpoint( self, *, endpoint_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete an endpoint. @@ -544,7 +546,7 @@ async def delete_endpoint( res = self._request( "DELETE", - f"/llm-inference/v1beta1/regions/{param_region}/endpoints/{param_endpoint_id}", + f"/inference/v1beta1/regions/{param_region}/endpoints/{param_endpoint_id}", ) self._throw_on_error(res) @@ -553,7 +555,7 @@ async def list_deployment_acl_rules( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListDeploymentACLRulesResponse: @@ -581,7 +583,7 @@ async def list_deployment_acl_rules( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", params={ "page": page, "page_size": page_size or self.client.default_page_size, @@ -595,7 +597,7 @@ async def list_deployment_acl_rules_all( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[ACLRule]: @@ -632,7 +634,7 @@ async def add_deployment_acl_rules( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, acls: Optional[List[ACLRuleRequest]] = None, ) -> AddDeploymentACLRulesResponse: """ @@ -658,7 +660,7 @@ async def add_deployment_acl_rules( res = self._request( "POST", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", body=marshal_AddDeploymentACLRulesRequest( AddDeploymentACLRulesRequest( deployment_id=deployment_id, @@ -676,7 +678,7 @@ async def set_deployment_acl_rules( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, acls: Optional[List[ACLRuleRequest]] = None, ) -> SetDeploymentACLRulesResponse: """ @@ -702,7 +704,7 @@ async def set_deployment_acl_rules( res = self._request( "PUT", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", body=marshal_SetDeploymentACLRulesRequest( SetDeploymentACLRulesRequest( deployment_id=deployment_id, @@ -720,10 +722,10 @@ async def delete_deployment_acl_rule( self, *, acl_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ - Delete an exising ACL. + Delete an existing ACL. :param acl_id: ID of the ACL rule to delete. :param region: Region to target. If none is passed will use default region from the config. @@ -742,7 +744,7 @@ async def delete_deployment_acl_rule( res = self._request( "DELETE", - f"/llm-inference/v1beta1/regions/{param_region}/acls/{param_acl_id}", + f"/inference/v1beta1/regions/{param_region}/acls/{param_acl_id}", ) self._throw_on_error(res) @@ -750,7 +752,7 @@ async def delete_deployment_acl_rule( async def list_models( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListModelsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -760,7 +762,7 @@ async def list_models( ) -> ListModelsResponse: """ List models. - List all available LLM models. + List all available models. :param region: Region to target. If none is passed will use default region from the config. :param order_by: Order in which to return results. :param page: Page number to return. @@ -782,7 +784,7 @@ async def list_models( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/models", + f"/inference/v1beta1/regions/{param_region}/models", params={ "name": name, "order_by": order_by, @@ -799,7 +801,7 @@ async def list_models( async def list_models_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListModelsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -809,7 +811,7 @@ async def list_models_all( ) -> List[Model]: """ List models. - List all available LLM models. + List all available models. :param region: Region to target. If none is passed will use default region from the config. :param order_by: Order in which to return results. :param page: Page number to return. @@ -844,7 +846,7 @@ async def get_model( self, *, model_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Model: """ Get a model. @@ -868,7 +870,7 @@ async def get_model( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/models/{param_model_id}", + f"/inference/v1beta1/regions/{param_region}/models/{param_model_id}", ) self._throw_on_error(res) @@ -878,7 +880,7 @@ async def get_model_eula( self, *, model_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Eula: """ :param model_id: @@ -900,7 +902,7 @@ async def get_model_eula( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/models/{param_model_id}/eula", + f"/inference/v1beta1/regions/{param_region}/models/{param_model_id}/eula", ) self._throw_on_error(res) @@ -910,7 +912,7 @@ async def list_node_types( self, *, include_disabled_types: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListNodeTypesResponse: @@ -937,7 +939,7 @@ async def list_node_types( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/node-types", + f"/inference/v1beta1/regions/{param_region}/node-types", params={ "include_disabled_types": include_disabled_types, "page": page, @@ -952,7 +954,7 @@ async def list_node_types_all( self, *, include_disabled_types: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[NodeType]: diff --git a/scaleway-async/scaleway_async/llm_inference/v1beta1/content.py b/scaleway-async/scaleway_async/inference/v1beta1/content.py similarity index 100% rename from scaleway-async/scaleway_async/llm_inference/v1beta1/content.py rename to scaleway-async/scaleway_async/inference/v1beta1/content.py diff --git a/scaleway-async/scaleway_async/llm_inference/v1beta1/marshalling.py b/scaleway-async/scaleway_async/inference/v1beta1/marshalling.py similarity index 95% rename from scaleway-async/scaleway_async/llm_inference/v1beta1/marshalling.py rename to scaleway-async/scaleway_async/inference/v1beta1/marshalling.py index e8146598..413ff779 100644 --- a/scaleway-async/scaleway_async/llm_inference/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/inference/v1beta1/marshalling.py @@ -87,10 +87,14 @@ def unmarshal_Endpoint(data: Any) -> Endpoint: field = data.get("public_access", None) if field is not None: args["public_access"] = unmarshal_EndpointPublicAccessDetails(field) + else: + args["public_access"] = None field = data.get("private_network", None) if field is not None: args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None return Endpoint(**args) @@ -149,6 +153,10 @@ def unmarshal_Deployment(data: Any) -> Deployment: if field is not None: args["model_name"] = field + field = data.get("model_id", None) + if field is not None: + args["model_id"] = field + field = data.get("region", None) if field is not None: args["region"] = field @@ -156,14 +164,20 @@ def unmarshal_Deployment(data: Any) -> Deployment: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Deployment(**args) @@ -187,10 +201,14 @@ def unmarshal_ModelS3Model(data: Any) -> ModelS3Model: field = data.get("node_type", None) if field is not None: args["node_type"] = field + else: + args["node_type"] = None field = data.get("triton_server_version", None) if field is not None: args["triton_server_version"] = field + else: + args["triton_server_version"] = None return ModelS3Model(**args) @@ -250,14 +268,20 @@ def unmarshal_Model(data: Any) -> Model: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("s3_model", None) if field is not None: args["s3_model"] = unmarshal_ModelS3Model(field) + else: + args["s3_model"] = None return Model(**args) @@ -433,10 +457,14 @@ def unmarshal_NodeType(data: Any) -> NodeType: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return NodeType(**args) @@ -597,7 +625,7 @@ def marshal_CreateEndpointRequest( output["deployment_id"] = request.deployment_id if request.endpoint is not None: - output["endpoint"] = (marshal_EndpointSpec(request.endpoint, defaults),) + output["endpoint"] = marshal_EndpointSpec(request.endpoint, defaults) return output diff --git a/scaleway/scaleway/llm_inference/v1beta1/types.py b/scaleway-async/scaleway_async/inference/v1beta1/types.py similarity index 93% rename from scaleway/scaleway/llm_inference/v1beta1/types.py rename to scaleway-async/scaleway_async/inference/v1beta1/types.py index eedd3d8b..c93b59bc 100644 --- a/scaleway/scaleway/llm_inference/v1beta1/types.py +++ b/scaleway-async/scaleway_async/inference/v1beta1/types.py @@ -8,7 +8,7 @@ from typing import Dict, List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -39,6 +39,7 @@ def __str__(self) -> str: class ListModelsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + DISPLAY_RANK_ASC = "display_rank_asc" CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" NAME_ASC = "name_asc" @@ -154,7 +155,7 @@ class ACLRule: class EndpointSpec: disable_auth: bool """ - By default, LLM deployments are protected by IAM authentication. + By default, deployments are protected by IAM authentication. When setting this field to true, the authentication will be disabled. """ @@ -220,7 +221,12 @@ class Deployment: The inference model used for the deployment. """ - region: Region + model_id: str + """ + ID of the model used for the deployment. + """ + + region: ScwRegion """ Region of the deployment. """ @@ -275,10 +281,10 @@ class Model: has_eula: bool """ - Defines whether the model has an end user licence agreement. + Defines whether the model has an end user license agreement. """ - region: Region + region: ScwRegion """ Region of the model. """ @@ -358,7 +364,7 @@ class NodeType: Number of GPUs. """ - region: Region + region: ScwRegion """ Region of the node type. """ @@ -381,7 +387,7 @@ class AddDeploymentACLRulesRequest: ID of the deployment to add ACL rules to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -417,7 +423,7 @@ class CreateDeploymentRequest: List of endpoints to create. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -466,7 +472,7 @@ class CreateEndpointRequest: Specification of the endpoint. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -479,7 +485,7 @@ class DeleteDeploymentACLRuleRequest: ID of the ACL rule to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -492,7 +498,7 @@ class DeleteDeploymentRequest: ID of the deployment to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -505,7 +511,7 @@ class DeleteEndpointRequest: ID of the endpoint to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -515,7 +521,7 @@ class DeleteEndpointRequest: class Eula: content: str """ - Content of the end user licence agreement. + Content of the end user license agreement. """ @@ -523,7 +529,7 @@ class Eula: class GetDeploymentCertificateRequest: deployment_id: str - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -536,7 +542,7 @@ class GetDeploymentRequest: ID of the deployment to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -546,7 +552,7 @@ class GetDeploymentRequest: class GetModelEulaRequest: model_id: str - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -559,7 +565,7 @@ class GetModelRequest: ID of the model to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -572,7 +578,7 @@ class ListDeploymentACLRulesRequest: ID of the deployment to list ACL rules for. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -603,7 +609,7 @@ class ListDeploymentACLRulesResponse: @dataclass class ListDeploymentsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -659,7 +665,7 @@ class ListDeploymentsResponse: @dataclass class ListModelsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -715,7 +721,7 @@ class ListNodeTypesRequest: Include disabled node types in the response. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -751,7 +757,7 @@ class SetDeploymentACLRulesRequest: ID of the deployment to set ACL rules for. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -777,7 +783,7 @@ class UpdateDeploymentRequest: ID of the deployment to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -810,13 +816,13 @@ class UpdateEndpointRequest: ID of the endpoint to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ disable_auth: Optional[bool] """ - By default, LLM deployments are protected by IAM authentication. + By default, deployments are protected by IAM authentication. When setting this field to true, the authentication will be disabled. """ diff --git a/scaleway-async/scaleway_async/instance/v1/__init__.py b/scaleway-async/scaleway_async/instance/v1/__init__.py index 8f2320f2..05aba600 100644 --- a/scaleway-async/scaleway_async/instance/v1/__init__.py +++ b/scaleway-async/scaleway_async/instance/v1/__init__.py @@ -55,6 +55,7 @@ from .types import VolumeServer from .types import SnapshotBaseVolume from .types import ServerTypeCapabilities +from .types import ServerTypeGPUInfo from .types import ServerTypeNetwork from .types import ServerTypeVolumeConstraintsByType from .types import VolumeTypeCapabilities @@ -77,8 +78,11 @@ from .types import VolumeImageUpdateTemplate from .types import SecurityGroupTemplate from .types import ApplyBlockMigrationRequest +from .types import AttachServerFileSystemRequest +from .types import AttachServerFileSystemResponse from .types import AttachServerVolumeRequest from .types import AttachServerVolumeResponse +from .types import CheckBlockMigrationOrganizationQuotasRequest from .types import CreateImageRequest from .types import CreateImageResponse from .types import CreateIpRequest @@ -107,12 +111,12 @@ from .types import DeleteServerUserDataRequest from .types import DeleteSnapshotRequest from .types import DeleteVolumeRequest +from .types import DetachServerFileSystemRequest +from .types import DetachServerFileSystemResponse from .types import DetachServerVolumeRequest from .types import DetachServerVolumeResponse from .types import ExportSnapshotRequest from .types import ExportSnapshotResponse -from .types import GetBootscriptRequest -from .types import GetBootscriptResponse from .types import GetDashboardRequest from .types import GetDashboardResponse from .types import GetImageRequest @@ -129,6 +133,7 @@ from .types import GetSecurityGroupResponse from .types import GetSecurityGroupRuleRequest from .types import GetSecurityGroupRuleResponse +from .types import GetServerCompatibleTypesRequest from .types import GetServerRequest from .types import GetServerResponse from .types import GetServerTypesAvailabilityRequest @@ -137,8 +142,6 @@ from .types import GetSnapshotResponse from .types import GetVolumeRequest from .types import GetVolumeResponse -from .types import ListBootscriptsRequest -from .types import ListBootscriptsResponse from .types import ListDefaultSecurityGroupRulesRequest from .types import ListImagesRequest from .types import ListImagesResponse @@ -170,6 +173,7 @@ from .types import PlanBlockMigrationRequest from .types import ServerActionRequest from .types import ServerActionResponse +from .types import ServerCompatibleTypes from .types import SetImageRequest from .types import SetPlacementGroupRequest from .types import SetPlacementGroupResponse @@ -254,6 +258,7 @@ "VolumeServer", "SnapshotBaseVolume", "ServerTypeCapabilities", + "ServerTypeGPUInfo", "ServerTypeNetwork", "ServerTypeVolumeConstraintsByType", "VolumeTypeCapabilities", @@ -276,8 +281,11 @@ "VolumeImageUpdateTemplate", "SecurityGroupTemplate", "ApplyBlockMigrationRequest", + "AttachServerFileSystemRequest", + "AttachServerFileSystemResponse", "AttachServerVolumeRequest", "AttachServerVolumeResponse", + "CheckBlockMigrationOrganizationQuotasRequest", "CreateImageRequest", "CreateImageResponse", "CreateIpRequest", @@ -306,12 +314,12 @@ "DeleteServerUserDataRequest", "DeleteSnapshotRequest", "DeleteVolumeRequest", + "DetachServerFileSystemRequest", + "DetachServerFileSystemResponse", "DetachServerVolumeRequest", "DetachServerVolumeResponse", "ExportSnapshotRequest", "ExportSnapshotResponse", - "GetBootscriptRequest", - "GetBootscriptResponse", "GetDashboardRequest", "GetDashboardResponse", "GetImageRequest", @@ -328,6 +336,7 @@ "GetSecurityGroupResponse", "GetSecurityGroupRuleRequest", "GetSecurityGroupRuleResponse", + "GetServerCompatibleTypesRequest", "GetServerRequest", "GetServerResponse", "GetServerTypesAvailabilityRequest", @@ -336,8 +345,6 @@ "GetSnapshotResponse", "GetVolumeRequest", "GetVolumeResponse", - "ListBootscriptsRequest", - "ListBootscriptsResponse", "ListDefaultSecurityGroupRulesRequest", "ListImagesRequest", "ListImagesResponse", @@ -369,6 +376,7 @@ "PlanBlockMigrationRequest", "ServerActionRequest", "ServerActionResponse", + "ServerCompatibleTypes", "SetImageRequest", "SetPlacementGroupRequest", "SetPlacementGroupResponse", diff --git a/scaleway-async/scaleway_async/instance/v1/api.py b/scaleway-async/scaleway_async/instance/v1/api.py index 2ff5c17e..2a49867d 100644 --- a/scaleway-async/scaleway_async/instance/v1/api.py +++ b/scaleway-async/scaleway_async/instance/v1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( random_name, @@ -43,9 +43,12 @@ SnapshotVolumeType, VolumeVolumeType, ApplyBlockMigrationRequest, + AttachServerFileSystemRequest, + AttachServerFileSystemResponse, AttachServerVolumeRequest, AttachServerVolumeResponse, Bootscript, + CheckBlockMigrationOrganizationQuotasRequest, CreateImageRequest, CreateImageResponse, CreateIpRequest, @@ -64,11 +67,12 @@ CreateSnapshotResponse, CreateVolumeRequest, CreateVolumeResponse, + DetachServerFileSystemRequest, + DetachServerFileSystemResponse, DetachServerVolumeRequest, DetachServerVolumeResponse, ExportSnapshotRequest, ExportSnapshotResponse, - GetBootscriptResponse, GetDashboardResponse, GetImageResponse, GetIpResponse, @@ -83,7 +87,6 @@ GetVolumeResponse, Image, Ip, - ListBootscriptsResponse, ListImagesResponse, ListIpsResponse, ListPlacementGroupsResponse, @@ -109,6 +112,7 @@ ServerActionRequest, ServerActionRequestVolumeBackupTemplate, ServerActionResponse, + ServerCompatibleTypes, ServerIp, ServerIpv6, ServerLocation, @@ -151,6 +155,7 @@ ) from .marshalling import ( unmarshal_PrivateNIC, + unmarshal_AttachServerFileSystemResponse, unmarshal_AttachServerVolumeResponse, unmarshal_CreateImageResponse, unmarshal_CreateIpResponse, @@ -161,9 +166,9 @@ unmarshal_CreateServerResponse, unmarshal_CreateSnapshotResponse, unmarshal_CreateVolumeResponse, + unmarshal_DetachServerFileSystemResponse, unmarshal_DetachServerVolumeResponse, unmarshal_ExportSnapshotResponse, - unmarshal_GetBootscriptResponse, unmarshal_GetDashboardResponse, unmarshal_GetImageResponse, unmarshal_GetIpResponse, @@ -176,7 +181,6 @@ unmarshal_GetServerTypesAvailabilityResponse, unmarshal_GetSnapshotResponse, unmarshal_GetVolumeResponse, - unmarshal_ListBootscriptsResponse, unmarshal_ListImagesResponse, unmarshal_ListIpsResponse, unmarshal_ListPlacementGroupsResponse, @@ -192,6 +196,7 @@ unmarshal_ListVolumesTypesResponse, unmarshal_MigrationPlan, unmarshal_ServerActionResponse, + unmarshal_ServerCompatibleTypes, unmarshal_SetPlacementGroupResponse, unmarshal_SetPlacementGroupServersResponse, unmarshal_SetSecurityGroupRulesResponse, @@ -210,7 +215,9 @@ unmarshal__SetServerResponse, unmarshal__SetSnapshotResponse, marshal_ApplyBlockMigrationRequest, + marshal_AttachServerFileSystemRequest, marshal_AttachServerVolumeRequest, + marshal_CheckBlockMigrationOrganizationQuotasRequest, marshal_CreateImageRequest, marshal_CreateIpRequest, marshal_CreatePlacementGroupRequest, @@ -220,6 +227,7 @@ marshal_CreateServerRequest, marshal_CreateSnapshotRequest, marshal_CreateVolumeRequest, + marshal_DetachServerFileSystemRequest, marshal_DetachServerVolumeRequest, marshal_ExportSnapshotRequest, marshal_PlanBlockMigrationRequest, @@ -247,13 +255,13 @@ class InstanceV1API(API): """ - Instance API. + This API allows you to manage your CPU and GPU Instances. """ async def get_server_types_availability( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, ) -> GetServerTypesAvailabilityResponse: @@ -288,7 +296,7 @@ async def get_server_types_availability( async def list_servers_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, ) -> ListServersTypesResponse: @@ -323,7 +331,7 @@ async def list_servers_types( async def list_volumes_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, ) -> ListVolumesTypesResponse: @@ -358,7 +366,7 @@ async def list_volumes_types( async def list_servers( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, organization: Optional[str] = None, @@ -366,6 +374,7 @@ async def list_servers( name: Optional[str] = None, private_ip: Optional[str] = None, without_ip: Optional[bool] = None, + with_ip: Optional[str] = None, commercial_type: Optional[str] = None, state: Optional[ServerState] = None, tags: Optional[List[str]] = None, @@ -386,6 +395,7 @@ async def list_servers( :param name: Filter Instances by name (eg. "server1" will return "server100" and "server1" but not "foo"). :param private_ip: List Instances by private_ip. :param without_ip: List Instances that are not attached to a public IP. + :param with_ip: List Instances by IP (both private_ip and public_ip are supported). :param commercial_type: List Instances of this commercial type. :param state: List Instances in this state. :param tags: List Instances with these exact tags (to filter with several tags, use commas to separate them). @@ -424,6 +434,7 @@ async def list_servers( "servers": ",".join(servers) if servers and len(servers) > 0 else None, "state": state, "tags": ",".join(tags) if tags and len(tags) > 0 else None, + "with_ip": with_ip, "without_ip": without_ip, }, ) @@ -434,7 +445,7 @@ async def list_servers( async def list_servers_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, organization: Optional[str] = None, @@ -442,6 +453,7 @@ async def list_servers_all( name: Optional[str] = None, private_ip: Optional[str] = None, without_ip: Optional[bool] = None, + with_ip: Optional[str] = None, commercial_type: Optional[str] = None, state: Optional[ServerState] = None, tags: Optional[List[str]] = None, @@ -462,6 +474,7 @@ async def list_servers_all( :param name: Filter Instances by name (eg. "server1" will return "server100" and "server1" but not "foo"). :param private_ip: List Instances by private_ip. :param without_ip: List Instances that are not attached to a public IP. + :param with_ip: List Instances by IP (both private_ip and public_ip are supported). :param commercial_type: List Instances of this commercial type. :param state: List Instances in this state. :param tags: List Instances with these exact tags (to filter with several tags, use commas to separate them). @@ -491,6 +504,7 @@ async def list_servers_all( "name": name, "private_ip": private_ip, "without_ip": without_ip, + "with_ip": with_ip, "commercial_type": commercial_type, "state": state, "tags": tags, @@ -505,40 +519,41 @@ async def list_servers_all( async def _create_server( self, *, + zone: Optional[ScwZone] = None, commercial_type: str, - image: str, - enable_ipv6: bool, - zone: Optional[Zone] = None, name: Optional[str] = None, dynamic_ip_required: Optional[bool] = None, routed_ip_enabled: Optional[bool] = None, + image: Optional[str] = None, volumes: Optional[Dict[str, VolumeServerTemplate]] = None, + enable_ipv6: Optional[bool] = None, + protected: bool, public_ip: Optional[str] = None, public_ips: Optional[List[str]] = None, boot_type: Optional[BootType] = None, - bootscript: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, tags: Optional[List[str]] = None, security_group: Optional[str] = None, placement_group: Optional[str] = None, + admin_password_encryption_ssh_key_id: Optional[str] = None, ) -> CreateServerResponse: """ Create an Instance. Create a new Instance of the specified commercial type in the specified zone. Pay attention to the volumes parameter, which takes an object which can be used in different ways to achieve different behaviors. Get more information in the [Technical Information](#technical-information) section of the introduction. - :param commercial_type: Define the Instance commercial type (i.e. GP1-S). - :param image: Instance image ID or label. - :param enable_ipv6: True if IPv6 is enabled on the server. :param zone: Zone to target. If none is passed will use default zone from the config. + :param commercial_type: Define the Instance commercial type (i.e. GP1-S). :param name: Instance name. :param dynamic_ip_required: Define if a dynamic IPv4 is required for the Instance. :param routed_ip_enabled: If true, configure the Instance so it uses the new routed IP mode. + :param image: Instance image ID or label. :param volumes: Volumes attached to the server. + :param enable_ipv6: True if IPv6 is enabled on the server (deprecated and always `False` when `routed_ip_enabled` is `True`). + :param protected: True to activate server protection option. :param public_ip: ID of the reserved IP to attach to the Instance. :param public_ips: A list of reserved IP IDs to attach to the Instance. :param boot_type: Boot type to use. - :param bootscript: Bootscript ID to use when `boot_type` is set to `bootscript`. :param organization: Instance Organization ID. One-Of ('project_identifier'): at most one of 'project', 'organization' could be set. :param project: Instance Project ID. @@ -546,6 +561,7 @@ async def _create_server( :param tags: Instance tags. :param security_group: Security group ID. :param placement_group: Placement group ID if Instance must be part of a placement group. + :param admin_password_encryption_ssh_key_id: The public_key value of this key is used to encrypt the admin password. :return: :class:`CreateServerResponse ` Usage: @@ -553,8 +569,7 @@ async def _create_server( result = await api._create_server( commercial_type="example", - image="example", - enable_ipv6=False, + protected=False, ) """ @@ -567,19 +582,20 @@ async def _create_server( CreateServerRequest( zone=zone, commercial_type=commercial_type, - image=image, name=name or random_name(prefix="srv"), dynamic_ip_required=dynamic_ip_required, routed_ip_enabled=routed_ip_enabled, - enable_ipv6=enable_ipv6, + image=image, volumes=volumes, + enable_ipv6=enable_ipv6, + protected=protected, public_ip=public_ip, public_ips=public_ips, boot_type=boot_type, - bootscript=bootscript, tags=tags, security_group=security_group, placement_group=placement_group, + admin_password_encryption_ssh_key_id=admin_password_encryption_ssh_key_id, project=project, organization=organization, ), @@ -594,7 +610,7 @@ async def delete_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an Instance. @@ -624,7 +640,7 @@ async def get_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetServerResponse: """ Get an Instance. @@ -655,12 +671,11 @@ async def get_server( async def _set_server( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, id: str, name: str, commercial_type: str, dynamic_ip_required: bool, - enable_ipv6: bool, hostname: str, organization: Optional[str] = None, project: Optional[str] = None, @@ -668,24 +683,25 @@ async def _set_server( tags: Optional[List[str]] = None, creation_date: Optional[datetime] = None, routed_ip_enabled: Optional[bool] = None, + enable_ipv6: Optional[bool] = None, image: Optional[Image] = None, protected: bool, private_ip: Optional[str] = None, public_ip: Optional[ServerIp] = None, public_ips: Optional[List[ServerIp]] = None, modification_date: Optional[datetime] = None, - state_detail: str, state: Optional[ServerState] = None, location: Optional[ServerLocation] = None, ipv6: Optional[ServerIpv6] = None, - bootscript: Optional[Bootscript] = None, boot_type: Optional[BootType] = None, + state_detail: str, volumes: Optional[Dict[str, Volume]] = None, security_group: Optional[SecurityGroupSummary] = None, maintenances: Optional[List[ServerMaintenance]] = None, arch: Optional[Arch] = None, placement_group: Optional[PlacementGroup] = None, private_nics: Optional[List[PrivateNIC]] = None, + admin_password_encryption_ssh_key_id: Optional[str] = None, ) -> _SetServerResponse: """ :param zone: Zone to target. If none is passed will use default zone from the config. @@ -693,7 +709,6 @@ async def _set_server( :param name: Instance name. :param commercial_type: Instance commercial type (eg. GP1-M). :param dynamic_ip_required: True if a dynamic IPv4 is required. - :param enable_ipv6: True if IPv6 is enabled. :param hostname: Instance host name. :param organization: Instance Organization ID. :param project: Instance Project ID. @@ -701,24 +716,25 @@ async def _set_server( :param tags: Tags associated with the Instance. :param creation_date: Instance creation date. :param routed_ip_enabled: True to configure the instance so it uses the new routed IP mode (once this is set to True you cannot set it back to False). + :param enable_ipv6: True if IPv6 is enabled (deprecated and always `False` when `routed_ip_enabled` is `True`). :param image: Provide information on the Instance image. :param protected: Instance protection option is activated. - :param private_ip: Instance private IP address. - :param public_ip: Information about the public IP. + :param private_ip: Instance private IP address (deprecated and always `null` when `routed_ip_enabled` is `True`). + :param public_ip: Information about the public IP (deprecated in favor of `public_ips`). :param public_ips: Information about all the public IPs attached to the server. :param modification_date: Instance modification date. - :param state_detail: Instance state_detail. :param state: Instance state. :param location: Instance location. - :param ipv6: Instance IPv6 address. - :param bootscript: Instance bootscript. + :param ipv6: Instance IPv6 address (deprecated when `routed_ip_enabled` is `True`). :param boot_type: Instance boot type. + :param state_detail: Instance state_detail. :param volumes: Instance volumes. :param security_group: Instance security group. :param maintenances: Instance planned maintenances. :param arch: Instance architecture (refers to the CPU architecture used for the Instance, e.g. x86_64, arm64). :param placement_group: Instance placement group. :param private_nics: Instance private NICs. + :param admin_password_encryption_ssh_key_id: The public_key value of this key is used to encrypt the admin password. When set to an empty string, reset this value and admin_password_encrypted_value to an empty string so a new password may be generated. :return: :class:`_SetServerResponse <_SetServerResponse>` Usage: @@ -729,7 +745,6 @@ async def _set_server( name="example", commercial_type="example", dynamic_ip_required=False, - enable_ipv6=False, hostname="example", protected=False, state_detail="example", @@ -748,26 +763,25 @@ async def _set_server( id=id, name=name, commercial_type=commercial_type, + organization=organization, dynamic_ip_required=dynamic_ip_required, - enable_ipv6=enable_ipv6, hostname=hostname, - organization=organization, + protected=protected, + state_detail=state_detail, project=project, allowed_actions=allowed_actions, tags=tags, creation_date=creation_date, routed_ip_enabled=routed_ip_enabled, + enable_ipv6=enable_ipv6, image=image, - protected=protected, private_ip=private_ip, public_ip=public_ip, public_ips=public_ips, modification_date=modification_date, - state_detail=state_detail, state=state, location=location, ipv6=ipv6, - bootscript=bootscript, boot_type=boot_type, volumes=volumes, security_group=security_group, @@ -775,6 +789,7 @@ async def _set_server( arch=arch, placement_group=placement_group, private_nics=private_nics, + admin_password_encryption_ssh_key_id=admin_password_encryption_ssh_key_id, ), self.client, ), @@ -787,12 +802,11 @@ async def _update_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, boot_type: Optional[BootType] = None, tags: Optional[List[str]] = None, volumes: Optional[Dict[str, VolumeServerTemplate]] = None, - bootscript: Optional[str] = None, dynamic_ip_required: Optional[bool] = None, routed_ip_enabled: Optional[bool] = None, public_ips: Optional[List[str]] = None, @@ -802,6 +816,7 @@ async def _update_server( placement_group: Optional[str] = None, private_nics: Optional[List[str]] = None, commercial_type: Optional[str] = None, + admin_password_encryption_ssh_key_id: Optional[str] = None, ) -> UpdateServerResponse: """ Update an Instance. @@ -812,19 +827,20 @@ async def _update_server( :param boot_type: :param tags: Tags of the Instance. :param volumes: - :param bootscript: :param dynamic_ip_required: :param routed_ip_enabled: True to configure the instance so it uses the new routed IP mode (once this is set to True you cannot set it back to False). :param public_ips: A list of reserved IP IDs to attach to the Instance. :param enable_ipv6: - :param protected: + :param protected: True to activate server protection option. :param security_group: :param placement_group: Placement group ID if Instance must be part of a placement group. :param private_nics: Instance private NICs. :param commercial_type: Warning: This field has some restrictions: - Cannot be changed if the Instance is not in `stopped` state. - Cannot be changed if the Instance is in a placement group. + - Cannot be changed from/to a Windows offer to/from a Linux offer. - Local storage requirements of the target commercial_types must be fulfilled (i.e. if an Instance has 80GB of local storage, it can be changed into a GP1-XS, which has a maximum of 150GB, but it cannot be changed into a DEV1-S, which has only 20GB). + :param admin_password_encryption_ssh_key_id: The public_key value of this key is used to encrypt the admin password. When set to an empty string, reset this value and admin_password_encrypted_value to an empty string so a new password may be generated. :return: :class:`UpdateServerResponse ` Usage: @@ -849,7 +865,6 @@ async def _update_server( boot_type=boot_type, tags=tags, volumes=volumes, - bootscript=bootscript, dynamic_ip_required=dynamic_ip_required, routed_ip_enabled=routed_ip_enabled, public_ips=public_ips, @@ -859,6 +874,7 @@ async def _update_server( placement_group=placement_group, private_nics=private_nics, commercial_type=commercial_type, + admin_password_encryption_ssh_key_id=admin_password_encryption_ssh_key_id, ), self.client, ), @@ -871,7 +887,7 @@ async def list_server_actions( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ListServerActionsResponse: """ List Instance actions. @@ -903,10 +919,11 @@ async def server_action( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, action: Optional[ServerAction] = None, name: Optional[str] = None, volumes: Optional[Dict[str, ServerActionRequestVolumeBackupTemplate]] = None, + disable_ipv6: Optional[bool] = None, ) -> ServerActionResponse: """ Perform action. @@ -917,12 +934,15 @@ async def server_action( * `stop_in_place`: Stop the Instance, but keep the slot on the hypervisor. * `reboot`: Stop the instance and restart it. * `backup`: Create an image with all the volumes of an Instance. - * `terminate`: Delete the Instance along with all attached volumes. + * `terminate`: Delete the Instance along with its attached volumes, except for SBS volumes. * `enable_routed_ip`: Migrate the Instance to the new network stack. - Keep in mind that terminating an Instance will result in the deletion of all attached volumes, including local and block storage. - If you want to preserve your local volumes, you should use the `archive` action instead of `terminate`. Similarly, if you want to keep your block storage volumes, you must first detach them before issuing the `terminate` command. - For more information, read the [Volumes](#path-volumes-list-volumes) documentation. + The `terminate` action will result in the deletion of `l_ssd`, `b_ssd` and `scratch` volumes types, `sbs_volume` volumes type will only be detached. + If you want to preserve your volumes, you should detach them before the Instance deletion or `terminate` action. + + The `backup` action can be done with: + * No `volumes` key in the body: an image is created with snapshots of all the server volumes, except for the `scratch` volumes types. + * `volumes` key in the body with a dictionary as value, in this dictionary volumes UUID as keys and empty dictionaries as values : an image is created with the snapshots of the volumes in `volumes` key. `scratch` volumes types can't be shapshotted. :param server_id: UUID of the Instance. :param zone: Zone to target. If none is passed will use default zone from the config. :param action: Action to perform on the Instance. @@ -930,6 +950,8 @@ async def server_action( This field should only be specified when performing a backup action. :param volumes: For each volume UUID, the snapshot parameters of the volume. This field should only be specified when performing a backup action. + :param disable_ipv6: Disable IPv6 on the Instance while performing migration to routed IPs. + This field should only be specified when performing a enable_routed_ip action. :return: :class:`ServerActionResponse ` Usage: @@ -953,6 +975,7 @@ async def server_action( action=action, name=name, volumes=volumes, + disable_ipv6=disable_ipv6, ), self.client, ), @@ -965,7 +988,7 @@ async def list_server_user_data( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ListServerUserDataResponse: """ List user data. @@ -998,7 +1021,7 @@ async def delete_server_user_data( *, server_id: str, key: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete user data. @@ -1027,12 +1050,49 @@ async def delete_server_user_data( self._throw_on_error(res) + async def get_server_compatible_types( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> ServerCompatibleTypes: + """ + Get Instance compatible types. + Get compatible commercial types that can be used to update the Instance. The compatibility of an Instance offer is based on: + * the CPU architecture + * the OS type + * the required l_ssd storage size + * the required scratch storage size + If the specified Instance offer is flagged as end of service, the best compatible offer is the first returned. + :param server_id: UUID of the Instance you want to get. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerCompatibleTypes ` + + Usage: + :: + + result = await api.get_server_compatible_types( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/instance/v1/zones/{param_zone}/servers/{param_server_id}/compatible-types", + ) + + self._throw_on_error(res) + return unmarshal_ServerCompatibleTypes(res.json()) + async def attach_server_volume( self, *, server_id: str, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, volume_type: Optional[AttachServerVolumeRequestVolumeType] = None, boot: Optional[bool] = None, ) -> AttachServerVolumeResponse: @@ -1079,7 +1139,7 @@ async def detach_server_volume( *, server_id: str, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> DetachServerVolumeResponse: """ :param server_id: @@ -1115,10 +1175,94 @@ async def detach_server_volume( self._throw_on_error(res) return unmarshal_DetachServerVolumeResponse(res.json()) + async def attach_server_file_system( + self, + *, + server_id: str, + filesystem_id: str, + zone: Optional[ScwZone] = None, + ) -> AttachServerFileSystemResponse: + """ + Attach a filesystem volume to an Instance. + :param server_id: + :param filesystem_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`AttachServerFileSystemResponse ` + + Usage: + :: + + result = await api.attach_server_file_system( + server_id="example", + filesystem_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/instance/v1/zones/{param_zone}/servers/{param_server_id}/attach-filesystem", + body=marshal_AttachServerFileSystemRequest( + AttachServerFileSystemRequest( + server_id=server_id, + filesystem_id=filesystem_id, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AttachServerFileSystemResponse(res.json()) + + async def detach_server_file_system( + self, + *, + server_id: str, + filesystem_id: str, + zone: Optional[ScwZone] = None, + ) -> DetachServerFileSystemResponse: + """ + Detach a filesystem volume to an Instance. + :param server_id: + :param filesystem_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`DetachServerFileSystemResponse ` + + Usage: + :: + + result = await api.detach_server_file_system( + server_id="example", + filesystem_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/instance/v1/zones/{param_zone}/servers/{param_server_id}/detach-filesystem", + body=marshal_DetachServerFileSystemRequest( + DetachServerFileSystemRequest( + server_id=server_id, + filesystem_id=filesystem_id, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DetachServerFileSystemResponse(res.json()) + async def list_images( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -1171,7 +1315,7 @@ async def list_images( async def list_images_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -1222,7 +1366,7 @@ async def get_image( self, *, image_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetImageResponse: """ Get an Instance image. @@ -1255,9 +1399,8 @@ async def create_image( *, root_volume: str, arch: Arch, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, - default_bootscript: Optional[str] = None, extra_volumes: Optional[Dict[str, VolumeTemplate]] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -1271,7 +1414,6 @@ async def create_image( :param arch: Architecture of the image. :param zone: Zone to target. If none is passed will use default zone from the config. :param name: Name of the image. - :param default_bootscript: Default bootscript of the image. :param extra_volumes: Additional volumes of the image. :param organization: Organization ID of the image. One-Of ('project_identifier'): at most one of 'project', 'organization' could be set. @@ -1301,7 +1443,6 @@ async def create_image( arch=arch, zone=zone, name=name or random_name(prefix="img"), - default_bootscript=default_bootscript, extra_volumes=extra_volumes, tags=tags, public=public, @@ -1318,7 +1459,7 @@ async def create_image( async def _set_image( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, id: str, name: str, arch: Optional[Arch] = None, @@ -1400,7 +1541,7 @@ async def update_image( self, *, image_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, arch: Optional[Arch] = None, extra_volumes: Optional[Dict[str, VolumeImageUpdateTemplate]] = None, @@ -1454,7 +1595,7 @@ async def delete_image( self, *, image_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an Instance image. @@ -1483,7 +1624,7 @@ async def delete_image( async def list_snapshots( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, project: Optional[str] = None, per_page: Optional[int] = None, @@ -1533,7 +1674,7 @@ async def list_snapshots( async def list_snapshots_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, project: Optional[str] = None, per_page: Optional[int] = None, @@ -1580,7 +1721,7 @@ async def list_snapshots_all( async def create_snapshot( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, volume_id: Optional[str] = None, tags: Optional[List[str]] = None, @@ -1644,7 +1785,7 @@ async def get_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetSnapshotResponse: """ Get a snapshot. @@ -1677,7 +1818,7 @@ async def _set_snapshot( *, id: str, name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, volume_type: Optional[VolumeVolumeType] = None, size: int, @@ -1751,7 +1892,7 @@ async def update_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, ) -> UpdateSnapshotResponse: @@ -1796,7 +1937,7 @@ async def delete_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a snapshot. @@ -1828,13 +1969,13 @@ async def export_snapshot( bucket: str, key: str, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ExportSnapshotResponse: """ Export a snapshot. - Export a snapshot to a specified S3 bucket in the same region. - :param bucket: S3 bucket name. - :param key: S3 object key. + Export a snapshot to a specified Object Storage bucket in the same region. + :param bucket: Object Storage bucket name. + :param key: Object key. :param snapshot_id: Snapshot ID. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`ExportSnapshotResponse ` @@ -1872,7 +2013,7 @@ async def export_snapshot( async def list_volumes( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, volume_type: Optional[VolumeVolumeType] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -1922,7 +2063,7 @@ async def list_volumes( async def list_volumes_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, volume_type: Optional[VolumeVolumeType] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -1969,7 +2110,7 @@ async def list_volumes_all( async def create_volume( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -2028,7 +2169,7 @@ async def get_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetVolumeResponse: """ Get a volume. @@ -2060,7 +2201,7 @@ async def update_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, size: Optional[int] = None, @@ -2108,7 +2249,7 @@ async def delete_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a volume. @@ -2137,7 +2278,7 @@ async def delete_volume( async def list_security_groups( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -2187,7 +2328,7 @@ async def list_security_groups( async def list_security_groups_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -2236,7 +2377,7 @@ async def create_security_group( *, description: str, stateful: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -2308,7 +2449,7 @@ async def get_security_group( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetSecurityGroupResponse: """ Get a security group. @@ -2342,7 +2483,7 @@ async def delete_security_group( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a security group. @@ -2373,7 +2514,7 @@ async def delete_security_group( async def _set_security_group( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, id: str, name: str, description: str, @@ -2460,7 +2601,7 @@ async def update_security_group( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, description: Optional[str] = None, enable_default_security: Optional[bool] = None, @@ -2527,7 +2668,7 @@ async def update_security_group( async def list_default_security_group_rules( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ListSecurityGroupRulesResponse: """ Get default rules. @@ -2555,7 +2696,7 @@ async def list_security_group_rules( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, ) -> ListSecurityGroupRulesResponse: @@ -2597,7 +2738,7 @@ async def list_security_group_rules_all( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, ) -> List[SecurityGroupRule]: @@ -2640,7 +2781,7 @@ async def create_security_group_rule( ip_range: str, position: int, editable: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, dest_port_from: Optional[int] = None, dest_port_to: Optional[int] = None, ) -> CreateSecurityGroupRuleResponse: @@ -2705,7 +2846,7 @@ async def set_security_group_rules( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, rules: Optional[List[SetSecurityGroupRulesRequestRule]] = None, ) -> SetSecurityGroupRulesResponse: """ @@ -2750,7 +2891,7 @@ async def delete_security_group_rule( *, security_group_id: str, security_group_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete rule. @@ -2788,7 +2929,7 @@ async def get_security_group_rule( *, security_group_id: str, security_group_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetSecurityGroupRuleResponse: """ Get rule. @@ -2832,7 +2973,7 @@ async def _set_security_group_rule( ip_range: str, position: int, editable: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, protocol: Optional[SecurityGroupRuleProtocol] = None, direction: Optional[SecurityGroupRuleDirection] = None, action: Optional[SecurityGroupRuleAction] = None, @@ -2907,7 +3048,7 @@ async def update_security_group_rule( *, security_group_id: str, security_group_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, protocol: Optional[SecurityGroupRuleProtocol] = None, direction: Optional[SecurityGroupRuleDirection] = None, action: Optional[SecurityGroupRuleAction] = None, @@ -2974,7 +3115,7 @@ async def update_security_group_rule( async def list_placement_groups( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, organization: Optional[str] = None, @@ -3021,7 +3162,7 @@ async def list_placement_groups( async def list_placement_groups_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, organization: Optional[str] = None, @@ -3065,7 +3206,7 @@ async def list_placement_groups_all( async def create_placement_group( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -3119,7 +3260,7 @@ async def get_placement_group( self, *, placement_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetPlacementGroupResponse: """ Get a placement group. @@ -3154,7 +3295,7 @@ async def set_placement_group( *, placement_group_id: str, name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, policy_mode: Optional[PlacementGroupPolicyMode] = None, policy_type: Optional[PlacementGroupPolicyType] = None, @@ -3213,7 +3354,7 @@ async def update_placement_group( self, *, placement_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, policy_mode: Optional[PlacementGroupPolicyMode] = None, @@ -3266,7 +3407,7 @@ async def delete_placement_group( self, *, placement_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete the specified placement group. @@ -3297,7 +3438,7 @@ async def get_placement_group_servers( self, *, placement_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetPlacementGroupServersResponse: """ Get placement group servers. @@ -3332,7 +3473,7 @@ async def set_placement_group_servers( *, placement_group_id: str, servers: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetPlacementGroupServersResponse: """ Set placement group servers. @@ -3377,7 +3518,7 @@ async def update_placement_group_servers( *, placement_group_id: str, servers: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> UpdatePlacementGroupServersResponse: """ Update placement group servers. @@ -3420,7 +3561,7 @@ async def update_placement_group_servers( async def list_ips( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project: Optional[str] = None, organization: Optional[str] = None, tags: Optional[List[str]] = None, @@ -3439,7 +3580,7 @@ async def list_ips( :param name: Filter on the IP address (Works as a LIKE operation on the IP address). :param per_page: A positive integer lower or equal to 100 to select the number of items to return. :param page: A positive integer to choose the page to return. - :param type_: Filter on the IP Mobility IP type (whose value should be either 'nat', 'routed_ipv4' or 'routed_ipv6'). + :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`ListIpsResponse ` Usage: @@ -3470,7 +3611,7 @@ async def list_ips( async def list_ips_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project: Optional[str] = None, organization: Optional[str] = None, tags: Optional[List[str]] = None, @@ -3489,7 +3630,7 @@ async def list_ips_all( :param name: Filter on the IP address (Works as a LIKE operation on the IP address). :param per_page: A positive integer lower or equal to 100 to select the number of items to return. :param page: A positive integer to choose the page to return. - :param type_: Filter on the IP Mobility IP type (whose value should be either 'nat', 'routed_ipv4' or 'routed_ipv6'). + :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`List[Ip] ` Usage: @@ -3517,7 +3658,7 @@ async def list_ips_all( async def create_ip( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, project: Optional[str] = None, tags: Optional[List[str]] = None, @@ -3534,7 +3675,7 @@ async def create_ip( One-Of ('project_identifier'): at most one of 'project', 'organization' could be set. :param tags: Tags of the IP. :param server: UUID of the Instance you want to attach the IP to. - :param type_: IP type to reserve (either 'nat', 'routed_ipv4' or 'routed_ipv6'). + :param type_: IP type to reserve (either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`CreateIpResponse ` Usage: @@ -3568,7 +3709,7 @@ async def get_ip( self, *, ip: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetIpResponse: """ Get a flexible IP. @@ -3600,7 +3741,7 @@ async def update_ip( self, *, ip: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, reverse: Optional[str] = None, type_: Optional[IpType] = None, tags: Optional[List[str]] = None, @@ -3612,7 +3753,7 @@ async def update_ip( :param ip: IP ID or IP address. :param zone: Zone to target. If none is passed will use default zone from the config. :param reverse: Reverse domain name. - :param type_: Convert a 'nat' IP to a 'routed_ipv4'. + :param type_: Should have no effect. :param tags: An array of keywords you want to tag this IP with. :param server: :return: :class:`UpdateIpResponse ` @@ -3651,7 +3792,7 @@ async def delete_ip( self, *, ip: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a flexible IP. @@ -3681,7 +3822,7 @@ async def list_private_ni_cs( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -3724,7 +3865,7 @@ async def list_private_ni_cs_all( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -3765,9 +3906,10 @@ async def create_private_nic( *, server_id: str, private_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, ip_ids: Optional[List[str]] = None, + ipam_ip_ids: Optional[List[str]] = None, ) -> CreatePrivateNICResponse: """ Create a private NIC connecting an Instance to a Private Network. @@ -3776,6 +3918,7 @@ async def create_private_nic( :param zone: Zone to target. If none is passed will use default zone from the config. :param tags: Private NIC tags. :param ip_ids: Ip_ids defined from IPAM. + :param ipam_ip_ids: UUID of IPAM ips, to be attached to the instance in the requested private network. :return: :class:`CreatePrivateNICResponse ` Usage: @@ -3800,6 +3943,7 @@ async def create_private_nic( zone=zone, tags=tags, ip_ids=ip_ids, + ipam_ip_ids=ipam_ip_ids, ), self.client, ), @@ -3813,7 +3957,7 @@ async def get_private_nic( *, server_id: str, private_nic_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetPrivateNICResponse: """ Get a private NIC. @@ -3849,7 +3993,7 @@ async def update_private_nic( *, server_id: str, private_nic_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, ) -> PrivateNIC: """ @@ -3896,7 +4040,7 @@ async def delete_private_nic( *, server_id: str, private_nic_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a private NIC. @@ -3924,134 +4068,10 @@ async def delete_private_nic( self._throw_on_error(res) - async def list_bootscripts( - self, - *, - zone: Optional[Zone] = None, - arch: Optional[str] = None, - title: Optional[str] = None, - default: Optional[bool] = None, - public: Optional[bool] = None, - per_page: Optional[int] = None, - page: Optional[int] = None, - ) -> ListBootscriptsResponse: - """ - List bootscripts. - :param zone: Zone to target. If none is passed will use default zone from the config. - :param arch: - :param title: - :param default: - :param public: - :param per_page: - :param page: - :return: :class:`ListBootscriptsResponse ` - :deprecated - - Usage: - :: - - result = await api.list_bootscripts() - """ - - param_zone = validate_path_param("zone", zone or self.client.default_zone) - - res = self._request( - "GET", - f"/instance/v1/zones/{param_zone}/bootscripts", - params={ - "arch": arch, - "default": default, - "page": page, - "per_page": per_page or self.client.default_page_size, - "public": public, - "title": title, - }, - ) - - self._throw_on_error(res) - return unmarshal_ListBootscriptsResponse(res.json()) - - async def list_bootscripts_all( - self, - *, - zone: Optional[Zone] = None, - arch: Optional[str] = None, - title: Optional[str] = None, - default: Optional[bool] = None, - public: Optional[bool] = None, - per_page: Optional[int] = None, - page: Optional[int] = None, - ) -> List[Bootscript]: - """ - List bootscripts. - :param zone: Zone to target. If none is passed will use default zone from the config. - :param arch: - :param title: - :param default: - :param public: - :param per_page: - :param page: - :return: :class:`List[Bootscript] ` - :deprecated - - Usage: - :: - - result = await api.list_bootscripts_all() - """ - - return await fetch_all_pages_async( - type=ListBootscriptsResponse, - key="bootscripts", - fetcher=self.list_bootscripts, - args={ - "zone": zone, - "arch": arch, - "title": title, - "default": default, - "public": public, - "per_page": per_page, - "page": page, - }, - ) - - async def get_bootscript( - self, - *, - bootscript_id: str, - zone: Optional[Zone] = None, - ) -> GetBootscriptResponse: - """ - Get bootscripts. - Get details of a bootscript with the specified ID. - :param bootscript_id: - :param zone: Zone to target. If none is passed will use default zone from the config. - :return: :class:`GetBootscriptResponse ` - :deprecated - - Usage: - :: - - result = await api.get_bootscript( - bootscript_id="example", - ) - """ - - param_zone = validate_path_param("zone", zone or self.client.default_zone) - param_bootscript_id = validate_path_param("bootscript_id", bootscript_id) - - res = self._request( - "GET", - f"/instance/v1/zones/{param_zone}/bootscripts/{param_bootscript_id}", - ) - - self._throw_on_error(res) - return unmarshal_GetBootscriptResponse(res.json()) - async def get_dashboard( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, project: Optional[str] = None, ) -> GetDashboardResponse: @@ -4084,13 +4104,17 @@ async def get_dashboard( async def plan_block_migration( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, volume_id: Optional[str] = None, snapshot_id: Optional[str] = None, ) -> MigrationPlan: """ Get a volume or snapshot's migration plan. - Given a volume or snapshot, returns the migration plan for a call to the RPC ApplyBlockMigration. This plan will include zero or one volume, and zero or more snapshots, which will need to be migrated together. This RPC does not perform the actual migration itself, ApplyBlockMigration must be used. The validation_key value returned by this call must be provided to the ApplyBlockMigration call to confirm that all resources listed in the plan should be migrated. + Given a volume or snapshot, returns the migration plan but does not perform the actual migration. To perform the migration, you have to call the [Migrate a volume and/or snapshots to SBS](#path-volumes-migrate-a-volume-andor-snapshots-to-sbs-scaleway-block-storage) endpoint afterward. + The endpoint returns the resources that should be migrated together: + - the volume and any snapshots created from the volume, if the call was made to plan a volume migration. + - the base volume of the snapshot (if the volume is not deleted) and its related snapshots, if the call was made to plan a snapshot migration. + The endpoint also returns the validation_key, which must be provided to the [Migrate a volume and/or snapshots to SBS](#path-volumes-migrate-a-volume-andor-snapshots-to-sbs-scaleway-block-storage) endpoint to confirm that all resources listed in the plan should be migrated. :param zone: Zone to target. If none is passed will use default zone from the config. :param volume_id: The volume for which the migration plan will be generated. One-Of ('resource'): at most one of 'volume_id', 'snapshot_id' could be set. @@ -4126,18 +4150,18 @@ async def apply_block_migration( self, *, validation_key: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, volume_id: Optional[str] = None, snapshot_id: Optional[str] = None, ) -> None: """ Migrate a volume and/or snapshots to SBS (Scaleway Block Storage). - To be used, this RPC must be preceded by a call to PlanBlockMigration. To migrate all resources mentioned in the MigrationPlan, the validation_key returned in the MigrationPlan must be provided. - :param validation_key: A value to be retrieved from a call to PlanBlockMigration, to confirm that the volume and/or snapshots specified in said plan should be migrated. + To be used, the call to this endpoint must be preceded by a call to the [Get a volume or snapshot's migration plan](#path-volumes-get-a-volume-or-snapshots-migration-plan) endpoint. To migrate all resources mentioned in the migration plan, the validation_key returned in the plan must be provided. + :param validation_key: A value to be retrieved from a call to the [Get a volume or snapshot's migration plan](#path-volumes-get-a-volume-or-snapshots-migration-plan) endpoint, to confirm that the volume and/or snapshots specified in said plan should be migrated. :param zone: Zone to target. If none is passed will use default zone from the config. - :param volume_id: The volume to migrate, along with potentially other resources, according to the migration plan generated with a call to PlanBlockMigration. + :param volume_id: The volume to migrate, along with potentially other resources, according to the migration plan generated with a call to the [Get a volume or snapshot's migration plan](#path-volumes-get-a-volume-or-snapshots-migration-plan) endpoint. One-Of ('resource'): at most one of 'volume_id', 'snapshot_id' could be set. - :param snapshot_id: The snapshot to migrate, along with potentially other resources, according to the migration plan generated with a call to PlanBlockMigration. + :param snapshot_id: The snapshot to migrate, along with potentially other resources, according to the migration plan generated with a call to the [Get a volume or snapshot's migration plan](#path-volumes-get-a-volume-or-snapshots-migration-plan) endpoint. One-Of ('resource'): at most one of 'volume_id', 'snapshot_id' could be set. Usage: @@ -4165,3 +4189,35 @@ async def apply_block_migration( ) self._throw_on_error(res) + + async def check_block_migration_organization_quotas( + self, + *, + zone: Optional[ScwZone] = None, + organization: Optional[str] = None, + ) -> None: + """ + :param zone: Zone to target. If none is passed will use default zone from the config. + :param organization: + + Usage: + :: + + result = await api.check_block_migration_organization_quotas() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/instance/v1/zones/{param_zone}/block-migration/check-organization-quotas", + body=marshal_CheckBlockMigrationOrganizationQuotasRequest( + CheckBlockMigrationOrganizationQuotasRequest( + zone=zone, + organization=organization, + ), + self.client, + ), + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/instance/v1/marshalling.py b/scaleway-async/scaleway_async/instance/v1/marshalling.py index 0d7765d5..86c38fc2 100644 --- a/scaleway-async/scaleway_async/instance/v1/marshalling.py +++ b/scaleway-async/scaleway_async/instance/v1/marshalling.py @@ -37,6 +37,7 @@ ServerMaintenance, VolumeServer, Server, + AttachServerFileSystemResponse, AttachServerVolumeResponse, CreateImageResponse, Ip, @@ -53,9 +54,9 @@ Task, CreateSnapshotResponse, CreateVolumeResponse, + DetachServerFileSystemResponse, DetachServerVolumeResponse, ExportSnapshotResponse, - GetBootscriptResponse, Dashboard, GetDashboardResponse, GetImageResponse, @@ -71,7 +72,6 @@ GetServerTypesAvailabilityResponse, GetSnapshotResponse, GetVolumeResponse, - ListBootscriptsResponse, ListImagesResponse, ListIpsResponse, ListPlacementGroupsResponse, @@ -84,6 +84,7 @@ ServerTypeNetworkInterface, ServerTypeVolumeConstraintSizes, ServerTypeCapabilities, + ServerTypeGPUInfo, ServerTypeNetwork, ServerTypeVolumeConstraintsByType, ServerType, @@ -96,6 +97,7 @@ ListVolumesTypesResponse, MigrationPlan, ServerActionResponse, + ServerCompatibleTypes, SetPlacementGroupResponse, SetPlacementGroupServersResponse, SetSecurityGroupRulesResponse, @@ -109,7 +111,9 @@ UpdateSnapshotResponse, UpdateVolumeResponse, ApplyBlockMigrationRequest, + AttachServerFileSystemRequest, AttachServerVolumeRequest, + CheckBlockMigrationOrganizationQuotasRequest, VolumeTemplate, CreateImageRequest, CreateIpRequest, @@ -121,6 +125,7 @@ CreateServerRequest, CreateSnapshotRequest, CreateVolumeRequest, + DetachServerFileSystemRequest, DetachServerVolumeRequest, ExportSnapshotRequest, PlanBlockMigrationRequest, @@ -208,6 +213,10 @@ def unmarshal_Bootscript(data: Any) -> Bootscript: args: Dict[str, Any] = {} + field = data.get("architecture", None) + if field is not None: + args["architecture"] = field + field = data.get("bootcmdargs", None) if field is not None: args["bootcmdargs"] = field @@ -236,10 +245,6 @@ def unmarshal_Bootscript(data: Any) -> Bootscript: if field is not None: args["organization"] = field - field = data.get("project", None) - if field is not None: - args["project"] = field - field = data.get("public", None) if field is not None: args["public"] = field @@ -248,9 +253,9 @@ def unmarshal_Bootscript(data: Any) -> Bootscript: if field is not None: args["title"] = field - field = data.get("arch", None) + field = data.get("project", None) if field is not None: - args["arch"] = field + args["project"] = field field = data.get("zone", None) if field is not None: @@ -294,18 +299,24 @@ def unmarshal_Volume(data: Any) -> Volume: field = data.get("export_uri", None) if field is not None: args["export_uri"] = field + else: + args["export_uri"] = None field = data.get("creation_date", None) if field is not None: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None field = data.get("tags", None) if field is not None: @@ -322,6 +333,8 @@ def unmarshal_Volume(data: Any) -> Volume: field = data.get("server", None) if field is not None: args["server"] = unmarshal_ServerSummary(field) + else: + args["server"] = None return Volume(**args) @@ -394,16 +407,22 @@ def unmarshal_Image(data: Any) -> Image: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None field = data.get("default_bootscript", None) if field is not None: args["default_bootscript"] = unmarshal_Bootscript(field) + else: + args["default_bootscript"] = None field = data.get("public", None) if field is not None: @@ -428,6 +447,8 @@ def unmarshal_Image(data: Any) -> Image: field = data.get("root_volume", None) if field is not None: args["root_volume"] = unmarshal_VolumeSummary(field) + else: + args["root_volume"] = None return Image(**args) @@ -618,6 +639,8 @@ def unmarshal_ServerMaintenance(data: Any) -> ServerMaintenance: field = data.get("start_date", None) if field is not None: args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None return ServerMaintenance(**args) @@ -637,34 +660,36 @@ def unmarshal_VolumeServer(data: Any) -> VolumeServer: field = data.get("name", None) if field is not None: args["name"] = field + else: + args["name"] = None field = data.get("export_uri", None) if field is not None: args["export_uri"] = field + else: + args["export_uri"] = None field = data.get("organization", None) if field is not None: args["organization"] = field - - field = data.get("size", None) - if field is not None: - args["size"] = field + else: + args["organization"] = None field = data.get("server", None) if field is not None: args["server"] = unmarshal_ServerSummary(field) + else: + args["server"] = None - field = data.get("volume_type", None) - if field is not None: - args["volume_type"] = field - - field = data.get("state", None) + field = data.get("size", None) if field is not None: - args["state"] = field + args["size"] = field + else: + args["size"] = None - field = data.get("project", None) + field = data.get("volume_type", None) if field is not None: - args["project"] = field + args["volume_type"] = field field = data.get("boot", None) if field is not None: @@ -679,12 +704,28 @@ def unmarshal_VolumeServer(data: Any) -> VolumeServer: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None + + field = data.get("state", None) + if field is not None: + args["state"] = field + else: + args["state"] = None + + field = data.get("project", None) + if field is not None: + args["project"] = field + else: + args["project"] = None return VolumeServer(**args) @@ -732,19 +773,13 @@ def unmarshal_Server(data: Any) -> Server: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("dynamic_ip_required", None) if field is not None: args["dynamic_ip_required"] = field - field = data.get("routed_ip_enabled", None) - if field is not None: - args["routed_ip_enabled"] = field - - field = data.get("enable_ipv6", None) - if field is not None: - args["enable_ipv6"] = field - field = data.get("hostname", None) if field is not None: args["hostname"] = field @@ -753,17 +788,35 @@ def unmarshal_Server(data: Any) -> Server: if field is not None: args["protected"] = field + field = data.get("routed_ip_enabled", None) + if field is not None: + args["routed_ip_enabled"] = field + else: + args["routed_ip_enabled"] = None + + field = data.get("enable_ipv6", None) + if field is not None: + args["enable_ipv6"] = field + else: + args["enable_ipv6"] = None + field = data.get("image", None) if field is not None: args["image"] = unmarshal_Image(field) + else: + args["image"] = None field = data.get("private_ip", None) if field is not None: args["private_ip"] = field + else: + args["private_ip"] = None field = data.get("public_ip", None) if field is not None: args["public_ip"] = unmarshal_ServerIp(field) + else: + args["public_ip"] = None field = data.get("public_ips", None) if field is not None: @@ -791,43 +844,53 @@ def unmarshal_Server(data: Any) -> Server: else None ) + field = data.get("maintenances", None) + if field is not None: + args["maintenances"] = ( + [unmarshal_ServerMaintenance(v) for v in field] + if field is not None + else None + ) + + field = data.get("state_detail", None) + if field is not None: + args["state_detail"] = field + + field = data.get("arch", None) + if field is not None: + args["arch"] = field + field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None field = data.get("location", None) if field is not None: args["location"] = unmarshal_ServerLocation(field) + else: + args["location"] = None field = data.get("ipv6", None) if field is not None: args["ipv6"] = unmarshal_ServerIpv6(field) - - field = data.get("bootscript", None) - if field is not None: - args["bootscript"] = unmarshal_Bootscript(field) + else: + args["ipv6"] = None field = data.get("security_group", None) if field is not None: args["security_group"] = unmarshal_SecurityGroupSummary(field) + else: + args["security_group"] = None - field = data.get("maintenances", None) - if field is not None: - args["maintenances"] = ( - [unmarshal_ServerMaintenance(v) for v in field] - if field is not None - else None - ) - - field = data.get("state_detail", None) - if field is not None: - args["state_detail"] = field - - field = data.get("arch", None) + field = data.get("placement_group", None) if field is not None: - args["arch"] = field + args["placement_group"] = unmarshal_PlacementGroup(field) + else: + args["placement_group"] = None field = data.get("private_nics", None) if field is not None: @@ -839,13 +902,44 @@ def unmarshal_Server(data: Any) -> Server: if field is not None: args["zone"] = field - field = data.get("placement_group", None) + field = data.get("end_of_service", None) if field is not None: - args["placement_group"] = unmarshal_PlacementGroup(field) + args["end_of_service"] = field + + field = data.get("admin_password_encryption_ssh_key_id", None) + if field is not None: + args["admin_password_encryption_ssh_key_id"] = field + else: + args["admin_password_encryption_ssh_key_id"] = None + + field = data.get("admin_password_encrypted_value", None) + if field is not None: + args["admin_password_encrypted_value"] = field + else: + args["admin_password_encrypted_value"] = None return Server(**args) +def unmarshal_AttachServerFileSystemResponse( + data: Any, +) -> AttachServerFileSystemResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AttachServerFileSystemResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("server", None) + if field is not None: + args["server"] = unmarshal_Server(field) + else: + args["server"] = None + + return AttachServerFileSystemResponse(**args) + + def unmarshal_AttachServerVolumeResponse(data: Any) -> AttachServerVolumeResponse: if not isinstance(data, dict): raise TypeError( @@ -857,6 +951,8 @@ def unmarshal_AttachServerVolumeResponse(data: Any) -> AttachServerVolumeRespons field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None return AttachServerVolumeResponse(**args) @@ -872,6 +968,8 @@ def unmarshal_CreateImageResponse(data: Any) -> CreateImageResponse: field = data.get("image", None) if field is not None: args["image"] = unmarshal_Image(field) + else: + args["image"] = None return CreateImageResponse(**args) @@ -904,7 +1002,7 @@ def unmarshal_Ip(data: Any) -> Ip: if field is not None: args["project"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -927,10 +1025,14 @@ def unmarshal_Ip(data: Any) -> Ip: field = data.get("reverse", None) if field is not None: args["reverse"] = field + else: + args["reverse"] = None field = data.get("server", None) if field is not None: args["server"] = unmarshal_ServerSummary(field) + else: + args["server"] = None return Ip(**args) @@ -946,6 +1048,8 @@ def unmarshal_CreateIpResponse(data: Any) -> CreateIpResponse: field = data.get("ip", None) if field is not None: args["ip"] = unmarshal_Ip(field) + else: + args["ip"] = None return CreateIpResponse(**args) @@ -961,6 +1065,8 @@ def unmarshal_CreatePlacementGroupResponse(data: Any) -> CreatePlacementGroupRes field = data.get("placement_group", None) if field is not None: args["placement_group"] = unmarshal_PlacementGroup(field) + else: + args["placement_group"] = None return CreatePlacementGroupResponse(**args) @@ -976,6 +1082,8 @@ def unmarshal_CreatePrivateNICResponse(data: Any) -> CreatePrivateNICResponse: field = data.get("private_nic", None) if field is not None: args["private_nic"] = unmarshal_PrivateNIC(field) + else: + args["private_nic"] = None return CreatePrivateNICResponse(**args) @@ -1049,18 +1157,24 @@ def unmarshal_SecurityGroup(data: Any) -> SecurityGroup: field = data.get("organization_default", None) if field is not None: args["organization_default"] = field + else: + args["organization_default"] = None field = data.get("creation_date", None) if field is not None: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None return SecurityGroup(**args) @@ -1076,6 +1190,8 @@ def unmarshal_CreateSecurityGroupResponse(data: Any) -> CreateSecurityGroupRespo field = data.get("security_group", None) if field is not None: args["security_group"] = unmarshal_SecurityGroup(field) + else: + args["security_group"] = None return CreateSecurityGroupResponse(**args) @@ -1123,10 +1239,14 @@ def unmarshal_SecurityGroupRule(data: Any) -> SecurityGroupRule: field = data.get("dest_port_from", None) if field is not None: args["dest_port_from"] = field + else: + args["dest_port_from"] = None field = data.get("dest_port_to", None) if field is not None: args["dest_port_to"] = field + else: + args["dest_port_to"] = None return SecurityGroupRule(**args) @@ -1144,6 +1264,8 @@ def unmarshal_CreateSecurityGroupRuleResponse( field = data.get("rule", None) if field is not None: args["rule"] = unmarshal_SecurityGroupRule(field) + else: + args["rule"] = None return CreateSecurityGroupRuleResponse(**args) @@ -1159,6 +1281,8 @@ def unmarshal_CreateServerResponse(data: Any) -> CreateServerResponse: field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None return CreateServerResponse(**args) @@ -1229,22 +1353,30 @@ def unmarshal_Snapshot(data: Any) -> Snapshot: field = data.get("base_volume", None) if field is not None: args["base_volume"] = unmarshal_SnapshotBaseVolume(field) + else: + args["base_volume"] = None field = data.get("creation_date", None) if field is not None: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None field = data.get("error_reason", None) if field is not None: args["error_reason"] = field + else: + args["error_reason"] = None return Snapshot(**args) @@ -1288,12 +1420,16 @@ def unmarshal_Task(data: Any) -> Task: field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None field = data.get("terminated_at", None) if field is not None: args["terminated_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["terminated_at"] = None return Task(**args) @@ -1309,10 +1445,14 @@ def unmarshal_CreateSnapshotResponse(data: Any) -> CreateSnapshotResponse: field = data.get("snapshot", None) if field is not None: args["snapshot"] = unmarshal_Snapshot(field) + else: + args["snapshot"] = None field = data.get("task", None) if field is not None: args["task"] = unmarshal_Task(field) + else: + args["task"] = None return CreateSnapshotResponse(**args) @@ -1328,14 +1468,18 @@ def unmarshal_CreateVolumeResponse(data: Any) -> CreateVolumeResponse: field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None return CreateVolumeResponse(**args) -def unmarshal_DetachServerVolumeResponse(data: Any) -> DetachServerVolumeResponse: +def unmarshal_DetachServerFileSystemResponse( + data: Any, +) -> DetachServerFileSystemResponse: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'DetachServerVolumeResponse' failed as data isn't a dictionary." + "Unmarshalling the type 'DetachServerFileSystemResponse' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} @@ -1343,38 +1487,44 @@ def unmarshal_DetachServerVolumeResponse(data: Any) -> DetachServerVolumeRespons field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None - return DetachServerVolumeResponse(**args) + return DetachServerFileSystemResponse(**args) -def unmarshal_ExportSnapshotResponse(data: Any) -> ExportSnapshotResponse: +def unmarshal_DetachServerVolumeResponse(data: Any) -> DetachServerVolumeResponse: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'ExportSnapshotResponse' failed as data isn't a dictionary." + "Unmarshalling the type 'DetachServerVolumeResponse' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} - field = data.get("task", None) + field = data.get("server", None) if field is not None: - args["task"] = unmarshal_Task(field) + args["server"] = unmarshal_Server(field) + else: + args["server"] = None - return ExportSnapshotResponse(**args) + return DetachServerVolumeResponse(**args) -def unmarshal_GetBootscriptResponse(data: Any) -> GetBootscriptResponse: +def unmarshal_ExportSnapshotResponse(data: Any) -> ExportSnapshotResponse: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'GetBootscriptResponse' failed as data isn't a dictionary." + "Unmarshalling the type 'ExportSnapshotResponse' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} - field = data.get("bootscript", None) + field = data.get("task", None) if field is not None: - args["bootscript"] = unmarshal_Bootscript(field) + args["task"] = unmarshal_Task(field) + else: + args["task"] = None - return GetBootscriptResponse(**args) + return ExportSnapshotResponse(**args) def unmarshal_Dashboard(data: Any) -> Dashboard: @@ -1425,18 +1575,10 @@ def unmarshal_Dashboard(data: Any) -> Dashboard: if field is not None: args["volumes_l_ssd_count"] = field - field = data.get("volumes_b_ssd_count", None) - if field is not None: - args["volumes_b_ssd_count"] = field - field = data.get("volumes_l_ssd_total_size", None) if field is not None: args["volumes_l_ssd_total_size"] = field - field = data.get("volumes_b_ssd_total_size", None) - if field is not None: - args["volumes_b_ssd_total_size"] = field - field = data.get("private_nics_count", None) if field is not None: args["private_nics_count"] = field @@ -1445,6 +1587,18 @@ def unmarshal_Dashboard(data: Any) -> Dashboard: if field is not None: args["placement_groups_count"] = field + field = data.get("volumes_b_ssd_count", None) + if field is not None: + args["volumes_b_ssd_count"] = field + else: + args["volumes_b_ssd_count"] = None + + field = data.get("volumes_b_ssd_total_size", None) + if field is not None: + args["volumes_b_ssd_total_size"] = field + else: + args["volumes_b_ssd_total_size"] = None + return Dashboard(**args) @@ -1459,6 +1613,8 @@ def unmarshal_GetDashboardResponse(data: Any) -> GetDashboardResponse: field = data.get("dashboard", None) if field is not None: args["dashboard"] = unmarshal_Dashboard(field) + else: + args["dashboard"] = None return GetDashboardResponse(**args) @@ -1474,6 +1630,8 @@ def unmarshal_GetImageResponse(data: Any) -> GetImageResponse: field = data.get("image", None) if field is not None: args["image"] = unmarshal_Image(field) + else: + args["image"] = None return GetImageResponse(**args) @@ -1489,6 +1647,8 @@ def unmarshal_GetIpResponse(data: Any) -> GetIpResponse: field = data.get("ip", None) if field is not None: args["ip"] = unmarshal_Ip(field) + else: + args["ip"] = None return GetIpResponse(**args) @@ -1504,6 +1664,8 @@ def unmarshal_GetPlacementGroupResponse(data: Any) -> GetPlacementGroupResponse: field = data.get("placement_group", None) if field is not None: args["placement_group"] = unmarshal_PlacementGroup(field) + else: + args["placement_group"] = None return GetPlacementGroupResponse(**args) @@ -1563,6 +1725,8 @@ def unmarshal_GetPrivateNICResponse(data: Any) -> GetPrivateNICResponse: field = data.get("private_nic", None) if field is not None: args["private_nic"] = unmarshal_PrivateNIC(field) + else: + args["private_nic"] = None return GetPrivateNICResponse(**args) @@ -1578,6 +1742,8 @@ def unmarshal_GetSecurityGroupResponse(data: Any) -> GetSecurityGroupResponse: field = data.get("security_group", None) if field is not None: args["security_group"] = unmarshal_SecurityGroup(field) + else: + args["security_group"] = None return GetSecurityGroupResponse(**args) @@ -1593,6 +1759,8 @@ def unmarshal_GetSecurityGroupRuleResponse(data: Any) -> GetSecurityGroupRuleRes field = data.get("rule", None) if field is not None: args["rule"] = unmarshal_SecurityGroupRule(field) + else: + args["rule"] = None return GetSecurityGroupRuleResponse(**args) @@ -1608,6 +1776,8 @@ def unmarshal_GetServerResponse(data: Any) -> GetServerResponse: field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None return GetServerResponse(**args) @@ -1668,6 +1838,8 @@ def unmarshal_GetSnapshotResponse(data: Any) -> GetSnapshotResponse: field = data.get("snapshot", None) if field is not None: args["snapshot"] = unmarshal_Snapshot(field) + else: + args["snapshot"] = None return GetSnapshotResponse(**args) @@ -1683,31 +1855,12 @@ def unmarshal_GetVolumeResponse(data: Any) -> GetVolumeResponse: field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None return GetVolumeResponse(**args) -def unmarshal_ListBootscriptsResponse(data: Any) -> ListBootscriptsResponse: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListBootscriptsResponse' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("total_count", None) - if field is not None: - args["total_count"] = field - - field = data.get("bootscripts", None) - if field is not None: - args["bootscripts"] = ( - [unmarshal_Bootscript(v) for v in field] if field is not None else None - ) - - return ListBootscriptsResponse(**args) - - def unmarshal_ListImagesResponse(data: Any) -> ListImagesResponse: if not isinstance(data, dict): raise TypeError( @@ -1900,10 +2053,14 @@ def unmarshal_ServerTypeNetworkInterface(data: Any) -> ServerTypeNetworkInterfac field = data.get("internal_bandwidth", None) if field is not None: args["internal_bandwidth"] = field + else: + args["internal_bandwidth"] = None field = data.get("internet_bandwidth", None) if field is not None: args["internet_bandwidth"] = field + else: + args["internet_bandwidth"] = None return ServerTypeNetworkInterface(**args) @@ -1941,13 +2098,42 @@ def unmarshal_ServerTypeCapabilities(data: Any) -> ServerTypeCapabilities: if field is not None: args["boot_types"] = [BootType(v) for v in field] if field is not None else None + field = data.get("max_file_systems", None) + if field is not None: + args["max_file_systems"] = field + field = data.get("block_storage", None) if field is not None: args["block_storage"] = field + else: + args["block_storage"] = None return ServerTypeCapabilities(**args) +def unmarshal_ServerTypeGPUInfo(data: Any) -> ServerTypeGPUInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerTypeGPUInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("gpu_manufacturer", None) + if field is not None: + args["gpu_manufacturer"] = field + + field = data.get("gpu_name", None) + if field is not None: + args["gpu_name"] = field + + field = data.get("gpu_memory", None) + if field is not None: + args["gpu_memory"] = field + + return ServerTypeGPUInfo(**args) + + def unmarshal_ServerTypeNetwork(data: Any) -> ServerTypeNetwork: if not isinstance(data, dict): raise TypeError( @@ -1971,10 +2157,14 @@ def unmarshal_ServerTypeNetwork(data: Any) -> ServerTypeNetwork: field = data.get("sum_internal_bandwidth", None) if field is not None: args["sum_internal_bandwidth"] = field + else: + args["sum_internal_bandwidth"] = None field = data.get("sum_internet_bandwidth", None) if field is not None: args["sum_internet_bandwidth"] = field + else: + args["sum_internet_bandwidth"] = None return ServerTypeNetwork(**args) @@ -1992,6 +2182,8 @@ def unmarshal_ServerTypeVolumeConstraintsByType( field = data.get("l_ssd", None) if field is not None: args["l_ssd"] = unmarshal_ServerTypeVolumeConstraintSizes(field) + else: + args["l_ssd"] = None return ServerTypeVolumeConstraintsByType(**args) @@ -2007,6 +2199,8 @@ def unmarshal_ServerType(data: Any) -> ServerType: field = data.get("monthly_price", None) if field is not None: args["monthly_price"] = field + else: + args["monthly_price"] = None field = data.get("hourly_price", None) if field is not None: @@ -2028,35 +2222,59 @@ def unmarshal_ServerType(data: Any) -> ServerType: if field is not None: args["arch"] = field - field = data.get("baremetal", None) + field = data.get("end_of_service", None) if field is not None: - args["baremetal"] = field + args["end_of_service"] = field field = data.get("per_volume_constraint", None) if field is not None: args["per_volume_constraint"] = unmarshal_ServerTypeVolumeConstraintsByType( field ) + else: + args["per_volume_constraint"] = None field = data.get("volumes_constraint", None) if field is not None: args["volumes_constraint"] = unmarshal_ServerTypeVolumeConstraintSizes(field) + else: + args["volumes_constraint"] = None field = data.get("gpu", None) if field is not None: args["gpu"] = field + else: + args["gpu"] = None + + field = data.get("gpu_info", None) + if field is not None: + args["gpu_info"] = unmarshal_ServerTypeGPUInfo(field) + else: + args["gpu_info"] = None field = data.get("network", None) if field is not None: args["network"] = unmarshal_ServerTypeNetwork(field) + else: + args["network"] = None field = data.get("capabilities", None) if field is not None: args["capabilities"] = unmarshal_ServerTypeCapabilities(field) + else: + args["capabilities"] = None field = data.get("scratch_storage_max_size", None) if field is not None: args["scratch_storage_max_size"] = field + else: + args["scratch_storage_max_size"] = None + + field = data.get("block_bandwidth", None) + if field is not None: + args["block_bandwidth"] = field + else: + args["block_bandwidth"] = None return ServerType(**args) @@ -2175,10 +2393,14 @@ def unmarshal_VolumeType(data: Any) -> VolumeType: field = data.get("capabilities", None) if field is not None: args["capabilities"] = unmarshal_VolumeTypeCapabilities(field) + else: + args["capabilities"] = None field = data.get("constraints", None) if field is not None: args["constraints"] = unmarshal_VolumeTypeConstraints(field) + else: + args["constraints"] = None return VolumeType(**args) @@ -2227,6 +2449,8 @@ def unmarshal_MigrationPlan(data: Any) -> MigrationPlan: field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None return MigrationPlan(**args) @@ -2242,10 +2466,27 @@ def unmarshal_ServerActionResponse(data: Any) -> ServerActionResponse: field = data.get("task", None) if field is not None: args["task"] = unmarshal_Task(field) + else: + args["task"] = None return ServerActionResponse(**args) +def unmarshal_ServerCompatibleTypes(data: Any) -> ServerCompatibleTypes: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerCompatibleTypes' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("compatible_types", None) + if field is not None: + args["compatible_types"] = field + + return ServerCompatibleTypes(**args) + + def unmarshal_SetPlacementGroupResponse(data: Any) -> SetPlacementGroupResponse: if not isinstance(data, dict): raise TypeError( @@ -2257,6 +2498,8 @@ def unmarshal_SetPlacementGroupResponse(data: Any) -> SetPlacementGroupResponse: field = data.get("placement_group", None) if field is not None: args["placement_group"] = unmarshal_PlacementGroup(field) + else: + args["placement_group"] = None return SetPlacementGroupResponse(**args) @@ -2312,6 +2555,8 @@ def unmarshal_UpdateImageResponse(data: Any) -> UpdateImageResponse: field = data.get("image", None) if field is not None: args["image"] = unmarshal_Image(field) + else: + args["image"] = None return UpdateImageResponse(**args) @@ -2327,6 +2572,8 @@ def unmarshal_UpdateIpResponse(data: Any) -> UpdateIpResponse: field = data.get("ip", None) if field is not None: args["ip"] = unmarshal_Ip(field) + else: + args["ip"] = None return UpdateIpResponse(**args) @@ -2342,6 +2589,8 @@ def unmarshal_UpdatePlacementGroupResponse(data: Any) -> UpdatePlacementGroupRes field = data.get("placement_group", None) if field is not None: args["placement_group"] = unmarshal_PlacementGroup(field) + else: + args["placement_group"] = None return UpdatePlacementGroupResponse(**args) @@ -2378,6 +2627,8 @@ def unmarshal_UpdateSecurityGroupResponse(data: Any) -> UpdateSecurityGroupRespo field = data.get("security_group", None) if field is not None: args["security_group"] = unmarshal_SecurityGroup(field) + else: + args["security_group"] = None return UpdateSecurityGroupResponse(**args) @@ -2395,6 +2646,8 @@ def unmarshal_UpdateSecurityGroupRuleResponse( field = data.get("rule", None) if field is not None: args["rule"] = unmarshal_SecurityGroupRule(field) + else: + args["rule"] = None return UpdateSecurityGroupRuleResponse(**args) @@ -2410,6 +2663,8 @@ def unmarshal_UpdateServerResponse(data: Any) -> UpdateServerResponse: field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None return UpdateServerResponse(**args) @@ -2425,6 +2680,8 @@ def unmarshal_UpdateSnapshotResponse(data: Any) -> UpdateSnapshotResponse: field = data.get("snapshot", None) if field is not None: args["snapshot"] = unmarshal_Snapshot(field) + else: + args["snapshot"] = None return UpdateSnapshotResponse(**args) @@ -2440,6 +2697,8 @@ def unmarshal_UpdateVolumeResponse(data: Any) -> UpdateVolumeResponse: field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None return UpdateVolumeResponse(**args) @@ -2455,6 +2714,8 @@ def unmarshal__SetImageResponse(data: Any) -> _SetImageResponse: field = data.get("image", None) if field is not None: args["image"] = unmarshal_Image(field) + else: + args["image"] = None return _SetImageResponse(**args) @@ -2470,6 +2731,8 @@ def unmarshal__SetSecurityGroupResponse(data: Any) -> _SetSecurityGroupResponse: field = data.get("security_group", None) if field is not None: args["security_group"] = unmarshal_SecurityGroup(field) + else: + args["security_group"] = None return _SetSecurityGroupResponse(**args) @@ -2485,6 +2748,8 @@ def unmarshal__SetSecurityGroupRuleResponse(data: Any) -> _SetSecurityGroupRuleR field = data.get("rule", None) if field is not None: args["rule"] = unmarshal_SecurityGroupRule(field) + else: + args["rule"] = None return _SetSecurityGroupRuleResponse(**args) @@ -2500,6 +2765,8 @@ def unmarshal__SetServerResponse(data: Any) -> _SetServerResponse: field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None return _SetServerResponse(**args) @@ -2515,6 +2782,8 @@ def unmarshal__SetSnapshotResponse(data: Any) -> _SetSnapshotResponse: field = data.get("snapshot", None) if field is not None: args["snapshot"] = unmarshal_Snapshot(field) + else: + args["snapshot"] = None return _SetSnapshotResponse(**args) @@ -2539,6 +2808,18 @@ def marshal_ApplyBlockMigrationRequest( return output +def marshal_AttachServerFileSystemRequest( + request: AttachServerFileSystemRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.filesystem_id is not None: + output["filesystem_id"] = request.filesystem_id + + return output + + def marshal_AttachServerVolumeRequest( request: AttachServerVolumeRequest, defaults: ProfileDefaults, @@ -2557,6 +2838,20 @@ def marshal_AttachServerVolumeRequest( return output +def marshal_CheckBlockMigrationOrganizationQuotasRequest( + request: CheckBlockMigrationOrganizationQuotasRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.organization is not None: + output["organization"] = ( + request.organization or defaults.default_organization_id + ) + + return output + + def marshal_VolumeTemplate( request: VolumeTemplate, defaults: ProfileDefaults, @@ -2621,9 +2916,6 @@ def marshal_CreateImageRequest( if request.name is not None: output["name"] = request.name - if request.default_bootscript is not None: - output["default_bootscript"] = request.default_bootscript - if request.extra_volumes is not None: output["extra_volumes"] = { key: marshal_VolumeTemplate(value, defaults) @@ -2721,6 +3013,9 @@ def marshal_CreatePrivateNICRequest( if request.ip_ids is not None: output["ip_ids"] = request.ip_ids + if request.ipam_ip_ids is not None: + output["ipam_ip_ids"] = request.ipam_ip_ids + return output @@ -2865,9 +3160,6 @@ def marshal_CreateServerRequest( if request.commercial_type is not None: output["commercial_type"] = request.commercial_type - if request.image is not None: - output["image"] = request.image - if request.name is not None: output["name"] = request.name @@ -2877,8 +3169,8 @@ def marshal_CreateServerRequest( if request.routed_ip_enabled is not None: output["routed_ip_enabled"] = request.routed_ip_enabled - if request.enable_ipv6 is not None: - output["enable_ipv6"] = request.enable_ipv6 + if request.image is not None: + output["image"] = request.image if request.volumes is not None: output["volumes"] = { @@ -2886,6 +3178,12 @@ def marshal_CreateServerRequest( for key, value in request.volumes.items() } + if request.enable_ipv6 is not None: + output["enable_ipv6"] = request.enable_ipv6 + + if request.protected is not None: + output["protected"] = request.protected + if request.public_ip is not None: output["public_ip"] = request.public_ip @@ -2895,9 +3193,6 @@ def marshal_CreateServerRequest( if request.boot_type is not None: output["boot_type"] = str(request.boot_type) - if request.bootscript is not None: - output["bootscript"] = request.bootscript - if request.tags is not None: output["tags"] = request.tags @@ -2907,6 +3202,11 @@ def marshal_CreateServerRequest( if request.placement_group is not None: output["placement_group"] = request.placement_group + if request.admin_password_encryption_ssh_key_id is not None: + output["admin_password_encryption_ssh_key_id"] = ( + request.admin_password_encryption_ssh_key_id + ) + return output @@ -2994,6 +3294,18 @@ def marshal_CreateVolumeRequest( return output +def marshal_DetachServerFileSystemRequest( + request: DetachServerFileSystemRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.filesystem_id is not None: + output["filesystem_id"] = request.filesystem_id + + return output + + def marshal_DetachServerVolumeRequest( request: DetachServerVolumeRequest, defaults: ProfileDefaults, @@ -3068,6 +3380,9 @@ def marshal_ServerActionRequest( for key, value in request.volumes.items() } + if request.disable_ipv6 is not None: + output["disable_ipv6"] = request.disable_ipv6 + return output @@ -3092,6 +3407,9 @@ def marshal_Bootscript( ) -> Dict[str, Any]: output: Dict[str, Any] = {} + if request.architecture is not None: + output["architecture"] = str(request.architecture) + if request.bootcmdargs is not None: output["bootcmdargs"] = request.bootcmdargs @@ -3115,17 +3433,14 @@ def marshal_Bootscript( request.organization or defaults.default_organization_id ) - if request.project is not None: - output["project"] = request.project or defaults.default_project_id - if request.public is not None: output["public"] = request.public if request.title is not None: output["title"] = request.title - if request.arch is not None: - output["arch"] = str(request.arch) + if request.project is not None: + output["project"] = request.project or defaults.default_project_id if request.zone is not None: output["zone"] = request.zone or defaults.default_zone @@ -3163,10 +3478,10 @@ def marshal_Volume( output["export_uri"] = request.export_uri if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.modification_date is not None: - output["modification_date"] = request.modification_date + output["modification_date"] = request.modification_date.isoformat() if request.tags is not None: output["tags"] = request.tags @@ -3178,7 +3493,7 @@ def marshal_Volume( output["zone"] = request.zone or defaults.default_zone if request.server is not None: - output["server"] = (marshal_ServerSummary(request.server, defaults),) + output["server"] = marshal_ServerSummary(request.server, defaults) return output @@ -3217,10 +3532,10 @@ def marshal_SetImageRequest( output["arch"] = str(request.arch) if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.modification_date is not None: - output["modification_date"] = request.modification_date + output["modification_date"] = request.modification_date.isoformat() if request.from_server is not None: output["from_server"] = request.from_server @@ -3229,8 +3544,8 @@ def marshal_SetImageRequest( output["public"] = request.public if request.default_bootscript is not None: - output["default_bootscript"] = ( - marshal_Bootscript(request.default_bootscript, defaults), + output["default_bootscript"] = marshal_Bootscript( + request.default_bootscript, defaults ) if request.extra_volumes is not None: @@ -3245,7 +3560,7 @@ def marshal_SetImageRequest( ) if request.root_volume is not None: - output["root_volume"] = (marshal_VolumeSummary(request.root_volume, defaults),) + output["root_volume"] = marshal_VolumeSummary(request.root_volume, defaults) if request.state is not None: output["state"] = str(request.state) @@ -3561,9 +3876,6 @@ def marshal_UpdateServerRequest( for key, value in request.volumes.items() } - if request.bootscript is not None: - output["bootscript"] = request.bootscript - if request.dynamic_ip_required is not None: output["dynamic_ip_required"] = request.dynamic_ip_required @@ -3580,8 +3892,8 @@ def marshal_UpdateServerRequest( output["protected"] = request.protected if request.security_group is not None: - output["security_group"] = ( - marshal_SecurityGroupTemplate(request.security_group, defaults), + output["security_group"] = marshal_SecurityGroupTemplate( + request.security_group, defaults ) if request.placement_group is not None: @@ -3593,6 +3905,11 @@ def marshal_UpdateServerRequest( if request.commercial_type is not None: output["commercial_type"] = request.commercial_type + if request.admin_password_encryption_ssh_key_id is not None: + output["admin_password_encryption_ssh_key_id"] = ( + request.admin_password_encryption_ssh_key_id + ) + return output @@ -3648,10 +3965,10 @@ def marshal__SetSecurityGroupRequest( output["tags"] = request.tags if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.modification_date is not None: - output["modification_date"] = request.modification_date + output["modification_date"] = request.modification_date.isoformat() if request.project_default is not None: output["project_default"] = request.project_default @@ -3750,14 +4067,14 @@ def marshal_Image( ) if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.modification_date is not None: - output["modification_date"] = request.modification_date + output["modification_date"] = request.modification_date.isoformat() if request.default_bootscript is not None: - output["default_bootscript"] = ( - marshal_Bootscript(request.default_bootscript, defaults), + output["default_bootscript"] = marshal_Bootscript( + request.default_bootscript, defaults ) if request.public is not None: @@ -3776,7 +4093,7 @@ def marshal_Image( output["zone"] = request.zone or defaults.default_zone if request.root_volume is not None: - output["root_volume"] = (marshal_VolumeSummary(request.root_volume, defaults),) + output["root_volume"] = marshal_VolumeSummary(request.root_volume, defaults) return output @@ -3952,7 +4269,7 @@ def marshal_ServerMaintenance( output["reason"] = request.reason if request.start_date is not None: - output["start_date"] = request.start_date + output["start_date"] = request.start_date.isoformat() return output @@ -3969,19 +4286,22 @@ def marshal__SetServerRequest( if request.commercial_type is not None: output["commercial_type"] = request.commercial_type + if request.organization is not None: + output["organization"] = ( + request.organization or defaults.default_organization_id + ) + if request.dynamic_ip_required is not None: output["dynamic_ip_required"] = request.dynamic_ip_required - if request.enable_ipv6 is not None: - output["enable_ipv6"] = request.enable_ipv6 - if request.hostname is not None: output["hostname"] = request.hostname - if request.organization is not None: - output["organization"] = ( - request.organization or defaults.default_organization_id - ) + if request.protected is not None: + output["protected"] = request.protected + + if request.state_detail is not None: + output["state_detail"] = request.state_detail if request.project is not None: output["project"] = request.project or defaults.default_project_id @@ -3993,22 +4313,22 @@ def marshal__SetServerRequest( output["tags"] = request.tags if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.routed_ip_enabled is not None: output["routed_ip_enabled"] = request.routed_ip_enabled - if request.image is not None: - output["image"] = (marshal_Image(request.image, defaults),) + if request.enable_ipv6 is not None: + output["enable_ipv6"] = request.enable_ipv6 - if request.protected is not None: - output["protected"] = request.protected + if request.image is not None: + output["image"] = marshal_Image(request.image, defaults) if request.private_ip is not None: output["private_ip"] = request.private_ip if request.public_ip is not None: - output["public_ip"] = (marshal_ServerIp(request.public_ip, defaults),) + output["public_ip"] = marshal_ServerIp(request.public_ip, defaults) if request.public_ips is not None: output["public_ips"] = [ @@ -4016,22 +4336,16 @@ def marshal__SetServerRequest( ] if request.modification_date is not None: - output["modification_date"] = request.modification_date - - if request.state_detail is not None: - output["state_detail"] = request.state_detail + output["modification_date"] = request.modification_date.isoformat() if request.state is not None: output["state"] = str(request.state) if request.location is not None: - output["location"] = (marshal_ServerLocation(request.location, defaults),) + output["location"] = marshal_ServerLocation(request.location, defaults) if request.ipv6 is not None: - output["ipv6"] = (marshal_ServerIpv6(request.ipv6, defaults),) - - if request.bootscript is not None: - output["bootscript"] = (marshal_Bootscript(request.bootscript, defaults),) + output["ipv6"] = marshal_ServerIpv6(request.ipv6, defaults) if request.boot_type is not None: output["boot_type"] = str(request.boot_type) @@ -4043,8 +4357,8 @@ def marshal__SetServerRequest( } if request.security_group is not None: - output["security_group"] = ( - marshal_SecurityGroupSummary(request.security_group, defaults), + output["security_group"] = marshal_SecurityGroupSummary( + request.security_group, defaults ) if request.maintenances is not None: @@ -4056,8 +4370,8 @@ def marshal__SetServerRequest( output["arch"] = str(request.arch) if request.placement_group is not None: - output["placement_group"] = ( - marshal_PlacementGroup(request.placement_group, defaults), + output["placement_group"] = marshal_PlacementGroup( + request.placement_group, defaults ) if request.private_nics is not None: @@ -4065,6 +4379,11 @@ def marshal__SetServerRequest( marshal_PrivateNIC(item, defaults) for item in request.private_nics ] + if request.admin_password_encryption_ssh_key_id is not None: + output["admin_password_encryption_ssh_key_id"] = ( + request.admin_password_encryption_ssh_key_id + ) + return output @@ -4110,15 +4429,15 @@ def marshal__SetSnapshotRequest( output["state"] = str(request.state) if request.base_volume is not None: - output["base_volume"] = ( - marshal_SnapshotBaseVolume(request.base_volume, defaults), + output["base_volume"] = marshal_SnapshotBaseVolume( + request.base_volume, defaults ) if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.modification_date is not None: - output["modification_date"] = request.modification_date + output["modification_date"] = request.modification_date.isoformat() if request.project is not None: output["project"] = request.project or defaults.default_project_id diff --git a/scaleway-async/scaleway_async/instance/v1/types.py b/scaleway-async/scaleway_async/instance/v1/types.py index ce054860..fb8865a7 100644 --- a/scaleway-async/scaleway_async/instance/v1/types.py +++ b/scaleway-async/scaleway_async/instance/v1/types.py @@ -8,7 +8,7 @@ from typing import Dict, List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -66,7 +66,6 @@ def __str__(self) -> str: class IpType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_IPTYPE = "unknown_iptype" - NAT = "nat" ROUTED_IPV4 = "routed_ipv4" ROUTED_IPV6 = "routed_ipv6" @@ -308,64 +307,31 @@ class ServerSummary: @dataclass class Bootscript: + architecture: Arch + bootcmdargs: str - """ - Bootscript arguments. - """ default: bool - """ - Display if the bootscript is the default bootscript (if no other boot option is configured). - """ dtb: str - """ - Provide information regarding a Device Tree Binary (DTB) for use with C1 servers. - """ id: str - """ - Bootscript ID. - """ initrd: str - """ - Initrd (initial ramdisk) configuration. - """ kernel: str - """ - Instance kernel version. - """ organization: str - """ - Bootscript Organization ID. - """ - - project: str - """ - Bootscript Project ID. - """ public: bool - """ - Provide information if the bootscript is public. - """ title: str - """ - Bootscript title. - """ - arch: Arch - """ - Bootscript architecture. - """ + project: str - zone: Zone + zone: ScwZone """ - Zone in which the bootscript is located. + Zone to target. If none is passed will use default zone from the config. """ @@ -426,7 +392,7 @@ class Volume: Volume state. """ - zone: Zone + zone: ScwZone """ Zone in which the volume is located. """ @@ -502,7 +468,7 @@ class Image: tags: List[str] - zone: Zone + zone: ScwZone """ Zone to target. If none is passed will use default zone from the config. """ @@ -549,10 +515,11 @@ class PlacementGroup: policy_respected: bool """ - Returns true if the policy is respected, false otherwise. + In the server endpoints the value is always false as it is deprecated. +In the placement group endpoints the value is correct. """ - zone: Zone + zone: ScwZone """ Zone in which the placement group is located. """ @@ -693,25 +660,21 @@ class ServerMaintenance: class VolumeServer: id: str - name: str - - export_uri: str + name: Optional[str] - organization: str + export_uri: Optional[str] - size: int + organization: Optional[str] server: Optional[ServerSummary] - volume_type: VolumeServerVolumeType - - state: VolumeServerState + size: Optional[int] - project: str + volume_type: VolumeServerVolumeType boot: bool - zone: Zone + zone: ScwZone """ Zone to target. If none is passed will use default zone from the config. """ @@ -720,6 +683,10 @@ class VolumeServer: modification_date: Optional[datetime] + state: Optional[VolumeServerState] + + project: Optional[str] + @dataclass class SnapshotBaseVolume: @@ -741,12 +708,35 @@ class ServerTypeCapabilities: List of supported boot types. """ + max_file_systems: int + """ + Max number of SFS (Scaleway File Systems) that can be attached to the Instance. + """ + block_storage: Optional[bool] """ Defines whether the Instance supports block storage. """ +@dataclass +class ServerTypeGPUInfo: + gpu_manufacturer: str + """ + GPU manufacturer. + """ + + gpu_name: str + """ + GPU model name. + """ + + gpu_memory: int + """ + RAM of a single GPU, in bytes. + """ + + @dataclass class ServerTypeNetwork: interfaces: List[ServerTypeNetworkInterface] @@ -837,114 +827,114 @@ class Server: True if a dynamic IPv4 is required. """ - routed_ip_enabled: bool + hostname: str """ - True to configure the instance so it uses the new routed IP mode. + Instance host name. """ - enable_ipv6: bool + protected: bool """ - True if IPv6 is enabled. + Defines whether the Instance protection option is activated. """ - hostname: str + public_ips: List[ServerIp] """ - Instance host name. + Information about all the public IPs attached to the server. """ - protected: bool + mac_address: str """ - Defines whether the Instance protection option is activated. + The server's MAC address. """ - image: Optional[Image] + state: ServerState """ - Information about the Instance image. + Instance state. """ - private_ip: Optional[str] + boot_type: BootType """ - Private IP address of the Instance. + Instance boot type. """ - public_ip: Optional[ServerIp] + volumes: Dict[str, VolumeServer] """ - Information about the public IP. + Instance volumes. """ - public_ips: List[ServerIp] + maintenances: List[ServerMaintenance] """ - Information about all the public IPs attached to the server. + Instance planned maintenance. """ - mac_address: str + state_detail: str """ - The server's MAC address. + Detailed information about the Instance state. """ - state: ServerState + arch: Arch """ - Instance state. + Instance architecture. """ - boot_type: BootType + private_nics: List[PrivateNIC] """ - Instance boot type. + Instance private NICs. """ - volumes: Dict[str, VolumeServer] + zone: ScwZone """ - Instance volumes. + Zone in which the Instance is located. """ - modification_date: Optional[datetime] + end_of_service: bool """ - Instance modification date. + True if the Instance type has reached end of service. """ - location: Optional[ServerLocation] + routed_ip_enabled: Optional[bool] """ - Instance location. + True to configure the instance so it uses the routed IP mode. Use of `routed_ip_enabled` as `False` is deprecated. """ - ipv6: Optional[ServerIpv6] + enable_ipv6: Optional[bool] """ - Instance IPv6 address. + True if IPv6 is enabled (deprecated and always `False` when `routed_ip_enabled` is `True`). """ - bootscript: Optional[Bootscript] + image: Optional[Image] """ - Instance bootscript. + Information about the Instance image. """ - security_group: Optional[SecurityGroupSummary] + private_ip: Optional[str] """ - Instance security group. + Private IP address of the Instance (deprecated and always `null` when `routed_ip_enabled` is `True`). """ - maintenances: List[ServerMaintenance] + public_ip: Optional[ServerIp] """ - Instance planned maintenance. + Information about the public IP (deprecated in favor of `public_ips`). """ - state_detail: str + modification_date: Optional[datetime] """ - Detailed information about the Instance state. + Instance modification date. """ - arch: Arch + location: Optional[ServerLocation] """ - Instance architecture. + Instance location. """ - private_nics: List[PrivateNIC] + ipv6: Optional[ServerIpv6] """ - Instance private NICs. + Instance IPv6 address (deprecated when `routed_ip_enabled` is `True`). """ - zone: Zone + security_group: Optional[SecurityGroupSummary] """ - Zone in which the Instance is located. + Instance security group. """ placement_group: Optional[PlacementGroup] @@ -952,6 +942,16 @@ class Server: Instance placement group. """ + admin_password_encryption_ssh_key_id: Optional[str] + """ + The public_key value of this key is used to encrypt the admin password. When set to an empty string, reset this value and admin_password_encrypted_value to an empty string so a new password may be generated. + """ + + admin_password_encrypted_value: Optional[str] + """ + This value is reset when admin_password_encryption_ssh_key_id is set to an empty string. + """ + @dataclass class VolumeTemplate: @@ -1000,7 +1000,7 @@ class Ip: ipam_id: str - zone: Zone + zone: ScwZone """ Zone to target. If none is passed will use default zone from the config. """ @@ -1077,7 +1077,7 @@ class SecurityGroup: Security group state. """ - zone: Zone + zone: ScwZone """ Zone in which the security group is located. """ @@ -1114,7 +1114,7 @@ class SecurityGroupRule: editable: bool - zone: Zone + zone: ScwZone """ Zone to target. If none is passed will use default zone from the config. """ @@ -1209,7 +1209,7 @@ class Snapshot: Snapshot state. """ - zone: Zone + zone: ScwZone """ Snapshot zone. """ @@ -1261,9 +1261,9 @@ class Task: href_result: str - zone: Zone + zone: ScwZone """ - Zone in which the task is excecuted. + Zone in which the task is executed. """ started_at: Optional[datetime] @@ -1299,16 +1299,16 @@ class Dashboard: volumes_l_ssd_count: int - volumes_b_ssd_count: int - volumes_l_ssd_total_size: int - volumes_b_ssd_total_size: int - private_nics_count: int placement_groups_count: int + volumes_b_ssd_count: Optional[int] + + volumes_b_ssd_total_size: Optional[int] + @dataclass class PlacementGroupServer: @@ -1365,9 +1365,9 @@ class ServerType: CPU architecture. """ - baremetal: bool + end_of_service: bool """ - True if it is a baremetal Instance. + True if this Instance type has reached end of service. """ per_volume_constraint: Optional[ServerTypeVolumeConstraintsByType] @@ -1385,6 +1385,11 @@ class ServerType: Number of GPU. """ + gpu_info: Optional[ServerTypeGPUInfo] + """ + GPU information. + """ + network: Optional[ServerTypeNetwork] """ Network available for the Instance. @@ -1400,6 +1405,11 @@ class ServerType: Maximum available scratch storage. """ + block_bandwidth: Optional[int] + """ + The maximum bandwidth allocated to block storage access (in bytes per second). + """ + @dataclass class VolumeType: @@ -1466,7 +1476,7 @@ class SetSecurityGroupRulesRequestRule: Indicates if this rule is editable. Rules with the value false will be ignored. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone of the rule. This field is ignored. """ @@ -1491,10 +1501,10 @@ class SecurityGroupTemplate: class ApplyBlockMigrationRequest: validation_key: str """ - A value to be retrieved from a call to PlanBlockMigration, to confirm that the volume and/or snapshots specified in said plan should be migrated. + A value to be retrieved from a call to the [Get a volume or snapshot's migration plan](#path-volumes-get-a-volume-or-snapshots-migration-plan) endpoint, to confirm that the volume and/or snapshots specified in said plan should be migrated. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1504,13 +1514,30 @@ class ApplyBlockMigrationRequest: snapshot_id: Optional[str] +@dataclass +class AttachServerFileSystemRequest: + server_id: str + + filesystem_id: str + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class AttachServerFileSystemResponse: + server: Optional[Server] + + @dataclass class AttachServerVolumeRequest: server_id: str volume_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1525,6 +1552,16 @@ class AttachServerVolumeResponse: server: Optional[Server] +@dataclass +class CheckBlockMigrationOrganizationQuotasRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + organization: Optional[str] + + @dataclass class CreateImageRequest: root_volume: str @@ -1537,7 +1574,7 @@ class CreateImageRequest: Architecture of the image. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1547,11 +1584,6 @@ class CreateImageRequest: Name of the image. """ - default_bootscript: Optional[str] - """ - Default bootscript of the image. - """ - extra_volumes: Optional[Dict[str, VolumeTemplate]] """ Additional volumes of the image. @@ -1579,7 +1611,7 @@ class CreateImageResponse: @dataclass class CreateIpRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1596,7 +1628,7 @@ class CreateIpRequest: type_: Optional[IpType] """ - IP type to reserve (either 'nat', 'routed_ipv4' or 'routed_ipv6'). + IP type to reserve (either 'routed_ipv4' or 'routed_ipv6'). """ project: Optional[str] @@ -1611,7 +1643,7 @@ class CreateIpResponse: @dataclass class CreatePlacementGroupRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1658,7 +1690,7 @@ class CreatePrivateNICRequest: UUID of the private network where the private NIC will be attached. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1673,6 +1705,11 @@ class CreatePrivateNICRequest: Ip_ids defined from IPAM. """ + ipam_ip_ids: Optional[List[str]] + """ + UUID of IPAM ips, to be attached to the instance in the requested private network. + """ + @dataclass class CreatePrivateNICResponse: @@ -1691,7 +1728,7 @@ class CreateSecurityGroupRequest: Whether the security group is stateful or not. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1760,7 +1797,7 @@ class CreateSecurityGroupRuleRequest: Indicates if this rule is editable (will be ignored). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1783,7 +1820,7 @@ class CreateSecurityGroupRuleResponse: @dataclass class CreateServerRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1793,11 +1830,6 @@ class CreateServerRequest: Define the Instance commercial type (i.e. GP1-S). """ - image: str - """ - Instance image ID or label. - """ - name: Optional[str] """ Instance name. @@ -1813,9 +1845,9 @@ class CreateServerRequest: If true, configure the Instance so it uses the new routed IP mode. """ - enable_ipv6: bool + image: Optional[str] """ - True if IPv6 is enabled on the server. + Instance image ID or label. """ volumes: Optional[Dict[str, VolumeServerTemplate]] @@ -1823,6 +1855,16 @@ class CreateServerRequest: Volumes attached to the server. """ + enable_ipv6: Optional[bool] + """ + True if IPv6 is enabled on the server (deprecated and always `False` when `routed_ip_enabled` is `True`). + """ + + protected: bool + """ + True to activate server protection option. + """ + public_ip: Optional[str] """ ID of the reserved IP to attach to the Instance. @@ -1838,11 +1880,6 @@ class CreateServerRequest: Boot type to use. """ - bootscript: Optional[str] - """ - Bootscript ID to use when `boot_type` is set to `bootscript`. - """ - tags: Optional[List[str]] """ Instance tags. @@ -1858,6 +1895,11 @@ class CreateServerRequest: Placement group ID if Instance must be part of a placement group. """ + admin_password_encryption_ssh_key_id: Optional[str] + """ + The public_key value of this key is used to encrypt the admin password. + """ + project: Optional[str] organization: Optional[str] @@ -1870,7 +1912,7 @@ class CreateServerResponse: @dataclass class CreateSnapshotRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1925,7 +1967,7 @@ class CreateSnapshotResponse: @dataclass class CreateVolumeRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1966,7 +2008,7 @@ class DeleteImageRequest: UUID of the image you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1979,7 +2021,7 @@ class DeleteIpRequest: ID or address of the IP to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1992,7 +2034,7 @@ class DeletePlacementGroupRequest: UUID of the placement group you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2010,7 +2052,7 @@ class DeletePrivateNICRequest: Private NIC unique ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2023,7 +2065,7 @@ class DeleteSecurityGroupRequest: UUID of the security group you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2035,7 +2077,7 @@ class DeleteSecurityGroupRuleRequest: security_group_rule_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2045,7 +2087,7 @@ class DeleteSecurityGroupRuleRequest: class DeleteServerRequest: server_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2063,7 +2105,7 @@ class DeleteServerUserDataRequest: Key of the user data to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2076,7 +2118,7 @@ class DeleteSnapshotRequest: UUID of the snapshot you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2089,19 +2131,36 @@ class DeleteVolumeRequest: UUID of the volume you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DetachServerFileSystemRequest: + server_id: str + + filesystem_id: str + + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ +@dataclass +class DetachServerFileSystemResponse: + server: Optional[Server] + + @dataclass class DetachServerVolumeRequest: server_id: str volume_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2116,12 +2175,12 @@ class DetachServerVolumeResponse: class ExportSnapshotRequest: bucket: str """ - S3 bucket name. + Object Storage bucket name. """ key: str """ - S3 object key. + Object key. """ snapshot_id: str @@ -2129,7 +2188,7 @@ class ExportSnapshotRequest: Snapshot ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2140,24 +2199,9 @@ class ExportSnapshotResponse: task: Optional[Task] -@dataclass -class GetBootscriptRequest: - bootscript_id: str - - zone: Optional[Zone] - """ - Zone to target. If none is passed will use default zone from the config. - """ - - -@dataclass -class GetBootscriptResponse: - bootscript: Optional[Bootscript] - - @dataclass class GetDashboardRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2179,7 +2223,7 @@ class GetImageRequest: UUID of the image you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2197,7 +2241,7 @@ class GetIpRequest: IP ID or address to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2215,7 +2259,7 @@ class GetPlacementGroupRequest: UUID of the placement group you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2233,7 +2277,7 @@ class GetPlacementGroupServersRequest: UUID of the placement group you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2259,7 +2303,7 @@ class GetPrivateNICRequest: Private NIC unique ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2277,7 +2321,7 @@ class GetSecurityGroupRequest: UUID of the security group you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2294,7 +2338,7 @@ class GetSecurityGroupRuleRequest: security_group_rule_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2305,6 +2349,19 @@ class GetSecurityGroupRuleResponse: rule: Optional[SecurityGroupRule] +@dataclass +class GetServerCompatibleTypesRequest: + server_id: str + """ + UUID of the Instance you want to get. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class GetServerRequest: server_id: str @@ -2312,7 +2369,7 @@ class GetServerRequest: UUID of the Instance you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2325,7 +2382,7 @@ class GetServerResponse: @dataclass class GetServerTypesAvailabilityRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2358,7 +2415,7 @@ class GetSnapshotRequest: UUID of the snapshot you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2376,7 +2433,7 @@ class GetVolumeRequest: UUID of the volume you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2387,42 +2444,9 @@ class GetVolumeResponse: volume: Optional[Volume] -@dataclass -class ListBootscriptsRequest: - zone: Optional[Zone] - """ - Zone to target. If none is passed will use default zone from the config. - """ - - arch: Optional[str] - - title: Optional[str] - - default: Optional[bool] - - public: Optional[bool] - - per_page: Optional[int] - - page: Optional[int] - - -@dataclass -class ListBootscriptsResponse: - total_count: int - """ - Total number of bootscripts. - """ - - bootscripts: List[Bootscript] - """ - List of bootscripts. - """ - - @dataclass class ListDefaultSecurityGroupRulesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2430,7 +2454,7 @@ class ListDefaultSecurityGroupRulesRequest: @dataclass class ListImagesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2467,7 +2491,7 @@ class ListImagesResponse: @dataclass class ListIpsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2504,7 +2528,7 @@ class ListIpsRequest: type_: Optional[str] """ - Filter on the IP Mobility IP type (whose value should be either 'nat', 'routed_ipv4' or 'routed_ipv6'). + Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). """ @@ -2523,7 +2547,7 @@ class ListIpsResponse: @dataclass class ListPlacementGroupsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2579,7 +2603,7 @@ class ListPrivateNICsRequest: Instance to which the private NIC is attached. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2614,7 +2638,7 @@ class ListSecurityGroupRulesRequest: UUID of the security group. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2645,7 +2669,7 @@ class ListSecurityGroupRulesResponse: @dataclass class ListSecurityGroupsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2703,7 +2727,7 @@ class ListSecurityGroupsResponse: class ListServerActionsRequest: server_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2721,7 +2745,7 @@ class ListServerUserDataRequest: UUID of the Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2734,7 +2758,7 @@ class ListServerUserDataResponse: @dataclass class ListServersRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2774,6 +2798,11 @@ class ListServersRequest: List Instances that are not attached to a public IP. """ + with_ip: Optional[str] + """ + List Instances by IP (both private_ip and public_ip are supported). + """ + commercial_type: Optional[str] """ List Instances of this commercial type. @@ -2830,7 +2859,7 @@ class ListServersResponse: @dataclass class ListServersTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2855,7 +2884,7 @@ class ListServersTypesResponse: @dataclass class ListSnapshotsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2911,7 +2940,7 @@ class ListSnapshotsResponse: @dataclass class ListVolumesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2967,7 +2996,7 @@ class ListVolumesResponse: @dataclass class ListVolumesTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2999,7 +3028,7 @@ class MigrationPlan: validation_key: str """ - A value to be passed to ApplyBlockMigrationRequest, to confirm that the execution of the plan is being requested. + A value to be passed to the call to the [Migrate a volume and/or snapshots to SBS](#path-volumes-migrate-a-volume-andor-snapshots-to-sbs-scaleway-block-storage) endpoint, to confirm that the execution of the plan is being requested. """ volume: Optional[Volume] @@ -3010,7 +3039,7 @@ class MigrationPlan: @dataclass class PlanBlockMigrationRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3027,7 +3056,7 @@ class ServerActionRequest: UUID of the Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3049,15 +3078,29 @@ class ServerActionRequest: This field should only be specified when performing a backup action. """ + disable_ipv6: Optional[bool] + """ + Disable IPv6 on the Instance while performing migration to routed IPs. +This field should only be specified when performing a enable_routed_ip action. + """ + @dataclass class ServerActionResponse: task: Optional[Task] +@dataclass +class ServerCompatibleTypes: + compatible_types: List[str] + """ + Instance compatible types. + """ + + @dataclass class SetImageRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3097,7 +3140,7 @@ class SetPlacementGroupRequest: name: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3130,7 +3173,7 @@ class SetPlacementGroupServersRequest: An array of the Instances' UUIDs you want to configure. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3151,7 +3194,7 @@ class SetSecurityGroupRulesRequest: UUID of the security group to update the rules on. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3174,7 +3217,7 @@ class UpdateImageRequest: UUID of the image. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3217,7 +3260,7 @@ class UpdateIpRequest: IP ID or IP address. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3229,7 +3272,7 @@ class UpdateIpRequest: type_: Optional[IpType] """ - Convert a 'nat' IP to a 'routed_ipv4'. + Should have no effect. """ tags: Optional[List[str]] @@ -3252,7 +3295,7 @@ class UpdatePlacementGroupRequest: UUID of the placement group. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3295,7 +3338,7 @@ class UpdatePlacementGroupServersRequest: An array of the Instances' UUIDs you want to configure. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3321,7 +3364,7 @@ class UpdatePrivateNICRequest: Private NIC unique ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3339,7 +3382,7 @@ class UpdateSecurityGroupRequest: UUID of the security group. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3407,7 +3450,7 @@ class UpdateSecurityGroupRuleRequest: UUID of the rule. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3460,7 +3503,7 @@ class UpdateServerRequest: UUID of the Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3479,8 +3522,6 @@ class UpdateServerRequest: volumes: Optional[Dict[str, VolumeServerTemplate]] - bootscript: Optional[str] - dynamic_ip_required: Optional[bool] routed_ip_enabled: Optional[bool] @@ -3496,6 +3537,9 @@ class UpdateServerRequest: enable_ipv6: Optional[bool] protected: Optional[bool] + """ + True to activate server protection option. + """ security_group: Optional[SecurityGroupTemplate] @@ -3514,9 +3558,15 @@ class UpdateServerRequest: Warning: This field has some restrictions: - Cannot be changed if the Instance is not in `stopped` state. - Cannot be changed if the Instance is in a placement group. +- Cannot be changed from/to a Windows offer to/from a Linux offer. - Local storage requirements of the target commercial_types must be fulfilled (i.e. if an Instance has 80GB of local storage, it can be changed into a GP1-XS, which has a maximum of 150GB, but it cannot be changed into a DEV1-S, which has only 20GB). """ + admin_password_encryption_ssh_key_id: Optional[str] + """ + The public_key value of this key is used to encrypt the admin password. When set to an empty string, reset this value and admin_password_encrypted_value to an empty string so a new password may be generated. + """ + @dataclass class UpdateServerResponse: @@ -3530,7 +3580,7 @@ class UpdateSnapshotRequest: UUID of the snapshot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3558,7 +3608,7 @@ class UpdateVolumeRequest: UUID of the volume. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway-async/scaleway_async/instance/v1/types_private.py b/scaleway-async/scaleway_async/instance/v1/types_private.py index 9acfb25e..38526ba0 100644 --- a/scaleway-async/scaleway_async/instance/v1/types_private.py +++ b/scaleway-async/scaleway_async/instance/v1/types_private.py @@ -7,7 +7,7 @@ from typing import Dict, List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from .types import ( @@ -22,7 +22,6 @@ SnapshotState, VolumeVolumeType, ServerSummary, - Bootscript, Volume, Image, PlacementGroup, @@ -47,7 +46,7 @@ class _SetImageResponse: @dataclass class _SetSecurityGroupRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -126,7 +125,7 @@ class _SetSecurityGroupRuleRequest: ip_range: str position: int editable: bool - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -144,7 +143,7 @@ class _SetSecurityGroupRuleResponse: @dataclass class _SetServerRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -160,21 +159,25 @@ class _SetServerRequest: """ Instance commercial type (eg. GP1-M). """ - dynamic_ip_required: bool + organization: Optional[str] """ - True if a dynamic IPv4 is required. + Instance Organization ID. """ - enable_ipv6: bool + dynamic_ip_required: bool """ - True if IPv6 is enabled. + True if a dynamic IPv4 is required. """ hostname: str """ Instance host name. """ - organization: Optional[str] + protected: bool """ - Instance Organization ID. + Instance protection option is activated. + """ + state_detail: str + """ + Instance state_detail. """ project: Optional[str] """ @@ -196,21 +199,21 @@ class _SetServerRequest: """ True to configure the instance so it uses the new routed IP mode (once this is set to True you cannot set it back to False). """ - image: Optional[Image] + enable_ipv6: Optional[bool] """ - Provide information on the Instance image. + True if IPv6 is enabled (deprecated and always `False` when `routed_ip_enabled` is `True`). """ - protected: bool + image: Optional[Image] """ - Instance protection option is activated. + Provide information on the Instance image. """ private_ip: Optional[str] """ - Instance private IP address. + Instance private IP address (deprecated and always `null` when `routed_ip_enabled` is `True`). """ public_ip: Optional[ServerIp] """ - Information about the public IP. + Information about the public IP (deprecated in favor of `public_ips`). """ public_ips: Optional[List[ServerIp]] """ @@ -220,10 +223,6 @@ class _SetServerRequest: """ Instance modification date. """ - state_detail: str - """ - Instance state_detail. - """ state: Optional[ServerState] """ Instance state. @@ -234,11 +233,7 @@ class _SetServerRequest: """ ipv6: Optional[ServerIpv6] """ - Instance IPv6 address. - """ - bootscript: Optional[Bootscript] - """ - Instance bootscript. + Instance IPv6 address (deprecated when `routed_ip_enabled` is `True`). """ boot_type: Optional[BootType] """ @@ -268,6 +263,10 @@ class _SetServerRequest: """ Instance private NICs. """ + admin_password_encryption_ssh_key_id: Optional[str] + """ + The public_key value of this key is used to encrypt the admin password. When set to an empty string, reset this value and admin_password_encrypted_value to an empty string so a new password may be generated. + """ @dataclass @@ -279,7 +278,7 @@ class _SetServerResponse: class _SetSnapshotRequest: id: str name: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway-async/scaleway_async/interlink/__init__.py b/scaleway-async/scaleway_async/interlink/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway-async/scaleway_async/interlink/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway-async/scaleway_async/interlink/v1beta1/__init__.py b/scaleway-async/scaleway_async/interlink/v1beta1/__init__.py new file mode 100644 index 00000000..66cc0eab --- /dev/null +++ b/scaleway-async/scaleway_async/interlink/v1beta1/__init__.py @@ -0,0 +1,99 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import BgpStatus +from .types import DedicatedConnectionStatus +from .content import DEDICATED_CONNECTION_TRANSIENT_STATUSES +from .types import LinkKind +from .types import LinkStatus +from .content import LINK_TRANSIENT_STATUSES +from .types import ListDedicatedConnectionsRequestOrderBy +from .types import ListLinksRequestOrderBy +from .types import ListPartnersRequestOrderBy +from .types import ListPopsRequestOrderBy +from .types import ListRoutingPoliciesRequestOrderBy +from .types import BgpConfig +from .types import PartnerHost +from .types import SelfHost +from .types import DedicatedConnection +from .types import Link +from .types import Partner +from .types import Pop +from .types import RoutingPolicy +from .types import AttachRoutingPolicyRequest +from .types import AttachVpcRequest +from .types import CreateLinkRequest +from .types import CreateRoutingPolicyRequest +from .types import DeleteLinkRequest +from .types import DeleteRoutingPolicyRequest +from .types import DetachRoutingPolicyRequest +from .types import DetachVpcRequest +from .types import DisableRoutePropagationRequest +from .types import EnableRoutePropagationRequest +from .types import GetDedicatedConnectionRequest +from .types import GetLinkRequest +from .types import GetPartnerRequest +from .types import GetPopRequest +from .types import GetRoutingPolicyRequest +from .types import ListDedicatedConnectionsRequest +from .types import ListDedicatedConnectionsResponse +from .types import ListLinksRequest +from .types import ListLinksResponse +from .types import ListPartnersRequest +from .types import ListPartnersResponse +from .types import ListPopsRequest +from .types import ListPopsResponse +from .types import ListRoutingPoliciesRequest +from .types import ListRoutingPoliciesResponse +from .types import UpdateLinkRequest +from .types import UpdateRoutingPolicyRequest +from .api import InterlinkV1Beta1API + +__all__ = [ + "BgpStatus", + "DedicatedConnectionStatus", + "DEDICATED_CONNECTION_TRANSIENT_STATUSES", + "LinkKind", + "LinkStatus", + "LINK_TRANSIENT_STATUSES", + "ListDedicatedConnectionsRequestOrderBy", + "ListLinksRequestOrderBy", + "ListPartnersRequestOrderBy", + "ListPopsRequestOrderBy", + "ListRoutingPoliciesRequestOrderBy", + "BgpConfig", + "PartnerHost", + "SelfHost", + "DedicatedConnection", + "Link", + "Partner", + "Pop", + "RoutingPolicy", + "AttachRoutingPolicyRequest", + "AttachVpcRequest", + "CreateLinkRequest", + "CreateRoutingPolicyRequest", + "DeleteLinkRequest", + "DeleteRoutingPolicyRequest", + "DetachRoutingPolicyRequest", + "DetachVpcRequest", + "DisableRoutePropagationRequest", + "EnableRoutePropagationRequest", + "GetDedicatedConnectionRequest", + "GetLinkRequest", + "GetPartnerRequest", + "GetPopRequest", + "GetRoutingPolicyRequest", + "ListDedicatedConnectionsRequest", + "ListDedicatedConnectionsResponse", + "ListLinksRequest", + "ListLinksResponse", + "ListPartnersRequest", + "ListPartnersResponse", + "ListPopsRequest", + "ListPopsResponse", + "ListRoutingPoliciesRequest", + "ListRoutingPoliciesResponse", + "UpdateLinkRequest", + "UpdateRoutingPolicyRequest", + "InterlinkV1Beta1API", +] diff --git a/scaleway-async/scaleway_async/interlink/v1beta1/api.py b/scaleway-async/scaleway_async/interlink/v1beta1/api.py new file mode 100644 index 00000000..56c00bb4 --- /dev/null +++ b/scaleway-async/scaleway_async/interlink/v1beta1/api.py @@ -0,0 +1,1410 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + BgpStatus, + DedicatedConnectionStatus, + LinkKind, + LinkStatus, + ListDedicatedConnectionsRequestOrderBy, + ListLinksRequestOrderBy, + ListPartnersRequestOrderBy, + ListPopsRequestOrderBy, + ListRoutingPoliciesRequestOrderBy, + AttachRoutingPolicyRequest, + AttachVpcRequest, + CreateLinkRequest, + CreateRoutingPolicyRequest, + DedicatedConnection, + Link, + ListDedicatedConnectionsResponse, + ListLinksResponse, + ListPartnersResponse, + ListPopsResponse, + ListRoutingPoliciesResponse, + Partner, + Pop, + RoutingPolicy, + UpdateLinkRequest, + UpdateRoutingPolicyRequest, +) +from .content import ( + DEDICATED_CONNECTION_TRANSIENT_STATUSES, + LINK_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_DedicatedConnection, + unmarshal_Link, + unmarshal_Partner, + unmarshal_Pop, + unmarshal_RoutingPolicy, + unmarshal_ListDedicatedConnectionsResponse, + unmarshal_ListLinksResponse, + unmarshal_ListPartnersResponse, + unmarshal_ListPopsResponse, + unmarshal_ListRoutingPoliciesResponse, + marshal_AttachRoutingPolicyRequest, + marshal_AttachVpcRequest, + marshal_CreateLinkRequest, + marshal_CreateRoutingPolicyRequest, + marshal_UpdateLinkRequest, + marshal_UpdateRoutingPolicyRequest, +) + + +class InterlinkV1Beta1API(API): + """ + This API allows you to manage your Scaleway InterLink, to connect your on-premises infrastructure with your Scaleway VPC. + """ + + async def list_dedicated_connections( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListDedicatedConnectionsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + status: Optional[DedicatedConnectionStatus] = None, + bandwidth_mbps: Optional[int] = None, + pop_id: Optional[str] = None, + ) -> ListDedicatedConnectionsResponse: + """ + List dedicated connections. + For self-hosted users, list their dedicated physical connections in a given region. By default, the connections returned in the list are ordered by name in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of connections to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Link name to filter for. + :param tags: Tags to filter for. + :param status: Connection status to filter for. + :param bandwidth_mbps: Filter for dedicated connections with this bandwidth size. + :param pop_id: Filter for dedicated connections present in this PoP. + :return: :class:`ListDedicatedConnectionsResponse ` + + Usage: + :: + + result = await api.list_dedicated_connections() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/dedicated-connections", + params={ + "bandwidth_mbps": bandwidth_mbps, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pop_id": pop_id, + "project_id": project_id or self.client.default_project_id, + "status": status, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDedicatedConnectionsResponse(res.json()) + + async def list_dedicated_connections_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListDedicatedConnectionsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + status: Optional[DedicatedConnectionStatus] = None, + bandwidth_mbps: Optional[int] = None, + pop_id: Optional[str] = None, + ) -> List[DedicatedConnection]: + """ + List dedicated connections. + For self-hosted users, list their dedicated physical connections in a given region. By default, the connections returned in the list are ordered by name in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of connections to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Link name to filter for. + :param tags: Tags to filter for. + :param status: Connection status to filter for. + :param bandwidth_mbps: Filter for dedicated connections with this bandwidth size. + :param pop_id: Filter for dedicated connections present in this PoP. + :return: :class:`List[DedicatedConnection] ` + + Usage: + :: + + result = await api.list_dedicated_connections_all() + """ + + return await fetch_all_pages_async( + type=ListDedicatedConnectionsResponse, + key="connections", + fetcher=self.list_dedicated_connections, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "organization_id": organization_id, + "name": name, + "tags": tags, + "status": status, + "bandwidth_mbps": bandwidth_mbps, + "pop_id": pop_id, + }, + ) + + async def get_dedicated_connection( + self, + *, + connection_id: str, + region: Optional[ScwRegion] = None, + ) -> DedicatedConnection: + """ + Get a dedicated connection. + For self-hosted users, get a dedicated physical connection corresponding to the given ID. The response object includes information such as the connection's name, status and total bandwidth. + :param connection_id: ID of connection to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DedicatedConnection ` + + Usage: + :: + + result = await api.get_dedicated_connection( + connection_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_connection_id = validate_path_param("connection_id", connection_id) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/dedicated-connections/{param_connection_id}", + ) + + self._throw_on_error(res) + return unmarshal_DedicatedConnection(res.json()) + + async def wait_for_dedicated_connection( + self, + *, + connection_id: str, + region: Optional[ScwRegion] = None, + options: Optional[ + WaitForOptions[DedicatedConnection, Union[bool, Awaitable[bool]]] + ] = None, + ) -> DedicatedConnection: + """ + Get a dedicated connection. + For self-hosted users, get a dedicated physical connection corresponding to the given ID. The response object includes information such as the connection's name, status and total bandwidth. + :param connection_id: ID of connection to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DedicatedConnection ` + + Usage: + :: + + result = await api.get_dedicated_connection( + connection_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in DEDICATED_CONNECTION_TRANSIENT_STATUSES + ) + + return await wait_for_resource_async( + fetcher=self.get_dedicated_connection, + options=options, + args={ + "connection_id": connection_id, + "region": region, + }, + ) + + async def list_partners( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListPartnersRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pop_ids: Optional[List[str]] = None, + ) -> ListPartnersResponse: + """ + List available partners. + List all available partners. By default, the partners returned in the list are ordered by name in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of partners to return per page. + :param pop_ids: Filter for partners present (offering a connection) in one of these PoPs. + :return: :class:`ListPartnersResponse ` + + Usage: + :: + + result = await api.list_partners() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/partners", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pop_ids": pop_ids, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPartnersResponse(res.json()) + + async def list_partners_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListPartnersRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pop_ids: Optional[List[str]] = None, + ) -> List[Partner]: + """ + List available partners. + List all available partners. By default, the partners returned in the list are ordered by name in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of partners to return per page. + :param pop_ids: Filter for partners present (offering a connection) in one of these PoPs. + :return: :class:`List[Partner] ` + + Usage: + :: + + result = await api.list_partners_all() + """ + + return await fetch_all_pages_async( + type=ListPartnersResponse, + key="partners", + fetcher=self.list_partners, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "pop_ids": pop_ids, + }, + ) + + async def get_partner( + self, + *, + partner_id: str, + region: Optional[ScwRegion] = None, + ) -> Partner: + """ + Get a partner. + Get a partner for the given partner IP. The response object includes information such as the partner's name, email address and portal URL. + :param partner_id: ID of partner to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Partner ` + + Usage: + :: + + result = await api.get_partner( + partner_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_partner_id = validate_path_param("partner_id", partner_id) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/partners/{param_partner_id}", + ) + + self._throw_on_error(res) + return unmarshal_Partner(res.json()) + + async def list_pops( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListPopsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + hosting_provider_name: Optional[str] = None, + partner_id: Optional[str] = None, + link_bandwidth_mbps: Optional[int] = None, + dedicated_available: Optional[bool] = None, + ) -> ListPopsResponse: + """ + List PoPs. + List all available PoPs (locations) for a given region. By default, the results are returned in ascending alphabetical order by name. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of PoPs to return per page. + :param name: PoP name to filter for. + :param hosting_provider_name: Hosting provider name to filter for. + :param partner_id: Filter for PoPs hosting an available shared connection from this partner. + :param link_bandwidth_mbps: Filter for PoPs with a shared connection allowing this bandwidth size. Note that we cannot guarantee that PoPs returned will have available capacity. + :param dedicated_available: Filter for PoPs with a dedicated connection available for self-hosted links. + :return: :class:`ListPopsResponse ` + + Usage: + :: + + result = await api.list_pops() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/pops", + params={ + "dedicated_available": dedicated_available, + "hosting_provider_name": hosting_provider_name, + "link_bandwidth_mbps": link_bandwidth_mbps, + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "partner_id": partner_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPopsResponse(res.json()) + + async def list_pops_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListPopsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + hosting_provider_name: Optional[str] = None, + partner_id: Optional[str] = None, + link_bandwidth_mbps: Optional[int] = None, + dedicated_available: Optional[bool] = None, + ) -> List[Pop]: + """ + List PoPs. + List all available PoPs (locations) for a given region. By default, the results are returned in ascending alphabetical order by name. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of PoPs to return per page. + :param name: PoP name to filter for. + :param hosting_provider_name: Hosting provider name to filter for. + :param partner_id: Filter for PoPs hosting an available shared connection from this partner. + :param link_bandwidth_mbps: Filter for PoPs with a shared connection allowing this bandwidth size. Note that we cannot guarantee that PoPs returned will have available capacity. + :param dedicated_available: Filter for PoPs with a dedicated connection available for self-hosted links. + :return: :class:`List[Pop] ` + + Usage: + :: + + result = await api.list_pops_all() + """ + + return await fetch_all_pages_async( + type=ListPopsResponse, + key="pops", + fetcher=self.list_pops, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "hosting_provider_name": hosting_provider_name, + "partner_id": partner_id, + "link_bandwidth_mbps": link_bandwidth_mbps, + "dedicated_available": dedicated_available, + }, + ) + + async def get_pop( + self, + *, + pop_id: str, + region: Optional[ScwRegion] = None, + ) -> Pop: + """ + Get a PoP. + Get a PoP for the given PoP ID. The response object includes the PoP's name and information about its physical location. + :param pop_id: ID of PoP to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Pop ` + + Usage: + :: + + result = await api.get_pop( + pop_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_pop_id = validate_path_param("pop_id", pop_id) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/pops/{param_pop_id}", + ) + + self._throw_on_error(res) + return unmarshal_Pop(res.json()) + + async def list_links( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListLinksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + status: Optional[LinkStatus] = None, + bgp_v4_status: Optional[BgpStatus] = None, + bgp_v6_status: Optional[BgpStatus] = None, + pop_id: Optional[str] = None, + bandwidth_mbps: Optional[int] = None, + partner_id: Optional[str] = None, + vpc_id: Optional[str] = None, + routing_policy_id: Optional[str] = None, + pairing_key: Optional[str] = None, + kind: Optional[LinkKind] = None, + connection_id: Optional[str] = None, + ) -> ListLinksResponse: + """ + List links. + List all your links (InterLink connections). A number of filters are available, including Project ID, name, tags and status. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of links to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Link name to filter for. + :param tags: Tags to filter for. + :param status: Link status to filter for. + :param bgp_v4_status: BGP IPv4 status to filter for. + :param bgp_v6_status: BGP IPv6 status to filter for. + :param pop_id: Filter for links attached to this PoP (via connections). + :param bandwidth_mbps: Filter for link bandwidth (in Mbps). + :param partner_id: Filter for links hosted by this partner. + :param vpc_id: Filter for links attached to this VPC. + :param routing_policy_id: Filter for links using this routing policy. + :param pairing_key: Filter for the link with this pairing_key. + :param kind: Filter for hosted or self-hosted links. + :param connection_id: Filter for links self-hosted on this connection. + :return: :class:`ListLinksResponse ` + + Usage: + :: + + result = await api.list_links() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/links", + params={ + "bandwidth_mbps": bandwidth_mbps, + "bgp_v4_status": bgp_v4_status, + "bgp_v6_status": bgp_v6_status, + "connection_id": connection_id, + "kind": kind, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pairing_key": pairing_key, + "partner_id": partner_id, + "pop_id": pop_id, + "project_id": project_id or self.client.default_project_id, + "routing_policy_id": routing_policy_id, + "status": status, + "tags": tags, + "vpc_id": vpc_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListLinksResponse(res.json()) + + async def list_links_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListLinksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + status: Optional[LinkStatus] = None, + bgp_v4_status: Optional[BgpStatus] = None, + bgp_v6_status: Optional[BgpStatus] = None, + pop_id: Optional[str] = None, + bandwidth_mbps: Optional[int] = None, + partner_id: Optional[str] = None, + vpc_id: Optional[str] = None, + routing_policy_id: Optional[str] = None, + pairing_key: Optional[str] = None, + kind: Optional[LinkKind] = None, + connection_id: Optional[str] = None, + ) -> List[Link]: + """ + List links. + List all your links (InterLink connections). A number of filters are available, including Project ID, name, tags and status. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of links to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Link name to filter for. + :param tags: Tags to filter for. + :param status: Link status to filter for. + :param bgp_v4_status: BGP IPv4 status to filter for. + :param bgp_v6_status: BGP IPv6 status to filter for. + :param pop_id: Filter for links attached to this PoP (via connections). + :param bandwidth_mbps: Filter for link bandwidth (in Mbps). + :param partner_id: Filter for links hosted by this partner. + :param vpc_id: Filter for links attached to this VPC. + :param routing_policy_id: Filter for links using this routing policy. + :param pairing_key: Filter for the link with this pairing_key. + :param kind: Filter for hosted or self-hosted links. + :param connection_id: Filter for links self-hosted on this connection. + :return: :class:`List[Link] ` + + Usage: + :: + + result = await api.list_links_all() + """ + + return await fetch_all_pages_async( + type=ListLinksResponse, + key="links", + fetcher=self.list_links, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "organization_id": organization_id, + "name": name, + "tags": tags, + "status": status, + "bgp_v4_status": bgp_v4_status, + "bgp_v6_status": bgp_v6_status, + "pop_id": pop_id, + "bandwidth_mbps": bandwidth_mbps, + "partner_id": partner_id, + "vpc_id": vpc_id, + "routing_policy_id": routing_policy_id, + "pairing_key": pairing_key, + "kind": kind, + "connection_id": connection_id, + }, + ) + + async def get_link( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Get a link. + Get a link (InterLink session / logical InterLink resource) for the given link ID. The response object includes information about the link's various configuration details. + :param link_id: ID of the link to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = await api.get_link( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}", + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + async def wait_for_link( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Link, Union[bool, Awaitable[bool]]]] = None, + ) -> Link: + """ + Get a link. + Get a link (InterLink session / logical InterLink resource) for the given link ID. The response object includes information about the link's various configuration details. + :param link_id: ID of the link to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = await api.get_link( + link_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in LINK_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_link, + options=options, + args={ + "link_id": link_id, + "region": region, + }, + ) + + async def create_link( + self, + *, + name: str, + pop_id: str, + bandwidth_mbps: int, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + connection_id: Optional[str] = None, + partner_id: Optional[str] = None, + peer_asn: Optional[int] = None, + ) -> Link: + """ + Create a link. + Create a link (InterLink session / logical InterLink resource) in a given PoP, specifying its various configuration details. Links can either be hosted (facilitated by partners' shared physical connections) or self-hosted (for users who have purchased a dedicated physical connection). + :param name: Name of the link. + :param pop_id: PoP (location) where the link will be created. + :param bandwidth_mbps: Desired bandwidth for the link. Must be compatible with available link bandwidths and remaining bandwidth capacity of the connection. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to create the link in. + :param tags: List of tags to apply to the link. + :param connection_id: If set, creates a self-hosted link using this dedicated physical connection. As the customer, specify the ID of the physical connection you already have for this link. + One-Of ('host'): at most one of 'connection_id', 'partner_id' could be set. + :param partner_id: If set, creates a hosted link on a partner's connection. Specify the ID of the chosen partner, who already has a shared connection with available bandwidth. + One-Of ('host'): at most one of 'connection_id', 'partner_id' could be set. + :param peer_asn: For self-hosted links we need the peer AS Number to establish BGP session. If not given, a default one will be assigned. + :return: :class:`Link ` + + Usage: + :: + + result = await api.create_link( + name="example", + pop_id="example", + bandwidth_mbps=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links", + body=marshal_CreateLinkRequest( + CreateLinkRequest( + name=name, + pop_id=pop_id, + bandwidth_mbps=bandwidth_mbps, + region=region, + project_id=project_id, + tags=tags, + peer_asn=peer_asn, + connection_id=connection_id, + partner_id=partner_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + async def update_link( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + peer_asn: Optional[int] = None, + ) -> Link: + """ + Update a link. + Update an existing link, specified by its link ID. Only its name and tags can be updated. + :param link_id: ID of the link to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the link. + :param tags: List of tags to apply to the link. + :param peer_asn: For self-hosted links, AS Number to establish BGP session. + :return: :class:`Link ` + + Usage: + :: + + result = await api.update_link( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "PATCH", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}", + body=marshal_UpdateLinkRequest( + UpdateLinkRequest( + link_id=link_id, + region=region, + name=name, + tags=tags, + peer_asn=peer_asn, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + async def delete_link( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Delete a link. + Delete an existing link, specified by its link ID. Note that as well as deleting the link here on the Scaleway side, it is also necessary to request deletion from the partner on their side. Only when this action has been carried out on both sides will the resource be completely deleted. + :param link_id: ID of the link to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = await api.delete_link( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "DELETE", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}", + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + async def attach_vpc( + self, + *, + link_id: str, + vpc_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Attach a VPC. + Attach a VPC to an existing link. This facilitates communication between the resources in your Scaleway VPC, and your on-premises infrastructure. + :param link_id: ID of the link to attach VPC to. + :param vpc_id: ID of the VPC to attach. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = await api.attach_vpc( + link_id="example", + vpc_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/attach-vpc", + body=marshal_AttachVpcRequest( + AttachVpcRequest( + link_id=link_id, + vpc_id=vpc_id, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + async def detach_vpc( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Detach a VPC. + Detach a VPC from an existing link. + :param link_id: ID of the link to detach the VPC from. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = await api.detach_vpc( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/detach-vpc", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + async def attach_routing_policy( + self, + *, + link_id: str, + routing_policy_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Attach a routing policy. + Attach a routing policy to an existing link. As all routes across the link are blocked by default, you must attach a routing policy to set IP prefix filters for allowed routes, facilitating traffic flow. + :param link_id: ID of the link to attach a routing policy to. + :param routing_policy_id: ID of the routing policy to be attached. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = await api.attach_routing_policy( + link_id="example", + routing_policy_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/attach-routing-policy", + body=marshal_AttachRoutingPolicyRequest( + AttachRoutingPolicyRequest( + link_id=link_id, + routing_policy_id=routing_policy_id, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + async def detach_routing_policy( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Detach a routing policy. + Detach a routing policy from an existing link. Without a routing policy, all routes across the link are blocked by default. + :param link_id: ID of the link to detach a routing policy from. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = await api.detach_routing_policy( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/detach-routing-policy", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + async def enable_route_propagation( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Enable route propagation. + Enable all allowed prefixes (defined in a routing policy) to be announced in the BGP session. This allows traffic to flow between the attached VPC and the on-premises infrastructure along the announced routes. Note that by default, even when route propagation is enabled, all routes are blocked. It is essential to attach a routing policy to define the ranges of routes to announce. + :param link_id: ID of the link on which to enable route propagation. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = await api.enable_route_propagation( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/enable-route-propagation", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + async def disable_route_propagation( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Disable route propagation. + Prevent any prefixes from being announced in the BGP session. Traffic will not be able to flow over the InterLink until route propagation is re-enabled. + :param link_id: ID of the link on which to disable route propagation. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = await api.disable_route_propagation( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/disable-route-propagation", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + async def list_routing_policies( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListRoutingPoliciesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListRoutingPoliciesResponse: + """ + List routing policies. + List all routing policies in a given region. A routing policy can be attached to one or multiple links (InterLink connections). + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of routing policies to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Routing policy name to filter for. + :param tags: Tags to filter for. + :return: :class:`ListRoutingPoliciesResponse ` + + Usage: + :: + + result = await api.list_routing_policies() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/routing-policies", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRoutingPoliciesResponse(res.json()) + + async def list_routing_policies_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListRoutingPoliciesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[RoutingPolicy]: + """ + List routing policies. + List all routing policies in a given region. A routing policy can be attached to one or multiple links (InterLink connections). + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of routing policies to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Routing policy name to filter for. + :param tags: Tags to filter for. + :return: :class:`List[RoutingPolicy] ` + + Usage: + :: + + result = await api.list_routing_policies_all() + """ + + return await fetch_all_pages_async( + type=ListRoutingPoliciesResponse, + key="routing_policies", + fetcher=self.list_routing_policies, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "organization_id": organization_id, + "name": name, + "tags": tags, + }, + ) + + async def get_routing_policy( + self, + *, + routing_policy_id: str, + region: Optional[ScwRegion] = None, + ) -> RoutingPolicy: + """ + Get routing policy. + Get a routing policy for the given routing policy ID. The response object gives information including the policy's name, tags and prefix filters. + :param routing_policy_id: ID of the routing policy to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`RoutingPolicy ` + + Usage: + :: + + result = await api.get_routing_policy( + routing_policy_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_routing_policy_id = validate_path_param( + "routing_policy_id", routing_policy_id + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/routing-policies/{param_routing_policy_id}", + ) + + self._throw_on_error(res) + return unmarshal_RoutingPolicy(res.json()) + + async def create_routing_policy( + self, + *, + name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + prefix_filter_in: Optional[List[str]] = None, + prefix_filter_out: Optional[List[str]] = None, + ) -> RoutingPolicy: + """ + Create a routing policy. + Create a routing policy. Routing policies allow you to set IP prefix filters to define the incoming route announcements to accept from the peer, and the outgoing routes to announce to the peer. + :param name: Name of the routing policy. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to create the routing policy in. + :param tags: List of tags to apply to the routing policy. + :param prefix_filter_in: IP prefixes to accept from the peer (ranges of route announcements to accept). + :param prefix_filter_out: IP prefix filters to advertise to the peer (ranges of routes to advertise). + :return: :class:`RoutingPolicy ` + + Usage: + :: + + result = await api.create_routing_policy( + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/routing-policies", + body=marshal_CreateRoutingPolicyRequest( + CreateRoutingPolicyRequest( + name=name, + region=region, + project_id=project_id, + tags=tags, + prefix_filter_in=prefix_filter_in, + prefix_filter_out=prefix_filter_out, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RoutingPolicy(res.json()) + + async def update_routing_policy( + self, + *, + routing_policy_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + prefix_filter_in: Optional[List[str]] = None, + prefix_filter_out: Optional[List[str]] = None, + ) -> RoutingPolicy: + """ + Update a routing policy. + Update an existing routing policy, specified by its routing policy ID. Its name, tags and incoming/outgoing prefix filters can be updated. + :param routing_policy_id: ID of the routing policy to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the routing policy. + :param tags: List of tags to apply to the routing policy. + :param prefix_filter_in: IP prefixes to accept from the peer (ranges of route announcements to accept). + :param prefix_filter_out: IP prefix filters for routes to advertise to the peer (ranges of routes to advertise). + :return: :class:`RoutingPolicy ` + + Usage: + :: + + result = await api.update_routing_policy( + routing_policy_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_routing_policy_id = validate_path_param( + "routing_policy_id", routing_policy_id + ) + + res = self._request( + "PATCH", + f"/interlink/v1beta1/regions/{param_region}/routing-policies/{param_routing_policy_id}", + body=marshal_UpdateRoutingPolicyRequest( + UpdateRoutingPolicyRequest( + routing_policy_id=routing_policy_id, + region=region, + name=name, + tags=tags, + prefix_filter_in=prefix_filter_in, + prefix_filter_out=prefix_filter_out, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RoutingPolicy(res.json()) + + async def delete_routing_policy( + self, + *, + routing_policy_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a routing policy. + Delete an existing routing policy, specified by its routing policy ID. + :param routing_policy_id: ID of the routing policy to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_routing_policy( + routing_policy_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_routing_policy_id = validate_path_param( + "routing_policy_id", routing_policy_id + ) + + res = self._request( + "DELETE", + f"/interlink/v1beta1/regions/{param_region}/routing-policies/{param_routing_policy_id}", + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/interlink/v1beta1/content.py b/scaleway-async/scaleway_async/interlink/v1beta1/content.py new file mode 100644 index 00000000..dea5950e --- /dev/null +++ b/scaleway-async/scaleway_async/interlink/v1beta1/content.py @@ -0,0 +1,21 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + DedicatedConnectionStatus, + LinkStatus, +) + +DEDICATED_CONNECTION_TRANSIENT_STATUSES: List[DedicatedConnectionStatus] = [ + DedicatedConnectionStatus.CONFIGURING, +] +""" +Lists transient statutes of the enum :class:`DedicatedConnectionStatus `. +""" +LINK_TRANSIENT_STATUSES: List[LinkStatus] = [ + LinkStatus.CONFIGURING, +] +""" +Lists transient statutes of the enum :class:`LinkStatus `. +""" diff --git a/scaleway-async/scaleway_async/interlink/v1beta1/marshalling.py b/scaleway-async/scaleway_async/interlink/v1beta1/marshalling.py new file mode 100644 index 00000000..0768e3db --- /dev/null +++ b/scaleway-async/scaleway_async/interlink/v1beta1/marshalling.py @@ -0,0 +1,645 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + DedicatedConnection, + BgpConfig, + PartnerHost, + SelfHost, + Link, + Partner, + Pop, + RoutingPolicy, + ListDedicatedConnectionsResponse, + ListLinksResponse, + ListPartnersResponse, + ListPopsResponse, + ListRoutingPoliciesResponse, + AttachRoutingPolicyRequest, + AttachVpcRequest, + CreateLinkRequest, + CreateRoutingPolicyRequest, + UpdateLinkRequest, + UpdateRoutingPolicyRequest, +) + + +def unmarshal_DedicatedConnection(data: Any) -> DedicatedConnection: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DedicatedConnection' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("pop_id", None) + if field is not None: + args["pop_id"] = field + + field = data.get("bandwidth_mbps", None) + if field is not None: + args["bandwidth_mbps"] = field + + field = data.get("available_link_bandwidths", None) + if field is not None: + args["available_link_bandwidths"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("demarcation_info", None) + if field is not None: + args["demarcation_info"] = field + else: + args["demarcation_info"] = None + + return DedicatedConnection(**args) + + +def unmarshal_BgpConfig(data: Any) -> BgpConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BgpConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("asn", None) + if field is not None: + args["asn"] = field + + field = data.get("ipv4", None) + if field is not None: + args["ipv4"] = field + + field = data.get("ipv6", None) + if field is not None: + args["ipv6"] = field + + return BgpConfig(**args) + + +def unmarshal_PartnerHost(data: Any) -> PartnerHost: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PartnerHost' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("partner_id", None) + if field is not None: + args["partner_id"] = field + + field = data.get("pairing_key", None) + if field is not None: + args["pairing_key"] = field + + field = data.get("disapproved_reason", None) + if field is not None: + args["disapproved_reason"] = field + else: + args["disapproved_reason"] = None + + return PartnerHost(**args) + + +def unmarshal_SelfHost(data: Any) -> SelfHost: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SelfHost' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("connection_id", None) + if field is not None: + args["connection_id"] = field + + return SelfHost(**args) + + +def unmarshal_Link(data: Any) -> Link: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Link' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("pop_id", None) + if field is not None: + args["pop_id"] = field + + field = data.get("bandwidth_mbps", None) + if field is not None: + args["bandwidth_mbps"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("bgp_v4_status", None) + if field is not None: + args["bgp_v4_status"] = field + + field = data.get("bgp_v6_status", None) + if field is not None: + args["bgp_v6_status"] = field + + field = data.get("enable_route_propagation", None) + if field is not None: + args["enable_route_propagation"] = field + + field = data.get("vlan", None) + if field is not None: + args["vlan"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("vpc_id", None) + if field is not None: + args["vpc_id"] = field + else: + args["vpc_id"] = None + + field = data.get("routing_policy_id", None) + if field is not None: + args["routing_policy_id"] = field + else: + args["routing_policy_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("partner", None) + if field is not None: + args["partner"] = unmarshal_PartnerHost(field) + else: + args["partner"] = None + + field = data.get("self", None) + if field is not None: + args["self_"] = unmarshal_SelfHost(field) + else: + args["self_"] = None + + field = data.get("scw_bgp_config", None) + if field is not None: + args["scw_bgp_config"] = unmarshal_BgpConfig(field) + else: + args["scw_bgp_config"] = None + + field = data.get("peer_bgp_config", None) + if field is not None: + args["peer_bgp_config"] = unmarshal_BgpConfig(field) + else: + args["peer_bgp_config"] = None + + return Link(**args) + + +def unmarshal_Partner(data: Any) -> Partner: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Partner' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("contact_email", None) + if field is not None: + args["contact_email"] = field + + field = data.get("logo_url", None) + if field is not None: + args["logo_url"] = field + + field = data.get("portal_url", None) + if field is not None: + args["portal_url"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Partner(**args) + + +def unmarshal_Pop(data: Any) -> Pop: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pop' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("hosting_provider_name", None) + if field is not None: + args["hosting_provider_name"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("city", None) + if field is not None: + args["city"] = field + + field = data.get("logo_url", None) + if field is not None: + args["logo_url"] = field + + field = data.get("available_link_bandwidths_mbps", None) + if field is not None: + args["available_link_bandwidths_mbps"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + return Pop(**args) + + +def unmarshal_RoutingPolicy(data: Any) -> RoutingPolicy: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RoutingPolicy' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("prefix_filter_in", None) + if field is not None: + args["prefix_filter_in"] = field + + field = data.get("prefix_filter_out", None) + if field is not None: + args["prefix_filter_out"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return RoutingPolicy(**args) + + +def unmarshal_ListDedicatedConnectionsResponse( + data: Any, +) -> ListDedicatedConnectionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDedicatedConnectionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("connections", None) + if field is not None: + args["connections"] = ( + [unmarshal_DedicatedConnection(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDedicatedConnectionsResponse(**args) + + +def unmarshal_ListLinksResponse(data: Any) -> ListLinksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListLinksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("links", None) + if field is not None: + args["links"] = ( + [unmarshal_Link(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListLinksResponse(**args) + + +def unmarshal_ListPartnersResponse(data: Any) -> ListPartnersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPartnersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("partners", None) + if field is not None: + args["partners"] = ( + [unmarshal_Partner(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPartnersResponse(**args) + + +def unmarshal_ListPopsResponse(data: Any) -> ListPopsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPopsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pops", None) + if field is not None: + args["pops"] = [unmarshal_Pop(v) for v in field] if field is not None else None + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPopsResponse(**args) + + +def unmarshal_ListRoutingPoliciesResponse(data: Any) -> ListRoutingPoliciesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRoutingPoliciesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("routing_policies", None) + if field is not None: + args["routing_policies"] = ( + [unmarshal_RoutingPolicy(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListRoutingPoliciesResponse(**args) + + +def marshal_AttachRoutingPolicyRequest( + request: AttachRoutingPolicyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.routing_policy_id is not None: + output["routing_policy_id"] = request.routing_policy_id + + return output + + +def marshal_AttachVpcRequest( + request: AttachVpcRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.vpc_id is not None: + output["vpc_id"] = request.vpc_id + + return output + + +def marshal_CreateLinkRequest( + request: CreateLinkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("connection_id", request.connection_id), + OneOfPossibility("partner_id", request.partner_id), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.pop_id is not None: + output["pop_id"] = request.pop_id + + if request.bandwidth_mbps is not None: + output["bandwidth_mbps"] = request.bandwidth_mbps + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.peer_asn is not None: + output["peer_asn"] = request.peer_asn + + return output + + +def marshal_CreateRoutingPolicyRequest( + request: CreateRoutingPolicyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.prefix_filter_in is not None: + output["prefix_filter_in"] = request.prefix_filter_in + + if request.prefix_filter_out is not None: + output["prefix_filter_out"] = request.prefix_filter_out + + return output + + +def marshal_UpdateLinkRequest( + request: UpdateLinkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.peer_asn is not None: + output["peer_asn"] = request.peer_asn + + return output + + +def marshal_UpdateRoutingPolicyRequest( + request: UpdateRoutingPolicyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.prefix_filter_in is not None: + output["prefix_filter_in"] = request.prefix_filter_in + + if request.prefix_filter_out is not None: + output["prefix_filter_out"] = request.prefix_filter_out + + return output diff --git a/scaleway-async/scaleway_async/interlink/v1beta1/types.py b/scaleway-async/scaleway_async/interlink/v1beta1/types.py new file mode 100644 index 00000000..b41c803a --- /dev/null +++ b/scaleway-async/scaleway_async/interlink/v1beta1/types.py @@ -0,0 +1,1114 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class BgpStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_BGP_STATUS = "unknown_bgp_status" + UP = "up" + DOWN = "down" + + def __str__(self) -> str: + return str(self.value) + + +class DedicatedConnectionStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATED = "created" + CONFIGURING = "configuring" + FAILED = "failed" + ACTIVE = "active" + DISABLED = "disabled" + DELETED = "deleted" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class LinkKind(str, Enum, metaclass=StrEnumMeta): + HOSTED = "hosted" + SELF_HOSTED = "self_hosted" + + def __str__(self) -> str: + return str(self.value) + + +class LinkStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_LINK_STATUS = "unknown_link_status" + CONFIGURING = "configuring" + FAILED = "failed" + REQUESTED = "requested" + REFUSED = "refused" + EXPIRED = "expired" + PROVISIONING = "provisioning" + ACTIVE = "active" + LIMITED_CONNECTIVITY = "limited_connectivity" + ALL_DOWN = "all_down" + DEPROVISIONING = "deprovisioning" + DELETED = "deleted" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class ListDedicatedConnectionsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + UPDATED_AT_ASC = "updated_at_asc" + UPDATED_AT_DESC = "updated_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListLinksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPartnersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPopsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRoutingPoliciesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class BgpConfig: + asn: int + """ + AS Number of the BGP peer. + """ + + ipv4: str + """ + IPv4 address of the BGP peer. + """ + + ipv6: str + """ + IPv6 address of the BGP peer. + """ + + +@dataclass +class PartnerHost: + partner_id: str + """ + ID of the partner facilitating the link. + """ + + pairing_key: str + """ + Used to identify a link from a user or partner's point of view. + """ + + disapproved_reason: Optional[str] + """ + Reason given by partner to explain why they did not approve the request for a hosted link. + """ + + +@dataclass +class SelfHost: + connection_id: str + """ + Dedicated physical connection supporting the link. + """ + + +@dataclass +class DedicatedConnection: + id: str + """ + Unique identifier of the dedicated connection. + """ + + project_id: str + """ + Project ID. + """ + + organization_id: str + """ + Organization ID. + """ + + status: DedicatedConnectionStatus + """ + Status of the dedicated connection. + """ + + name: str + """ + Name of the dedicated connection. + """ + + tags: List[str] + """ + List of tags associated with the dedicated connection. + """ + + pop_id: str + """ + ID of the PoP where the dedicated connection is located. + """ + + bandwidth_mbps: int + """ + Bandwidth size of the dedicated connection. + """ + + available_link_bandwidths: List[int] + """ + Size of the links supported on this dedicated connection. + """ + + region: ScwRegion + """ + Region of the dedicated connection. + """ + + created_at: Optional[datetime] + """ + Creation date of the dedicated connection. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the dedicated connection. + """ + + demarcation_info: Optional[str] + """ + Demarcation details required by the data center to set up the supporting Cross Connect. This generally includes the physical space in the facility, the cabinet or rack the connection should land in, the patch panel to go in, the port designation, and the media type. + """ + + +@dataclass +class Link: + id: str + """ + Unique identifier of the link. + """ + + project_id: str + """ + Project ID. + """ + + organization_id: str + """ + Organization ID. + """ + + name: str + """ + Name of the link. + """ + + tags: List[str] + """ + List of tags associated with the link. + """ + + pop_id: str + """ + ID of the PoP where the link's corresponding connection is located. + """ + + bandwidth_mbps: int + """ + Rate limited bandwidth of the link. + """ + + status: LinkStatus + """ + Status of the link. + """ + + bgp_v4_status: BgpStatus + """ + Status of the link's BGP IPv4 session. + """ + + bgp_v6_status: BgpStatus + """ + Status of the link's BGP IPv6 session. + """ + + enable_route_propagation: bool + """ + Defines whether route propagation is enabled or not. To enable or disable route propagation, use the dedicated endpoint. + """ + + vlan: int + """ + VLAN of the link. + """ + + region: ScwRegion + """ + Region of the link. + """ + + vpc_id: Optional[str] + """ + ID of the Scaleway VPC attached to the link. + """ + + routing_policy_id: Optional[str] + """ + ID of the routing policy attached to the link. + """ + + created_at: Optional[datetime] + """ + Creation date of the link. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the link. + """ + + scw_bgp_config: Optional[BgpConfig] + """ + BGP configuration on Scaleway's side. + """ + + peer_bgp_config: Optional[BgpConfig] + """ + BGP configuration on peer's side (on-premises or other hosting provider). + """ + + partner: Optional[PartnerHost] + + self_: Optional[SelfHost] + + +@dataclass +class Partner: + id: str + """ + Unique identifier of the partner. + """ + + name: str + """ + Name of the partner. + """ + + contact_email: str + """ + Contact email address of partner. + """ + + logo_url: str + """ + Image URL of the partner's logo. + """ + + portal_url: str + """ + URL of the partner's portal. + """ + + created_at: Optional[datetime] + """ + Creation date of the partner. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the partner. + """ + + +@dataclass +class Pop: + id: str + """ + Unique identifier of the PoP. + """ + + name: str + """ + Name of the PoP. It is the common reference of Hosting DC (ex: TH2). + """ + + hosting_provider_name: str + """ + Name of the PoP's hosting provider, e.g. Telehouse for TH2 or OpCore for DC3. + """ + + address: str + """ + Physical address of the PoP. + """ + + city: str + """ + City where PoP is located. + """ + + logo_url: str + """ + Image URL of the PoP's logo. + """ + + available_link_bandwidths_mbps: List[int] + """ + Available bandwidth in Mbits/s for future hosted links from available connections in this PoP. + """ + + region: ScwRegion + """ + Region of the PoP. + """ + + +@dataclass +class RoutingPolicy: + id: str + """ + Unique identifier of the routing policy. + """ + + project_id: str + """ + Project ID. + """ + + organization_id: str + """ + Organization ID. + """ + + name: str + """ + Name of the routing policy. + """ + + tags: List[str] + """ + List of tags associated with the routing policy. + """ + + prefix_filter_in: List[str] + """ + IP prefixes to accept from the peer (ranges of route announcements to accept). + """ + + prefix_filter_out: List[str] + """ + IP prefix filters to advertise to the peer (ranges of routes to advertise). + """ + + region: ScwRegion + """ + Region of the routing policy. + """ + + created_at: Optional[datetime] + """ + Creation date of the routing policy. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the routing policy. + """ + + +@dataclass +class AttachRoutingPolicyRequest: + link_id: str + """ + ID of the link to attach a routing policy to. + """ + + routing_policy_id: str + """ + ID of the routing policy to be attached. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class AttachVpcRequest: + link_id: str + """ + ID of the link to attach VPC to. + """ + + vpc_id: str + """ + ID of the VPC to attach. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateLinkRequest: + name: str + """ + Name of the link. + """ + + pop_id: str + """ + PoP (location) where the link will be created. + """ + + bandwidth_mbps: int + """ + Desired bandwidth for the link. Must be compatible with available link bandwidths and remaining bandwidth capacity of the connection. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to create the link in. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the link. + """ + + peer_asn: Optional[int] + """ + For self-hosted links we need the peer AS Number to establish BGP session. If not given, a default one will be assigned. + """ + + connection_id: Optional[str] + + partner_id: Optional[str] + + +@dataclass +class CreateRoutingPolicyRequest: + name: str + """ + Name of the routing policy. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to create the routing policy in. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the routing policy. + """ + + prefix_filter_in: Optional[List[str]] + """ + IP prefixes to accept from the peer (ranges of route announcements to accept). + """ + + prefix_filter_out: Optional[List[str]] + """ + IP prefix filters to advertise to the peer (ranges of routes to advertise). + """ + + +@dataclass +class DeleteLinkRequest: + link_id: str + """ + ID of the link to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteRoutingPolicyRequest: + routing_policy_id: str + """ + ID of the routing policy to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DetachRoutingPolicyRequest: + link_id: str + """ + ID of the link to detach a routing policy from. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DetachVpcRequest: + link_id: str + """ + ID of the link to detach the VPC from. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DisableRoutePropagationRequest: + link_id: str + """ + ID of the link on which to disable route propagation. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class EnableRoutePropagationRequest: + link_id: str + """ + ID of the link on which to enable route propagation. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDedicatedConnectionRequest: + connection_id: str + """ + ID of connection to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetLinkRequest: + link_id: str + """ + ID of the link to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetPartnerRequest: + partner_id: str + """ + ID of partner to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetPopRequest: + pop_id: str + """ + ID of PoP to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetRoutingPolicyRequest: + routing_policy_id: str + """ + ID of the routing policy to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListDedicatedConnectionsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListDedicatedConnectionsRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of connections to return per page. + """ + + project_id: Optional[str] + """ + Project ID to filter for. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. + """ + + name: Optional[str] + """ + Link name to filter for. + """ + + tags: Optional[List[str]] + """ + Tags to filter for. + """ + + status: Optional[DedicatedConnectionStatus] + """ + Connection status to filter for. + """ + + bandwidth_mbps: Optional[int] + """ + Filter for dedicated connections with this bandwidth size. + """ + + pop_id: Optional[str] + """ + Filter for dedicated connections present in this PoP. + """ + + +@dataclass +class ListDedicatedConnectionsResponse: + connections: List[DedicatedConnection] + """ + List of connections on current page. + """ + + total_count: int + """ + Total number of connections returned. + """ + + +@dataclass +class ListLinksRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListLinksRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of links to return per page. + """ + + project_id: Optional[str] + """ + Project ID to filter for. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. + """ + + name: Optional[str] + """ + Link name to filter for. + """ + + tags: Optional[List[str]] + """ + Tags to filter for. + """ + + status: Optional[LinkStatus] + """ + Link status to filter for. + """ + + bgp_v4_status: Optional[BgpStatus] + """ + BGP IPv4 status to filter for. + """ + + bgp_v6_status: Optional[BgpStatus] + """ + BGP IPv6 status to filter for. + """ + + pop_id: Optional[str] + """ + Filter for links attached to this PoP (via connections). + """ + + bandwidth_mbps: Optional[int] + """ + Filter for link bandwidth (in Mbps). + """ + + partner_id: Optional[str] + """ + Filter for links hosted by this partner. + """ + + vpc_id: Optional[str] + """ + Filter for links attached to this VPC. + """ + + routing_policy_id: Optional[str] + """ + Filter for links using this routing policy. + """ + + pairing_key: Optional[str] + """ + Filter for the link with this pairing_key. + """ + + kind: Optional[LinkKind] + """ + Filter for hosted or self-hosted links. + """ + + connection_id: Optional[str] + """ + Filter for links self-hosted on this connection. + """ + + +@dataclass +class ListLinksResponse: + links: List[Link] + """ + List of links on the current page. + """ + + total_count: int + """ + Total number of links. + """ + + +@dataclass +class ListPartnersRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListPartnersRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of partners to return per page. + """ + + pop_ids: Optional[List[str]] + """ + Filter for partners present (offering a connection) in one of these PoPs. + """ + + +@dataclass +class ListPartnersResponse: + partners: List[Partner] + """ + List of partners on current page. + """ + + total_count: int + """ + Total number of partners returned. + """ + + +@dataclass +class ListPopsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListPopsRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of PoPs to return per page. + """ + + name: Optional[str] + """ + PoP name to filter for. + """ + + hosting_provider_name: Optional[str] + """ + Hosting provider name to filter for. + """ + + partner_id: Optional[str] + """ + Filter for PoPs hosting an available shared connection from this partner. + """ + + link_bandwidth_mbps: Optional[int] + """ + Filter for PoPs with a shared connection allowing this bandwidth size. Note that we cannot guarantee that PoPs returned will have available capacity. + """ + + dedicated_available: Optional[bool] + """ + Filter for PoPs with a dedicated connection available for self-hosted links. + """ + + +@dataclass +class ListPopsResponse: + pops: List[Pop] + """ + List of PoPs on the current page. + """ + + total_count: int + """ + Total number of PoPs. + """ + + +@dataclass +class ListRoutingPoliciesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListRoutingPoliciesRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of routing policies to return per page. + """ + + project_id: Optional[str] + """ + Project ID to filter for. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. + """ + + name: Optional[str] + """ + Routing policy name to filter for. + """ + + tags: Optional[List[str]] + """ + Tags to filter for. + """ + + +@dataclass +class ListRoutingPoliciesResponse: + routing_policies: List[RoutingPolicy] + + total_count: int + + +@dataclass +class UpdateLinkRequest: + link_id: str + """ + ID of the link to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the link. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the link. + """ + + peer_asn: Optional[int] + """ + For self-hosted links, AS Number to establish BGP session. + """ + + +@dataclass +class UpdateRoutingPolicyRequest: + routing_policy_id: str + """ + ID of the routing policy to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the routing policy. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the routing policy. + """ + + prefix_filter_in: Optional[List[str]] + """ + IP prefixes to accept from the peer (ranges of route announcements to accept). + """ + + prefix_filter_out: Optional[List[str]] + """ + IP prefix filters for routes to advertise to the peer (ranges of routes to advertise). + """ diff --git a/scaleway-async/scaleway_async/iot/v1/api.py b/scaleway-async/scaleway_async/iot/v1/api.py index 041db4fd..fc9386bb 100644 --- a/scaleway-async/scaleway_async/iot/v1/api.py +++ b/scaleway-async/scaleway_async/iot/v1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( WaitForOptions, @@ -100,13 +100,13 @@ class IotV1API(API): """ - This API allows you to manage IoT hubs and devices. + This API allows you to manage your IoT hubs and devices. """ async def list_hubs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListHubsRequestOrderBy] = None, @@ -156,7 +156,7 @@ async def list_hubs( async def list_hubs_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListHubsRequestOrderBy] = None, @@ -201,7 +201,7 @@ async def create_hub( self, *, product_plan: HubProductPlan, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, project_id: Optional[str] = None, disable_events: Optional[bool] = None, @@ -257,7 +257,7 @@ async def get_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hub: """ Get a hub. @@ -291,7 +291,7 @@ async def wait_for_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Hub, Union[bool, Awaitable[bool]]]] = None, ) -> Hub: """ @@ -328,7 +328,7 @@ async def update_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, product_plan: Optional[HubProductPlan] = None, disable_events: Optional[bool] = None, @@ -388,7 +388,7 @@ async def enable_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hub: """ Enable a hub. @@ -423,7 +423,7 @@ async def disable_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hub: """ Disable a hub. @@ -458,7 +458,7 @@ async def delete_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, delete_devices: Optional[bool] = None, ) -> None: """ @@ -495,7 +495,7 @@ async def get_hub_metrics( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, start_date: Optional[datetime] = None, ) -> GetHubMetricsResponse: """ @@ -537,7 +537,7 @@ async def set_hub_ca( hub_id: str, ca_cert_pem: str, challenge_cert_pem: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hub: """ Set the certificate authority of a hub. @@ -584,7 +584,7 @@ async def get_hub_ca( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> GetHubCAResponse: """ Get the certificate authority of a hub. @@ -617,7 +617,7 @@ async def get_hub_ca( async def list_devices( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDevicesRequestOrderBy] = None, @@ -635,7 +635,7 @@ async def list_devices( :param order_by: Ordering of requested devices. :param name: Name to filter for, only devices with this name will be returned. :param hub_id: Hub ID to filter for, only devices attached to this Hub will be returned. - :param allow_insecure: Defines wheter to filter the allow_insecure flag. + :param allow_insecure: Defines whether to filter the allow_insecure flag. :param status: Device status (enabled, disabled, etc.). :return: :class:`ListDevicesResponse ` @@ -669,7 +669,7 @@ async def list_devices( async def list_devices_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDevicesRequestOrderBy] = None, @@ -687,7 +687,7 @@ async def list_devices_all( :param order_by: Ordering of requested devices. :param name: Name to filter for, only devices with this name will be returned. :param hub_id: Hub ID to filter for, only devices attached to this Hub will be returned. - :param allow_insecure: Defines wheter to filter the allow_insecure flag. + :param allow_insecure: Defines whether to filter the allow_insecure flag. :param status: Device status (enabled, disabled, etc.). :return: :class:`List[Device] ` @@ -719,7 +719,7 @@ async def create_device( hub_id: str, allow_insecure: bool, allow_multiple_connections: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, message_filters: Optional[DeviceMessageFilters] = None, description: Optional[str] = None, @@ -774,7 +774,7 @@ async def get_device( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Device: """ Get a device. @@ -808,7 +808,7 @@ async def update_device( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, allow_insecure: Optional[bool] = None, allow_multiple_connections: Optional[bool] = None, @@ -864,7 +864,7 @@ async def enable_device( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Device: """ Enable a device. @@ -899,7 +899,7 @@ async def disable_device( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Device: """ Disable a device. @@ -934,7 +934,7 @@ async def renew_device_certificate( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> RenewDeviceCertificateResponse: """ Renew a device certificate. @@ -970,7 +970,7 @@ async def set_device_certificate( *, device_id: str, certificate_pem: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SetDeviceCertificateResponse: """ Set a custom certificate on a device. @@ -1014,7 +1014,7 @@ async def get_device_certificate( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> GetDeviceCertificateResponse: """ Get a device's certificate. @@ -1048,7 +1048,7 @@ async def delete_device( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Remove a device. @@ -1080,7 +1080,7 @@ async def get_device_metrics( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, start_date: Optional[datetime] = None, ) -> GetDeviceMetricsResponse: """ @@ -1119,7 +1119,7 @@ async def get_device_metrics( async def list_routes( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, @@ -1165,7 +1165,7 @@ async def list_routes( async def list_routes_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, @@ -1208,7 +1208,7 @@ async def create_route( *, hub_id: str, topic: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, s3_config: Optional[CreateRouteRequestS3Config] = None, db_config: Optional[CreateRouteRequestDatabaseConfig] = None, @@ -1222,15 +1222,15 @@ async def create_route( You need to manage the database by yourself. - REST Route. Create a route that will call a REST API on received subscribed MQTT messages. - - S3 Routes. - Create a route that will put subscribed MQTT messages into an S3 bucket. + - Amazon S3 Routes. + Create a route that will put subscribed MQTT messages into an Object Storage bucket. You need to create the bucket yourself and grant write access. Granting can be done with s3cmd (`s3cmd setacl s3:// --acl-grant=write:555c69c3-87d0-4bf8-80f1-99a2f757d031:555c69c3-87d0-4bf8-80f1-99a2f757d031`). :param hub_id: Hub ID of the route. :param topic: Topic the route subscribes to. It must be a valid MQTT topic and up to 65535 characters. :param region: Region to target. If none is passed will use default region from the config. :param name: Route name. - :param s3_config: If creating S3 Route, S3-specific configuration fields. + :param s3_config: If creating Amazon S3 Routes, Amazon S3-specific configuration fields. One-Of ('config'): at most one of 's3_config', 'db_config', 'rest_config' could be set. :param db_config: If creating Database Route, DB-specific configuration fields. One-Of ('config'): at most one of 's3_config', 'db_config', 'rest_config' could be set. @@ -1275,7 +1275,7 @@ async def update_route( self, *, route_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, topic: Optional[str] = None, s3_config: Optional[UpdateRouteRequestS3Config] = None, @@ -1289,7 +1289,7 @@ async def update_route( :param region: Region to target. If none is passed will use default region from the config. :param name: Route name. :param topic: Topic the route subscribes to. It must be a valid MQTT topic and up to 65535 characters. - :param s3_config: When updating S3 Route, S3-specific configuration fields. + :param s3_config: When updating Amazon S3 Route, Amazon S3-specific configuration fields. One-Of ('config'): at most one of 's3_config', 'db_config', 'rest_config' could be set. :param db_config: When updating Database Route, DB-specific configuration fields. One-Of ('config'): at most one of 's3_config', 'db_config', 'rest_config' could be set. @@ -1334,7 +1334,7 @@ async def get_route( self, *, route_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Route: """ Get a route. @@ -1368,7 +1368,7 @@ async def delete_route( self, *, route_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a route. @@ -1399,7 +1399,7 @@ async def delete_route( async def list_networks( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNetworksRequestOrderBy] = None, @@ -1447,7 +1447,7 @@ async def list_networks( async def list_networks_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNetworksRequestOrderBy] = None, @@ -1493,7 +1493,7 @@ async def create_network( type_: NetworkNetworkType, hub_id: str, topic_prefix: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, ) -> CreateNetworkResponse: """ @@ -1542,7 +1542,7 @@ async def get_network( self, *, network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Network: """ Retrieve a specific network. @@ -1576,7 +1576,7 @@ async def delete_network( self, *, network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a Network. @@ -1609,7 +1609,7 @@ async def get_twin_document( *, twin_id: str, document_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> TwinDocument: """ BETA - Get a Cloud Twin Document. @@ -1646,7 +1646,7 @@ async def put_twin_document( *, twin_id: str, document_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, version: Optional[int] = None, data: Optional[Dict[str, Any]] = None, ) -> TwinDocument: @@ -1697,7 +1697,7 @@ async def patch_twin_document( *, twin_id: str, document_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, version: Optional[int] = None, data: Optional[Dict[str, Any]] = None, ) -> TwinDocument: @@ -1753,7 +1753,7 @@ async def delete_twin_document( *, twin_id: str, document_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ BETA - Delete a Cloud Twin Document. @@ -1787,7 +1787,7 @@ async def list_twin_documents( self, *, twin_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListTwinDocumentsResponse: """ BETA - List the documents of a Cloud Twin. @@ -1820,7 +1820,7 @@ async def delete_twin_documents( self, *, twin_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ BETA - Delete all the documents of a Cloud Twin. diff --git a/scaleway-async/scaleway_async/iot/v1/marshalling.py b/scaleway-async/scaleway_async/iot/v1/marshalling.py index 97f75d2c..518fb91e 100644 --- a/scaleway-async/scaleway_async/iot/v1/marshalling.py +++ b/scaleway-async/scaleway_async/iot/v1/marshalling.py @@ -75,6 +75,8 @@ def unmarshal_DeviceMessageFiltersRule(data: Any) -> DeviceMessageFiltersRule: field = data.get("topics", None) if field is not None: args["topics"] = field + else: + args["topics"] = None return DeviceMessageFiltersRule(**args) @@ -90,10 +92,14 @@ def unmarshal_DeviceMessageFilters(data: Any) -> DeviceMessageFilters: field = data.get("publish", None) if field is not None: args["publish"] = unmarshal_DeviceMessageFiltersRule(field) + else: + args["publish"] = None field = data.get("subscribe", None) if field is not None: args["subscribe"] = unmarshal_DeviceMessageFiltersRule(field) + else: + args["subscribe"] = None return DeviceMessageFilters(**args) @@ -131,6 +137,8 @@ def unmarshal_Device(data: Any) -> Device: args["last_activity_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_activity_at"] = None field = data.get("is_connected", None) if field is not None: @@ -151,14 +159,20 @@ def unmarshal_Device(data: Any) -> Device: field = data.get("message_filters", None) if field is not None: args["message_filters"] = unmarshal_DeviceMessageFilters(field) + else: + args["message_filters"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Device(**args) @@ -179,7 +193,7 @@ def unmarshal_Network(data: Any) -> Network: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -198,6 +212,8 @@ def unmarshal_Network(data: Any) -> Network: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return Network(**args) @@ -288,14 +304,20 @@ def unmarshal_Hub(data: Any) -> Hub: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("twins_graphite_config", None) if field is not None: args["twins_graphite_config"] = unmarshal_HubTwinsGraphiteConfig(field) + else: + args["twins_graphite_config"] = None return Hub(**args) @@ -330,10 +352,14 @@ def unmarshal_CreateDeviceResponse(data: Any) -> CreateDeviceResponse: field = data.get("device", None) if field is not None: args["device"] = unmarshal_Device(field) + else: + args["device"] = None field = data.get("certificate", None) if field is not None: args["certificate"] = unmarshal_Certificate(field) + else: + args["certificate"] = None return CreateDeviceResponse(**args) @@ -353,6 +379,8 @@ def unmarshal_CreateNetworkResponse(data: Any) -> CreateNetworkResponse: field = data.get("network", None) if field is not None: args["network"] = unmarshal_Network(field) + else: + args["network"] = None return CreateNetworkResponse(**args) @@ -372,6 +400,8 @@ def unmarshal_GetDeviceCertificateResponse(data: Any) -> GetDeviceCertificateRes field = data.get("device", None) if field is not None: args["device"] = unmarshal_Device(field) + else: + args["device"] = None return GetDeviceCertificateResponse(**args) @@ -510,17 +540,21 @@ def unmarshal_RouteSummary(data: Any) -> RouteSummary: if field is not None: args["topic"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return RouteSummary(**args) @@ -595,10 +629,14 @@ def unmarshal_RenewDeviceCertificateResponse( field = data.get("device", None) if field is not None: args["device"] = unmarshal_Device(field) + else: + args["device"] = None field = data.get("certificate", None) if field is not None: args["certificate"] = unmarshal_Certificate(field) + else: + args["certificate"] = None return RenewDeviceCertificateResponse(**args) @@ -716,29 +754,39 @@ def unmarshal_Route(data: Any) -> Route: if field is not None: args["topic"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("s3_config", None) if field is not None: args["s3_config"] = unmarshal_RouteS3Config(field) + else: + args["s3_config"] = None field = data.get("db_config", None) if field is not None: args["db_config"] = unmarshal_RouteDatabaseConfig(field) + else: + args["db_config"] = None field = data.get("rest_config", None) if field is not None: args["rest_config"] = unmarshal_RouteRestConfig(field) + else: + args["rest_config"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Route(**args) @@ -758,6 +806,8 @@ def unmarshal_SetDeviceCertificateResponse(data: Any) -> SetDeviceCertificateRes field = data.get("device", None) if field is not None: args["device"] = unmarshal_Device(field) + else: + args["device"] = None return SetDeviceCertificateResponse(**args) @@ -785,6 +835,8 @@ def unmarshal_TwinDocument(data: Any) -> TwinDocument: field = data.get("data", None) if field is not None: args["data"] = field + else: + args["data"] = None return TwinDocument(**args) @@ -811,13 +863,11 @@ def marshal_DeviceMessageFilters( output: Dict[str, Any] = {} if request.publish is not None: - output["publish"] = ( - marshal_DeviceMessageFiltersRule(request.publish, defaults), - ) + output["publish"] = marshal_DeviceMessageFiltersRule(request.publish, defaults) if request.subscribe is not None: - output["subscribe"] = ( - marshal_DeviceMessageFiltersRule(request.subscribe, defaults), + output["subscribe"] = marshal_DeviceMessageFiltersRule( + request.subscribe, defaults ) return output @@ -842,8 +892,8 @@ def marshal_CreateDeviceRequest( output["name"] = request.name if request.message_filters is not None: - output["message_filters"] = ( - marshal_DeviceMessageFilters(request.message_filters, defaults), + output["message_filters"] = marshal_DeviceMessageFilters( + request.message_filters, defaults ) if request.description is not None: @@ -1087,8 +1137,8 @@ def marshal_UpdateDeviceRequest( output["allow_multiple_connections"] = request.allow_multiple_connections if request.message_filters is not None: - output["message_filters"] = ( - marshal_DeviceMessageFilters(request.message_filters, defaults), + output["message_filters"] = marshal_DeviceMessageFilters( + request.message_filters, defaults ) if request.hub_id is not None: diff --git a/scaleway-async/scaleway_async/iot/v1/types.py b/scaleway-async/scaleway_async/iot/v1/types.py index a967258a..b6d2338a 100644 --- a/scaleway-async/scaleway_async/iot/v1/types.py +++ b/scaleway-async/scaleway_async/iot/v1/types.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, TimeSeries, ) from scaleway_core.utils import ( @@ -400,7 +400,7 @@ class Hub: Hub events topic prefix. """ - region: Region + region: ScwRegion """ Region of the Hub. """ @@ -544,12 +544,12 @@ class RouteRestConfig: class RouteS3Config: bucket_region: str """ - Region of the S3 route's destination bucket (e.g., 'fr-par'). + Region of the Amazon S3 route's destination bucket (e.g., 'fr-par'). """ bucket_name: str """ - Destination bucket name of the S3 route. + Destination bucket name of the Amazon S3 route. """ object_prefix: str @@ -559,7 +559,7 @@ class RouteS3Config: strategy: RouteS3ConfigS3Strategy """ - How the S3 route's objects will be created: one per topic or one per message. + How the Amazon S3 route's objects will be created: one per topic or one per message. """ @@ -617,7 +617,7 @@ class CreateDeviceRequest: Defines whether to allow multiple physical devices to connect with this device's credentials. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -658,7 +658,7 @@ class CreateHubRequest: Hub product plan. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -703,7 +703,7 @@ class CreateNetworkRequest: Topic prefix for the Network. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -739,7 +739,7 @@ class CreateRouteRequest: Topic the route subscribes to. It must be a valid MQTT topic and up to 65535 characters. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -763,7 +763,7 @@ class DeleteDeviceRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -776,7 +776,7 @@ class DeleteHubRequest: Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -794,7 +794,7 @@ class DeleteNetworkRequest: Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -807,7 +807,7 @@ class DeleteRouteRequest: Route ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -825,7 +825,7 @@ class DeleteTwinDocumentRequest: Name of the document. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -838,7 +838,7 @@ class DeleteTwinDocumentsRequest: Twin ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -851,7 +851,7 @@ class DisableDeviceRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -864,7 +864,7 @@ class DisableHubRequest: Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -877,7 +877,7 @@ class EnableDeviceRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -890,7 +890,7 @@ class EnableHubRequest: Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -903,7 +903,7 @@ class GetDeviceCertificateRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -929,7 +929,7 @@ class GetDeviceMetricsRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -955,7 +955,7 @@ class GetDeviceRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -965,7 +965,7 @@ class GetDeviceRequest: class GetHubCARequest: hub_id: str - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -983,7 +983,7 @@ class GetHubMetricsRequest: Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1009,7 +1009,7 @@ class GetHubRequest: Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1022,7 +1022,7 @@ class GetNetworkRequest: Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1035,7 +1035,7 @@ class GetRouteRequest: Route ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1053,7 +1053,7 @@ class GetTwinDocumentRequest: Name of the document. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1061,7 +1061,7 @@ class GetTwinDocumentRequest: @dataclass class ListDevicesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1093,7 +1093,7 @@ class ListDevicesRequest: allow_insecure: Optional[bool] """ - Defines wheter to filter the allow_insecure flag. + Defines whether to filter the allow_insecure flag. """ status: Optional[DeviceStatus] @@ -1117,7 +1117,7 @@ class ListDevicesResponse: @dataclass class ListHubsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1168,7 +1168,7 @@ class ListHubsResponse: @dataclass class ListNetworksRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1219,7 +1219,7 @@ class ListNetworksResponse: @dataclass class ListRoutesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1270,7 +1270,7 @@ class ListTwinDocumentsRequest: Twin ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1296,7 +1296,7 @@ class PatchTwinDocumentRequest: Name of the document. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1329,7 +1329,7 @@ class PutTwinDocumentRequest: Name of the document. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1352,7 +1352,7 @@ class RenewDeviceCertificateRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1427,7 +1427,7 @@ class SetDeviceCertificateRequest: PEM-encoded custom certificate. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1457,7 +1457,7 @@ class SetHubCARequest: Challenge is a PEM-encoded certificate that acts as proof of possession of the CA. It must be signed by the CA, and have a Common Name equal to the Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1493,7 +1493,7 @@ class UpdateDeviceRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1531,7 +1531,7 @@ class UpdateHubRequest: ID of the Hub you want to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1571,7 +1571,7 @@ class UpdateRouteRequest: Route id. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway-async/scaleway_async/ipam/v1/__init__.py b/scaleway-async/scaleway_async/ipam/v1/__init__.py index 78a2a03c..0cbf4d27 100644 --- a/scaleway-async/scaleway_async/ipam/v1/__init__.py +++ b/scaleway-async/scaleway_async/ipam/v1/__init__.py @@ -5,12 +5,17 @@ from .types import Resource from .types import Reverse from .types import Source +from .types import CustomResource from .types import IP +from .types import AttachIPRequest from .types import BookIPRequest +from .types import DetachIPRequest from .types import GetIPRequest from .types import ListIPsRequest from .types import ListIPsResponse +from .types import MoveIPRequest from .types import ReleaseIPRequest +from .types import ReleaseIPSetRequest from .types import UpdateIPRequest from .api import IpamV1API @@ -20,12 +25,17 @@ "Resource", "Reverse", "Source", + "CustomResource", "IP", + "AttachIPRequest", "BookIPRequest", + "DetachIPRequest", "GetIPRequest", "ListIPsRequest", "ListIPsResponse", + "MoveIPRequest", "ReleaseIPRequest", + "ReleaseIPSetRequest", "UpdateIPRequest", "IpamV1API", ] diff --git a/scaleway-async/scaleway_async/ipam/v1/api.py b/scaleway-async/scaleway_async/ipam/v1/api.py index 50da0304..3b7962f7 100644 --- a/scaleway-async/scaleway_async/ipam/v1/api.py +++ b/scaleway-async/scaleway_async/ipam/v1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( OneOfPossibility, @@ -16,9 +16,14 @@ from .types import ( ListIPsRequestOrderBy, ResourceType, + AttachIPRequest, BookIPRequest, + CustomResource, + DetachIPRequest, IP, ListIPsResponse, + MoveIPRequest, + ReleaseIPSetRequest, Reverse, Source, UpdateIPRequest, @@ -26,14 +31,18 @@ from .marshalling import ( unmarshal_IP, unmarshal_ListIPsResponse, + marshal_AttachIPRequest, marshal_BookIPRequest, + marshal_DetachIPRequest, + marshal_MoveIPRequest, + marshal_ReleaseIPSetRequest, marshal_UpdateIPRequest, ) class IpamV1API(API): """ - This API allows you to manage IP addresses with Scaleway's IP Address Management tool. + This API allows you to manage your Scaleway IP addresses with our IP Address Management tool. """ async def book_ip( @@ -41,20 +50,22 @@ async def book_ip( *, source: Source, is_ipv6: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, address: Optional[str] = None, tags: Optional[List[str]] = None, + resource: Optional[CustomResource] = None, ) -> IP: """ - Book a new IP. - Book a new IP from the specified source. Currently IPs can only be booked from a Private Network. - :param source: Source in which to book the IP. Not all sources are available for booking. + Reserve a new IP. + Reserve a new IP from the specified source. Currently IPs can only be reserved from a Private Network. + :param source: Source in which to reserve the IP. Not all sources are available for reservation. :param is_ipv6: Request an IPv6 instead of an IPv4. :param region: Region to target. If none is passed will use default region from the config. :param project_id: When creating an IP in a Private Network, the Project must match the Private Network's Project. - :param address: Note that only the Private Network source allows you to pick a specific IP. If the requested IP is already booked, then the call will fail. + :param address: The requested address should not include the subnet mask (/suffix). Note that only the Private Network source allows you to pick a specific IP. If the requested IP is already reserved, then the call will fail. :param tags: Tags for the IP. + :param resource: Custom resource to attach to the IP being reserved. An example of a custom resource is a virtual machine hosted on an Elastic Metal server. Do not use this for attaching IP addresses to standard Scaleway resources, as it will fail - instead, see the relevant product API for an equivalent method. :return: :class:`IP ` Usage: @@ -81,6 +92,7 @@ async def book_ip( project_id=project_id, address=address, tags=tags, + resource=resource, ), self.client, ), @@ -93,7 +105,7 @@ async def release_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Release an IP. @@ -122,11 +134,45 @@ async def release_ip( self._throw_on_error(res) + async def release_ip_set( + self, + *, + region: Optional[ScwRegion] = None, + ip_ids: Optional[List[str]] = None, + ) -> None: + """ + :param region: Region to target. If none is passed will use default region from the config. + :param ip_ids: + + Usage: + :: + + result = await api.release_ip_set() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/ipam/v1/regions/{param_region}/ip-sets/release", + body=marshal_ReleaseIPSetRequest( + ReleaseIPSetRequest( + region=region, + ip_ids=ip_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + async def get_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> IP: """ Get an IP. @@ -160,7 +206,7 @@ async def update_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, tags: Optional[List[str]] = None, reverses: Optional[List[Reverse]] = None, ) -> IP: @@ -206,21 +252,26 @@ async def update_ip( async def list_i_ps( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, zonal: Optional[str] = None, private_network_id: Optional[str] = None, + subnet_id: Optional[str] = None, + vpc_id: Optional[str] = None, attached: Optional[bool] = None, + resource_name: Optional[str] = None, resource_id: Optional[str] = None, + resource_ids: Optional[List[str]] = None, resource_type: Optional[ResourceType] = None, + resource_types: Optional[List[ResourceType]] = None, mac_address: Optional[str] = None, tags: Optional[List[str]] = None, organization_id: Optional[str] = None, is_ipv6: Optional[bool] = None, - resource_name: Optional[str] = None, + ip_ids: Optional[List[str]] = None, ) -> ListIPsResponse: """ List existing IPs. @@ -231,17 +282,23 @@ async def list_i_ps( :param page_size: Maximum number of IPs to return per page. :param project_id: Project ID to filter for. Only IPs belonging to this Project will be returned. :param zonal: Zone to filter for. Only IPs that are zonal, and in this zone, will be returned. - One-Of ('source'): at most one of 'zonal', 'private_network_id' could be set. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. :param private_network_id: Only IPs that are private, and in this Private Network, will be returned. - One-Of ('source'): at most one of 'zonal', 'private_network_id' could be set. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. + :param subnet_id: Only IPs inside this exact subnet will be returned. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. + :param vpc_id: Only IPs owned by resources in this VPC will be returned. :param attached: Defines whether to filter only for IPs which are attached to a resource. + :param resource_name: Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. :param resource_id: Resource ID to filter for. Only IPs attached to this resource will be returned. + :param resource_ids: Resource IDs to filter for. Only IPs attached to at least one of these resources will be returned. :param resource_type: Resource type to filter for. Only IPs attached to this type of resource will be returned. + :param resource_types: Resource types to filter for. Only IPs attached to these types of resources will be returned. :param mac_address: MAC address to filter for. Only IPs attached to a resource with this MAC address will be returned. :param tags: Tags to filter for, only IPs with one or more matching tags will be returned. :param organization_id: Organization ID to filter for. Only IPs belonging to this Organization will be returned. :param is_ipv6: Defines whether to filter only for IPv4s or IPv6s. - :param resource_name: Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. + :param ip_ids: IP IDs to filter for. Only IPs with these UUIDs will be returned. :return: :class:`ListIPsResponse ` Usage: @@ -259,6 +316,7 @@ async def list_i_ps( f"/ipam/v1/regions/{param_region}/ips", params={ "attached": attached, + "ip_ids": ip_ids, "is_ipv6": is_ipv6, "mac_address": mac_address, "order_by": order_by, @@ -268,12 +326,16 @@ async def list_i_ps( "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, "resource_id": resource_id, + "resource_ids": resource_ids, "resource_name": resource_name, "resource_type": resource_type, + "resource_types": resource_types, "tags": tags, + "vpc_id": vpc_id, **resolve_one_of( [ OneOfPossibility("private_network_id", private_network_id), + OneOfPossibility("subnet_id", subnet_id), OneOfPossibility("zonal", zonal), ] ), @@ -286,21 +348,26 @@ async def list_i_ps( async def list_i_ps_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, zonal: Optional[str] = None, private_network_id: Optional[str] = None, + subnet_id: Optional[str] = None, + vpc_id: Optional[str] = None, attached: Optional[bool] = None, + resource_name: Optional[str] = None, resource_id: Optional[str] = None, + resource_ids: Optional[List[str]] = None, resource_type: Optional[ResourceType] = None, + resource_types: Optional[List[ResourceType]] = None, mac_address: Optional[str] = None, tags: Optional[List[str]] = None, organization_id: Optional[str] = None, is_ipv6: Optional[bool] = None, - resource_name: Optional[str] = None, + ip_ids: Optional[List[str]] = None, ) -> List[IP]: """ List existing IPs. @@ -311,17 +378,23 @@ async def list_i_ps_all( :param page_size: Maximum number of IPs to return per page. :param project_id: Project ID to filter for. Only IPs belonging to this Project will be returned. :param zonal: Zone to filter for. Only IPs that are zonal, and in this zone, will be returned. - One-Of ('source'): at most one of 'zonal', 'private_network_id' could be set. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. :param private_network_id: Only IPs that are private, and in this Private Network, will be returned. - One-Of ('source'): at most one of 'zonal', 'private_network_id' could be set. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. + :param subnet_id: Only IPs inside this exact subnet will be returned. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. + :param vpc_id: Only IPs owned by resources in this VPC will be returned. :param attached: Defines whether to filter only for IPs which are attached to a resource. + :param resource_name: Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. :param resource_id: Resource ID to filter for. Only IPs attached to this resource will be returned. + :param resource_ids: Resource IDs to filter for. Only IPs attached to at least one of these resources will be returned. :param resource_type: Resource type to filter for. Only IPs attached to this type of resource will be returned. + :param resource_types: Resource types to filter for. Only IPs attached to these types of resources will be returned. :param mac_address: MAC address to filter for. Only IPs attached to a resource with this MAC address will be returned. :param tags: Tags to filter for, only IPs with one or more matching tags will be returned. :param organization_id: Organization ID to filter for. Only IPs belonging to this Organization will be returned. :param is_ipv6: Defines whether to filter only for IPv4s or IPv6s. - :param resource_name: Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. + :param ip_ids: IP IDs to filter for. Only IPs with these UUIDs will be returned. :return: :class:`List[IP] ` Usage: @@ -340,15 +413,158 @@ async def list_i_ps_all( "page": page, "page_size": page_size, "project_id": project_id, + "vpc_id": vpc_id, "attached": attached, + "resource_name": resource_name, "resource_id": resource_id, + "resource_ids": resource_ids, "resource_type": resource_type, + "resource_types": resource_types, "mac_address": mac_address, "tags": tags, "organization_id": organization_id, "is_ipv6": is_ipv6, - "resource_name": resource_name, + "ip_ids": ip_ids, "zonal": zonal, "private_network_id": private_network_id, + "subnet_id": subnet_id, }, ) + + async def attach_ip( + self, + *, + ip_id: str, + resource: CustomResource, + region: Optional[ScwRegion] = None, + ) -> IP: + """ + Attach IP to custom resource. + Attach an existing reserved IP from a Private Network subnet to a custom, named resource via its MAC address. An example of a custom resource is a virtual machine hosted on an Elastic Metal server. Do not use this method for attaching IP addresses to standard Scaleway resources as it will fail - see the relevant product API for an equivalent method. + :param ip_id: IP ID. + :param resource: Custom resource to be attached to the IP. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`IP ` + + Usage: + :: + + result = await api.attach_ip( + ip_id="example", + resource=CustomResource(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "POST", + f"/ipam/v1/regions/{param_region}/ips/{param_ip_id}/attach", + body=marshal_AttachIPRequest( + AttachIPRequest( + ip_id=ip_id, + resource=resource, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + async def detach_ip( + self, + *, + ip_id: str, + resource: CustomResource, + region: Optional[ScwRegion] = None, + ) -> IP: + """ + Detach IP from a custom resource. + Detach a private IP from a custom resource. An example of a custom resource is a virtual machine hosted on an Elastic Metal server. Do not use this method for detaching IP addresses from standard Scaleway resources (e.g. Instances, Load Balancers) as it will fail - see the relevant product API for an equivalent method. + :param ip_id: IP ID. + :param resource: Custom resource currently attached to the IP. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`IP ` + + Usage: + :: + + result = await api.detach_ip( + ip_id="example", + resource=CustomResource(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "POST", + f"/ipam/v1/regions/{param_region}/ips/{param_ip_id}/detach", + body=marshal_DetachIPRequest( + DetachIPRequest( + ip_id=ip_id, + resource=resource, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + async def move_ip( + self, + *, + ip_id: str, + from_resource: CustomResource, + region: Optional[ScwRegion] = None, + to_resource: Optional[CustomResource] = None, + ) -> IP: + """ + Move IP to a custom resource. + Move an existing reserved private IP from one custom resource (e.g. a virtual machine hosted on an Elastic Metal server) to another custom resource. This will detach it from the first resource, and attach it to the second. Do not use this method for moving IP addresses between standard Scaleway resources (e.g. Instances, Load Balancers) as it will fail - see the relevant product API for an equivalent method. + :param ip_id: IP ID. + :param from_resource: Custom resource currently attached to the IP. + :param region: Region to target. If none is passed will use default region from the config. + :param to_resource: Custom resource to be attached to the IP. + :return: :class:`IP ` + + Usage: + :: + + result = await api.move_ip( + ip_id="example", + from_resource=CustomResource(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "POST", + f"/ipam/v1/regions/{param_region}/ips/{param_ip_id}/move", + body=marshal_MoveIPRequest( + MoveIPRequest( + ip_id=ip_id, + from_resource=from_resource, + region=region, + to_resource=to_resource, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) diff --git a/scaleway-async/scaleway_async/ipam/v1/marshalling.py b/scaleway-async/scaleway_async/ipam/v1/marshalling.py index bcd99871..dc61dff9 100644 --- a/scaleway-async/scaleway_async/ipam/v1/marshalling.py +++ b/scaleway-async/scaleway_async/ipam/v1/marshalling.py @@ -15,7 +15,12 @@ Source, IP, ListIPsResponse, + CustomResource, + AttachIPRequest, BookIPRequest, + DetachIPRequest, + MoveIPRequest, + ReleaseIPSetRequest, UpdateIPRequest, ) @@ -28,7 +33,7 @@ def unmarshal_Resource(data: Any) -> Resource: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -39,10 +44,14 @@ def unmarshal_Resource(data: Any) -> Resource: field = data.get("mac_address", None) if field is not None: args["mac_address"] = field + else: + args["mac_address"] = None field = data.get("name", None) if field is not None: args["name"] = field + else: + args["name"] = None return Resource(**args) @@ -62,6 +71,8 @@ def unmarshal_Reverse(data: Any) -> Reverse: field = data.get("address", None) if field is not None: args["address"] = field + else: + args["address"] = None return Reverse(**args) @@ -77,14 +88,20 @@ def unmarshal_Source(data: Any) -> Source: field = data.get("zonal", None) if field is not None: args["zonal"] = field + else: + args["zonal"] = None field = data.get("private_network_id", None) if field is not None: args["private_network_id"] = field + else: + args["private_network_id"] = None field = data.get("subnet_id", None) if field is not None: args["subnet_id"] = field + else: + args["subnet_id"] = None return Source(**args) @@ -113,10 +130,6 @@ def unmarshal_IP(data: Any) -> IP: if field is not None: args["is_ipv6"] = field - field = data.get("source", None) - if field is not None: - args["source"] = unmarshal_Source(field) - field = data.get("tags", None) if field is not None: args["tags"] = field @@ -134,18 +147,32 @@ def unmarshal_IP(data: Any) -> IP: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("source", None) + if field is not None: + args["source"] = unmarshal_Source(field) + else: + args["source"] = None field = data.get("resource", None) if field is not None: args["resource"] = unmarshal_Resource(field) + else: + args["resource"] = None field = data.get("zone", None) if field is not None: args["zone"] = field + else: + args["zone"] = None return IP(**args) @@ -169,6 +196,33 @@ def unmarshal_ListIPsResponse(data: Any) -> ListIPsResponse: return ListIPsResponse(**args) +def marshal_CustomResource( + request: CustomResource, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.mac_address is not None: + output["mac_address"] = request.mac_address + + if request.name is not None: + output["name"] = request.name + + return output + + +def marshal_AttachIPRequest( + request: AttachIPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.resource is not None: + output["resource"] = marshal_CustomResource(request.resource, defaults) + + return output + + def marshal_Source( request: Source, defaults: ProfileDefaults, @@ -194,7 +248,7 @@ def marshal_BookIPRequest( output: Dict[str, Any] = {} if request.source is not None: - output["source"] = (marshal_Source(request.source, defaults),) + output["source"] = marshal_Source(request.source, defaults) if request.is_ipv6 is not None: output["is_ipv6"] = request.is_ipv6 @@ -208,6 +262,50 @@ def marshal_BookIPRequest( if request.tags is not None: output["tags"] = request.tags + if request.resource is not None: + output["resource"] = marshal_CustomResource(request.resource, defaults) + + return output + + +def marshal_DetachIPRequest( + request: DetachIPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.resource is not None: + output["resource"] = marshal_CustomResource(request.resource, defaults) + + return output + + +def marshal_MoveIPRequest( + request: MoveIPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.from_resource is not None: + output["from_resource"] = marshal_CustomResource( + request.from_resource, defaults + ) + + if request.to_resource is not None: + output["to_resource"] = marshal_CustomResource(request.to_resource, defaults) + + return output + + +def marshal_ReleaseIPSetRequest( + request: ReleaseIPSetRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip_ids is not None: + output["ip_ids"] = request.ip_ids + return output diff --git a/scaleway-async/scaleway_async/ipam/v1/types.py b/scaleway-async/scaleway_async/ipam/v1/types.py index 61365126..1c7ed6fb 100644 --- a/scaleway-async/scaleway_async/ipam/v1/types.py +++ b/scaleway-async/scaleway_async/ipam/v1/types.py @@ -8,8 +8,8 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, - Zone, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -30,6 +30,7 @@ def __str__(self) -> str: class ResourceType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_TYPE = "unknown_type" + CUSTOM = "custom" INSTANCE_SERVER = "instance_server" INSTANCE_IP = "instance_ip" INSTANCE_PRIVATE_NIC = "instance_private_nic" @@ -44,6 +45,13 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): BAREMETAL_SERVER = "baremetal_server" BAREMETAL_PRIVATE_NIC = "baremetal_private_nic" LLM_DEPLOYMENT = "llm_deployment" + MGDB_INSTANCE = "mgdb_instance" + APPLE_SILICON_SERVER = "apple_silicon_server" + APPLE_SILICON_PRIVATE_NIC = "apple_silicon_private_nic" + SERVERLESS_CONTAINER = "serverless_container" + SERVERLESS_FUNCTION = "serverless_function" + VPN_GATEWAY = "vpn_gateway" + DDL_DATALAB = "ddl_datalab" def __str__(self) -> str: return str(self.value) @@ -94,6 +102,19 @@ class Source: subnet_id: Optional[str] +@dataclass +class CustomResource: + mac_address: str + """ + MAC address of the custom resource. + """ + + name: Optional[str] + """ + When the resource is in a Private Network, a DNS record is available to resolve the resource name. + """ + + @dataclass class IP: id: str @@ -116,11 +137,6 @@ class IP: Defines whether the IP is an IPv6 (false = IPv4). """ - source: Source - """ - Source pool where the IP was booked in. - """ - tags: List[str] """ Tags for the IP. @@ -131,14 +147,14 @@ class IP: Array of reverses associated with the IP. """ - region: Region + region: ScwRegion """ Region of the IP. """ created_at: Optional[datetime] """ - Date the IP was booked. + Date the IP was reserved. """ updated_at: Optional[datetime] @@ -146,22 +162,45 @@ class IP: Date the IP was last modified. """ + source: Optional[Source] + """ + Source pool where the IP was reserved in. + """ + resource: Optional[Resource] """ Resource which the IP is attached to. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone of the IP, if zonal. """ +@dataclass +class AttachIPRequest: + ip_id: str + """ + IP ID. + """ + + resource: CustomResource + """ + Custom resource to be attached to the IP. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class BookIPRequest: source: Source """ - Source in which to book the IP. Not all sources are available for booking. + Source in which to reserve the IP. Not all sources are available for reservation. """ is_ipv6: bool @@ -169,7 +208,7 @@ class BookIPRequest: Request an IPv6 instead of an IPv4. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -181,7 +220,7 @@ class BookIPRequest: address: Optional[str] """ - Note that only the Private Network source allows you to pick a specific IP. If the requested IP is already booked, then the call will fail. + The requested address should not include the subnet mask (/suffix). Note that only the Private Network source allows you to pick a specific IP. If the requested IP is already reserved, then the call will fail. """ tags: Optional[List[str]] @@ -189,6 +228,29 @@ class BookIPRequest: Tags for the IP. """ + resource: Optional[CustomResource] + """ + Custom resource to attach to the IP being reserved. An example of a custom resource is a virtual machine hosted on an Elastic Metal server. Do not use this for attaching IP addresses to standard Scaleway resources, as it will fail - instead, see the relevant product API for an equivalent method. + """ + + +@dataclass +class DetachIPRequest: + ip_id: str + """ + IP ID. + """ + + resource: CustomResource + """ + Custom resource currently attached to the IP. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + @dataclass class GetIPRequest: @@ -197,7 +259,7 @@ class GetIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -205,7 +267,7 @@ class GetIPRequest: @dataclass class ListIPsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -230,21 +292,41 @@ class ListIPsRequest: Project ID to filter for. Only IPs belonging to this Project will be returned. """ + vpc_id: Optional[str] + """ + Only IPs owned by resources in this VPC will be returned. + """ + attached: Optional[bool] """ Defines whether to filter only for IPs which are attached to a resource. """ + resource_name: Optional[str] + """ + Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. + """ + resource_id: Optional[str] """ Resource ID to filter for. Only IPs attached to this resource will be returned. """ + resource_ids: Optional[List[str]] + """ + Resource IDs to filter for. Only IPs attached to at least one of these resources will be returned. + """ + resource_type: Optional[ResourceType] """ Resource type to filter for. Only IPs attached to this type of resource will be returned. """ + resource_types: Optional[List[ResourceType]] + """ + Resource types to filter for. Only IPs attached to these types of resources will be returned. + """ + mac_address: Optional[str] """ MAC address to filter for. Only IPs attached to a resource with this MAC address will be returned. @@ -265,15 +347,17 @@ class ListIPsRequest: Defines whether to filter only for IPv4s or IPv6s. """ - resource_name: Optional[str] + ip_ids: Optional[List[str]] """ - Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. + IP IDs to filter for. Only IPs with these UUIDs will be returned. """ zonal: Optional[str] private_network_id: Optional[str] + subnet_id: Optional[str] + @dataclass class ListIPsResponse: @@ -282,6 +366,29 @@ class ListIPsResponse: ips: List[IP] +@dataclass +class MoveIPRequest: + ip_id: str + """ + IP ID. + """ + + from_resource: CustomResource + """ + Custom resource currently attached to the IP. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + to_resource: Optional[CustomResource] + """ + Custom resource to be attached to the IP. + """ + + @dataclass class ReleaseIPRequest: ip_id: str @@ -289,12 +396,22 @@ class ReleaseIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class ReleaseIPSetRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + ip_ids: Optional[List[str]] + + @dataclass class UpdateIPRequest: ip_id: str @@ -302,7 +419,7 @@ class UpdateIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway-async/scaleway_async/jobs/v1alpha1/__init__.py b/scaleway-async/scaleway_async/jobs/v1alpha1/__init__.py index 5fb7578b..31880b35 100644 --- a/scaleway-async/scaleway_async/jobs/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/jobs/v1alpha1/__init__.py @@ -4,23 +4,39 @@ from .content import JOB_RUN_TRANSIENT_STATUSES from .types import ListJobDefinitionsRequestOrderBy from .types import ListJobRunsRequestOrderBy +from .types import SecretEnvVar +from .types import SecretFile from .types import CronSchedule from .types import CreateJobDefinitionRequestCronScheduleConfig +from .types import CreateJobDefinitionSecretsRequestSecretConfig +from .types import Secret from .types import JobDefinition from .types import JobRun +from .types import Resource from .types import UpdateJobDefinitionRequestCronScheduleConfig from .types import CreateJobDefinitionRequest +from .types import CreateJobDefinitionSecretsRequest +from .types import CreateJobDefinitionSecretsResponse from .types import DeleteJobDefinitionRequest +from .types import DeleteJobDefinitionSecretRequest from .types import GetJobDefinitionRequest +from .types import GetJobDefinitionSecretRequest from .types import GetJobRunRequest +from .types import GetJobsLimitsRequest +from .types import JobsLimits +from .types import ListJobDefinitionSecretsRequest +from .types import ListJobDefinitionSecretsResponse from .types import ListJobDefinitionsRequest from .types import ListJobDefinitionsResponse from .types import ListJobRunsRequest from .types import ListJobRunsResponse +from .types import ListJobsResourcesRequest +from .types import ListJobsResourcesResponse from .types import StartJobDefinitionRequest from .types import StartJobDefinitionResponse from .types import StopJobRunRequest from .types import UpdateJobDefinitionRequest +from .types import UpdateJobDefinitionSecretRequest from .api import JobsV1Alpha1API __all__ = [ @@ -28,22 +44,38 @@ "JOB_RUN_TRANSIENT_STATUSES", "ListJobDefinitionsRequestOrderBy", "ListJobRunsRequestOrderBy", + "SecretEnvVar", + "SecretFile", "CronSchedule", "CreateJobDefinitionRequestCronScheduleConfig", + "CreateJobDefinitionSecretsRequestSecretConfig", + "Secret", "JobDefinition", "JobRun", + "Resource", "UpdateJobDefinitionRequestCronScheduleConfig", "CreateJobDefinitionRequest", + "CreateJobDefinitionSecretsRequest", + "CreateJobDefinitionSecretsResponse", "DeleteJobDefinitionRequest", + "DeleteJobDefinitionSecretRequest", "GetJobDefinitionRequest", + "GetJobDefinitionSecretRequest", "GetJobRunRequest", + "GetJobsLimitsRequest", + "JobsLimits", + "ListJobDefinitionSecretsRequest", + "ListJobDefinitionSecretsResponse", "ListJobDefinitionsRequest", "ListJobDefinitionsResponse", "ListJobRunsRequest", "ListJobRunsResponse", + "ListJobsResourcesRequest", + "ListJobsResourcesResponse", "StartJobDefinitionRequest", "StartJobDefinitionResponse", "StopJobRunRequest", "UpdateJobDefinitionRequest", + "UpdateJobDefinitionSecretRequest", "JobsV1Alpha1API", ] diff --git a/scaleway-async/scaleway_async/jobs/v1alpha1/api.py b/scaleway-async/scaleway_async/jobs/v1alpha1/api.py index 3260c1c5..6b3dab57 100644 --- a/scaleway-async/scaleway_async/jobs/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/jobs/v1alpha1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( random_name, @@ -13,34 +13,50 @@ fetch_all_pages_async, ) from .types import ( + JobRunState, ListJobDefinitionsRequestOrderBy, ListJobRunsRequestOrderBy, CreateJobDefinitionRequest, CreateJobDefinitionRequestCronScheduleConfig, + CreateJobDefinitionSecretsRequest, + CreateJobDefinitionSecretsRequestSecretConfig, + CreateJobDefinitionSecretsResponse, JobDefinition, JobRun, + JobsLimits, + ListJobDefinitionSecretsResponse, ListJobDefinitionsResponse, ListJobRunsResponse, + ListJobsResourcesResponse, + Secret, StartJobDefinitionRequest, StartJobDefinitionResponse, UpdateJobDefinitionRequest, UpdateJobDefinitionRequestCronScheduleConfig, + UpdateJobDefinitionSecretRequest, ) from .marshalling import ( + unmarshal_Secret, unmarshal_JobDefinition, unmarshal_JobRun, + unmarshal_CreateJobDefinitionSecretsResponse, + unmarshal_JobsLimits, + unmarshal_ListJobDefinitionSecretsResponse, unmarshal_ListJobDefinitionsResponse, unmarshal_ListJobRunsResponse, + unmarshal_ListJobsResourcesResponse, unmarshal_StartJobDefinitionResponse, marshal_CreateJobDefinitionRequest, + marshal_CreateJobDefinitionSecretsRequest, marshal_StartJobDefinitionRequest, marshal_UpdateJobDefinitionRequest, + marshal_UpdateJobDefinitionSecretRequest, ) class JobsV1Alpha1API(API): """ - Serverless Jobs API. + This API allows you to manage your Serverless Jobs. """ async def create_job_definition( @@ -51,7 +67,7 @@ async def create_job_definition( image_uri: str, command: str, description: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, local_storage_capacity: Optional[int] = None, project_id: Optional[str] = None, @@ -64,7 +80,7 @@ async def create_job_definition( :param cpu_limit: CPU limit of the job. :param memory_limit: Memory limit of the job (in MiB). :param image_uri: Image to use for the job. - :param command: Startup command. + :param command: Startup command. If empty or not defined, the image's default command is used. :param description: Description of the job. :param region: Region to target. If none is passed will use default region from the config. :param name: Name of the job definition. @@ -72,7 +88,7 @@ async def create_job_definition( :param project_id: UUID of the Scaleway Project containing the job. :param environment_variables: Environment variables of the job. :param job_timeout: Timeout of the job in seconds. - :param cron_schedule: + :param cron_schedule: Configure a cron for the job. :return: :class:`JobDefinition ` Usage: @@ -120,7 +136,7 @@ async def get_job_definition( self, *, job_definition_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> JobDefinition: """ Get a job definition by its unique identifier. @@ -154,11 +170,12 @@ async def get_job_definition( async def list_job_definitions( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListJobDefinitionsRequestOrderBy] = None, project_id: Optional[str] = None, + organization_id: Optional[str] = None, ) -> ListJobDefinitionsResponse: """ List all your job definitions with filters. @@ -167,6 +184,7 @@ async def list_job_definitions( :param page_size: :param order_by: :param project_id: + :param organization_id: :return: :class:`ListJobDefinitionsResponse ` Usage: @@ -184,6 +202,8 @@ async def list_job_definitions( f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions", params={ "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, @@ -196,11 +216,12 @@ async def list_job_definitions( async def list_job_definitions_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListJobDefinitionsRequestOrderBy] = None, project_id: Optional[str] = None, + organization_id: Optional[str] = None, ) -> List[JobDefinition]: """ List all your job definitions with filters. @@ -209,6 +230,7 @@ async def list_job_definitions_all( :param page_size: :param order_by: :param project_id: + :param organization_id: :return: :class:`List[JobDefinition] ` Usage: @@ -227,6 +249,7 @@ async def list_job_definitions_all( "page_size": page_size, "order_by": order_by, "project_id": project_id, + "organization_id": organization_id, }, ) @@ -234,7 +257,7 @@ async def update_job_definition( self, *, job_definition_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, cpu_limit: Optional[int] = None, memory_limit: Optional[int] = None, @@ -306,7 +329,7 @@ async def delete_job_definition( self, *, job_definition_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete an exsisting job definition by its unique identifier. @@ -339,7 +362,7 @@ async def start_job_definition( self, *, job_definition_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, command: Optional[str] = None, environment_variables: Optional[Dict[str, str]] = None, replicas: Optional[int] = None, @@ -386,11 +409,226 @@ async def start_job_definition( self._throw_on_error(res) return unmarshal_StartJobDefinitionResponse(res.json()) + async def create_job_definition_secrets( + self, + *, + job_definition_id: str, + secrets: List[CreateJobDefinitionSecretsRequestSecretConfig], + region: Optional[ScwRegion] = None, + ) -> CreateJobDefinitionSecretsResponse: + """ + Create a secret reference within a job definition. + :param job_definition_id: UUID of the job definition. + :param secrets: List of secrets to inject into the job. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`CreateJobDefinitionSecretsResponse ` + + Usage: + :: + + result = await api.create_job_definition_secrets( + job_definition_id="example", + secrets=[], + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_job_definition_id = validate_path_param( + "job_definition_id", job_definition_id + ) + + res = self._request( + "POST", + f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions/{param_job_definition_id}/secrets", + body=marshal_CreateJobDefinitionSecretsRequest( + CreateJobDefinitionSecretsRequest( + job_definition_id=job_definition_id, + secrets=secrets, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CreateJobDefinitionSecretsResponse(res.json()) + + async def get_job_definition_secret( + self, + *, + job_definition_id: str, + secret_id: str, + region: Optional[ScwRegion] = None, + ) -> Secret: + """ + Get a secret references within a job definition. + :param job_definition_id: UUID of the job definition. + :param secret_id: UUID of the secret reference within the job. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Secret ` + + Usage: + :: + + result = await api.get_job_definition_secret( + job_definition_id="example", + secret_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_job_definition_id = validate_path_param( + "job_definition_id", job_definition_id + ) + param_secret_id = validate_path_param("secret_id", secret_id) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions/{param_job_definition_id}/secrets/{param_secret_id}", + ) + + self._throw_on_error(res) + return unmarshal_Secret(res.json()) + + async def list_job_definition_secrets( + self, + *, + job_definition_id: str, + region: Optional[ScwRegion] = None, + ) -> ListJobDefinitionSecretsResponse: + """ + List secrets references within a job definition. + :param job_definition_id: UUID of the job definition. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ListJobDefinitionSecretsResponse ` + + Usage: + :: + + result = await api.list_job_definition_secrets( + job_definition_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_job_definition_id = validate_path_param( + "job_definition_id", job_definition_id + ) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions/{param_job_definition_id}/secrets", + ) + + self._throw_on_error(res) + return unmarshal_ListJobDefinitionSecretsResponse(res.json()) + + async def update_job_definition_secret( + self, + *, + job_definition_id: str, + secret_id: str, + region: Optional[ScwRegion] = None, + secret_manager_version: Optional[str] = None, + path: Optional[str] = None, + env_var_name: Optional[str] = None, + ) -> Secret: + """ + Update a secret reference within a job definition. + :param job_definition_id: UUID of the job definition. + :param secret_id: UUID of the secret reference within the job. + :param region: Region to target. If none is passed will use default region from the config. + :param secret_manager_version: Version of the secret in Secret Manager. + :param path: Path of the secret to mount inside the job (either `path` or `env_var_name` must be set). + One-Of ('secret_config'): at most one of 'path', 'env_var_name' could be set. + :param env_var_name: Environment variable name used to expose the secret inside the job (either `path` or `env_var_name` must be set). + One-Of ('secret_config'): at most one of 'path', 'env_var_name' could be set. + :return: :class:`Secret ` + + Usage: + :: + + result = await api.update_job_definition_secret( + job_definition_id="example", + secret_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_job_definition_id = validate_path_param( + "job_definition_id", job_definition_id + ) + param_secret_id = validate_path_param("secret_id", secret_id) + + res = self._request( + "PATCH", + f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions/{param_job_definition_id}/secrets/{param_secret_id}", + body=marshal_UpdateJobDefinitionSecretRequest( + UpdateJobDefinitionSecretRequest( + job_definition_id=job_definition_id, + secret_id=secret_id, + region=region, + secret_manager_version=secret_manager_version, + path=path, + env_var_name=env_var_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Secret(res.json()) + + async def delete_job_definition_secret( + self, + *, + job_definition_id: str, + secret_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a secret reference within a job definition. + :param job_definition_id: UUID of the job definition. + :param secret_id: UUID of the secret reference within the job. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_job_definition_secret( + job_definition_id="example", + secret_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_job_definition_id = validate_path_param( + "job_definition_id", job_definition_id + ) + param_secret_id = validate_path_param("secret_id", secret_id) + + res = self._request( + "DELETE", + f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions/{param_job_definition_id}/secrets/{param_secret_id}", + ) + + self._throw_on_error(res) + async def get_job_run( self, *, job_run_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> JobRun: """ Get a job run by its unique identifier. @@ -423,7 +661,7 @@ async def stop_job_run( self, *, job_run_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> JobRun: """ Stop a job run by its unique identifier. @@ -456,12 +694,14 @@ async def stop_job_run( async def list_job_runs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListJobRunsRequestOrderBy] = None, job_definition_id: Optional[str] = None, project_id: Optional[str] = None, + organization_id: Optional[str] = None, + state: Optional[JobRunState] = None, ) -> ListJobRunsResponse: """ List all job runs with filters. @@ -471,6 +711,8 @@ async def list_job_runs( :param order_by: :param job_definition_id: :param project_id: + :param organization_id: + :param state: :return: :class:`ListJobRunsResponse ` Usage: @@ -489,9 +731,12 @@ async def list_job_runs( params={ "job_definition_id": job_definition_id, "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, + "state": state, }, ) @@ -501,12 +746,14 @@ async def list_job_runs( async def list_job_runs_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListJobRunsRequestOrderBy] = None, job_definition_id: Optional[str] = None, project_id: Optional[str] = None, + organization_id: Optional[str] = None, + state: Optional[JobRunState] = None, ) -> List[JobRun]: """ List all job runs with filters. @@ -516,6 +763,8 @@ async def list_job_runs_all( :param order_by: :param job_definition_id: :param project_id: + :param organization_id: + :param state: :return: :class:`List[JobRun] ` Usage: @@ -535,5 +784,63 @@ async def list_job_runs_all( "order_by": order_by, "job_definition_id": job_definition_id, "project_id": project_id, + "organization_id": organization_id, + "state": state, }, ) + + async def list_jobs_resources( + self, + *, + region: Optional[ScwRegion] = None, + ) -> ListJobsResourcesResponse: + """ + List jobs resources for the console. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ListJobsResourcesResponse ` + + Usage: + :: + + result = await api.list_jobs_resources() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha1/regions/{param_region}/jobs-resources", + ) + + self._throw_on_error(res) + return unmarshal_ListJobsResourcesResponse(res.json()) + + async def get_jobs_limits( + self, + *, + region: Optional[ScwRegion] = None, + ) -> JobsLimits: + """ + Get jobs limits for the console. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`JobsLimits ` + + Usage: + :: + + result = await api.get_jobs_limits() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha1/regions/{param_region}/jobs-limits", + ) + + self._throw_on_error(res) + return unmarshal_JobsLimits(res.json()) diff --git a/scaleway-async/scaleway_async/jobs/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/jobs/v1alpha1/marshalling.py index ecb70454..17cb1e1d 100644 --- a/scaleway-async/scaleway_async/jobs/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/jobs/v1alpha1/marshalling.py @@ -5,21 +5,101 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) from .types import ( + SecretEnvVar, + SecretFile, + Secret, CronSchedule, JobDefinition, JobRun, + CreateJobDefinitionSecretsResponse, + JobsLimits, + ListJobDefinitionSecretsResponse, ListJobDefinitionsResponse, ListJobRunsResponse, + Resource, + ListJobsResourcesResponse, StartJobDefinitionResponse, CreateJobDefinitionRequestCronScheduleConfig, CreateJobDefinitionRequest, + CreateJobDefinitionSecretsRequestSecretConfig, + CreateJobDefinitionSecretsRequest, StartJobDefinitionRequest, UpdateJobDefinitionRequestCronScheduleConfig, UpdateJobDefinitionRequest, + UpdateJobDefinitionSecretRequest, ) +def unmarshal_SecretEnvVar(data: Any) -> SecretEnvVar: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SecretEnvVar' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + return SecretEnvVar(**args) + + +def unmarshal_SecretFile(data: Any) -> SecretFile: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SecretFile' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("path", None) + if field is not None: + args["path"] = field + + return SecretFile(**args) + + +def unmarshal_Secret(data: Any) -> Secret: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Secret' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secret_id", None) + if field is not None: + args["secret_id"] = field + + field = data.get("secret_manager_id", None) + if field is not None: + args["secret_manager_id"] = field + + field = data.get("secret_manager_version", None) + if field is not None: + args["secret_manager_version"] = field + + field = data.get("file", None) + if field is not None: + args["file"] = unmarshal_SecretFile(field) + else: + args["file"] = None + + field = data.get("env_var", None) + if field is not None: + args["env_var"] = unmarshal_SecretEnvVar(field) + else: + args["env_var"] = None + + return Secret(**args) + + def unmarshal_CronSchedule(data: Any) -> CronSchedule: if not isinstance(data, dict): raise TypeError( @@ -78,10 +158,14 @@ def unmarshal_JobDefinition(data: Any) -> JobDefinition: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("environment_variables", None) if field is not None: @@ -102,10 +186,14 @@ def unmarshal_JobDefinition(data: Any) -> JobDefinition: field = data.get("job_timeout", None) if field is not None: args["job_timeout"] = field + else: + args["job_timeout"] = None field = data.get("cron_schedule", None) if field is not None: args["cron_schedule"] = unmarshal_CronSchedule(field) + else: + args["cron_schedule"] = None return JobDefinition(**args) @@ -149,24 +237,34 @@ def unmarshal_JobRun(data: Any) -> JobRun: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("terminated_at", None) if field is not None: args["terminated_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["terminated_at"] = None field = data.get("exit_code", None) if field is not None: args["exit_code"] = field + else: + args["exit_code"] = None field = data.get("run_duration", None) if field is not None: args["run_duration"] = field + else: + args["run_duration"] = None field = data.get("environment_variables", None) if field is not None: @@ -183,10 +281,69 @@ def unmarshal_JobRun(data: Any) -> JobRun: field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None return JobRun(**args) +def unmarshal_CreateJobDefinitionSecretsResponse( + data: Any, +) -> CreateJobDefinitionSecretsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CreateJobDefinitionSecretsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secrets", None) + if field is not None: + args["secrets"] = ( + [unmarshal_Secret(v) for v in field] if field is not None else None + ) + + return CreateJobDefinitionSecretsResponse(**args) + + +def unmarshal_JobsLimits(data: Any) -> JobsLimits: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'JobsLimits' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secrets_per_job_definition", None) + if field is not None: + args["secrets_per_job_definition"] = field + + return JobsLimits(**args) + + +def unmarshal_ListJobDefinitionSecretsResponse( + data: Any, +) -> ListJobDefinitionSecretsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListJobDefinitionSecretsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secrets", None) + if field is not None: + args["secrets"] = ( + [unmarshal_Secret(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListJobDefinitionSecretsResponse(**args) + + def unmarshal_ListJobDefinitionsResponse(data: Any) -> ListJobDefinitionsResponse: if not isinstance(data, dict): raise TypeError( @@ -229,6 +386,42 @@ def unmarshal_ListJobRunsResponse(data: Any) -> ListJobRunsResponse: return ListJobRunsResponse(**args) +def unmarshal_Resource(data: Any) -> Resource: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Resource' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("cpu_limit", None) + if field is not None: + args["cpu_limit"] = field + + field = data.get("memory_limit", None) + if field is not None: + args["memory_limit"] = field + + return Resource(**args) + + +def unmarshal_ListJobsResourcesResponse(data: Any) -> ListJobsResourcesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListJobsResourcesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("resources", None) + if field is not None: + args["resources"] = ( + [unmarshal_Resource(v) for v in field] if field is not None else None + ) + + return ListJobsResourcesResponse(**args) + + def unmarshal_StartJobDefinitionResponse(data: Any) -> StartJobDefinitionResponse: if not isinstance(data, dict): raise TypeError( @@ -300,15 +493,51 @@ def marshal_CreateJobDefinitionRequest( output["job_timeout"] = request.job_timeout if request.cron_schedule is not None: - output["cron_schedule"] = ( - marshal_CreateJobDefinitionRequestCronScheduleConfig( - request.cron_schedule, defaults - ), + output["cron_schedule"] = marshal_CreateJobDefinitionRequestCronScheduleConfig( + request.cron_schedule, defaults ) return output +def marshal_CreateJobDefinitionSecretsRequestSecretConfig( + request: CreateJobDefinitionSecretsRequestSecretConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("path", request.path), + OneOfPossibility("env_var_name", request.env_var_name), + ] + ), + ) + + if request.secret_manager_id is not None: + output["secret_manager_id"] = request.secret_manager_id + + if request.secret_manager_version is not None: + output["secret_manager_version"] = request.secret_manager_version + + return output + + +def marshal_CreateJobDefinitionSecretsRequest( + request: CreateJobDefinitionSecretsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secrets is not None: + output["secrets"] = [ + marshal_CreateJobDefinitionSecretsRequestSecretConfig(item, defaults) + for item in request.secrets + ] + + return output + + def marshal_StartJobDefinitionRequest( request: StartJobDefinitionRequest, defaults: ProfileDefaults, @@ -376,10 +605,28 @@ def marshal_UpdateJobDefinitionRequest( output["job_timeout"] = request.job_timeout if request.cron_schedule is not None: - output["cron_schedule"] = ( - marshal_UpdateJobDefinitionRequestCronScheduleConfig( - request.cron_schedule, defaults - ), + output["cron_schedule"] = marshal_UpdateJobDefinitionRequestCronScheduleConfig( + request.cron_schedule, defaults ) return output + + +def marshal_UpdateJobDefinitionSecretRequest( + request: UpdateJobDefinitionSecretRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("path", request.path), + OneOfPossibility("env_var_name", request.env_var_name), + ] + ), + ) + + if request.secret_manager_version is not None: + output["secret_manager_version"] = request.secret_manager_version + + return output diff --git a/scaleway-async/scaleway_async/jobs/v1alpha1/types.py b/scaleway-async/scaleway_async/jobs/v1alpha1/types.py index 63579d2d..edaaaf92 100644 --- a/scaleway-async/scaleway_async/jobs/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/jobs/v1alpha1/types.py @@ -8,7 +8,7 @@ from typing import Dict, List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -45,11 +45,27 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class SecretEnvVar: + name: str + + +@dataclass +class SecretFile: + path: str + + @dataclass class CronSchedule: schedule: str + """ + UNIX cron schedule to run job (e.g., '* * * * *'). + """ timezone: str + """ + Timezone for the cron schedule, in tz database format (e.g., 'Europe/Paris'). + """ @dataclass @@ -59,6 +75,39 @@ class CreateJobDefinitionRequestCronScheduleConfig: timezone: str +@dataclass +class CreateJobDefinitionSecretsRequestSecretConfig: + secret_manager_id: str + + secret_manager_version: str + + path: Optional[str] + + env_var_name: Optional[str] + + +@dataclass +class Secret: + secret_id: str + """ + UUID of the secret reference within the job. + """ + + secret_manager_id: str + """ + UUID of the secret in Secret Manager. + """ + + secret_manager_version: str + """ + Version of the secret in Secret Manager. + """ + + file: Optional[SecretFile] + + env_var: Optional[SecretEnvVar] + + @dataclass class JobDefinition: id: str @@ -85,7 +134,7 @@ class JobDefinition: local_storage_capacity: int - region: Region + region: ScwRegion """ Region to target. If none is passed will use default region from the config. """ @@ -125,7 +174,7 @@ class JobRun: local_storage_capacity: int - region: Region + region: ScwRegion """ Region to target. If none is passed will use default region from the config. """ @@ -133,6 +182,13 @@ class JobRun: started_at: Optional[datetime] +@dataclass +class Resource: + cpu_limit: int + + memory_limit: int + + @dataclass class UpdateJobDefinitionRequestCronScheduleConfig: schedule: Optional[str] @@ -159,7 +215,7 @@ class CreateJobDefinitionRequest: command: str """ - Startup command. + Startup command. If empty or not defined, the image's default command is used. """ description: str @@ -167,7 +223,7 @@ class CreateJobDefinitionRequest: Description of the job. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -198,6 +254,35 @@ class CreateJobDefinitionRequest: """ cron_schedule: Optional[CreateJobDefinitionRequestCronScheduleConfig] + """ + Configure a cron for the job. + """ + + +@dataclass +class CreateJobDefinitionSecretsRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + secrets: List[CreateJobDefinitionSecretsRequestSecretConfig] + """ + List of secrets to inject into the job. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateJobDefinitionSecretsResponse: + secrets: List[Secret] + """ + List of secrets created. + """ @dataclass @@ -207,7 +292,25 @@ class DeleteJobDefinitionRequest: UUID of the job definition to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteJobDefinitionSecretRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + secret_id: str + """ + UUID of the secret reference within the job. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -220,7 +323,25 @@ class GetJobDefinitionRequest: UUID of the job definition to get. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetJobDefinitionSecretRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + secret_id: str + """ + UUID of the secret reference within the job. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -233,15 +354,54 @@ class GetJobRunRequest: UUID of the job run to get. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetJobsLimitsRequest: + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class JobsLimits: + secrets_per_job_definition: int + + +@dataclass +class ListJobDefinitionSecretsRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListJobDefinitionSecretsResponse: + secrets: List[Secret] + """ + List of secret references within a job definition. + """ + + total_count: int + """ + Total count of secret references within a job definition. + """ + + @dataclass class ListJobDefinitionsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -254,6 +414,8 @@ class ListJobDefinitionsRequest: project_id: Optional[str] + organization_id: Optional[str] + @dataclass class ListJobDefinitionsResponse: @@ -264,7 +426,7 @@ class ListJobDefinitionsResponse: @dataclass class ListJobRunsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -279,6 +441,10 @@ class ListJobRunsRequest: project_id: Optional[str] + organization_id: Optional[str] + + state: Optional[JobRunState] + @dataclass class ListJobRunsResponse: @@ -287,6 +453,19 @@ class ListJobRunsResponse: total_count: int +@dataclass +class ListJobsResourcesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListJobsResourcesResponse: + resources: List[Resource] + + @dataclass class StartJobDefinitionRequest: job_definition_id: str @@ -294,7 +473,7 @@ class StartJobDefinitionRequest: UUID of the job definition to start. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -327,7 +506,7 @@ class StopJobRunRequest: UUID of the job run to stop. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -340,7 +519,7 @@ class UpdateJobDefinitionRequest: UUID of the job definition to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -391,3 +570,30 @@ class UpdateJobDefinitionRequest: """ cron_schedule: Optional[UpdateJobDefinitionRequestCronScheduleConfig] + + +@dataclass +class UpdateJobDefinitionSecretRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + secret_id: str + """ + UUID of the secret reference within the job. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + secret_manager_version: Optional[str] + """ + Version of the secret in Secret Manager. + """ + + path: Optional[str] + + env_var_name: Optional[str] diff --git a/scaleway-async/scaleway_async/k8s/v1/__init__.py b/scaleway-async/scaleway_async/k8s/v1/__init__.py index 2eafd7b7..fcfdc43b 100644 --- a/scaleway-async/scaleway_async/k8s/v1/__init__.py +++ b/scaleway-async/scaleway_async/k8s/v1/__init__.py @@ -24,6 +24,8 @@ from .types import ClusterAutoscalerConfig from .types import ClusterOpenIDConnectConfig from .types import Pool +from .types import ACLRuleRequest +from .types import ACLRule from .types import CreateClusterRequestAutoUpgrade from .types import CreateClusterRequestAutoscalerConfig from .types import CreateClusterRequestOpenIDConnectConfig @@ -34,22 +36,31 @@ from .types import Version from .types import Cluster from .types import Node +from .types import NodeMetadataCoreV1Taint from .types import UpdateClusterRequestAutoUpgrade from .types import UpdateClusterRequestAutoscalerConfig from .types import UpdateClusterRequestOpenIDConnectConfig from .types import UpdatePoolRequestUpgradePolicy +from .types import AddClusterACLRulesRequest +from .types import AddClusterACLRulesResponse +from .types import AuthExternalNodeRequest from .types import CreateClusterRequest from .types import CreateExternalNodeRequest from .types import CreatePoolRequest +from .types import DeleteACLRuleRequest from .types import DeleteClusterRequest from .types import DeleteNodeRequest from .types import DeletePoolRequest from .types import ExternalNode +from .types import ExternalNodeAuth from .types import GetClusterKubeConfigRequest from .types import GetClusterRequest +from .types import GetNodeMetadataRequest from .types import GetNodeRequest from .types import GetPoolRequest from .types import GetVersionRequest +from .types import ListClusterACLRulesRequest +from .types import ListClusterACLRulesResponse from .types import ListClusterAvailableTypesRequest from .types import ListClusterAvailableTypesResponse from .types import ListClusterAvailableVersionsRequest @@ -64,10 +75,13 @@ from .types import ListPoolsResponse from .types import ListVersionsRequest from .types import ListVersionsResponse -from .types import MigrateToPrivateNetworkClusterRequest +from .types import MigratePoolsToNewImagesRequest +from .types import NodeMetadata from .types import RebootNodeRequest from .types import ReplaceNodeRequest from .types import ResetClusterAdminTokenRequest +from .types import SetClusterACLRulesRequest +from .types import SetClusterACLRulesResponse from .types import SetClusterTypeRequest from .types import UpdateClusterRequest from .types import UpdatePoolRequest @@ -100,6 +114,8 @@ "ClusterAutoscalerConfig", "ClusterOpenIDConnectConfig", "Pool", + "ACLRuleRequest", + "ACLRule", "CreateClusterRequestAutoUpgrade", "CreateClusterRequestAutoscalerConfig", "CreateClusterRequestOpenIDConnectConfig", @@ -110,22 +126,31 @@ "Version", "Cluster", "Node", + "NodeMetadataCoreV1Taint", "UpdateClusterRequestAutoUpgrade", "UpdateClusterRequestAutoscalerConfig", "UpdateClusterRequestOpenIDConnectConfig", "UpdatePoolRequestUpgradePolicy", + "AddClusterACLRulesRequest", + "AddClusterACLRulesResponse", + "AuthExternalNodeRequest", "CreateClusterRequest", "CreateExternalNodeRequest", "CreatePoolRequest", + "DeleteACLRuleRequest", "DeleteClusterRequest", "DeleteNodeRequest", "DeletePoolRequest", "ExternalNode", + "ExternalNodeAuth", "GetClusterKubeConfigRequest", "GetClusterRequest", + "GetNodeMetadataRequest", "GetNodeRequest", "GetPoolRequest", "GetVersionRequest", + "ListClusterACLRulesRequest", + "ListClusterACLRulesResponse", "ListClusterAvailableTypesRequest", "ListClusterAvailableTypesResponse", "ListClusterAvailableVersionsRequest", @@ -140,10 +165,13 @@ "ListPoolsResponse", "ListVersionsRequest", "ListVersionsResponse", - "MigrateToPrivateNetworkClusterRequest", + "MigratePoolsToNewImagesRequest", + "NodeMetadata", "RebootNodeRequest", "ReplaceNodeRequest", "ResetClusterAdminTokenRequest", + "SetClusterACLRulesRequest", + "SetClusterACLRulesResponse", "SetClusterTypeRequest", "UpdateClusterRequest", "UpdatePoolRequest", diff --git a/scaleway-async/scaleway_async/k8s/v1/api.py b/scaleway-async/scaleway_async/k8s/v1/api.py index 25e9f27c..ecce75cd 100644 --- a/scaleway-async/scaleway_async/k8s/v1/api.py +++ b/scaleway-async/scaleway_async/k8s/v1/api.py @@ -5,9 +5,9 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ScwFile, - Zone, + Zone as ScwZone, unmarshal_ScwFile, ) from scaleway_core.utils import ( @@ -27,6 +27,10 @@ PoolStatus, PoolVolumeType, Runtime, + ACLRule, + ACLRuleRequest, + AddClusterACLRulesRequest, + AddClusterACLRulesResponse, Cluster, ClusterType, CreateClusterRequest, @@ -37,6 +41,8 @@ CreatePoolRequest, CreatePoolRequestUpgradePolicy, ExternalNode, + ExternalNodeAuth, + ListClusterACLRulesResponse, ListClusterAvailableTypesResponse, ListClusterAvailableVersionsResponse, ListClusterTypesResponse, @@ -44,9 +50,12 @@ ListNodesResponse, ListPoolsResponse, ListVersionsResponse, - MigrateToPrivateNetworkClusterRequest, + MigratePoolsToNewImagesRequest, Node, + NodeMetadata, Pool, + SetClusterACLRulesRequest, + SetClusterACLRulesResponse, SetClusterTypeRequest, UpdateClusterRequest, UpdateClusterRequestAutoUpgrade, @@ -68,7 +77,10 @@ unmarshal_Version, unmarshal_Cluster, unmarshal_Node, + unmarshal_AddClusterACLRulesResponse, unmarshal_ExternalNode, + unmarshal_ExternalNodeAuth, + unmarshal_ListClusterACLRulesResponse, unmarshal_ListClusterAvailableTypesResponse, unmarshal_ListClusterAvailableVersionsResponse, unmarshal_ListClusterTypesResponse, @@ -76,9 +88,13 @@ unmarshal_ListNodesResponse, unmarshal_ListPoolsResponse, unmarshal_ListVersionsResponse, + unmarshal_NodeMetadata, + unmarshal_SetClusterACLRulesResponse, + marshal_AddClusterACLRulesRequest, marshal_CreateClusterRequest, marshal_CreatePoolRequest, - marshal_MigrateToPrivateNetworkClusterRequest, + marshal_MigratePoolsToNewImagesRequest, + marshal_SetClusterACLRulesRequest, marshal_SetClusterTypeRequest, marshal_UpdateClusterRequest, marshal_UpdatePoolRequest, @@ -89,13 +105,13 @@ class K8SV1API(API): """ - Kubernetes API. + This API allows you to manage Kubernetes Kapsule and Kosmos clusters. """ async def list_clusters( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, order_by: Optional[ListClustersRequestOrderBy] = None, @@ -154,7 +170,7 @@ async def list_clusters( async def list_clusters_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, order_by: Optional[ListClustersRequestOrderBy] = None, @@ -210,7 +226,7 @@ async def create_cluster( type_: str, description: str, version: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, name: Optional[str] = None, @@ -230,7 +246,7 @@ async def create_cluster( """ Create a new Cluster. Create a new Kubernetes cluster in a Scaleway region. - :param type_: Type of the cluster (possible values are kapsule, multicloud, kapsule-dedicated-8, kapsule-dedicated-16). + :param type_: Type of the cluster. See [list available cluster types](#list-available-cluster-types-for-a-cluster) for a list of valid types. :param description: Cluster description. :param version: Kubernetes version of the cluster. :param region: Region to target. If none is passed will use default region from the config. @@ -300,7 +316,7 @@ async def get_cluster( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cluster: """ Get a Cluster. @@ -334,7 +350,7 @@ async def wait_for_cluster( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Cluster, Union[bool, Awaitable[bool]]]] = None, ) -> Cluster: """ @@ -371,7 +387,7 @@ async def update_cluster( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, @@ -393,7 +409,7 @@ async def update_cluster( :param description: New description for the cluster. :param tags: New tags associated with the cluster. :param autoscaler_config: New autoscaler config for the cluster. - :param auto_upgrade: New auto upgrade configuration for the cluster. Note that all fields need to be set. + :param auto_upgrade: New auto upgrade configuration for the cluster. Note that all fields needs to be set. :param feature_gates: List of feature gates to enable. :param admission_plugins: List of admission plugins to enable. :param open_id_connect_config: OpenID Connect configuration of the cluster. This configuration enables to update the OpenID Connect configuration of the Kubernetes API server. @@ -442,11 +458,11 @@ async def delete_cluster( *, cluster_id: str, with_additional_resources: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cluster: """ Delete a Cluster. - Delete a specific Kubernetes cluster and all its associated pools and nodes. Note that this method will not delete any Load Balancer or Block Volume that are associated with the cluster. + Delete a specific Kubernetes cluster and all its associated pools and nodes, and possibly its associated Load Balancers or Block Volumes. :param cluster_id: ID of the cluster to delete. :param with_additional_resources: Defines whether all volumes (including retain volume type), empty Private Networks and Load Balancers with a name starting with the cluster ID will also be deleted. :param region: Region to target. If none is passed will use default region from the config. @@ -483,7 +499,7 @@ async def upgrade_cluster( cluster_id: str, version: str, upgrade_pools: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cluster: """ Upgrade a Cluster. @@ -531,11 +547,11 @@ async def set_cluster_type( *, cluster_id: str, type_: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cluster: """ Change the Cluster type. - Change the type of a specific Kubernetes cluster. To see the possible values you can enter for the `type` field, [list available cluster types](#path-clusters-list-available-cluster-types-for-a-cluster). + Change the type of a specific Kubernetes cluster. To see the possible values you can enter for the `type` field, [list available cluster types](#list-available-cluster-types-for-a-cluster). :param cluster_id: ID of the cluster to migrate from one type to another. :param type_: Type of the cluster. Note that some migrations are not possible (please refer to product documentation). :param region: Region to target. If none is passed will use default region from the config. @@ -575,7 +591,7 @@ async def list_cluster_available_versions( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListClusterAvailableVersionsResponse: """ List available versions for a Cluster. @@ -609,7 +625,7 @@ async def list_cluster_available_types( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListClusterAvailableTypesResponse: """ List available cluster types for a cluster. @@ -643,7 +659,7 @@ async def _get_cluster_kube_config( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, redacted: Optional[bool] = None, ) -> ScwFile: """ @@ -683,11 +699,11 @@ async def reset_cluster_admin_token( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Reset the admin token of a Cluster. - Reset the admin token for a specific Kubernetes cluster. This will revoke the old admin token (which will not be usable afterwards) and create a new one. Note that you will need to download kubeconfig again to keep interacting with the cluster. + Reset the admin token for a specific Kubernetes cluster. This will revoke the old admin token (which will not be usable afterwards) and create a new one. Note that you will need to download the kubeconfig again to keep interacting with the cluster. :param cluster_id: Cluster ID on which the admin token will be renewed. :param region: Region to target. If none is passed will use default region from the config. @@ -712,27 +728,105 @@ async def reset_cluster_admin_token( self._throw_on_error(res) - async def migrate_to_private_network_cluster( + async def list_cluster_acl_rules( self, *, cluster_id: str, - private_network_id: str, - region: Optional[Region] = None, - ) -> Cluster: + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListClusterACLRulesResponse: """ - Migrate an existing cluster to a Private Network cluster. - Migrate a cluster that was created before the release of Private Network clusters to a new one with a Private Network. - :param cluster_id: ID of the cluster to migrate. - :param private_network_id: ID of the Private Network to link to the cluster. + List ACLs. + List ACLs for a specific cluster. + :param cluster_id: ID of the cluster whose ACLs will be listed. :param region: Region to target. If none is passed will use default region from the config. - :return: :class:`Cluster ` + :param page: Page number for the returned ACLs. + :param page_size: Maximum number of ACLs per page. + :return: :class:`ListClusterACLRulesResponse ` + + Usage: + :: + + result = await api.list_cluster_acl_rules( + cluster_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_cluster_id = validate_path_param("cluster_id", cluster_id) + + res = self._request( + "GET", + f"/k8s/v1/regions/{param_region}/clusters/{param_cluster_id}/acls", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListClusterACLRulesResponse(res.json()) + + async def list_cluster_acl_rules_all( + self, + *, + cluster_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[ACLRule]: + """ + List ACLs. + List ACLs for a specific cluster. + :param cluster_id: ID of the cluster whose ACLs will be listed. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number for the returned ACLs. + :param page_size: Maximum number of ACLs per page. + :return: :class:`List[ACLRule] ` + + Usage: + :: + + result = await api.list_cluster_acl_rules_all( + cluster_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListClusterACLRulesResponse, + key="rules", + fetcher=self.list_cluster_acl_rules, + args={ + "cluster_id": cluster_id, + "region": region, + "page": page, + "page_size": page_size, + }, + ) + + async def add_cluster_acl_rules( + self, + *, + cluster_id: str, + region: Optional[ScwRegion] = None, + acls: Optional[List[ACLRuleRequest]] = None, + ) -> AddClusterACLRulesResponse: + """ + Add new ACLs. + Add new ACL rules for a specific cluster. + :param cluster_id: ID of the cluster whose ACLs will be added. + :param region: Region to target. If none is passed will use default region from the config. + :param acls: ACLs to add. + :return: :class:`AddClusterACLRulesResponse ` Usage: :: - result = await api.migrate_to_private_network_cluster( + result = await api.add_cluster_acl_rules( cluster_id="example", - private_network_id="example", ) """ @@ -743,25 +837,100 @@ async def migrate_to_private_network_cluster( res = self._request( "POST", - f"/k8s/v1/regions/{param_region}/clusters/{param_cluster_id}/migrate-to-private-network", - body=marshal_MigrateToPrivateNetworkClusterRequest( - MigrateToPrivateNetworkClusterRequest( + f"/k8s/v1/regions/{param_region}/clusters/{param_cluster_id}/acls", + body=marshal_AddClusterACLRulesRequest( + AddClusterACLRulesRequest( cluster_id=cluster_id, - private_network_id=private_network_id, region=region, + acls=acls, ), self.client, ), ) self._throw_on_error(res) - return unmarshal_Cluster(res.json()) + return unmarshal_AddClusterACLRulesResponse(res.json()) + + async def set_cluster_acl_rules( + self, + *, + cluster_id: str, + region: Optional[ScwRegion] = None, + acls: Optional[List[ACLRuleRequest]] = None, + ) -> SetClusterACLRulesResponse: + """ + Set new ACLs. + Set new ACL rules for a specific cluster. + :param cluster_id: ID of the cluster whose ACLs will be set. + :param region: Region to target. If none is passed will use default region from the config. + :param acls: ACLs to set. + :return: :class:`SetClusterACLRulesResponse ` + + Usage: + :: + + result = await api.set_cluster_acl_rules( + cluster_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_cluster_id = validate_path_param("cluster_id", cluster_id) + + res = self._request( + "PUT", + f"/k8s/v1/regions/{param_region}/clusters/{param_cluster_id}/acls", + body=marshal_SetClusterACLRulesRequest( + SetClusterACLRulesRequest( + cluster_id=cluster_id, + region=region, + acls=acls, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetClusterACLRulesResponse(res.json()) + + async def delete_acl_rule( + self, + *, + acl_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete an existing ACL. + :param acl_id: ID of the ACL rule to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_acl_rule( + acl_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_acl_id = validate_path_param("acl_id", acl_id) + + res = self._request( + "DELETE", + f"/k8s/v1/regions/{param_region}/acls/{param_acl_id}", + ) + + self._throw_on_error(res) async def list_pools( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPoolsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -812,7 +981,7 @@ async def list_pools_all( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPoolsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -857,7 +1026,7 @@ async def list_pools_all( async def create_pool( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, cluster_id: str, node_type: str, autoscaling: bool, @@ -872,7 +1041,7 @@ async def create_pool( tags: Optional[List[str]] = None, kubelet_args: Optional[Dict[str, str]] = None, upgrade_policy: Optional[CreatePoolRequestUpgradePolicy] = None, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, root_volume_type: Optional[PoolVolumeType] = None, root_volume_size: Optional[int] = None, ) -> Pool: @@ -885,17 +1054,20 @@ async def create_pool( :param autoscaling: Defines whether the autoscaling feature is enabled for the pool. :param size: Size (number of nodes) of the pool. :param name: Pool name. - :param placement_group_id: Placement group ID in which all the nodes of the pool will be created. + :param placement_group_id: Placement group ID in which all the nodes of the pool will be created, placement groups are limited to 20 instances. :param min_size: Defines the minimum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. :param autohealing: Defines whether the autohealing feature is enabled for the pool. :param public_ip_disabled: Defines if the public IP should be removed from Nodes. To use this feature, your Cluster must have an attached Private Network set up with a Public Gateway. :param max_size: Defines the maximum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. - :param container_runtime: Customization of the container runtime is available for each pool. Note that `docker` has been deprecated since version 1.20 and will be removed by version 1.24. - :param tags: Tags associated with the pool. + :param container_runtime: Customization of the container runtime is available for each pool. + :param tags: Tags associated with the pool, see [managing tags](https://www.scaleway.com/en/docs/containers/kubernetes/api-cli/managing-tags). :param kubelet_args: Kubelet arguments to be used by this pool. Note that this feature is experimental. :param upgrade_policy: Pool upgrade policy. :param zone: Zone in which the pool's nodes will be spawned. - :param root_volume_type: Defines the system volume disk type. Two different types of volume (`volume_type`) are provided: `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. `b_ssd` is a remote block storage which means your system is stored on a centralized and resilient cluster. + :param root_volume_type: * `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. This type is not available for all node types + * `sbs-5k` is a remote block storage which means your system is stored on a centralized and resilient cluster with 5k IOPS limits + * `sbs-15k` is a faster remote block storage which means your system is stored on a centralized and resilient cluster with 15k IOPS limits + * `b_ssd` is the legacy remote block storage which means your system is stored on a centralized and resilient cluster. Consider using `sbs-5k` or `sbs-15k` instead. :param root_volume_size: System volume disk size. :return: :class:`Pool ` @@ -952,7 +1124,7 @@ async def get_pool( self, *, pool_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Pool: """ Get a Pool in a Cluster. @@ -986,7 +1158,7 @@ async def wait_for_pool( self, *, pool_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Pool, Union[bool, Awaitable[bool]]]] = None, ) -> Pool: """ @@ -1024,11 +1196,12 @@ async def upgrade_pool( *, pool_id: str, version: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Pool: """ Upgrade a Pool in a Cluster. Upgrade the Kubernetes version of a specific pool. Note that it only works if the targeted version matches the cluster's version. + This will drain and replace the nodes in that pool. :param pool_id: ID of the pool to upgrade. :param version: New Kubernetes version for the pool. :param region: Region to target. If none is passed will use default region from the config. @@ -1068,7 +1241,7 @@ async def update_pool( self, *, pool_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, autoscaling: Optional[bool] = None, size: Optional[int] = None, min_size: Optional[int] = None, @@ -1080,7 +1253,7 @@ async def update_pool( ) -> Pool: """ Update a Pool in a Cluster. - Update the attributes of a specific pool, such as its desired size, autoscaling settings, and tags. + Update the attributes of a specific pool, such as its desired size, autoscaling settings, and tags. To upgrade a pool, you will need to use the dedicated endpoint. :param pool_id: ID of the pool to update. :param region: Region to target. If none is passed will use default region from the config. :param autoscaling: New value for the pool autoscaling enablement. @@ -1133,7 +1306,7 @@ async def delete_pool( self, *, pool_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Pool: """ Delete a Pool in a Cluster. @@ -1163,11 +1336,117 @@ async def delete_pool( self._throw_on_error(res) return unmarshal_Pool(res.json()) + async def migrate_pools_to_new_images( + self, + *, + cluster_id: str, + region: Optional[ScwRegion] = None, + pool_ids: Optional[List[str]] = None, + ) -> None: + """ + Migrate specific pools or all pools of a cluster to new images. + If no pool is specified, all pools of the cluster will be migrated to new images. + :param cluster_id: + :param region: Region to target. If none is passed will use default region from the config. + :param pool_ids: + + Usage: + :: + + result = await api.migrate_pools_to_new_images( + cluster_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_cluster_id = validate_path_param("cluster_id", cluster_id) + + res = self._request( + "POST", + f"/k8s/v1/regions/{param_region}/clusters/{param_cluster_id}/migrate-pools-to-new-images", + body=marshal_MigratePoolsToNewImagesRequest( + MigratePoolsToNewImagesRequest( + cluster_id=cluster_id, + region=region, + pool_ids=pool_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + async def get_node_metadata( + self, + *, + region: Optional[ScwRegion] = None, + ) -> NodeMetadata: + """ + Fetch node metadata. + Rerieve metadata to instantiate a Kapsule/Kosmos node. This method is not intended to be called by end users but rather programmatically by the node-installer. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`NodeMetadata ` + + Usage: + :: + + result = await api.get_node_metadata() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/k8s/v1/regions/{param_region}/node-metadata", + ) + + self._throw_on_error(res) + return unmarshal_NodeMetadata(res.json()) + + async def auth_external_node( + self, + *, + pool_id: str, + region: Optional[ScwRegion] = None, + ) -> ExternalNodeAuth: + """ + Authenticate Kosmos external node. + Creates a newer Kosmos node and returns its token. This method is not intended to be called by end users but rather programmatically by the node-installer. + :param pool_id: Pool the node will be attached to. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ExternalNodeAuth ` + + Usage: + :: + + result = await api.auth_external_node( + pool_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_pool_id = validate_path_param("pool_id", pool_id) + + res = self._request( + "POST", + f"/k8s/v1/regions/{param_region}/pools/{param_pool_id}/external-nodes/auth", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_ExternalNodeAuth(res.json()) + async def create_external_node( self, *, pool_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ExternalNode: """ Create a Kosmos node. @@ -1202,7 +1481,7 @@ async def list_nodes( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, pool_id: Optional[str] = None, order_by: Optional[ListNodesRequestOrderBy] = None, page: Optional[int] = None, @@ -1256,7 +1535,7 @@ async def list_nodes_all( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, pool_id: Optional[str] = None, order_by: Optional[ListNodesRequestOrderBy] = None, page: Optional[int] = None, @@ -1305,7 +1584,7 @@ async def get_node( self, *, node_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Node: """ Get a Node in a Cluster. @@ -1339,7 +1618,7 @@ async def wait_for_node( self, *, node_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Node, Union[bool, Awaitable[bool]]]] = None, ) -> Node: """ @@ -1376,11 +1655,11 @@ async def replace_node( self, *, node_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Node: """ Replace a Node in a Cluster. - Replace a specific Node. The node will first be cordoned (scheduling will be disabled on it). The existing pods on the node will then be drained and rescheduled onto another schedulable node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster), disruption of your applications can be expected. + Replace a specific Node. The node will first be drained and pods will be rescheduled onto another node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster, or with specific constraints), disruption of your applications may occur. :param node_id: ID of the node to replace. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Node ` @@ -1412,11 +1691,11 @@ async def reboot_node( self, *, node_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Node: """ Reboot a Node in a Cluster. - Reboot a specific Node. The node will first be cordoned (scheduling will be disabled on it). The existing pods on the node will then be drained and rescheduled onto another schedulable node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster), disruption of your applications can be expected. + Reboot a specific Node. The node will first be drained and pods will be rescheduled onto another node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster, or with specific constraints), disruption of your applications may occur. :param node_id: ID of the node to reboot. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Node ` @@ -1449,11 +1728,11 @@ async def delete_node( node_id: str, skip_drain: bool, replace: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Node: """ Delete a Node in a Cluster. - Delete a specific Node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster), disruption of your applications can be expected. + Delete a specific Node. The node will first be drained and pods will be rescheduled onto another node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster, or with specific constraints), disruption of your applications may occur. :param node_id: ID of the node to replace. :param skip_drain: Skip draining node from its workload (Note: this parameter is currently inactive). :param replace: Add a new node after the deletion of this node. @@ -1490,7 +1769,7 @@ async def delete_node( async def list_versions( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListVersionsResponse: """ List all available Versions. @@ -1520,7 +1799,7 @@ async def get_version( self, *, version_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Version: """ Get a Version. @@ -1553,7 +1832,7 @@ async def get_version( async def list_cluster_types( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListClusterTypesResponse: @@ -1590,7 +1869,7 @@ async def list_cluster_types( async def list_cluster_types_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[ClusterType]: diff --git a/scaleway-async/scaleway_async/k8s/v1/marshalling.py b/scaleway-async/scaleway_async/k8s/v1/marshalling.py index 337381a2..0f7d2149 100644 --- a/scaleway-async/scaleway_async/k8s/v1/marshalling.py +++ b/scaleway-async/scaleway_async/k8s/v1/marshalling.py @@ -21,8 +21,12 @@ ClusterOpenIDConnectConfig, Cluster, Node, + ACLRule, + AddClusterACLRulesResponse, ExternalNodeCoreV1Taint, ExternalNode, + ExternalNodeAuth, + ListClusterACLRulesResponse, ClusterType, ListClusterAvailableTypesResponse, ListClusterAvailableVersionsResponse, @@ -31,6 +35,11 @@ ListNodesResponse, ListPoolsResponse, ListVersionsResponse, + NodeMetadataCoreV1Taint, + NodeMetadata, + SetClusterACLRulesResponse, + ACLRuleRequest, + AddClusterACLRulesRequest, CreateClusterRequestPoolConfigUpgradePolicy, CreateClusterRequestAutoUpgrade, CreateClusterRequestAutoscalerConfig, @@ -39,7 +48,8 @@ CreateClusterRequest, CreatePoolRequestUpgradePolicy, CreatePoolRequest, - MigrateToPrivateNetworkClusterRequest, + MigratePoolsToNewImagesRequest, + SetClusterACLRulesRequest, SetClusterTypeRequest, UpdateClusterRequestAutoUpgrade, UpdateClusterRequestAutoscalerConfig, @@ -111,14 +121,6 @@ def unmarshal_Pool(data: Any) -> Pool: if field is not None: args["size"] = field - field = data.get("created_at", None) - if field is not None: - args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field - - field = data.get("updated_at", None) - if field is not None: - args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field - field = data.get("min_size", None) if field is not None: args["min_size"] = field @@ -127,6 +129,18 @@ def unmarshal_Pool(data: Any) -> Pool: if field is not None: args["max_size"] = field + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + field = data.get("container_runtime", None) if field is not None: args["container_runtime"] = field @@ -162,14 +176,26 @@ def unmarshal_Pool(data: Any) -> Pool: field = data.get("placement_group_id", None) if field is not None: args["placement_group_id"] = field + else: + args["placement_group_id"] = None field = data.get("upgrade_policy", None) if field is not None: args["upgrade_policy"] = unmarshal_PoolUpgradePolicy(field) + else: + args["upgrade_policy"] = None field = data.get("root_volume_size", None) if field is not None: args["root_volume_size"] = field + else: + args["root_volume_size"] = None + + field = data.get("new_images_enabled", None) + if field is not None: + args["new_images_enabled"] = field + else: + args["new_images_enabled"] = None return Pool(**args) @@ -253,6 +279,8 @@ def unmarshal_ClusterAutoUpgrade(data: Any) -> ClusterAutoUpgrade: field = data.get("maintenance_window", None) if field is not None: args["maintenance_window"] = unmarshal_MaintenanceWindow(field) + else: + args["maintenance_window"] = None return ClusterAutoUpgrade(**args) @@ -359,7 +387,7 @@ def unmarshal_Cluster(data: Any) -> Cluster: if field is not None: args["id"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -415,43 +443,73 @@ def unmarshal_Cluster(data: Any) -> Cluster: if field is not None: args["feature_gates"] = field - field = data.get("admission_plugins", None) - if field is not None: - args["admission_plugins"] = field - - field = data.get("apiserver_cert_sans", None) - if field is not None: - args["apiserver_cert_sans"] = field - field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("autoscaler_config", None) if field is not None: args["autoscaler_config"] = unmarshal_ClusterAutoscalerConfig(field) + else: + args["autoscaler_config"] = None field = data.get("auto_upgrade", None) if field is not None: args["auto_upgrade"] = unmarshal_ClusterAutoUpgrade(field) + else: + args["auto_upgrade"] = None + + field = data.get("admission_plugins", None) + if field is not None: + args["admission_plugins"] = field + + field = data.get("apiserver_cert_sans", None) + if field is not None: + args["apiserver_cert_sans"] = field + + field = data.get("iam_nodes_group_id", None) + if field is not None: + args["iam_nodes_group_id"] = field field = data.get("open_id_connect_config", None) if field is not None: args["open_id_connect_config"] = unmarshal_ClusterOpenIDConnectConfig(field) + else: + args["open_id_connect_config"] = None field = data.get("private_network_id", None) if field is not None: args["private_network_id"] = field + else: + args["private_network_id"] = None field = data.get("commitment_ends_at", None) if field is not None: args["commitment_ends_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["commitment_ends_at"] = None + + field = data.get("acl_available", None) + if field is not None: + args["acl_available"] = field + else: + args["acl_available"] = None + + field = data.get("new_images_enabled", None) + if field is not None: + args["new_images_enabled"] = field + else: + args["new_images_enabled"] = None return Cluster(**args) @@ -491,14 +549,20 @@ def unmarshal_Node(data: Any) -> Node: field = data.get("public_ip_v4", None) if field is not None: args["public_ip_v4"] = field + else: + args["public_ip_v4"] = None field = data.get("public_ip_v6", None) if field is not None: args["public_ip_v6"] = field + else: + args["public_ip_v6"] = None field = data.get("conditions", None) if field is not None: args["conditions"] = field + else: + args["conditions"] = None field = data.get("status", None) if field is not None: @@ -507,18 +571,72 @@ def unmarshal_Node(data: Any) -> Node: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Node(**args) +def unmarshal_ACLRule(data: Any) -> ACLRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ACLRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("ip", None) + if field is not None: + args["ip"] = field + else: + args["ip"] = None + + field = data.get("scaleway_ranges", None) + if field is not None: + args["scaleway_ranges"] = field + else: + args["scaleway_ranges"] = None + + return ACLRule(**args) + + +def unmarshal_AddClusterACLRulesResponse(data: Any) -> AddClusterACLRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AddClusterACLRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_ACLRule(v) for v in field] if field is not None else None + ) + + return AddClusterACLRulesResponse(**args) + + def unmarshal_ExternalNodeCoreV1Taint(data: Any) -> ExternalNodeCoreV1Taint: if not isinstance(data, dict): raise TypeError( @@ -606,9 +724,53 @@ def unmarshal_ExternalNode(data: Any) -> ExternalNode: else None ) + field = data.get("iam_token", None) + if field is not None: + args["iam_token"] = field + return ExternalNode(**args) +def unmarshal_ExternalNodeAuth(data: Any) -> ExternalNodeAuth: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ExternalNodeAuth' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_secret_key", None) + if field is not None: + args["node_secret_key"] = field + + field = data.get("metadata_url", None) + if field is not None: + args["metadata_url"] = field + + return ExternalNodeAuth(**args) + + +def unmarshal_ListClusterACLRulesResponse(data: Any) -> ListClusterACLRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListClusterACLRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_ACLRule(v) for v in field] if field is not None else None + ) + + return ListClusterACLRulesResponse(**args) + + def unmarshal_ClusterType(data: Any) -> ClusterType: if not isinstance(data, dict): raise TypeError( @@ -649,9 +811,15 @@ def unmarshal_ClusterType(data: Any) -> ClusterType: if field is not None: args["audit_logs_supported"] = field + field = data.get("max_etcd_size", None) + if field is not None: + args["max_etcd_size"] = field + field = data.get("commitment_delay", None) if field is not None: args["commitment_delay"] = field + else: + args["commitment_delay"] = None return ClusterType(**args) @@ -799,6 +967,143 @@ def unmarshal_ListVersionsResponse(data: Any) -> ListVersionsResponse: return ListVersionsResponse(**args) +def unmarshal_NodeMetadataCoreV1Taint(data: Any) -> NodeMetadataCoreV1Taint: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeMetadataCoreV1Taint' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key", None) + if field is not None: + args["key"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + field = data.get("effect", None) + if field is not None: + args["effect"] = field + + return NodeMetadataCoreV1Taint(**args) + + +def unmarshal_NodeMetadata(data: Any) -> NodeMetadata: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeMetadata' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("cluster_url", None) + if field is not None: + args["cluster_url"] = field + + field = data.get("cluster_ca", None) + if field is not None: + args["cluster_ca"] = field + + field = data.get("credential_provider_config", None) + if field is not None: + args["credential_provider_config"] = field + + field = data.get("pool_version", None) + if field is not None: + args["pool_version"] = field + + field = data.get("kubelet_config", None) + if field is not None: + args["kubelet_config"] = field + + field = data.get("node_labels", None) + if field is not None: + args["node_labels"] = field + + field = data.get("node_taints", None) + if field is not None: + args["node_taints"] = ( + [unmarshal_NodeMetadataCoreV1Taint(v) for v in field] + if field is not None + else None + ) + + field = data.get("has_gpu", None) + if field is not None: + args["has_gpu"] = field + + field = data.get("external_ip", None) + if field is not None: + args["external_ip"] = field + + field = data.get("repo_uri", None) + if field is not None: + args["repo_uri"] = field + + return NodeMetadata(**args) + + +def unmarshal_SetClusterACLRulesResponse(data: Any) -> SetClusterACLRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetClusterACLRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_ACLRule(v) for v in field] if field is not None else None + ) + + return SetClusterACLRulesResponse(**args) + + +def marshal_ACLRuleRequest( + request: ACLRuleRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("ip", request.ip), + OneOfPossibility("scaleway_ranges", request.scaleway_ranges), + ] + ), + ) + + if request.description is not None: + output["description"] = request.description + + return output + + +def marshal_AddClusterACLRulesRequest( + request: AddClusterACLRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.acls is not None: + output["acls"] = [ + marshal_ACLRuleRequest(item, defaults) for item in request.acls + ] + + return output + + def marshal_MaintenanceWindow( request: MaintenanceWindow, defaults: ProfileDefaults, @@ -839,8 +1144,8 @@ def marshal_CreateClusterRequestAutoUpgrade( output["enable"] = request.enable if request.maintenance_window is not None: - output["maintenance_window"] = ( - marshal_MaintenanceWindow(request.maintenance_window, defaults), + output["maintenance_window"] = marshal_MaintenanceWindow( + request.maintenance_window, defaults ) return output @@ -970,10 +1275,8 @@ def marshal_CreateClusterRequestPoolConfig( output["public_ip_disabled"] = request.public_ip_disabled if request.upgrade_policy is not None: - output["upgrade_policy"] = ( - marshal_CreateClusterRequestPoolConfigUpgradePolicy( - request.upgrade_policy, defaults - ), + output["upgrade_policy"] = marshal_CreateClusterRequestPoolConfigUpgradePolicy( + request.upgrade_policy, defaults ) if request.root_volume_size is not None: @@ -1027,15 +1330,13 @@ def marshal_CreateClusterRequest( ] if request.autoscaler_config is not None: - output["autoscaler_config"] = ( - marshal_CreateClusterRequestAutoscalerConfig( - request.autoscaler_config, defaults - ), + output["autoscaler_config"] = marshal_CreateClusterRequestAutoscalerConfig( + request.autoscaler_config, defaults ) if request.auto_upgrade is not None: - output["auto_upgrade"] = ( - marshal_CreateClusterRequestAutoUpgrade(request.auto_upgrade, defaults), + output["auto_upgrade"] = marshal_CreateClusterRequestAutoUpgrade( + request.auto_upgrade, defaults ) if request.feature_gates is not None: @@ -1048,7 +1349,7 @@ def marshal_CreateClusterRequest( output["open_id_connect_config"] = ( marshal_CreateClusterRequestOpenIDConnectConfig( request.open_id_connect_config, defaults - ), + ) ) if request.apiserver_cert_sans is not None: @@ -1120,8 +1421,8 @@ def marshal_CreatePoolRequest( } if request.upgrade_policy is not None: - output["upgrade_policy"] = ( - marshal_CreatePoolRequestUpgradePolicy(request.upgrade_policy, defaults), + output["upgrade_policy"] = marshal_CreatePoolRequestUpgradePolicy( + request.upgrade_policy, defaults ) if request.zone is not None: @@ -1136,14 +1437,28 @@ def marshal_CreatePoolRequest( return output -def marshal_MigrateToPrivateNetworkClusterRequest( - request: MigrateToPrivateNetworkClusterRequest, +def marshal_MigratePoolsToNewImagesRequest( + request: MigratePoolsToNewImagesRequest, defaults: ProfileDefaults, ) -> Dict[str, Any]: output: Dict[str, Any] = {} - if request.private_network_id is not None: - output["private_network_id"] = request.private_network_id + if request.pool_ids is not None: + output["pool_ids"] = request.pool_ids + + return output + + +def marshal_SetClusterACLRulesRequest( + request: SetClusterACLRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.acls is not None: + output["acls"] = [ + marshal_ACLRuleRequest(item, defaults) for item in request.acls + ] return output @@ -1170,8 +1485,8 @@ def marshal_UpdateClusterRequestAutoUpgrade( output["enable"] = request.enable if request.maintenance_window is not None: - output["maintenance_window"] = ( - marshal_MaintenanceWindow(request.maintenance_window, defaults), + output["maintenance_window"] = marshal_MaintenanceWindow( + request.maintenance_window, defaults ) return output @@ -1266,15 +1581,13 @@ def marshal_UpdateClusterRequest( output["tags"] = request.tags if request.autoscaler_config is not None: - output["autoscaler_config"] = ( - marshal_UpdateClusterRequestAutoscalerConfig( - request.autoscaler_config, defaults - ), + output["autoscaler_config"] = marshal_UpdateClusterRequestAutoscalerConfig( + request.autoscaler_config, defaults ) if request.auto_upgrade is not None: - output["auto_upgrade"] = ( - marshal_UpdateClusterRequestAutoUpgrade(request.auto_upgrade, defaults), + output["auto_upgrade"] = marshal_UpdateClusterRequestAutoUpgrade( + request.auto_upgrade, defaults ) if request.feature_gates is not None: @@ -1287,7 +1600,7 @@ def marshal_UpdateClusterRequest( output["open_id_connect_config"] = ( marshal_UpdateClusterRequestOpenIDConnectConfig( request.open_id_connect_config, defaults - ), + ) ) if request.apiserver_cert_sans is not None: @@ -1339,8 +1652,8 @@ def marshal_UpdatePoolRequest( output["kubelet_args"] = request.kubelet_args if request.upgrade_policy is not None: - output["upgrade_policy"] = ( - marshal_UpdatePoolRequestUpgradePolicy(request.upgrade_policy, defaults), + output["upgrade_policy"] = marshal_UpdatePoolRequestUpgradePolicy( + request.upgrade_policy, defaults ) return output diff --git a/scaleway-async/scaleway_async/k8s/v1/types.py b/scaleway-async/scaleway_async/k8s/v1/types.py index c03be2b1..d2333e28 100644 --- a/scaleway-async/scaleway_async/k8s/v1/types.py +++ b/scaleway-async/scaleway_async/k8s/v1/types.py @@ -8,8 +8,8 @@ from typing import Dict, List, Optional from scaleway_core.bridge import ( - Region, - Zone, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -100,6 +100,14 @@ def __str__(self) -> str: class ListNodesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" + UPDATED_AT_ASC = "updated_at_asc" + UPDATED_AT_DESC = "updated_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + VERSION_ASC = "version_asc" + VERSION_DESC = "version_desc" def __str__(self) -> str: return str(self.value) @@ -171,6 +179,8 @@ class PoolVolumeType(str, Enum, metaclass=StrEnumMeta): DEFAULT_VOLUME_TYPE = "default_volume_type" L_SSD = "l_ssd" B_SSD = "b_ssd" + SBS_5K = "sbs_5k" + SBS_15K = "sbs_15k" def __str__(self) -> str: return str(self.value) @@ -241,7 +251,7 @@ class ClusterAutoscalerConfig: scale_down_delay_after_add: str """ - How long after scale up that scale down evaluation resumes. + How long after scale up the scale down evaluation resumes. """ estimator: AutoscalerEstimator @@ -365,29 +375,29 @@ class Pool: Size (number of nodes) of the pool. """ - created_at: Optional[datetime] + min_size: int """ - Date on which the pool was created. + Defines the minimum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. """ - updated_at: Optional[datetime] + max_size: int """ - Date on which the pool was last updated. + Defines the maximum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. """ - min_size: int + created_at: Optional[datetime] """ - Defines the minimum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. + Date on which the pool was created. """ - max_size: int + updated_at: Optional[datetime] """ - Defines the maximum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. + Date on which the pool was last updated. """ container_runtime: Runtime """ - Customization of the container runtime is available for each pool. Note that `docker` has been deprecated since version 1.20 and will be removed by version 1.24. + Customization of the container runtime is available for each pool. """ autohealing: bool @@ -397,7 +407,7 @@ class Pool: tags: List[str] """ - Tags associated with the pool. + Tags associated with the pool, see [managing tags](https://www.scaleway.com/en/docs/containers/kubernetes/api-cli/managing-tags). """ kubelet_args: Dict[str, str] @@ -405,14 +415,17 @@ class Pool: Kubelet arguments to be used by this pool. Note that this feature is experimental. """ - zone: Zone + zone: ScwZone """ Zone in which the pool's nodes will be spawned. """ root_volume_type: PoolVolumeType """ - Defines the system volume disk type. Two different types of volume (`volume_type`) are provided: `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. `b_ssd` is a remote block storage which means your system is stored on a centralized and resilient cluster. + * `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. This type is not available for all node types +* `sbs-5k` is a remote block storage which means your system is stored on a centralized and resilient cluster with 5k IOPS limits +* `sbs-15k` is a faster remote block storage which means your system is stored on a centralized and resilient cluster with 15k IOPS limits +* `b_ssd` is the legacy remote block storage which means your system is stored on a centralized and resilient cluster. Consider using `sbs-5k` or `sbs-15k` instead. """ public_ip_disabled: bool @@ -420,14 +433,14 @@ class Pool: Defines if the public IP should be removed from Nodes. To use this feature, your Cluster must have an attached Private Network set up with a Public Gateway. """ - region: Region + region: ScwRegion """ Cluster region of the pool. """ placement_group_id: Optional[str] """ - Placement group ID in which all the nodes of the pool will be created. + Placement group ID in which all the nodes of the pool will be created, placement groups are limited to 20 instances. """ upgrade_policy: Optional[PoolUpgradePolicy] @@ -440,6 +453,40 @@ class Pool: System volume disk size. """ + new_images_enabled: Optional[bool] + """ + Defines whether the pool is migrated to new images. + """ + + +@dataclass +class ACLRuleRequest: + description: str + """ + Description of the ACL. + """ + + ip: Optional[str] + + scaleway_ranges: Optional[bool] + + +@dataclass +class ACLRule: + id: str + """ + ID of the ACL rule. + """ + + description: str + """ + Description of the ACL. + """ + + ip: Optional[str] + + scaleway_ranges: Optional[bool] + @dataclass class CreateClusterRequestAutoUpgrade: @@ -473,7 +520,7 @@ class CreateClusterRequestAutoscalerConfig: scale_down_delay_after_add: Optional[str] """ - How long after scale up that scale down evaluation resumes. + How long after scale up the scale down evaluation resumes. """ ignore_daemonsets_utilization: Optional[bool] @@ -569,12 +616,12 @@ class CreateClusterRequestPoolConfig: container_runtime: Runtime """ - Customization of the container runtime is available for each pool. Note that `docker` has been deprecated since version 1.20 and will be removed by version 1.24. + Customization of the container runtime is available for each pool. """ placement_group_id: Optional[str] """ - Placement group ID in which all the nodes of the pool will be created. + Placement group ID in which all the nodes of the pool will be created, placement groups are limited to 20 instances. """ min_size: Optional[int] @@ -594,7 +641,7 @@ class CreateClusterRequestPoolConfig: tags: List[str] """ - Tags associated with the pool. + Tags associated with the pool, see [managing tags](https://www.scaleway.com/en/docs/containers/kubernetes/api-cli/managing-tags). """ kubelet_args: Dict[str, str] @@ -602,14 +649,17 @@ class CreateClusterRequestPoolConfig: Kubelet arguments to be used by this pool. Note that this feature is experimental. """ - zone: Zone + zone: ScwZone """ Zone in which the pool's nodes will be spawned. """ root_volume_type: PoolVolumeType """ - Defines the system volume disk type. Two different types of volume (`volume_type`) are provided: `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. `b_ssd` is a remote block storage which means your system is stored on a centralized and resilient cluster. + * `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. This type is not available for all node types +* `sbs-5k` is a remote block storage which means your system is stored on a centralized and resilient cluster with 5k IOPS limits +* `sbs-15k` is a faster remote block storage which means your system is stored on a centralized and resilient cluster with 15k IOPS limits +* `b_ssd` is the legacy remote block storage which means your system is stored on a centralized and resilient cluster. Consider using `sbs-5k` or `sbs-15k` instead. """ public_ip_disabled: bool @@ -686,6 +736,11 @@ class ClusterType: True if the offer allows activation of the audit log functionality. Please note that audit logs are sent to Cockpit. """ + max_etcd_size: int + """ + Maximum amount of data that can be stored in etcd for the offer. + """ + commitment_delay: Optional[str] """ Time period during which you can no longer switch to a lower offer. @@ -704,7 +759,7 @@ class Version: Label of the Kubernetes version. """ - region: Region + region: ScwRegion """ Region in which this version is available. """ @@ -762,7 +817,7 @@ class Cluster: Kubernetes version of the cluster. """ - region: Region + region: ScwRegion """ Region in which the cluster is deployed. """ @@ -812,16 +867,6 @@ class Cluster: List of enabled feature gates. """ - admission_plugins: List[str] - """ - List of enabled admission plugins. - """ - - apiserver_cert_sans: List[str] - """ - Additional Subject Alternative Names for the Kubernetes API server certificate. - """ - created_at: Optional[datetime] """ Date on which the cluster was created. @@ -839,7 +884,22 @@ class Cluster: auto_upgrade: Optional[ClusterAutoUpgrade] """ - Auto upgrade configuration of the cluster. + Auto upgrade Kubernetes version of the cluster. + """ + + admission_plugins: List[str] + """ + List of enabled admission plugins. + """ + + apiserver_cert_sans: List[str] + """ + Additional Subject Alternative Names for the Kubernetes API server certificate. + """ + + iam_nodes_group_id: str + """ + IAM group that nodes are members of (this field might be empty during early stage of cluster creation). """ open_id_connect_config: Optional[ClusterOpenIDConnectConfig] @@ -857,6 +917,16 @@ class Cluster: Date on which it will be possible to switch to a smaller offer. """ + acl_available: Optional[bool] + """ + Defines whether ACL is available on the cluster. + """ + + new_images_enabled: Optional[bool] + """ + Defines whether all pools are migrated to new images. + """ + @dataclass class Node: @@ -880,7 +950,7 @@ class Node: Underlying instance ID. It is prefixed by instance type and location information (see https://pkg.go.dev/k8s.io/api/core/v1#NodeSpec.ProviderID). """ - region: Region + region: ScwRegion """ Cluster region of the node. """ @@ -926,6 +996,15 @@ class Node: """ +@dataclass +class NodeMetadataCoreV1Taint: + key: str + + value: str + + effect: str + + @dataclass class UpdateClusterRequestAutoUpgrade: enable: Optional[bool] @@ -958,7 +1037,7 @@ class UpdateClusterRequestAutoscalerConfig: scale_down_delay_after_add: Optional[str] """ - How long after scale up that scale down evaluation resumes. + How long after scale up the scale down evaluation resumes. """ ignore_daemonsets_utilization: Optional[bool] @@ -1037,11 +1116,50 @@ class UpdatePoolRequestUpgradePolicy: max_surge: Optional[int] +@dataclass +class AddClusterACLRulesRequest: + cluster_id: str + """ + ID of the cluster whose ACLs will be added. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + acls: Optional[List[ACLRuleRequest]] + """ + ACLs to add. + """ + + +@dataclass +class AddClusterACLRulesResponse: + rules: List[ACLRule] + """ + ACLs that were added. + """ + + +@dataclass +class AuthExternalNodeRequest: + pool_id: str + """ + Pool the node will be attached to. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class CreateClusterRequest: type_: str """ - Type of the cluster (possible values are kapsule, multicloud, kapsule-dedicated-8, kapsule-dedicated-16). + Type of the cluster. See [list available cluster types](#list-available-cluster-types-for-a-cluster) for a list of valid types. """ description: str @@ -1054,7 +1172,7 @@ class CreateClusterRequest: Kubernetes version of the cluster. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1123,7 +1241,7 @@ class CreateClusterRequest: class CreateExternalNodeRequest: pool_id: str - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1131,7 +1249,7 @@ class CreateExternalNodeRequest: @dataclass class CreatePoolRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1163,7 +1281,7 @@ class CreatePoolRequest: placement_group_id: Optional[str] """ - Placement group ID in which all the nodes of the pool will be created. + Placement group ID in which all the nodes of the pool will be created, placement groups are limited to 20 instances. """ min_size: Optional[int] @@ -1188,12 +1306,12 @@ class CreatePoolRequest: container_runtime: Optional[Runtime] """ - Customization of the container runtime is available for each pool. Note that `docker` has been deprecated since version 1.20 and will be removed by version 1.24. + Customization of the container runtime is available for each pool. """ tags: Optional[List[str]] """ - Tags associated with the pool. + Tags associated with the pool, see [managing tags](https://www.scaleway.com/en/docs/containers/kubernetes/api-cli/managing-tags). """ kubelet_args: Optional[Dict[str, str]] @@ -1206,14 +1324,17 @@ class CreatePoolRequest: Pool upgrade policy. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone in which the pool's nodes will be spawned. """ root_volume_type: Optional[PoolVolumeType] """ - Defines the system volume disk type. Two different types of volume (`volume_type`) are provided: `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. `b_ssd` is a remote block storage which means your system is stored on a centralized and resilient cluster. + * `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. This type is not available for all node types +* `sbs-5k` is a remote block storage which means your system is stored on a centralized and resilient cluster with 5k IOPS limits +* `sbs-15k` is a faster remote block storage which means your system is stored on a centralized and resilient cluster with 15k IOPS limits +* `b_ssd` is the legacy remote block storage which means your system is stored on a centralized and resilient cluster. Consider using `sbs-5k` or `sbs-15k` instead. """ root_volume_size: Optional[int] @@ -1222,6 +1343,19 @@ class CreatePoolRequest: """ +@dataclass +class DeleteACLRuleRequest: + acl_id: str + """ + ID of the ACL rule to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class DeleteClusterRequest: cluster_id: str @@ -1234,7 +1368,7 @@ class DeleteClusterRequest: Defines whether all volumes (including retain volume type), empty Private Networks and Load Balancers with a name starting with the cluster ID will also be deleted. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1257,7 +1391,7 @@ class DeleteNodeRequest: Add a new node after the deletion of this node. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1270,7 +1404,7 @@ class DeletePoolRequest: ID of the pool to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1304,6 +1438,15 @@ class ExternalNode: node_taints: List[ExternalNodeCoreV1Taint] + iam_token: str + + +@dataclass +class ExternalNodeAuth: + node_secret_key: str + + metadata_url: str + @dataclass class GetClusterKubeConfigRequest: @@ -1312,7 +1455,7 @@ class GetClusterKubeConfigRequest: Cluster ID for which to download the kubeconfig. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1330,7 +1473,15 @@ class GetClusterRequest: ID of the requested cluster. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetNodeMetadataRequest: + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1343,7 +1494,7 @@ class GetNodeRequest: ID of the requested node. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1356,7 +1507,7 @@ class GetPoolRequest: ID of the requested pool. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1369,11 +1520,47 @@ class GetVersionRequest: Requested version name. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListClusterACLRulesRequest: + cluster_id: str + """ + ID of the cluster whose ACLs will be listed. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ + page: Optional[int] + """ + Page number for the returned ACLs. + """ + + page_size: Optional[int] + """ + Maximum number of ACLs per page. + """ + + +@dataclass +class ListClusterACLRulesResponse: + total_count: int + """ + Total number of ACLs that exist for the cluster. + """ + + rules: List[ACLRule] + """ + Paginated returned ACLs. + """ + @dataclass class ListClusterAvailableTypesRequest: @@ -1382,7 +1569,7 @@ class ListClusterAvailableTypesRequest: Cluster ID for which the available Kubernetes types will be listed. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1408,7 +1595,7 @@ class ListClusterAvailableVersionsRequest: Cluster ID for which the available Kubernetes versions will be listed. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1424,7 +1611,7 @@ class ListClusterAvailableVersionsResponse: @dataclass class ListClusterTypesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1455,7 +1642,7 @@ class ListClusterTypesResponse: @dataclass class ListClustersRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1526,7 +1713,7 @@ class ListNodesRequest: Cluster ID from which the nodes will be listed from. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1582,7 +1769,7 @@ class ListPoolsRequest: ID of the cluster whose pools will be listed. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1628,7 +1815,7 @@ class ListPoolsResponse: @dataclass class ListVersionsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1643,22 +1830,43 @@ class ListVersionsResponse: @dataclass -class MigrateToPrivateNetworkClusterRequest: +class MigratePoolsToNewImagesRequest: cluster_id: str - """ - ID of the cluster to migrate. - """ - - private_network_id: str - """ - ID of the Private Network to link to the cluster. - """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ + pool_ids: Optional[List[str]] + + +@dataclass +class NodeMetadata: + id: str + + name: str + + cluster_url: str + + cluster_ca: str + + credential_provider_config: str + + pool_version: str + + kubelet_config: str + + node_labels: Dict[str, str] + + node_taints: List[NodeMetadataCoreV1Taint] + + has_gpu: bool + + external_ip: str + + repo_uri: str + @dataclass class RebootNodeRequest: @@ -1667,7 +1875,7 @@ class RebootNodeRequest: ID of the node to reboot. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1680,7 +1888,7 @@ class ReplaceNodeRequest: ID of the node to replace. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1693,11 +1901,37 @@ class ResetClusterAdminTokenRequest: Cluster ID on which the admin token will be renewed. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SetClusterACLRulesRequest: + cluster_id: str + """ + ID of the cluster whose ACLs will be set. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ + acls: Optional[List[ACLRuleRequest]] + """ + ACLs to set. + """ + + +@dataclass +class SetClusterACLRulesResponse: + rules: List[ACLRule] + """ + ACLs that were set. + """ + @dataclass class SetClusterTypeRequest: @@ -1711,7 +1945,7 @@ class SetClusterTypeRequest: Type of the cluster. Note that some migrations are not possible (please refer to product documentation). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1724,7 +1958,7 @@ class UpdateClusterRequest: ID of the cluster to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1751,7 +1985,7 @@ class UpdateClusterRequest: auto_upgrade: Optional[UpdateClusterRequestAutoUpgrade] """ - New auto upgrade configuration for the cluster. Note that all fields need to be set. + New auto upgrade configuration for the cluster. Note that all fields needs to be set. """ feature_gates: Optional[List[str]] @@ -1782,7 +2016,7 @@ class UpdatePoolRequest: ID of the pool to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1845,7 +2079,7 @@ class UpgradeClusterRequest: Defines whether pools will also be upgraded once the control plane is upgraded. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1863,7 +2097,7 @@ class UpgradePoolRequest: New Kubernetes version for the pool. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway-async/scaleway_async/key_manager/__init__.py b/scaleway-async/scaleway_async/key_manager/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway-async/scaleway_async/key_manager/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway-async/scaleway_async/key_manager/v1alpha1/__init__.py b/scaleway-async/scaleway_async/key_manager/v1alpha1/__init__.py new file mode 100644 index 00000000..fb3ad375 --- /dev/null +++ b/scaleway-async/scaleway_async/key_manager/v1alpha1/__init__.py @@ -0,0 +1,79 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DataKeyAlgorithmSymmetricEncryption +from .types import KeyAlgorithmAsymmetricEncryption +from .types import KeyAlgorithmAsymmetricSigning +from .types import KeyAlgorithmSymmetricEncryption +from .types import KeyOrigin +from .types import KeyState +from .types import ListKeysRequestOrderBy +from .types import ListKeysRequestUsage +from .types import KeyRotationPolicy +from .types import KeyUsage +from .types import Key +from .types import CreateKeyRequest +from .types import DataKey +from .types import DecryptRequest +from .types import DecryptResponse +from .types import DeleteKeyMaterialRequest +from .types import DeleteKeyRequest +from .types import DisableKeyRequest +from .types import EnableKeyRequest +from .types import EncryptRequest +from .types import EncryptResponse +from .types import GenerateDataKeyRequest +from .types import GetKeyRequest +from .types import GetPublicKeyRequest +from .types import ImportKeyMaterialRequest +from .types import ListKeysRequest +from .types import ListKeysResponse +from .types import ProtectKeyRequest +from .types import PublicKey +from .types import RotateKeyRequest +from .types import SignRequest +from .types import SignResponse +from .types import UnprotectKeyRequest +from .types import UpdateKeyRequest +from .types import VerifyRequest +from .types import VerifyResponse +from .api import KeyManagerV1Alpha1API + +__all__ = [ + "DataKeyAlgorithmSymmetricEncryption", + "KeyAlgorithmAsymmetricEncryption", + "KeyAlgorithmAsymmetricSigning", + "KeyAlgorithmSymmetricEncryption", + "KeyOrigin", + "KeyState", + "ListKeysRequestOrderBy", + "ListKeysRequestUsage", + "KeyRotationPolicy", + "KeyUsage", + "Key", + "CreateKeyRequest", + "DataKey", + "DecryptRequest", + "DecryptResponse", + "DeleteKeyMaterialRequest", + "DeleteKeyRequest", + "DisableKeyRequest", + "EnableKeyRequest", + "EncryptRequest", + "EncryptResponse", + "GenerateDataKeyRequest", + "GetKeyRequest", + "GetPublicKeyRequest", + "ImportKeyMaterialRequest", + "ListKeysRequest", + "ListKeysResponse", + "ProtectKeyRequest", + "PublicKey", + "RotateKeyRequest", + "SignRequest", + "SignResponse", + "UnprotectKeyRequest", + "UpdateKeyRequest", + "VerifyRequest", + "VerifyResponse", + "KeyManagerV1Alpha1API", +] diff --git a/scaleway-async/scaleway_async/key_manager/v1alpha1/api.py b/scaleway-async/scaleway_async/key_manager/v1alpha1/api.py new file mode 100644 index 00000000..ad78a6dc --- /dev/null +++ b/scaleway-async/scaleway_async/key_manager/v1alpha1/api.py @@ -0,0 +1,878 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + validate_path_param, + fetch_all_pages_async, +) +from .types import ( + DataKeyAlgorithmSymmetricEncryption, + KeyOrigin, + ListKeysRequestOrderBy, + ListKeysRequestUsage, + CreateKeyRequest, + DataKey, + DecryptRequest, + DecryptResponse, + EncryptRequest, + EncryptResponse, + GenerateDataKeyRequest, + ImportKeyMaterialRequest, + Key, + KeyRotationPolicy, + KeyUsage, + ListKeysResponse, + PublicKey, + SignRequest, + SignResponse, + UpdateKeyRequest, + VerifyRequest, + VerifyResponse, +) +from .marshalling import ( + unmarshal_Key, + unmarshal_DataKey, + unmarshal_DecryptResponse, + unmarshal_EncryptResponse, + unmarshal_ListKeysResponse, + unmarshal_PublicKey, + unmarshal_SignResponse, + unmarshal_VerifyResponse, + marshal_CreateKeyRequest, + marshal_DecryptRequest, + marshal_EncryptRequest, + marshal_GenerateDataKeyRequest, + marshal_ImportKeyMaterialRequest, + marshal_SignRequest, + marshal_UpdateKeyRequest, + marshal_VerifyRequest, +) + + +class KeyManagerV1Alpha1API(API): + """ + This API allows you to create, manage and use cryptographic keys in a centralized and secure service. + """ + + async def create_key( + self, + *, + unprotected: bool, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + usage: Optional[KeyUsage] = None, + description: Optional[str] = None, + tags: Optional[List[str]] = None, + rotation_policy: Optional[KeyRotationPolicy] = None, + origin: Optional[KeyOrigin] = None, + ) -> Key: + """ + Create a key. + Create a key in a given region specified by the `region` parameter. Keys only support symmetric encryption. You can use keys to encrypt or decrypt arbitrary payloads, or to generate data encryption keys. **Data encryption keys are not stored in Key Manager**. + :param unprotected: Default value is `false`. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project containing the key. + :param name: (Optional) Name of the key. + :param usage: See the `Key.Algorithm.SymmetricEncryption` enum for a description of values. + :param description: (Optional) Description of the key. + :param tags: (Optional) List of the key's tags. + :param rotation_policy: If not specified, no rotation policy will be applied to the key. + :param origin: Refer to the `Key.Origin` enum for a description of values. + :return: :class:`Key ` + + Usage: + :: + + result = await api.create_key( + unprotected=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys", + body=marshal_CreateKeyRequest( + CreateKeyRequest( + unprotected=unprotected, + region=region, + project_id=project_id, + name=name, + usage=usage, + description=description, + tags=tags, + rotation_policy=rotation_policy, + origin=origin, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + async def get_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Get key metadata. + Retrieve metadata for a specified key using the `region` and `key_id` parameters. + :param key_id: ID of the key to target. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = await api.get_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "GET", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}", + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + async def get_public_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> PublicKey: + """ + Get the public key in PEM format. + Retrieves the public portion of an asymmetric cryptographic key in PEM format. + :param key_id: ID of the key. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`PublicKey ` + + Usage: + :: + + result = await api.get_public_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "GET", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/public-key", + ) + + self._throw_on_error(res) + return unmarshal_PublicKey(res.json()) + + async def update_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + description: Optional[str] = None, + tags: Optional[List[str]] = None, + rotation_policy: Optional[KeyRotationPolicy] = None, + ) -> Key: + """ + Update a key. + Modify a key's metadata including name, description and tags, specified by the `key_id` and `region` parameters. + :param key_id: ID of the key to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: (Optional) Updated name of the key. + :param description: (Optional) Updated description of the key. + :param tags: (Optional) Updated list of the key's tags. + :param rotation_policy: If not specified, the key's existing rotation policy applies. + :return: :class:`Key ` + + Usage: + :: + + result = await api.update_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "PATCH", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}", + body=marshal_UpdateKeyRequest( + UpdateKeyRequest( + key_id=key_id, + region=region, + name=name, + description=description, + tags=tags, + rotation_policy=rotation_policy, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + async def delete_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a key. + Permanently delete a key specified by the `region` and `key_id` parameters. This action is irreversible. Any data encrypted with this key, including data encryption keys, will no longer be decipherable. + :param key_id: ID of the key to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "DELETE", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}", + ) + + self._throw_on_error(res) + + async def rotate_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Rotate a key. + Generate a new version of an existing key with new key material. Previous key versions remain usable to decrypt previously encrypted data, but the key's new version will be used for subsequent encryption operations and data key generation. + :param key_id: ID of the key to rotate. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = await api.rotate_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/rotate", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + async def protect_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Apply key protection. + Apply protection to a given key specified by the `key_id` parameter. Applying key protection means that your key can be used and modified, but it cannot be deleted. + :param key_id: ID of the key to apply key protection to. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = await api.protect_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/protect", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + async def unprotect_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Remove key protection. + Remove key protection from a given key specified by the `key_id` parameter. Removing key protection means that your key can be deleted anytime. + :param key_id: ID of the key to remove key protection from. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = await api.unprotect_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/unprotect", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + async def enable_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Enable key. + Enable a given key to be used for cryptographic operations. Enabling a key allows you to make a disabled key usable again. You must specify the `region` and `key_id` parameters. + :param key_id: ID of the key to enable. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = await api.enable_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/enable", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + async def disable_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Disable key. + Disable a given key, preventing it to be used for cryptographic operations. Disabling a key renders it unusable. You must specify the `region` and `key_id` parameters. + :param key_id: ID of the key to disable. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = await api.disable_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/disable", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + async def list_keys( + self, + *, + region: Optional[ScwRegion] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + order_by: Optional[ListKeysRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + tags: Optional[List[str]] = None, + name: Optional[str] = None, + usage: Optional[ListKeysRequestUsage] = None, + ) -> ListKeysResponse: + """ + List keys. + Retrieve a list of keys across all Projects in an Organization or within a specific Project. You must specify the `region`, and either the `organization_id` or the `project_id`. + :param region: Region to target. If none is passed will use default region from the config. + :param organization_id: (Optional) Filter by Organization ID. + :param project_id: (Optional) Filter by Project ID. + :param order_by: + :param page: + :param page_size: + :param tags: (Optional) List of tags to filter on. + :param name: (Optional) Filter by key name. + :param usage: Select from symmetric encryption, asymmetric encryption, or asymmetric signing. + :return: :class:`ListKeysResponse ` + + Usage: + :: + + result = await api.list_keys() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/key-manager/v1alpha1/regions/{param_region}/keys", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + "usage": usage, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListKeysResponse(res.json()) + + async def list_keys_all( + self, + *, + region: Optional[ScwRegion] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + order_by: Optional[ListKeysRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + tags: Optional[List[str]] = None, + name: Optional[str] = None, + usage: Optional[ListKeysRequestUsage] = None, + ) -> List[Key]: + """ + List keys. + Retrieve a list of keys across all Projects in an Organization or within a specific Project. You must specify the `region`, and either the `organization_id` or the `project_id`. + :param region: Region to target. If none is passed will use default region from the config. + :param organization_id: (Optional) Filter by Organization ID. + :param project_id: (Optional) Filter by Project ID. + :param order_by: + :param page: + :param page_size: + :param tags: (Optional) List of tags to filter on. + :param name: (Optional) Filter by key name. + :param usage: Select from symmetric encryption, asymmetric encryption, or asymmetric signing. + :return: :class:`List[Key] ` + + Usage: + :: + + result = await api.list_keys_all() + """ + + return await fetch_all_pages_async( + type=ListKeysResponse, + key="keys", + fetcher=self.list_keys, + args={ + "region": region, + "organization_id": organization_id, + "project_id": project_id, + "order_by": order_by, + "page": page, + "page_size": page_size, + "tags": tags, + "name": name, + "usage": usage, + }, + ) + + async def generate_data_key( + self, + *, + key_id: str, + without_plaintext: bool, + region: Optional[ScwRegion] = None, + algorithm: Optional[DataKeyAlgorithmSymmetricEncryption] = None, + ) -> DataKey: + """ + Create a data encryption key. + Create a new data encryption key for cryptographic operations outside of Key Manager. The data encryption key is encrypted and must be decrypted using the key you have created in Key Manager. + + The data encryption key is returned in plaintext and ciphertext but it should only be stored in its encrypted form (ciphertext). Key Manager does not store your data encryption key. To retrieve your key's plaintext, use the `Decrypt` method with your key's ID and ciphertext. + :param key_id: ID of the key. + :param without_plaintext: Default value is `false`, meaning that the plaintext is returned. + Set it to `true` if you do not wish the plaintext to be returned in the response object. + :param region: Region to target. If none is passed will use default region from the config. + :param algorithm: See the `DataKey.Algorithm.SymmetricEncryption` enum for a description of values. + :return: :class:`DataKey ` + + Usage: + :: + + result = await api.generate_data_key( + key_id="example", + without_plaintext=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/generate-data-key", + body=marshal_GenerateDataKeyRequest( + GenerateDataKeyRequest( + key_id=key_id, + without_plaintext=without_plaintext, + region=region, + algorithm=algorithm, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DataKey(res.json()) + + async def encrypt( + self, + *, + key_id: str, + plaintext: str, + region: Optional[ScwRegion] = None, + associated_data: Optional[str] = None, + ) -> EncryptResponse: + """ + Encrypt a payload. + Encrypt a payload using an existing key, specified by the `key_id` parameter. Only keys with a usage set to `symmetric_encryption` are supported by this method. The maximum payload size that can be encrypted is 64 KB of plaintext. + :param key_id: The key must have an usage set to `symmetric_encryption` or `asymmetric_encryption`. + :param plaintext: Data size must be between 1 and 65535 bytes. + :param region: Region to target. If none is passed will use default region from the config. + :param associated_data: Additional data which will not be encrypted, but authenticated and appended to the encrypted payload. Only supported by keys with a usage set to `symmetric_encryption`. + :return: :class:`EncryptResponse ` + + Usage: + :: + + result = await api.encrypt( + key_id="example", + plaintext="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/encrypt", + body=marshal_EncryptRequest( + EncryptRequest( + key_id=key_id, + plaintext=plaintext, + region=region, + associated_data=associated_data, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_EncryptResponse(res.json()) + + async def decrypt( + self, + *, + key_id: str, + ciphertext: str, + region: Optional[ScwRegion] = None, + associated_data: Optional[str] = None, + ) -> DecryptResponse: + """ + Decrypt an encrypted payload. + Decrypt an encrypted payload using an existing key, specified by the `key_id` parameter. The maximum payload size that can be decrypted is equivalent to the encrypted output of 64 KB of data (around 131 KB). + :param key_id: The key must have an usage set to `symmetric_encryption` or `asymmetric_encryption`. + :param ciphertext: Data size must be between 1 and 131071 bytes. + :param region: Region to target. If none is passed will use default region from the config. + :param associated_data: The additional data must match the value passed in the encryption request. Only supported by keys with a usage set to `symmetric_encryption`. + :return: :class:`DecryptResponse ` + + Usage: + :: + + result = await api.decrypt( + key_id="example", + ciphertext="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/decrypt", + body=marshal_DecryptRequest( + DecryptRequest( + key_id=key_id, + ciphertext=ciphertext, + region=region, + associated_data=associated_data, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DecryptResponse(res.json()) + + async def sign( + self, + *, + key_id: str, + digest: str, + region: Optional[ScwRegion] = None, + ) -> SignResponse: + """ + Sign a message digest. + Use a given key to sign a message digest. The key must have its usage set to `asymmetric_signing`. The digest must be created using the same digest algorithm that is defined in the key's algorithm configuration. + :param key_id: ID of the key to use for signing. + :param digest: The digest must be generated using the same algorithm defined in the key’s algorithm settings. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`SignResponse ` + + Usage: + :: + + result = await api.sign( + key_id="example", + digest="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/sign", + body=marshal_SignRequest( + SignRequest( + key_id=key_id, + digest=digest, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SignResponse(res.json()) + + async def verify( + self, + *, + key_id: str, + digest: str, + signature: str, + region: Optional[ScwRegion] = None, + ) -> VerifyResponse: + """ + Verify a message signature. + Use a given key to verify a message signature against a message digest. The key must have its usage set to `asymmetric_signing`. The message digest must be generated using the same digest algorithm that is defined in the key's algorithm configuration. + :param key_id: ID of the key to use for signature verification. + :param digest: Must be generated using the same algorithm specified in the key’s configuration. + :param signature: The message signature to verify. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`VerifyResponse ` + + Usage: + :: + + result = await api.verify( + key_id="example", + digest="example", + signature="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/verify", + body=marshal_VerifyRequest( + VerifyRequest( + key_id=key_id, + digest=digest, + signature=signature, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_VerifyResponse(res.json()) + + async def import_key_material( + self, + *, + key_id: str, + key_material: str, + region: Optional[ScwRegion] = None, + salt: Optional[str] = None, + ) -> Key: + """ + Import key material. + Import externally generated key material into Key Manager to derive a new cryptographic key. The key's origin must be `external`. + :param key_id: The key's origin must be `external`. + :param key_material: The key material The key material is a random sequence of bytes used to derive a cryptographic key. + :param region: Region to target. If none is passed will use default region from the config. + :param salt: A salt is random data added to key material to ensure unique derived keys, even if the input is similar. It helps strengthen security when the key material has low randomness (low entropy). + :return: :class:`Key ` + + Usage: + :: + + result = await api.import_key_material( + key_id="example", + key_material="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/import-key-material", + body=marshal_ImportKeyMaterialRequest( + ImportKeyMaterialRequest( + key_id=key_id, + key_material=key_material, + region=region, + salt=salt, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + async def delete_key_material( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete key material. + Delete previously imported key material. This renders the associated cryptographic key unusable for any operation. The key's origin must be `external`. + :param key_id: ID of the key of which to delete the key material. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_key_material( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/delete-key-material", + body={}, + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/key_manager/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/key_manager/v1alpha1/marshalling.py new file mode 100644 index 00000000..2f1cab95 --- /dev/null +++ b/scaleway-async/scaleway_async/key_manager/v1alpha1/marshalling.py @@ -0,0 +1,503 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + KeyRotationPolicy, + KeyUsage, + Key, + DataKey, + DecryptResponse, + EncryptResponse, + ListKeysResponse, + PublicKey, + SignResponse, + VerifyResponse, + CreateKeyRequest, + DecryptRequest, + EncryptRequest, + GenerateDataKeyRequest, + ImportKeyMaterialRequest, + SignRequest, + UpdateKeyRequest, + VerifyRequest, +) + + +def unmarshal_KeyRotationPolicy(data: Any) -> KeyRotationPolicy: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KeyRotationPolicy' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rotation_period", None) + if field is not None: + args["rotation_period"] = field + else: + args["rotation_period"] = None + + field = data.get("next_rotation_at", None) + if field is not None: + args["next_rotation_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["next_rotation_at"] = None + + return KeyRotationPolicy(**args) + + +def unmarshal_KeyUsage(data: Any) -> KeyUsage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KeyUsage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("symmetric_encryption", None) + if field is not None: + args["symmetric_encryption"] = field + else: + args["symmetric_encryption"] = None + + field = data.get("asymmetric_encryption", None) + if field is not None: + args["asymmetric_encryption"] = field + else: + args["asymmetric_encryption"] = None + + field = data.get("asymmetric_signing", None) + if field is not None: + args["asymmetric_signing"] = field + else: + args["asymmetric_signing"] = None + + return KeyUsage(**args) + + +def unmarshal_Key(data: Any) -> Key: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Key' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("state", None) + if field is not None: + args["state"] = field + + field = data.get("rotation_count", None) + if field is not None: + args["rotation_count"] = field + + field = data.get("usage", None) + if field is not None: + args["usage"] = unmarshal_KeyUsage(field) + else: + args["usage"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("protected", None) + if field is not None: + args["protected"] = field + + field = data.get("locked", None) + if field is not None: + args["locked"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("origin", None) + if field is not None: + args["origin"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + else: + args["description"] = None + + field = data.get("rotated_at", None) + if field is not None: + args["rotated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["rotated_at"] = None + + field = data.get("rotation_policy", None) + if field is not None: + args["rotation_policy"] = unmarshal_KeyRotationPolicy(field) + else: + args["rotation_policy"] = None + + return Key(**args) + + +def unmarshal_DataKey(data: Any) -> DataKey: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DataKey' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + + field = data.get("algorithm", None) + if field is not None: + args["algorithm"] = field + + field = data.get("ciphertext", None) + if field is not None: + args["ciphertext"] = field + + field = data.get("plaintext", None) + if field is not None: + args["plaintext"] = field + else: + args["plaintext"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + return DataKey(**args) + + +def unmarshal_DecryptResponse(data: Any) -> DecryptResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DecryptResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + + field = data.get("plaintext", None) + if field is not None: + args["plaintext"] = field + + field = data.get("ciphertext", None) + if field is not None: + args["ciphertext"] = field + else: + args["ciphertext"] = None + + return DecryptResponse(**args) + + +def unmarshal_EncryptResponse(data: Any) -> EncryptResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EncryptResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + + field = data.get("ciphertext", None) + if field is not None: + args["ciphertext"] = field + + return EncryptResponse(**args) + + +def unmarshal_ListKeysResponse(data: Any) -> ListKeysResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListKeysResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("keys", None) + if field is not None: + args["keys"] = [unmarshal_Key(v) for v in field] if field is not None else None + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListKeysResponse(**args) + + +def unmarshal_PublicKey(data: Any) -> PublicKey: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicKey' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pem", None) + if field is not None: + args["pem"] = field + + return PublicKey(**args) + + +def unmarshal_SignResponse(data: Any) -> SignResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SignResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + + field = data.get("signature", None) + if field is not None: + args["signature"] = field + + return SignResponse(**args) + + +def unmarshal_VerifyResponse(data: Any) -> VerifyResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VerifyResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + + field = data.get("valid", None) + if field is not None: + args["valid"] = field + + return VerifyResponse(**args) + + +def marshal_KeyRotationPolicy( + request: KeyRotationPolicy, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.rotation_period is not None: + output["rotation_period"] = request.rotation_period + + if request.next_rotation_at is not None: + output["next_rotation_at"] = request.next_rotation_at.isoformat() + + return output + + +def marshal_KeyUsage( + request: KeyUsage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("symmetric_encryption", request.symmetric_encryption), + OneOfPossibility( + "asymmetric_encryption", request.asymmetric_encryption + ), + OneOfPossibility("asymmetric_signing", request.asymmetric_signing), + ] + ), + ) + + return output + + +def marshal_CreateKeyRequest( + request: CreateKeyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.unprotected is not None: + output["unprotected"] = request.unprotected + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.name is not None: + output["name"] = request.name + + if request.usage is not None: + output["usage"] = marshal_KeyUsage(request.usage, defaults) + + if request.description is not None: + output["description"] = request.description + + if request.tags is not None: + output["tags"] = request.tags + + if request.rotation_policy is not None: + output["rotation_policy"] = marshal_KeyRotationPolicy( + request.rotation_policy, defaults + ) + + if request.origin is not None: + output["origin"] = str(request.origin) + + return output + + +def marshal_DecryptRequest( + request: DecryptRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ciphertext is not None: + output["ciphertext"] = request.ciphertext + + if request.associated_data is not None: + output["associated_data"] = request.associated_data + + return output + + +def marshal_EncryptRequest( + request: EncryptRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.plaintext is not None: + output["plaintext"] = request.plaintext + + if request.associated_data is not None: + output["associated_data"] = request.associated_data + + return output + + +def marshal_GenerateDataKeyRequest( + request: GenerateDataKeyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.without_plaintext is not None: + output["without_plaintext"] = request.without_plaintext + + if request.algorithm is not None: + output["algorithm"] = str(request.algorithm) + + return output + + +def marshal_ImportKeyMaterialRequest( + request: ImportKeyMaterialRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.key_material is not None: + output["key_material"] = request.key_material + + if request.salt is not None: + output["salt"] = request.salt + + return output + + +def marshal_SignRequest( + request: SignRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.digest is not None: + output["digest"] = request.digest + + return output + + +def marshal_UpdateKeyRequest( + request: UpdateKeyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + if request.tags is not None: + output["tags"] = request.tags + + if request.rotation_policy is not None: + output["rotation_policy"] = marshal_KeyRotationPolicy( + request.rotation_policy, defaults + ) + + return output + + +def marshal_VerifyRequest( + request: VerifyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.digest is not None: + output["digest"] = request.digest + + if request.signature is not None: + output["signature"] = request.signature + + return output diff --git a/scaleway-async/scaleway_async/key_manager/v1alpha1/types.py b/scaleway-async/scaleway_async/key_manager/v1alpha1/types.py new file mode 100644 index 00000000..aa250709 --- /dev/null +++ b/scaleway-async/scaleway_async/key_manager/v1alpha1/types.py @@ -0,0 +1,676 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DataKeyAlgorithmSymmetricEncryption(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SYMMETRIC_ENCRYPTION = "unknown_symmetric_encryption" + AES_256_GCM = "aes_256_gcm" + + def __str__(self) -> str: + return str(self.value) + + +class KeyAlgorithmAsymmetricEncryption(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ASYMMETRIC_ENCRYPTION = "unknown_asymmetric_encryption" + RSA_OAEP_2048_SHA256 = "rsa_oaep_2048_sha256" + RSA_OAEP_3072_SHA256 = "rsa_oaep_3072_sha256" + RSA_OAEP_4096_SHA256 = "rsa_oaep_4096_sha256" + + def __str__(self) -> str: + return str(self.value) + + +class KeyAlgorithmAsymmetricSigning(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ASYMMETRIC_SIGNING = "unknown_asymmetric_signing" + EC_P256_SHA256 = "ec_p256_sha256" + EC_P384_SHA384 = "ec_p384_sha384" + RSA_PSS_2048_SHA256 = "rsa_pss_2048_sha256" + RSA_PSS_3072_SHA256 = "rsa_pss_3072_sha256" + RSA_PSS_4096_SHA256 = "rsa_pss_4096_sha256" + RSA_PKCS1_2048_SHA256 = "rsa_pkcs1_2048_sha256" + RSA_PKCS1_3072_SHA256 = "rsa_pkcs1_3072_sha256" + RSA_PKCS1_4096_SHA256 = "rsa_pkcs1_4096_sha256" + + def __str__(self) -> str: + return str(self.value) + + +class KeyAlgorithmSymmetricEncryption(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SYMMETRIC_ENCRYPTION = "unknown_symmetric_encryption" + AES_256_GCM = "aes_256_gcm" + + def __str__(self) -> str: + return str(self.value) + + +class KeyOrigin(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ORIGIN = "unknown_origin" + SCALEWAY_KMS = "scaleway_kms" + EXTERNAL = "external" + + def __str__(self) -> str: + return str(self.value) + + +class KeyState(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATE = "unknown_state" + ENABLED = "enabled" + DISABLED = "disabled" + PENDING_KEY_MATERIAL = "pending_key_material" + + def __str__(self) -> str: + return str(self.value) + + +class ListKeysRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + UPDATED_AT_ASC = "updated_at_asc" + UPDATED_AT_DESC = "updated_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListKeysRequestUsage(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_USAGE = "unknown_usage" + SYMMETRIC_ENCRYPTION = "symmetric_encryption" + ASYMMETRIC_ENCRYPTION = "asymmetric_encryption" + ASYMMETRIC_SIGNING = "asymmetric_signing" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class KeyRotationPolicy: + rotation_period: Optional[str] + """ + Time interval between two key rotations. The minimum duration is 24 hours and the maximum duration is 1 year (876000 hours). + """ + + next_rotation_at: Optional[datetime] + """ + Timestamp indicating the next scheduled rotation. + """ + + +@dataclass +class KeyUsage: + symmetric_encryption: Optional[KeyAlgorithmSymmetricEncryption] + + asymmetric_encryption: Optional[KeyAlgorithmAsymmetricEncryption] + + asymmetric_signing: Optional[KeyAlgorithmAsymmetricSigning] + + +@dataclass +class Key: + id: str + """ + ID of the key. + """ + + project_id: str + """ + ID of the Project containing the key. + """ + + name: str + """ + Name of the key. + """ + + state: KeyState + """ + See the `Key.State` enum for a description of possible values. + """ + + rotation_count: int + """ + The rotation count tracks the number of times the key has been rotated. + """ + + usage: Optional[KeyUsage] + """ + Keys with a usage set to `symmetric_encryption` can encrypt and decrypt data using the `AES-256-GCM` key algorithm. Key Manager currently only supports `AES-256-GCM`. + """ + + created_at: Optional[datetime] + """ + Key creation date. + """ + + updated_at: Optional[datetime] + """ + Key last modification date. + """ + + protected: bool + """ + Returns `true` if key protection is applied to the key. + """ + + locked: bool + """ + Returns `true` if the key is locked. + """ + + tags: List[str] + """ + List of the key's tags. + """ + + origin: KeyOrigin + """ + Refer to the `Key.Origin` enum for a description of values. + """ + + region: ScwRegion + """ + Region where the key is stored. + """ + + description: Optional[str] + """ + Description of the key. + """ + + rotated_at: Optional[datetime] + """ + Key last rotation date. + """ + + rotation_policy: Optional[KeyRotationPolicy] + """ + Key rotation policy. + """ + + +@dataclass +class CreateKeyRequest: + unprotected: bool + """ + Default value is `false`. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project containing the key. + """ + + name: Optional[str] + """ + (Optional) Name of the key. + """ + + usage: Optional[KeyUsage] + """ + See the `Key.Algorithm.SymmetricEncryption` enum for a description of values. + """ + + description: Optional[str] + """ + (Optional) Description of the key. + """ + + tags: Optional[List[str]] + """ + (Optional) List of the key's tags. + """ + + rotation_policy: Optional[KeyRotationPolicy] + """ + If not specified, no rotation policy will be applied to the key. + """ + + origin: Optional[KeyOrigin] + """ + Refer to the `Key.Origin` enum for a description of values. + """ + + +@dataclass +class DataKey: + key_id: str + """ + ID of the data encryption key. + """ + + algorithm: DataKeyAlgorithmSymmetricEncryption + """ + Symmetric encryption algorithm of the data encryption key (`AES-256-GCM`). + """ + + ciphertext: str + """ + Your data encryption key's ciphertext can be stored safely. It can only be decrypted through the keys you create in Key Manager, using the relevant key ID. + """ + + plaintext: Optional[str] + """ + (Optional) Your data encryption key's plaintext allows you to use the key immediately upon creation. It must neither be stored or shared. + """ + + created_at: Optional[datetime] + """ + Data encryption key creation date. + """ + + +@dataclass +class DecryptRequest: + key_id: str + """ + The key must have an usage set to `symmetric_encryption` or `asymmetric_encryption`. + """ + + ciphertext: str + """ + Data size must be between 1 and 131071 bytes. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + associated_data: Optional[str] + """ + The additional data must match the value passed in the encryption request. Only supported by keys with a usage set to `symmetric_encryption`. + """ + + +@dataclass +class DecryptResponse: + key_id: str + """ + ID of the key used for decryption. + """ + + plaintext: str + """ + Key's decrypted data. + """ + + ciphertext: Optional[str] + """ + If the data was already encrypted with the latest key rotation, no output will be returned in the response object. + """ + + +@dataclass +class DeleteKeyMaterialRequest: + key_id: str + """ + ID of the key of which to delete the key material. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteKeyRequest: + key_id: str + """ + ID of the key to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DisableKeyRequest: + key_id: str + """ + ID of the key to disable. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class EnableKeyRequest: + key_id: str + """ + ID of the key to enable. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class EncryptRequest: + key_id: str + """ + The key must have an usage set to `symmetric_encryption` or `asymmetric_encryption`. + """ + + plaintext: str + """ + Data size must be between 1 and 65535 bytes. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + associated_data: Optional[str] + """ + Additional data which will not be encrypted, but authenticated and appended to the encrypted payload. Only supported by keys with a usage set to `symmetric_encryption`. + """ + + +@dataclass +class EncryptResponse: + key_id: str + """ + ID of the key used for encryption. + """ + + ciphertext: str + """ + Key's encrypted data. + """ + + +@dataclass +class GenerateDataKeyRequest: + key_id: str + """ + ID of the key. + """ + + without_plaintext: bool + """ + Default value is `false`, meaning that the plaintext is returned. +Set it to `true` if you do not wish the plaintext to be returned in the response object. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + algorithm: Optional[DataKeyAlgorithmSymmetricEncryption] + """ + See the `DataKey.Algorithm.SymmetricEncryption` enum for a description of values. + """ + + +@dataclass +class GetKeyRequest: + key_id: str + """ + ID of the key to target. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetPublicKeyRequest: + key_id: str + """ + ID of the key. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ImportKeyMaterialRequest: + key_id: str + """ + The key's origin must be `external`. + """ + + key_material: str + """ + The key material The key material is a random sequence of bytes used to derive a cryptographic key. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + salt: Optional[str] + """ + A salt is random data added to key material to ensure unique derived keys, even if the input is similar. It helps strengthen security when the key material has low randomness (low entropy). + """ + + +@dataclass +class ListKeysRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + organization_id: Optional[str] + """ + (Optional) Filter by Organization ID. + """ + + project_id: Optional[str] + """ + (Optional) Filter by Project ID. + """ + + order_by: Optional[ListKeysRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + tags: Optional[List[str]] + """ + (Optional) List of tags to filter on. + """ + + name: Optional[str] + """ + (Optional) Filter by key name. + """ + + usage: Optional[ListKeysRequestUsage] + """ + Select from symmetric encryption, asymmetric encryption, or asymmetric signing. + """ + + +@dataclass +class ListKeysResponse: + keys: List[Key] + """ + Single page of keys matching the requested criteria. + """ + + total_count: int + """ + Total count of keys matching the requested criteria. + """ + + +@dataclass +class ProtectKeyRequest: + key_id: str + """ + ID of the key to apply key protection to. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class PublicKey: + pem: str + + +@dataclass +class RotateKeyRequest: + key_id: str + """ + ID of the key to rotate. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SignRequest: + key_id: str + """ + ID of the key to use for signing. + """ + + digest: str + """ + The digest must be generated using the same algorithm defined in the key’s algorithm settings. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SignResponse: + key_id: str + """ + ID of the key used to generate the signature. + """ + + signature: str + """ + The message signature. + """ + + +@dataclass +class UnprotectKeyRequest: + key_id: str + """ + ID of the key to remove key protection from. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class UpdateKeyRequest: + key_id: str + """ + ID of the key to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + (Optional) Updated name of the key. + """ + + description: Optional[str] + """ + (Optional) Updated description of the key. + """ + + tags: Optional[List[str]] + """ + (Optional) Updated list of the key's tags. + """ + + rotation_policy: Optional[KeyRotationPolicy] + """ + If not specified, the key's existing rotation policy applies. + """ + + +@dataclass +class VerifyRequest: + key_id: str + """ + ID of the key to use for signature verification. + """ + + digest: str + """ + Must be generated using the same algorithm specified in the key’s configuration. + """ + + signature: str + """ + The message signature to verify. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class VerifyResponse: + key_id: str + """ + ID of the key used for verification. + """ + + valid: bool + """ + Returns `true` if the signature is valid for the digest and key, `false` otherwise. + """ diff --git a/scaleway-async/scaleway_async/lb/v1/api.py b/scaleway-async/scaleway_async/lb/v1/api.py index bea7a6c2..64ed333c 100644 --- a/scaleway-async/scaleway_async/lb/v1/api.py +++ b/scaleway-async/scaleway_async/lb/v1/api.py @@ -5,8 +5,8 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, - Zone, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, @@ -107,6 +107,7 @@ ZonedApiCreateLbRequest, ZonedApiCreateRouteRequest, ZonedApiCreateSubscriberRequest, + ZonedApiDetachPrivateNetworkRequest, ZonedApiMigrateLbRequest, ZonedApiRemoveBackendServersRequest, ZonedApiSetAclsRequest, @@ -183,6 +184,7 @@ marshal_ZonedApiCreateLbRequest, marshal_ZonedApiCreateRouteRequest, marshal_ZonedApiCreateSubscriberRequest, + marshal_ZonedApiDetachPrivateNetworkRequest, marshal_ZonedApiMigrateLbRequest, marshal_ZonedApiRemoveBackendServersRequest, marshal_ZonedApiSetAclsRequest, @@ -208,7 +210,7 @@ class LbV1ZonedAPI(API): async def list_lbs( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListLbsRequestOrderBy] = None, page_size: Optional[int] = None, @@ -259,7 +261,7 @@ async def list_lbs( async def list_lbs_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListLbsRequestOrderBy] = None, page_size: Optional[int] = None, @@ -308,7 +310,7 @@ async def create_lb( *, description: str, type_: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, name: Optional[str] = None, @@ -331,7 +333,7 @@ async def create_lb( One-Of ('project_identifier'): at most one of 'project_id', 'organization_id' could be set. :param name: Name for the Load Balancer. :param ip_id: ID of an existing flexible IP address to attach to the Load Balancer. - :param assign_flexible_ip: Defines whether to automatically assign a flexible public IP to lb. Default value is `false` (do not assign). + :param assign_flexible_ip: Defines whether to automatically assign a flexible public IP to the Load Balancer. Default value is `true` (assign). :param assign_flexible_ipv6: Defines whether to automatically assign a flexible public IPv6 to the Load Balancer. Default value is `false` (do not assign). :param ip_ids: List of IP IDs to attach to the Load Balancer. :param tags: List of tags for the Load Balancer. @@ -378,7 +380,7 @@ async def get_lb( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Lb: """ Get a Load Balancer. @@ -410,7 +412,7 @@ async def wait_for_lb( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Lb, Union[bool, Awaitable[bool]]]] = None, ) -> Lb: """ @@ -449,7 +451,7 @@ async def update_lb( lb_id: str, name: str, description: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, ssl_compatibility_level: Optional[SSLCompatibilityLevel] = None, ) -> Lb: @@ -501,7 +503,7 @@ async def delete_lb( *, lb_id: str, release_ip: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a Load Balancer. @@ -537,7 +539,7 @@ async def migrate_lb( *, lb_id: str, type_: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Lb: """ Migrate a Load Balancer. @@ -578,13 +580,14 @@ async def migrate_lb( async def list_i_ps( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ip_address: Optional[str] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, ip_type: Optional[ListIpsRequestIpType] = None, + tags: Optional[List[str]] = None, ) -> ListIpsResponse: """ List IP addresses. @@ -596,6 +599,7 @@ async def list_i_ps( :param organization_id: Organization ID to filter for, only Load Balancer IP addresses from this Organization will be returned. :param project_id: Project ID to filter for, only Load Balancer IP addresses from this Project will be returned. :param ip_type: IP type to filter for. + :param tags: Tag to filter for, only IPs with one or more matching tags will be returned. :return: :class:`ListIpsResponse ` Usage: @@ -617,6 +621,7 @@ async def list_i_ps( "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, + "tags": tags, }, ) @@ -626,13 +631,14 @@ async def list_i_ps( async def list_i_ps_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ip_address: Optional[str] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, ip_type: Optional[ListIpsRequestIpType] = None, + tags: Optional[List[str]] = None, ) -> List[Ip]: """ List IP addresses. @@ -644,6 +650,7 @@ async def list_i_ps_all( :param organization_id: Organization ID to filter for, only Load Balancer IP addresses from this Organization will be returned. :param project_id: Project ID to filter for, only Load Balancer IP addresses from this Project will be returned. :param ip_type: IP type to filter for. + :param tags: Tag to filter for, only IPs with one or more matching tags will be returned. :return: :class:`List[Ip] ` Usage: @@ -664,6 +671,7 @@ async def list_i_ps_all( "organization_id": organization_id, "project_id": project_id, "ip_type": ip_type, + "tags": tags, }, ) @@ -671,10 +679,11 @@ async def create_ip( self, *, is_ipv6: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, reverse: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> Ip: """ Create an IP address. @@ -686,6 +695,7 @@ async def create_ip( :param project_id: Project ID of the Project where the IP address should be created. One-Of ('project_identifier'): at most one of 'project_id', 'organization_id' could be set. :param reverse: Reverse DNS (domain name) for the IP address. + :param tags: List of tags for the IP. :return: :class:`Ip ` Usage: @@ -706,6 +716,7 @@ async def create_ip( is_ipv6=is_ipv6, zone=zone, reverse=reverse, + tags=tags, project_id=project_id, organization_id=organization_id, ), @@ -720,7 +731,7 @@ async def get_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Ip: """ Get an IP address. @@ -752,7 +763,7 @@ async def release_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an IP address. @@ -782,9 +793,10 @@ async def update_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, reverse: Optional[str] = None, lb_id: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> Ip: """ Update an IP address. @@ -793,6 +805,7 @@ async def update_ip( :param zone: Zone to target. If none is passed will use default zone from the config. :param reverse: Reverse DNS (domain name) for the IP address. :param lb_id: ID of the server on which to attach the flexible IP. + :param tags: List of tags for the IP. :return: :class:`Ip ` Usage: @@ -815,6 +828,7 @@ async def update_ip( zone=zone, reverse=reverse, lb_id=lb_id, + tags=tags, ), self.client, ), @@ -827,7 +841,7 @@ async def list_backends( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListBackendsRequestOrderBy] = None, page: Optional[int] = None, @@ -873,7 +887,7 @@ async def list_backends_all( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListBackendsRequestOrderBy] = None, page: Optional[int] = None, @@ -923,7 +937,7 @@ async def create_backend( lb_id: str, health_check: HealthCheck, server_ip: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, send_proxy_v2: Optional[bool] = None, timeout_server: Optional[str] = None, @@ -958,7 +972,7 @@ async def create_backend( :param timeout_tunnel: Maximum allowed tunnel inactivity time after Websocket is established (takes precedence over client and server timeout). :param on_marked_down_action: Action to take when a backend server is marked as down. :param proxy_protocol: Protocol to use between the Load Balancer and backend servers. Allows the backend servers to be informed of the client's real IP address. The PROXY protocol must be supported by the backend servers' software. - :param failover_host: Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + :param failover_host: Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. :param ssl_bridging: Defines whether to enable SSL bridging between the Load Balancer and backend servers. :param ignore_ssl_server_verify: Defines whether the server certificate verification should be ignored. :param redispatch_attempt_count: Whether to use another backend server on each attempt. @@ -1025,7 +1039,7 @@ async def get_backend( self, *, backend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Backend: """ Get a backend of a given Load Balancer. @@ -1063,7 +1077,7 @@ async def update_backend( forward_port_algorithm: ForwardPortAlgorithm, sticky_sessions: StickySessionsType, sticky_sessions_cookie_name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, send_proxy_v2: Optional[bool] = None, timeout_server: Optional[str] = None, timeout_connect: Optional[str] = None, @@ -1095,7 +1109,7 @@ async def update_backend( :param timeout_tunnel: Maximum allowed tunnel inactivity time after Websocket is established (takes precedence over client and server timeout). :param on_marked_down_action: Action to take when a backend server is marked as down. :param proxy_protocol: Protocol to use between the Load Balancer and backend servers. Allows the backend servers to be informed of the client's real IP address. The PROXY protocol must be supported by the backend servers' software. - :param failover_host: Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + :param failover_host: Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. :param ssl_bridging: Defines whether to enable SSL bridging between the Load Balancer and backend servers. :param ignore_ssl_server_verify: Defines whether the server certificate verification should be ignored. :param redispatch_attempt_count: Whether to use another backend server on each attempt. @@ -1159,7 +1173,7 @@ async def delete_backend( self, *, backend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a backend of a given Load Balancer. @@ -1190,7 +1204,7 @@ async def add_backend_servers( *, backend_id: str, server_ip: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Backend: """ Add a set of backend servers to a given backend. @@ -1233,7 +1247,7 @@ async def remove_backend_servers( *, backend_id: str, server_ip: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Backend: """ Remove a set of servers for a given backend. @@ -1276,7 +1290,7 @@ async def set_backend_servers( *, backend_id: str, server_ip: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Backend: """ Define all backend servers for a given backend. @@ -1320,7 +1334,7 @@ async def update_health_check( port: int, check_max_retries: int, backend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, check_delay: Optional[str] = None, check_timeout: Optional[str] = None, check_send_proxy: bool, @@ -1345,7 +1359,7 @@ async def update_health_check( :param check_send_proxy: Defines whether proxy protocol should be activated for the health check. :param tcp_config: Object to configure a basic TCP health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. - :param mysql_config: Object to configure a MySQL health check. The check requires MySQL >=3.22, for older versions, use a TCP health check. + :param mysql_config: Object to configure a MySQL health check. The check requires MySQL >=3.22 or <9.0. For older or newer versions, use a TCP health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. :param pgsql_config: Object to configure a PostgreSQL health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. @@ -1406,7 +1420,7 @@ async def list_frontends( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListFrontendsRequestOrderBy] = None, page: Optional[int] = None, @@ -1452,7 +1466,7 @@ async def list_frontends_all( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListFrontendsRequestOrderBy] = None, page: Optional[int] = None, @@ -1498,11 +1512,12 @@ async def create_frontend( lb_id: str, backend_id: str, enable_http3: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Create a frontend in a given Load Balancer. @@ -1516,6 +1531,7 @@ async def create_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -1546,6 +1562,7 @@ async def create_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -1558,7 +1575,7 @@ async def get_frontend( self, *, frontend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Frontend: """ Get a frontend. @@ -1594,10 +1611,11 @@ async def update_frontend( inbound_port: int, backend_id: str, enable_http3: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Update a frontend. @@ -1611,6 +1629,7 @@ async def update_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -1642,6 +1661,7 @@ async def update_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -1654,7 +1674,7 @@ async def delete_frontend( self, *, frontend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a frontend. @@ -1683,7 +1703,7 @@ async def delete_frontend( async def list_routes( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -1724,7 +1744,7 @@ async def list_routes( async def list_routes_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -1764,7 +1784,7 @@ async def create_route( *, frontend_id: str, backend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, match: Optional[RouteMatch] = None, ) -> Route: """ @@ -1808,7 +1828,7 @@ async def get_route( self, *, route_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Route: """ Get a route. @@ -1841,7 +1861,7 @@ async def update_route( *, route_id: str, backend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, match: Optional[RouteMatch] = None, ) -> Route: """ @@ -1886,7 +1906,7 @@ async def delete_route( self, *, route_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a route. @@ -1916,7 +1936,7 @@ async def get_lb_stats( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, backend_id: Optional[str] = None, ) -> LbStats: """ @@ -1953,7 +1973,7 @@ async def list_backend_stats( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, backend_id: Optional[str] = None, @@ -1996,7 +2016,7 @@ async def list_backend_stats_all( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, backend_id: Optional[str] = None, @@ -2036,7 +2056,7 @@ async def list_acls( self, *, frontend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListAclRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2082,7 +2102,7 @@ async def list_acls_all( self, *, frontend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListAclRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2128,7 +2148,7 @@ async def create_acl( action: AclAction, index: int, description: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, match: Optional[AclMatch] = None, ) -> Acl: @@ -2182,7 +2202,7 @@ async def get_acl( self, *, acl_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Acl: """ Get an ACL. @@ -2217,7 +2237,7 @@ async def update_acl( name: str, action: AclAction, index: int, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, match: Optional[AclMatch] = None, description: Optional[str] = None, ) -> Acl: @@ -2271,7 +2291,7 @@ async def delete_acl( self, *, acl_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an ACL. @@ -2302,7 +2322,7 @@ async def set_acls( *, acls: List[AclSpec], frontend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetAclsResponse: """ Define all ACLs for a given frontend. @@ -2344,7 +2364,7 @@ async def create_certificate( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, letsencrypt: Optional[CreateCertificateRequestLetsencryptConfig] = None, custom_certificate: Optional[CreateCertificateRequestCustomCertificate] = None, @@ -2394,7 +2414,7 @@ async def list_certificates( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListCertificatesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2440,7 +2460,7 @@ async def list_certificates_all( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListCertificatesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2483,7 +2503,7 @@ async def get_certificate( self, *, certificate_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Certificate: """ Get an SSL/TLS certificate. @@ -2515,7 +2535,7 @@ async def wait_for_certificate( self, *, certificate_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[ WaitForOptions[Certificate, Union[bool, Awaitable[bool]]] ] = None, @@ -2555,7 +2575,7 @@ async def update_certificate( *, certificate_id: str, name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Certificate: """ Update an SSL/TLS certificate. @@ -2597,7 +2617,7 @@ async def delete_certificate( self, *, certificate_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an SSL/TLS certificate. @@ -2626,7 +2646,7 @@ async def delete_certificate( async def list_lb_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListLbTypesResponse: @@ -2661,7 +2681,7 @@ async def list_lb_types( async def list_lb_types_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[LbType]: @@ -2694,7 +2714,7 @@ async def create_subscriber( self, *, name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, email_config: Optional[SubscriberEmailConfig] = None, webhook_config: Optional[SubscriberWebhookConfig] = None, organization_id: Optional[str] = None, @@ -2748,7 +2768,7 @@ async def get_subscriber( self, *, subscriber_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Subscriber: """ Get a subscriber. @@ -2779,7 +2799,7 @@ async def get_subscriber( async def list_subscriber( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListSubscriberRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2827,7 +2847,7 @@ async def list_subscriber( async def list_subscriber_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListSubscriberRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2873,7 +2893,7 @@ async def update_subscriber( *, subscriber_id: str, name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, email_config: Optional[SubscriberEmailConfig] = None, webhook_config: Optional[SubscriberWebhookConfig] = None, ) -> Subscriber: @@ -2923,7 +2943,7 @@ async def delete_subscriber( self, *, subscriber_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a subscriber. @@ -2954,7 +2974,7 @@ async def subscribe_to_lb( *, lb_id: str, subscriber_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Lb: """ Subscribe a subscriber to alerts for a given Load Balancer. @@ -2996,7 +3016,7 @@ async def unsubscribe_from_lb( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Lb: """ Unsubscribe a subscriber from alerts for a given Load Balancer. @@ -3028,7 +3048,7 @@ async def list_lb_private_networks( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -3071,7 +3091,7 @@ async def list_lb_private_networks_all( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -3112,10 +3132,11 @@ async def attach_private_network( *, lb_id: str, private_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, static_config: Optional[PrivateNetworkStaticConfig] = None, dhcp_config: Optional[PrivateNetworkDHCPConfig] = None, ipam_config: Optional[PrivateNetworkIpamConfig] = None, + ipam_ids: Optional[List[str]] = None, ) -> PrivateNetwork: """ Attach a Load Balancer to a Private Network. @@ -3129,6 +3150,7 @@ async def attach_private_network( One-Of ('config'): at most one of 'static_config', 'dhcp_config', 'ipam_config' could be set. :param ipam_config: For internal use only. One-Of ('config'): at most one of 'static_config', 'dhcp_config', 'ipam_config' could be set. + :param ipam_ids: IPAM ID of a pre-reserved IP address to assign to the Load Balancer on this Private Network. In the future, it will be possible to specify multiple IPs in this field (IPv4 and IPv6), for now only one ID of an IPv4 address is expected. When null, a new private IP address is created for the Load Balancer on this Private Network. :return: :class:`PrivateNetwork ` Usage: @@ -3142,18 +3164,16 @@ async def attach_private_network( param_zone = validate_path_param("zone", zone or self.client.default_zone) param_lb_id = validate_path_param("lb_id", lb_id) - param_private_network_id = validate_path_param( - "private_network_id", private_network_id - ) res = self._request( "POST", - f"/lb/v1/zones/{param_zone}/lbs/{param_lb_id}/private-networks/{param_private_network_id}/attach", + f"/lb/v1/zones/{param_zone}/lbs/{param_lb_id}/attach-private-network", body=marshal_ZonedApiAttachPrivateNetworkRequest( ZonedApiAttachPrivateNetworkRequest( lb_id=lb_id, private_network_id=private_network_id, zone=zone, + ipam_ids=ipam_ids, static_config=static_config, dhcp_config=dhcp_config, ipam_config=ipam_config, @@ -3170,7 +3190,7 @@ async def detach_private_network( *, lb_id: str, private_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Detach Load Balancer from Private Network. @@ -3190,14 +3210,18 @@ async def detach_private_network( param_zone = validate_path_param("zone", zone or self.client.default_zone) param_lb_id = validate_path_param("lb_id", lb_id) - param_private_network_id = validate_path_param( - "private_network_id", private_network_id - ) res = self._request( "POST", - f"/lb/v1/zones/{param_zone}/lbs/{param_lb_id}/private-networks/{param_private_network_id}/detach", - body={}, + f"/lb/v1/zones/{param_zone}/lbs/{param_lb_id}/detach-private-network", + body=marshal_ZonedApiDetachPrivateNetworkRequest( + ZonedApiDetachPrivateNetworkRequest( + lb_id=lb_id, + private_network_id=private_network_id, + zone=zone, + ), + self.client, + ), ) self._throw_on_error(res) @@ -3205,13 +3229,13 @@ async def detach_private_network( class LbV1API(API): """ - This API allows you to manage your load balancer service. + This API allows you to manage your Load Balancers. """ async def list_lbs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListLbsRequestOrderBy] = None, page_size: Optional[int] = None, @@ -3263,7 +3287,7 @@ async def list_lbs( async def list_lbs_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListLbsRequestOrderBy] = None, page_size: Optional[int] = None, @@ -3311,7 +3335,7 @@ async def create_lb( *, description: str, type_: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, name: Optional[str] = None, @@ -3333,7 +3357,7 @@ async def create_lb( One-Of ('project_identifier'): at most one of 'project_id', 'organization_id' could be set. :param name: Name for the Load Balancer. :param ip_id: ID of an existing flexible IP address to attach to the Load Balancer. - :param assign_flexible_ip: Defines whether to automatically assign a flexible public IP to lb. Default value is `false` (do not assign). + :param assign_flexible_ip: Defines whether to automatically assign a flexible public IP to the Load Balancer. Default value is `true` (assign). :param assign_flexible_ipv6: Defines whether to automatically assign a flexible public IPv6 to the Load Balancer. Default value is `false` (do not assign). :param ip_ids: List of IP IDs to attach to the Load Balancer. :param tags: List of tags for the Load Balancer. @@ -3382,7 +3406,7 @@ async def get_lb( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Lb: """ Get a load balancer. @@ -3415,7 +3439,7 @@ async def wait_for_lb( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Lb, Union[bool, Awaitable[bool]]]] = None, ) -> Lb: """ @@ -3453,7 +3477,7 @@ async def update_lb( lb_id: str, name: str, description: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, tags: Optional[List[str]] = None, ssl_compatibility_level: Optional[SSLCompatibilityLevel] = None, ) -> Lb: @@ -3506,7 +3530,7 @@ async def delete_lb( *, lb_id: str, release_ip: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a load balancer. @@ -3543,7 +3567,7 @@ async def migrate_lb( *, lb_id: str, type_: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Lb: """ Migrate a load balancer. @@ -3585,13 +3609,14 @@ async def migrate_lb( async def list_i_ps( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ip_address: Optional[str] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, ip_type: Optional[ListIpsRequestIpType] = None, + tags: Optional[List[str]] = None, ) -> ListIpsResponse: """ List IPs. @@ -3602,6 +3627,7 @@ async def list_i_ps( :param organization_id: Organization ID to filter for, only Load Balancer IP addresses from this Organization will be returned. :param project_id: Project ID to filter for, only Load Balancer IP addresses from this Project will be returned. :param ip_type: IP type to filter for. + :param tags: Tag to filter for, only IPs with one or more matching tags will be returned. :return: :class:`ListIpsResponse ` Usage: @@ -3625,6 +3651,7 @@ async def list_i_ps( "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, + "tags": tags, }, ) @@ -3634,13 +3661,14 @@ async def list_i_ps( async def list_i_ps_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ip_address: Optional[str] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, ip_type: Optional[ListIpsRequestIpType] = None, + tags: Optional[List[str]] = None, ) -> List[Ip]: """ List IPs. @@ -3651,6 +3679,7 @@ async def list_i_ps_all( :param organization_id: Organization ID to filter for, only Load Balancer IP addresses from this Organization will be returned. :param project_id: Project ID to filter for, only Load Balancer IP addresses from this Project will be returned. :param ip_type: IP type to filter for. + :param tags: Tag to filter for, only IPs with one or more matching tags will be returned. :return: :class:`List[Ip] ` Usage: @@ -3671,6 +3700,7 @@ async def list_i_ps_all( "organization_id": organization_id, "project_id": project_id, "ip_type": ip_type, + "tags": tags, }, ) @@ -3678,10 +3708,11 @@ async def create_ip( self, *, is_ipv6: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, reverse: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> Ip: """ Create an IP. @@ -3692,6 +3723,7 @@ async def create_ip( :param project_id: Project ID of the Project where the IP address should be created. One-Of ('project_identifier'): at most one of 'project_id', 'organization_id' could be set. :param reverse: Reverse DNS (domain name) for the IP address. + :param tags: List of tags for the IP. :return: :class:`Ip ` Usage: @@ -3714,6 +3746,7 @@ async def create_ip( is_ipv6=is_ipv6, region=region, reverse=reverse, + tags=tags, project_id=project_id, organization_id=organization_id, ), @@ -3728,7 +3761,7 @@ async def get_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Ip: """ Get an IP. @@ -3761,7 +3794,7 @@ async def release_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete an IP. @@ -3792,9 +3825,10 @@ async def update_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, reverse: Optional[str] = None, lb_id: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> Ip: """ Update an IP. @@ -3802,6 +3836,7 @@ async def update_ip( :param region: Region to target. If none is passed will use default region from the config. :param reverse: Reverse DNS (domain name) for the IP address. :param lb_id: ID of the server on which to attach the flexible IP. + :param tags: List of tags for the IP. :return: :class:`Ip ` Usage: @@ -3826,6 +3861,7 @@ async def update_ip( region=region, reverse=reverse, lb_id=lb_id, + tags=tags, ), self.client, ), @@ -3838,7 +3874,7 @@ async def list_backends( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListBackendsRequestOrderBy] = None, page: Optional[int] = None, @@ -3885,7 +3921,7 @@ async def list_backends_all( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListBackendsRequestOrderBy] = None, page: Optional[int] = None, @@ -3934,7 +3970,7 @@ async def create_backend( lb_id: str, health_check: HealthCheck, server_ip: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, send_proxy_v2: Optional[bool] = None, timeout_server: Optional[str] = None, @@ -3968,7 +4004,7 @@ async def create_backend( :param timeout_tunnel: Maximum allowed tunnel inactivity time after Websocket is established (takes precedence over client and server timeout). :param on_marked_down_action: Action to take when a backend server is marked as down. :param proxy_protocol: Protocol to use between the Load Balancer and backend servers. Allows the backend servers to be informed of the client's real IP address. The PROXY protocol must be supported by the backend servers' software. - :param failover_host: Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + :param failover_host: Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. :param ssl_bridging: Defines whether to enable SSL bridging between the Load Balancer and backend servers. :param ignore_ssl_server_verify: Defines whether the server certificate verification should be ignored. :param redispatch_attempt_count: Whether to use another backend server on each attempt. @@ -4037,7 +4073,7 @@ async def get_backend( self, *, backend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Backend: """ Get a backend in a given load balancer. @@ -4076,7 +4112,7 @@ async def update_backend( forward_port_algorithm: ForwardPortAlgorithm, sticky_sessions: StickySessionsType, sticky_sessions_cookie_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, send_proxy_v2: Optional[bool] = None, timeout_server: Optional[str] = None, timeout_connect: Optional[str] = None, @@ -4107,7 +4143,7 @@ async def update_backend( :param timeout_tunnel: Maximum allowed tunnel inactivity time after Websocket is established (takes precedence over client and server timeout). :param on_marked_down_action: Action to take when a backend server is marked as down. :param proxy_protocol: Protocol to use between the Load Balancer and backend servers. Allows the backend servers to be informed of the client's real IP address. The PROXY protocol must be supported by the backend servers' software. - :param failover_host: Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + :param failover_host: Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. :param ssl_bridging: Defines whether to enable SSL bridging between the Load Balancer and backend servers. :param ignore_ssl_server_verify: Defines whether the server certificate verification should be ignored. :param redispatch_attempt_count: Whether to use another backend server on each attempt. @@ -4173,7 +4209,7 @@ async def delete_backend( self, *, backend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a backend in a given load balancer. @@ -4205,7 +4241,7 @@ async def add_backend_servers( *, backend_id: str, server_ip: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Backend: """ Add a set of servers in a given backend. @@ -4249,7 +4285,7 @@ async def remove_backend_servers( *, backend_id: str, server_ip: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Backend: """ Remove a set of servers for a given backend. @@ -4293,7 +4329,7 @@ async def set_backend_servers( *, backend_id: str, server_ip: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Backend: """ Define all servers in a given backend. @@ -4338,7 +4374,7 @@ async def update_health_check( port: int, check_max_retries: int, backend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, check_delay: Optional[str] = None, check_timeout: Optional[str] = None, check_send_proxy: bool, @@ -4362,7 +4398,7 @@ async def update_health_check( :param check_send_proxy: Defines whether proxy protocol should be activated for the health check. :param tcp_config: Object to configure a basic TCP health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. - :param mysql_config: Object to configure a MySQL health check. The check requires MySQL >=3.22, for older versions, use a TCP health check. + :param mysql_config: Object to configure a MySQL health check. The check requires MySQL >=3.22 or <9.0. For older or newer versions, use a TCP health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. :param pgsql_config: Object to configure a PostgreSQL health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. @@ -4425,7 +4461,7 @@ async def list_frontends( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListFrontendsRequestOrderBy] = None, page: Optional[int] = None, @@ -4472,7 +4508,7 @@ async def list_frontends_all( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListFrontendsRequestOrderBy] = None, page: Optional[int] = None, @@ -4517,11 +4553,12 @@ async def create_frontend( lb_id: str, backend_id: str, enable_http3: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Create a frontend in a given load balancer. @@ -4534,6 +4571,7 @@ async def create_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -4566,6 +4604,7 @@ async def create_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -4578,7 +4617,7 @@ async def get_frontend( self, *, frontend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Frontend: """ Get a frontend. @@ -4615,10 +4654,11 @@ async def update_frontend( inbound_port: int, backend_id: str, enable_http3: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Update a frontend. @@ -4631,6 +4671,7 @@ async def update_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -4664,6 +4705,7 @@ async def update_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -4676,7 +4718,7 @@ async def delete_frontend( self, *, frontend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a frontend. @@ -4706,7 +4748,7 @@ async def delete_frontend( async def list_routes( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -4748,7 +4790,7 @@ async def list_routes( async def list_routes_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -4787,7 +4829,7 @@ async def create_route( *, frontend_id: str, backend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, match: Optional[RouteMatch] = None, ) -> Route: """ @@ -4832,7 +4874,7 @@ async def get_route( self, *, route_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Route: """ Get single backend redirection. @@ -4866,7 +4908,7 @@ async def update_route( *, route_id: str, backend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, match: Optional[RouteMatch] = None, ) -> Route: """ @@ -4912,7 +4954,7 @@ async def delete_route( self, *, route_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a backend redirection. @@ -4943,7 +4985,7 @@ async def get_lb_stats( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, backend_id: Optional[str] = None, ) -> LbStats: """ @@ -4982,7 +5024,7 @@ async def list_backend_stats( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, backend_id: Optional[str] = None, @@ -5026,7 +5068,7 @@ async def list_backend_stats_all( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, backend_id: Optional[str] = None, @@ -5065,7 +5107,7 @@ async def list_acls( self, *, frontend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListAclRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5112,7 +5154,7 @@ async def list_acls_all( self, *, frontend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListAclRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5157,7 +5199,7 @@ async def create_acl( action: AclAction, index: int, description: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, match: Optional[AclMatch] = None, ) -> Acl: @@ -5212,7 +5254,7 @@ async def get_acl( self, *, acl_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Acl: """ Get an ACL. @@ -5248,7 +5290,7 @@ async def update_acl( name: str, action: AclAction, index: int, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, match: Optional[AclMatch] = None, description: Optional[str] = None, ) -> Acl: @@ -5303,7 +5345,7 @@ async def delete_acl( self, *, acl_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete an ACL. @@ -5334,7 +5376,7 @@ async def create_certificate( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, letsencrypt: Optional[CreateCertificateRequestLetsencryptConfig] = None, custom_certificate: Optional[CreateCertificateRequestCustomCertificate] = None, @@ -5386,7 +5428,7 @@ async def list_certificates( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListCertificatesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5433,7 +5475,7 @@ async def list_certificates_all( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListCertificatesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5475,7 +5517,7 @@ async def get_certificate( self, *, certificate_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Certificate: """ Get a TLS certificate. @@ -5508,7 +5550,7 @@ async def wait_for_certificate( self, *, certificate_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[Certificate, Union[bool, Awaitable[bool]]] ] = None, @@ -5547,7 +5589,7 @@ async def update_certificate( *, certificate_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Certificate: """ Update a TLS certificate. @@ -5590,7 +5632,7 @@ async def delete_certificate( self, *, certificate_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a TLS certificate. @@ -5620,7 +5662,7 @@ async def delete_certificate( async def list_lb_types( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListLbTypesResponse: @@ -5656,7 +5698,7 @@ async def list_lb_types( async def list_lb_types_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[LbType]: @@ -5688,7 +5730,7 @@ async def create_subscriber( self, *, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, email_config: Optional[SubscriberEmailConfig] = None, webhook_config: Optional[SubscriberWebhookConfig] = None, organization_id: Optional[str] = None, @@ -5743,7 +5785,7 @@ async def get_subscriber( self, *, subscriber_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Subscriber: """ Get a subscriber. @@ -5775,7 +5817,7 @@ async def get_subscriber( async def list_subscriber( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListSubscriberRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5824,7 +5866,7 @@ async def list_subscriber( async def list_subscriber_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListSubscriberRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5869,7 +5911,7 @@ async def update_subscriber( *, subscriber_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, email_config: Optional[SubscriberEmailConfig] = None, webhook_config: Optional[SubscriberWebhookConfig] = None, ) -> Subscriber: @@ -5920,7 +5962,7 @@ async def delete_subscriber( self, *, subscriber_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a subscriber. @@ -5952,7 +5994,7 @@ async def subscribe_to_lb( *, lb_id: str, subscriber_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Lb: """ Subscribe a subscriber to a given load balancer. @@ -5995,7 +6037,7 @@ async def unsubscribe_from_lb( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Lb: """ Unsubscribe a subscriber from a given load balancer. @@ -6028,7 +6070,7 @@ async def list_lb_private_networks( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -6072,7 +6114,7 @@ async def list_lb_private_networks_all( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -6112,10 +6154,11 @@ async def attach_private_network( *, lb_id: str, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, static_config: Optional[PrivateNetworkStaticConfig] = None, dhcp_config: Optional[PrivateNetworkDHCPConfig] = None, ipam_config: Optional[PrivateNetworkIpamConfig] = None, + ipam_ids: Optional[List[str]] = None, ) -> PrivateNetwork: """ Add load balancer on instance private network. @@ -6128,6 +6171,7 @@ async def attach_private_network( One-Of ('config'): at most one of 'static_config', 'dhcp_config', 'ipam_config' could be set. :param ipam_config: For internal use only. One-Of ('config'): at most one of 'static_config', 'dhcp_config', 'ipam_config' could be set. + :param ipam_ids: IPAM ID of a pre-reserved IP address to assign to the Load Balancer on this Private Network. In the future, it will be possible to specify multiple IPs in this field (IPv4 and IPv6), for now only one ID of an IPv4 address is expected. When null, a new private IP address is created for the Load Balancer on this Private Network. :return: :class:`PrivateNetwork ` Usage: @@ -6155,6 +6199,7 @@ async def attach_private_network( lb_id=lb_id, private_network_id=private_network_id, region=region, + ipam_ids=ipam_ids, static_config=static_config, dhcp_config=dhcp_config, ipam_config=ipam_config, @@ -6171,7 +6216,7 @@ async def detach_private_network( *, lb_id: str, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Remove load balancer of private network. diff --git a/scaleway-async/scaleway_async/lb/v1/marshalling.py b/scaleway-async/scaleway_async/lb/v1/marshalling.py index b68ee34b..bbf09e77 100644 --- a/scaleway-async/scaleway_async/lb/v1/marshalling.py +++ b/scaleway-async/scaleway_async/lb/v1/marshalling.py @@ -87,6 +87,7 @@ ZonedApiCreateLbRequest, ZonedApiCreateRouteRequest, ZonedApiCreateSubscriberRequest, + ZonedApiDetachPrivateNetworkRequest, ZonedApiMigrateLbRequest, ZonedApiRemoveBackendServersRequest, AclSpec, @@ -133,6 +134,10 @@ def unmarshal_Ip(data: Any) -> Ip: if field is not None: args["reverse"] = field + field = data.get("tags", None) + if field is not None: + args["tags"] = field + field = data.get("zone", None) if field is not None: args["zone"] = field @@ -140,10 +145,14 @@ def unmarshal_Ip(data: Any) -> Ip: field = data.get("lb_id", None) if field is not None: args["lb_id"] = field + else: + args["lb_id"] = None field = data.get("region", None) if field is not None: args["region"] = field + else: + args["region"] = None return Ip(**args) @@ -197,10 +206,14 @@ def unmarshal_Subscriber(data: Any) -> Subscriber: field = data.get("email_config", None) if field is not None: args["email_config"] = unmarshal_SubscriberEmailConfig(field) + else: + args["email_config"] = None field = data.get("webhook_config", None) if field is not None: args["webhook_config"] = unmarshal_SubscriberWebhookConfig(field) + else: + args["webhook_config"] = None return Subscriber(**args) @@ -228,6 +241,8 @@ def unmarshal_HealthCheckHttpConfig(data: Any) -> HealthCheckHttpConfig: field = data.get("code", None) if field is not None: args["code"] = field + else: + args["code"] = None return HealthCheckHttpConfig(**args) @@ -259,6 +274,8 @@ def unmarshal_HealthCheckHttpsConfig(data: Any) -> HealthCheckHttpsConfig: field = data.get("code", None) if field is not None: args["code"] = field + else: + args["code"] = None return HealthCheckHttpsConfig(**args) @@ -345,18 +362,26 @@ def unmarshal_HealthCheck(data: Any) -> HealthCheck: field = data.get("check_delay", None) if field is not None: args["check_delay"] = field + else: + args["check_delay"] = None field = data.get("check_timeout", None) if field is not None: args["check_timeout"] = field + else: + args["check_timeout"] = None field = data.get("tcp_config", None) if field is not None: args["tcp_config"] = unmarshal_HealthCheckTcpConfig(field) + else: + args["tcp_config"] = None field = data.get("mysql_config", None) if field is not None: args["mysql_config"] = unmarshal_HealthCheckMysqlConfig(field) + else: + args["mysql_config"] = None field = data.get("check_send_proxy", None) if field is not None: @@ -365,26 +390,38 @@ def unmarshal_HealthCheck(data: Any) -> HealthCheck: field = data.get("pgsql_config", None) if field is not None: args["pgsql_config"] = unmarshal_HealthCheckPgsqlConfig(field) + else: + args["pgsql_config"] = None field = data.get("ldap_config", None) if field is not None: args["ldap_config"] = unmarshal_HealthCheckLdapConfig(field) + else: + args["ldap_config"] = None field = data.get("redis_config", None) if field is not None: args["redis_config"] = unmarshal_HealthCheckRedisConfig(field) + else: + args["redis_config"] = None field = data.get("http_config", None) if field is not None: args["http_config"] = unmarshal_HealthCheckHttpConfig(field) + else: + args["http_config"] = None field = data.get("https_config", None) if field is not None: args["https_config"] = unmarshal_HealthCheckHttpsConfig(field) + else: + args["https_config"] = None field = data.get("transient_check_delay", None) if field is not None: args["transient_check_delay"] = field + else: + args["transient_check_delay"] = None return HealthCheck(**args) @@ -416,14 +453,20 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("region", None) if field is not None: args["region"] = field + else: + args["region"] = None return Instance(**args) @@ -482,7 +525,7 @@ def unmarshal_Lb(data: Any) -> Lb: if field is not None: args["backend_count"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -505,18 +548,26 @@ def unmarshal_Lb(data: Any) -> Lb: field = data.get("subscriber", None) if field is not None: args["subscriber"] = unmarshal_Subscriber(field) + else: + args["subscriber"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("region", None) if field is not None: args["region"] = field + else: + args["region"] = None return Lb(**args) @@ -572,62 +623,92 @@ def unmarshal_Backend(data: Any) -> Backend: field = data.get("health_check", None) if field is not None: args["health_check"] = unmarshal_HealthCheck(field) + else: + args["health_check"] = None field = data.get("lb", None) if field is not None: args["lb"] = unmarshal_Lb(field) + else: + args["lb"] = None field = data.get("send_proxy_v2", None) if field is not None: args["send_proxy_v2"] = field + else: + args["send_proxy_v2"] = None field = data.get("timeout_server", None) if field is not None: args["timeout_server"] = field + else: + args["timeout_server"] = None field = data.get("timeout_connect", None) if field is not None: args["timeout_connect"] = field + else: + args["timeout_connect"] = None field = data.get("timeout_tunnel", None) if field is not None: args["timeout_tunnel"] = field + else: + args["timeout_tunnel"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("failover_host", None) if field is not None: args["failover_host"] = field + else: + args["failover_host"] = None field = data.get("ssl_bridging", None) if field is not None: args["ssl_bridging"] = field + else: + args["ssl_bridging"] = None field = data.get("ignore_ssl_server_verify", None) if field is not None: args["ignore_ssl_server_verify"] = field + else: + args["ignore_ssl_server_verify"] = None field = data.get("redispatch_attempt_count", None) if field is not None: args["redispatch_attempt_count"] = field + else: + args["redispatch_attempt_count"] = None field = data.get("max_retries", None) if field is not None: args["max_retries"] = field + else: + args["max_retries"] = None field = data.get("max_connections", None) if field is not None: args["max_connections"] = field + else: + args["max_connections"] = None field = data.get("timeout_queue", None) if field is not None: args["timeout_queue"] = field + else: + args["timeout_queue"] = None return Backend(**args) @@ -640,7 +721,7 @@ def unmarshal_Certificate(data: Any) -> Certificate: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -669,16 +750,22 @@ def unmarshal_Certificate(data: Any) -> Certificate: args["not_valid_before"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["not_valid_before"] = None field = data.get("not_valid_after", None) if field is not None: args["not_valid_after"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["not_valid_after"] = None field = data.get("lb", None) if field is not None: args["lb"] = unmarshal_Lb(field) + else: + args["lb"] = None field = data.get("name", None) if field is not None: @@ -687,14 +774,20 @@ def unmarshal_Certificate(data: Any) -> Certificate: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("status_details", None) if field is not None: args["status_details"] = field + else: + args["status_details"] = None return Certificate(**args) @@ -730,26 +823,44 @@ def unmarshal_Frontend(data: Any) -> Frontend: field = data.get("backend", None) if field is not None: args["backend"] = unmarshal_Backend(field) + else: + args["backend"] = None field = data.get("lb", None) if field is not None: args["lb"] = unmarshal_Lb(field) + else: + args["lb"] = None field = data.get("timeout_client", None) if field is not None: args["timeout_client"] = field + else: + args["timeout_client"] = None field = data.get("certificate", None) if field is not None: args["certificate"] = unmarshal_Certificate(field) + else: + args["certificate"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("connection_rate_limit", None) + if field is not None: + args["connection_rate_limit"] = field + else: + args["connection_rate_limit"] = None return Frontend(**args) @@ -762,7 +873,7 @@ def unmarshal_AclActionRedirect(data: Any) -> AclActionRedirect: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -773,6 +884,8 @@ def unmarshal_AclActionRedirect(data: Any) -> AclActionRedirect: field = data.get("code", None) if field is not None: args["code"] = field + else: + args["code"] = None return AclActionRedirect(**args) @@ -785,13 +898,15 @@ def unmarshal_AclAction(data: Any) -> AclAction: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field field = data.get("redirect", None) if field is not None: args["redirect"] = unmarshal_AclActionRedirect(field) + else: + args["redirect"] = None return AclAction(**args) @@ -808,6 +923,10 @@ def unmarshal_AclMatch(data: Any) -> AclMatch: if field is not None: args["ip_subnet"] = field + field = data.get("ips_edge_services", None) + if field is not None: + args["ips_edge_services"] = field + field = data.get("http_filter", None) if field is not None: args["http_filter"] = field @@ -823,6 +942,8 @@ def unmarshal_AclMatch(data: Any) -> AclMatch: field = data.get("http_filter_option", None) if field is not None: args["http_filter_option"] = field + else: + args["http_filter_option"] = None return AclMatch(**args) @@ -854,22 +975,32 @@ def unmarshal_Acl(data: Any) -> Acl: field = data.get("match", None) if field is not None: args["match"] = unmarshal_AclMatch(field) + else: + args["match"] = None field = data.get("action", None) if field is not None: args["action"] = unmarshal_AclAction(field) + else: + args["action"] = None field = data.get("frontend", None) if field is not None: args["frontend"] = unmarshal_Frontend(field) + else: + args["frontend"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Acl(**args) @@ -885,6 +1016,8 @@ def unmarshal_PrivateNetworkDHCPConfig(data: Any) -> PrivateNetworkDHCPConfig: field = data.get("ip_id", None) if field is not None: args["ip_id"] = field + else: + args["ip_id"] = None return PrivateNetworkDHCPConfig(**args) @@ -911,6 +1044,8 @@ def unmarshal_PrivateNetworkStaticConfig(data: Any) -> PrivateNetworkStaticConfi field = data.get("ip_address", None) if field is not None: args["ip_address"] = field + else: + args["ip_address"] = None return PrivateNetworkStaticConfig(**args) @@ -938,26 +1073,38 @@ def unmarshal_PrivateNetwork(data: Any) -> PrivateNetwork: field = data.get("lb", None) if field is not None: args["lb"] = unmarshal_Lb(field) + else: + args["lb"] = None field = data.get("static_config", None) if field is not None: args["static_config"] = unmarshal_PrivateNetworkStaticConfig(field) + else: + args["static_config"] = None field = data.get("dhcp_config", None) if field is not None: args["dhcp_config"] = unmarshal_PrivateNetworkDHCPConfig(field) + else: + args["dhcp_config"] = None field = data.get("ipam_config", None) if field is not None: args["ipam_config"] = unmarshal_PrivateNetworkIpamConfig(field) + else: + args["ipam_config"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return PrivateNetwork(**args) @@ -970,13 +1117,27 @@ def unmarshal_RouteMatch(data: Any) -> RouteMatch: args: Dict[str, Any] = {} + field = data.get("match_subdomains", None) + if field is not None: + args["match_subdomains"] = field + field = data.get("sni", None) if field is not None: args["sni"] = field + else: + args["sni"] = None field = data.get("host_header", None) if field is not None: args["host_header"] = field + else: + args["host_header"] = None + + field = data.get("path_begin", None) + if field is not None: + args["path_begin"] = field + else: + args["path_begin"] = None return RouteMatch(**args) @@ -1004,14 +1165,20 @@ def unmarshal_Route(data: Any) -> Route: field = data.get("match", None) if field is not None: args["match"] = unmarshal_RouteMatch(field) + else: + args["match"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Route(**args) @@ -1049,6 +1216,8 @@ def unmarshal_BackendServerStats(data: Any) -> BackendServerStats: args["server_state_changed_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["server_state_changed_at"] = None return BackendServerStats(**args) @@ -1244,6 +1413,8 @@ def unmarshal_LbType(data: Any) -> LbType: field = data.get("region", None) if field is not None: args["region"] = field + else: + args["region"] = None return LbType(**args) @@ -1409,6 +1580,9 @@ def marshal_AttachPrivateNetworkRequest( ), ) + if request.ipam_ids is not None: + output["ipam_ids"] = request.ipam_ids + return output @@ -1440,7 +1614,7 @@ def marshal_AclAction( output["type"] = str(request.type_) if request.redirect is not None: - output["redirect"] = (marshal_AclActionRedirect(request.redirect, defaults),) + output["redirect"] = marshal_AclActionRedirect(request.redirect, defaults) return output @@ -1454,6 +1628,9 @@ def marshal_AclMatch( if request.ip_subnet is not None: output["ip_subnet"] = request.ip_subnet + if request.ips_edge_services is not None: + output["ips_edge_services"] = request.ips_edge_services + if request.http_filter is not None: output["http_filter"] = str(request.http_filter) @@ -1476,7 +1653,7 @@ def marshal_CreateAclRequest( output: Dict[str, Any] = {} if request.action is not None: - output["action"] = (marshal_AclAction(request.action, defaults),) + output["action"] = marshal_AclAction(request.action, defaults) if request.index is not None: output["index"] = request.index @@ -1488,7 +1665,7 @@ def marshal_CreateAclRequest( output["name"] = request.name if request.match is not None: - output["match"] = (marshal_AclMatch(request.match, defaults),) + output["match"] = marshal_AclMatch(request.match, defaults) return output @@ -1651,7 +1828,7 @@ def marshal_CreateBackendRequest( output["sticky_sessions_cookie_name"] = request.sticky_sessions_cookie_name if request.health_check is not None: - output["health_check"] = (marshal_HealthCheck(request.health_check, defaults),) + output["health_check"] = marshal_HealthCheck(request.health_check, defaults) if request.server_ip is not None: output["server_ip"] = request.server_ip @@ -1775,6 +1952,9 @@ def marshal_CreateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -1804,6 +1984,9 @@ def marshal_CreateIpRequest( if request.reverse is not None: output["reverse"] = request.reverse + if request.tags is not None: + output["tags"] = request.tags + return output @@ -1867,10 +2050,14 @@ def marshal_RouteMatch( [ OneOfPossibility("sni", request.sni), OneOfPossibility("host_header", request.host_header), + OneOfPossibility("path_begin", request.path_begin), ] ), ) + if request.match_subdomains is not None: + output["match_subdomains"] = request.match_subdomains + return output @@ -1887,7 +2074,7 @@ def marshal_CreateRouteRequest( output["backend_id"] = request.backend_id if request.match is not None: - output["match"] = (marshal_RouteMatch(request.match, defaults),) + output["match"] = marshal_RouteMatch(request.match, defaults) return output @@ -2008,13 +2195,13 @@ def marshal_UpdateAclRequest( output["name"] = request.name if request.action is not None: - output["action"] = (marshal_AclAction(request.action, defaults),) + output["action"] = marshal_AclAction(request.action, defaults) if request.index is not None: output["index"] = request.index if request.match is not None: - output["match"] = (marshal_AclMatch(request.match, defaults),) + output["match"] = marshal_AclMatch(request.match, defaults) if request.description is not None: output["description"] = request.description @@ -2127,6 +2314,9 @@ def marshal_UpdateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2182,6 +2372,9 @@ def marshal_UpdateIpRequest( if request.lb_id is not None: output["lb_id"] = request.lb_id + if request.tags is not None: + output["tags"] = request.tags + return output @@ -2216,7 +2409,7 @@ def marshal_UpdateRouteRequest( output["backend_id"] = request.backend_id if request.match is not None: - output["match"] = (marshal_RouteMatch(request.match, defaults),) + output["match"] = marshal_RouteMatch(request.match, defaults) return output @@ -2268,6 +2461,12 @@ def marshal_ZonedApiAttachPrivateNetworkRequest( ), ) + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + if request.ipam_ids is not None: + output["ipam_ids"] = request.ipam_ids + return output @@ -2278,7 +2477,7 @@ def marshal_ZonedApiCreateAclRequest( output: Dict[str, Any] = {} if request.action is not None: - output["action"] = (marshal_AclAction(request.action, defaults),) + output["action"] = marshal_AclAction(request.action, defaults) if request.index is not None: output["index"] = request.index @@ -2290,7 +2489,7 @@ def marshal_ZonedApiCreateAclRequest( output["name"] = request.name if request.match is not None: - output["match"] = (marshal_AclMatch(request.match, defaults),) + output["match"] = marshal_AclMatch(request.match, defaults) return output @@ -2317,7 +2516,7 @@ def marshal_ZonedApiCreateBackendRequest( output["sticky_sessions_cookie_name"] = request.sticky_sessions_cookie_name if request.health_check is not None: - output["health_check"] = (marshal_HealthCheck(request.health_check, defaults),) + output["health_check"] = marshal_HealthCheck(request.health_check, defaults) if request.server_ip is not None: output["server_ip"] = request.server_ip @@ -2414,6 +2613,9 @@ def marshal_ZonedApiCreateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2443,6 +2645,9 @@ def marshal_ZonedApiCreateIpRequest( if request.reverse is not None: output["reverse"] = request.reverse + if request.tags is not None: + output["tags"] = request.tags + return output @@ -2509,7 +2714,7 @@ def marshal_ZonedApiCreateRouteRequest( output["backend_id"] = request.backend_id if request.match is not None: - output["match"] = (marshal_RouteMatch(request.match, defaults),) + output["match"] = marshal_RouteMatch(request.match, defaults) return output @@ -2548,6 +2753,18 @@ def marshal_ZonedApiCreateSubscriberRequest( return output +def marshal_ZonedApiDetachPrivateNetworkRequest( + request: ZonedApiDetachPrivateNetworkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + return output + + def marshal_ZonedApiMigrateLbRequest( request: ZonedApiMigrateLbRequest, defaults: ProfileDefaults, @@ -2582,7 +2799,7 @@ def marshal_AclSpec( output["name"] = request.name if request.action is not None: - output["action"] = (marshal_AclAction(request.action, defaults),) + output["action"] = marshal_AclAction(request.action, defaults) if request.index is not None: output["index"] = request.index @@ -2591,7 +2808,7 @@ def marshal_AclSpec( output["description"] = request.description if request.match is not None: - output["match"] = (marshal_AclMatch(request.match, defaults),) + output["match"] = marshal_AclMatch(request.match, defaults) return output @@ -2642,13 +2859,13 @@ def marshal_ZonedApiUpdateAclRequest( output["name"] = request.name if request.action is not None: - output["action"] = (marshal_AclAction(request.action, defaults),) + output["action"] = marshal_AclAction(request.action, defaults) if request.index is not None: output["index"] = request.index if request.match is not None: - output["match"] = (marshal_AclMatch(request.match, defaults),) + output["match"] = marshal_AclMatch(request.match, defaults) if request.description is not None: output["description"] = request.description @@ -2761,6 +2978,9 @@ def marshal_ZonedApiUpdateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2816,6 +3036,9 @@ def marshal_ZonedApiUpdateIpRequest( if request.lb_id is not None: output["lb_id"] = request.lb_id + if request.tags is not None: + output["tags"] = request.tags + return output @@ -2850,7 +3073,7 @@ def marshal_ZonedApiUpdateRouteRequest( output["backend_id"] = request.backend_id if request.match is not None: - output["match"] = (marshal_RouteMatch(request.match, defaults),) + output["match"] = marshal_RouteMatch(request.match, defaults) return output diff --git a/scaleway-async/scaleway_async/lb/v1/types.py b/scaleway-async/scaleway_async/lb/v1/types.py index 59c722e2..d66e8a69 100644 --- a/scaleway-async/scaleway_async/lb/v1/types.py +++ b/scaleway-async/scaleway_async/lb/v1/types.py @@ -8,8 +8,8 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, - Zone, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -297,7 +297,7 @@ class SubscriberWebhookConfig: class HealthCheckHttpConfig: uri: str """ - The HTTP URI to use when performing a health check on backend servers. + The HTTP path to use when performing a health check on backend servers. """ method: str @@ -320,7 +320,7 @@ class HealthCheckHttpConfig: class HealthCheckHttpsConfig: uri: str """ - The HTTP URI to use when performing a health check on backend servers. + The HTTP path to use when performing a health check on backend servers. """ method: str @@ -392,7 +392,7 @@ class Instance: Instance IP address. """ - zone: Zone + zone: ScwZone """ The zone the Instance is in. """ @@ -407,7 +407,7 @@ class Instance: Date on which the Instance was last updated. """ - region: Optional[Region] + region: Optional[ScwRegion] """ The region the Instance is in. """ @@ -440,7 +440,12 @@ class Ip: Reverse DNS (domain name) of the IP address. """ - zone: Zone + tags: List[str] + """ + IP tags. + """ + + zone: ScwZone """ The zone the IP address is in. """ @@ -450,7 +455,7 @@ class Ip: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ The region the IP address is in. """ @@ -601,7 +606,7 @@ class Lb: Number of routes configured on the Load Balancer. """ - zone: Zone + zone: ScwZone """ The zone the Load Balancer is in. """ @@ -621,7 +626,7 @@ class Lb: Date on which the Load Balancer was last updated. """ - region: Optional[Region] + region: Optional[ScwRegion] """ The region the Load Balancer is in. """ @@ -739,7 +744,7 @@ class Backend: failover_host: Optional[str] """ - Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. """ ssl_bridging: Optional[bool] @@ -861,6 +866,11 @@ class AclMatch: List of IPs or CIDR v4/v6 addresses to filter for from the client side. """ + ips_edge_services: bool + """ + Defines whether Edge Services IPs should be matched. + """ + http_filter: AclHttpFilter """ Type of HTTP filter to match. Extracts the request's URL path, which starts at the first slash and ends before the question mark (without the host part). Defines where to filter for the http_filter_value. Only supported for HTTP backends. @@ -939,6 +949,11 @@ class Frontend: Date on which the frontend was last updated. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class PrivateNetworkDHCPConfig: @@ -960,10 +975,17 @@ class PrivateNetworkStaticConfig: @dataclass class RouteMatch: + match_subdomains: bool + """ + If true, all subdomains will match. + """ + sni: Optional[str] host_header: Optional[str] + path_begin: Optional[str] + @dataclass class CreateCertificateRequestCustomCertificate: @@ -1123,12 +1145,12 @@ class LbType: Load Balancer commercial offer type description. """ - zone: Zone + zone: ScwZone """ The zone the Load Balancer stock is in. """ - region: Optional[Region] + region: Optional[ScwRegion] """ The region the Load Balancer stock is in. """ @@ -1207,7 +1229,7 @@ class AddBackendServersRequest: List of IP addresses to add to backend servers. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1225,11 +1247,16 @@ class AttachPrivateNetworkRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ + ipam_ids: Optional[List[str]] + """ + IPAM ID of a pre-reserved IP address to assign to the Load Balancer on this Private Network. In the future, it will be possible to specify multiple IPs in this field (IPv4 and IPv6), for now only one ID of an IPv4 address is expected. When null, a new private IP address is created for the Load Balancer on this Private Network. + """ + static_config: Optional[PrivateNetworkStaticConfig] dhcp_config: Optional[PrivateNetworkDHCPConfig] @@ -1263,7 +1290,7 @@ class CreateAclRequest: ACL description. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1321,7 +1348,7 @@ class CreateBackendRequest: List of backend server IP addresses (IPv4 or IPv6) the backend should forward traffic to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1363,7 +1390,7 @@ class CreateBackendRequest: failover_host: Optional[str] """ - Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. """ ssl_bridging: Optional[bool] @@ -1404,7 +1431,7 @@ class CreateCertificateRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1441,7 +1468,7 @@ class CreateFrontendRequest: Defines whether to enable HTTP/3 protocol on the frontend. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1466,6 +1493,11 @@ class CreateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class CreateIpRequest: @@ -1474,7 +1506,7 @@ class CreateIpRequest: If true, creates a Flexible IP with an ipv6 address. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1484,6 +1516,11 @@ class CreateIpRequest: Reverse DNS (domain name) for the IP address. """ + tags: Optional[List[str]] + """ + List of tags for the IP. + """ + project_id: Optional[str] organization_id: Optional[str] @@ -1501,7 +1538,7 @@ class CreateLbRequest: Load Balancer commercial offer type. Use the Load Balancer types endpoint to retrieve a list of available offer types. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1518,7 +1555,7 @@ class CreateLbRequest: assign_flexible_ip: Optional[bool] """ - Defines whether to automatically assign a flexible public IP to lb. Default value is `false` (do not assign). + Defines whether to automatically assign a flexible public IP to the Load Balancer. Default value is `true` (assign). """ assign_flexible_ipv6: Optional[bool] @@ -1558,7 +1595,7 @@ class CreateRouteRequest: ID of the target backend for the route. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1580,7 +1617,7 @@ class CreateSubscriberRequest: Subscriber name. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1601,7 +1638,7 @@ class DeleteAclRequest: ACL ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1614,7 +1651,7 @@ class DeleteBackendRequest: ID of the backend to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1627,7 +1664,7 @@ class DeleteCertificateRequest: Certificate ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1640,7 +1677,7 @@ class DeleteFrontendRequest: ID of the frontend to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1658,7 +1695,7 @@ class DeleteLbRequest: Defines whether the Load Balancer's flexible IP should be deleted. Set to true to release the flexible IP, or false to keep it available in your account for future Load Balancers. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1671,7 +1708,7 @@ class DeleteRouteRequest: Route ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1684,7 +1721,7 @@ class DeleteSubscriberRequest: Subscriber ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1702,7 +1739,7 @@ class DetachPrivateNetworkRequest: Set your instance private network id. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1715,7 +1752,7 @@ class GetAclRequest: ACL ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1728,7 +1765,7 @@ class GetBackendRequest: Backend ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1741,7 +1778,7 @@ class GetCertificateRequest: Certificate ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1754,7 +1791,7 @@ class GetFrontendRequest: Frontend ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1767,7 +1804,7 @@ class GetIpRequest: IP address ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1780,7 +1817,7 @@ class GetLbRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1797,7 +1834,7 @@ class GetLbStatsRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1815,7 +1852,7 @@ class GetRouteRequest: Route ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1828,7 +1865,7 @@ class GetSubscriberRequest: Subscriber ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1862,7 +1899,7 @@ class ListAclsRequest: Frontend ID (ACLs attached to this frontend will be returned in the response). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1895,7 +1932,7 @@ class ListBackendStatsRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1936,7 +1973,7 @@ class ListBackendsRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1982,7 +2019,7 @@ class ListCertificatesRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2028,7 +2065,7 @@ class ListFrontendsRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2069,7 +2106,7 @@ class ListFrontendsResponse: @dataclass class ListIPsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2104,6 +2141,11 @@ class ListIPsRequest: IP type to filter for. """ + tags: Optional[List[str]] + """ + Tag to filter for, only IPs with one or more matching tags will be returned. + """ + @dataclass class ListIpsResponse: @@ -2125,7 +2167,7 @@ class ListLbPrivateNetworksRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2161,7 +2203,7 @@ class ListLbPrivateNetworksResponse: @dataclass class ListLbTypesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2192,7 +2234,7 @@ class ListLbTypesResponse: @dataclass class ListLbsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2248,7 +2290,7 @@ class ListLbsResponse: @dataclass class ListRoutesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2289,7 +2331,7 @@ class ListRoutesResponse: @dataclass class ListSubscriberRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2350,7 +2392,7 @@ class MigrateLbRequest: Load Balancer type to migrate to (use the List all Load Balancer offer types endpoint to get a list of available offer types). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2363,7 +2405,7 @@ class ReleaseIpRequest: IP address ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2381,7 +2423,7 @@ class RemoveBackendServersRequest: List of IP addresses to remove from backend servers. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2412,7 +2454,7 @@ class SetBackendServersRequest: List of IP addresses for backend servers. Any other existing backend servers will be removed. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2430,7 +2472,7 @@ class SubscribeToLbRequest: Subscriber ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2443,7 +2485,7 @@ class UnsubscribeFromLbRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2471,7 +2513,7 @@ class UpdateAclRequest: Priority of this ACL (ACLs are applied in ascending order, 0 is the first ACL executed). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2524,7 +2566,7 @@ class UpdateBackendRequest: Cookie name for cookie-based sticky sessions. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2561,7 +2603,7 @@ class UpdateBackendRequest: failover_host: Optional[str] """ - Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. """ ssl_bridging: Optional[bool] @@ -2607,7 +2649,7 @@ class UpdateCertificateRequest: Certificate name. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2640,7 +2682,7 @@ class UpdateFrontendRequest: Defines whether to enable HTTP/3 protocol on the frontend. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2660,6 +2702,11 @@ class UpdateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class UpdateHealthCheckRequest: @@ -2683,7 +2730,7 @@ class UpdateHealthCheckRequest: Defines whether proxy protocol should be activated for the health check. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2725,7 +2772,7 @@ class UpdateIpRequest: IP address ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2740,6 +2787,11 @@ class UpdateIpRequest: ID of the server on which to attach the flexible IP. """ + tags: Optional[List[str]] + """ + List of tags for the IP. + """ + @dataclass class UpdateLbRequest: @@ -2758,7 +2810,7 @@ class UpdateLbRequest: Load Balancer description. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2786,7 +2838,7 @@ class UpdateRouteRequest: ID of the target backend for the route. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2809,7 +2861,7 @@ class UpdateSubscriberRequest: Subscriber name. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2831,7 +2883,7 @@ class ZonedApiAddBackendServersRequest: List of IP addresses to add to backend servers. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2849,11 +2901,16 @@ class ZonedApiAttachPrivateNetworkRequest: Private Network ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ + ipam_ids: Optional[List[str]] + """ + IPAM ID of a pre-reserved IP address to assign to the Load Balancer on this Private Network. In the future, it will be possible to specify multiple IPs in this field (IPv4 and IPv6), for now only one ID of an IPv4 address is expected. When null, a new private IP address is created for the Load Balancer on this Private Network. + """ + static_config: Optional[PrivateNetworkStaticConfig] dhcp_config: Optional[PrivateNetworkDHCPConfig] @@ -2887,7 +2944,7 @@ class ZonedApiCreateAclRequest: ACL description. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2945,7 +3002,7 @@ class ZonedApiCreateBackendRequest: List of backend server IP addresses (IPv4 or IPv6) the backend should forward traffic to. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2987,7 +3044,7 @@ class ZonedApiCreateBackendRequest: failover_host: Optional[str] """ - Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. """ ssl_bridging: Optional[bool] @@ -3028,7 +3085,7 @@ class ZonedApiCreateCertificateRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3065,7 +3122,7 @@ class ZonedApiCreateFrontendRequest: Defines whether to enable HTTP/3 protocol on the frontend. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3090,6 +3147,11 @@ class ZonedApiCreateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class ZonedApiCreateIpRequest: @@ -3098,7 +3160,7 @@ class ZonedApiCreateIpRequest: If true, creates a Flexible IP with an ipv6 address. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3108,6 +3170,11 @@ class ZonedApiCreateIpRequest: Reverse DNS (domain name) for the IP address. """ + tags: Optional[List[str]] + """ + List of tags for the IP. + """ + project_id: Optional[str] organization_id: Optional[str] @@ -3125,7 +3192,7 @@ class ZonedApiCreateLbRequest: Load Balancer commercial offer type. Use the Load Balancer types endpoint to retrieve a list of available offer types. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3142,7 +3209,7 @@ class ZonedApiCreateLbRequest: assign_flexible_ip: Optional[bool] """ - Defines whether to automatically assign a flexible public IP to lb. Default value is `false` (do not assign). + Defines whether to automatically assign a flexible public IP to the Load Balancer. Default value is `true` (assign). """ assign_flexible_ipv6: Optional[bool] @@ -3182,7 +3249,7 @@ class ZonedApiCreateRouteRequest: ID of the target backend for the route. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3204,7 +3271,7 @@ class ZonedApiCreateSubscriberRequest: Subscriber name. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3225,7 +3292,7 @@ class ZonedApiDeleteAclRequest: ACL ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3238,7 +3305,7 @@ class ZonedApiDeleteBackendRequest: ID of the backend to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3251,7 +3318,7 @@ class ZonedApiDeleteCertificateRequest: Certificate ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3264,7 +3331,7 @@ class ZonedApiDeleteFrontendRequest: ID of the frontend to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3282,7 +3349,7 @@ class ZonedApiDeleteLbRequest: Defines whether the Load Balancer's flexible IP should be deleted. Set to true to release the flexible IP, or false to keep it available in your account for future Load Balancers. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3295,7 +3362,7 @@ class ZonedApiDeleteRouteRequest: Route ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3308,7 +3375,7 @@ class ZonedApiDeleteSubscriberRequest: Subscriber ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3326,7 +3393,7 @@ class ZonedApiDetachPrivateNetworkRequest: Set your instance private network id. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3339,7 +3406,7 @@ class ZonedApiGetAclRequest: ACL ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3352,7 +3419,7 @@ class ZonedApiGetBackendRequest: Backend ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3365,7 +3432,7 @@ class ZonedApiGetCertificateRequest: Certificate ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3378,7 +3445,7 @@ class ZonedApiGetFrontendRequest: Frontend ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3391,7 +3458,7 @@ class ZonedApiGetIpRequest: IP address ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3404,7 +3471,7 @@ class ZonedApiGetLbRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3421,7 +3488,7 @@ class ZonedApiGetLbStatsRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3439,7 +3506,7 @@ class ZonedApiGetRouteRequest: Route ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3452,7 +3519,7 @@ class ZonedApiGetSubscriberRequest: Subscriber ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3465,7 +3532,7 @@ class ZonedApiListAclsRequest: Frontend ID (ACLs attached to this frontend will be returned in the response). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3498,7 +3565,7 @@ class ZonedApiListBackendStatsRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3526,7 +3593,7 @@ class ZonedApiListBackendsRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3559,7 +3626,7 @@ class ZonedApiListCertificatesRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3592,7 +3659,7 @@ class ZonedApiListFrontendsRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3620,7 +3687,7 @@ class ZonedApiListFrontendsRequest: @dataclass class ZonedApiListIPsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3655,6 +3722,11 @@ class ZonedApiListIPsRequest: IP type to filter for. """ + tags: Optional[List[str]] + """ + Tag to filter for, only IPs with one or more matching tags will be returned. + """ + @dataclass class ZonedApiListLbPrivateNetworksRequest: @@ -3663,7 +3735,7 @@ class ZonedApiListLbPrivateNetworksRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3686,7 +3758,7 @@ class ZonedApiListLbPrivateNetworksRequest: @dataclass class ZonedApiListLbTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3704,7 +3776,7 @@ class ZonedApiListLbTypesRequest: @dataclass class ZonedApiListLbsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3747,7 +3819,7 @@ class ZonedApiListLbsRequest: @dataclass class ZonedApiListRoutesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3775,7 +3847,7 @@ class ZonedApiListRoutesRequest: @dataclass class ZonedApiListSubscriberRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3823,7 +3895,7 @@ class ZonedApiMigrateLbRequest: Load Balancer type to migrate to (use the List all Load Balancer offer types endpoint to get a list of available offer types). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3836,7 +3908,7 @@ class ZonedApiReleaseIpRequest: IP address ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3854,7 +3926,7 @@ class ZonedApiRemoveBackendServersRequest: List of IP addresses to remove from backend servers. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3872,7 +3944,7 @@ class ZonedApiSetAclsRequest: Frontend ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3890,7 +3962,7 @@ class ZonedApiSetBackendServersRequest: List of IP addresses for backend servers. Any other existing backend servers will be removed. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3908,7 +3980,7 @@ class ZonedApiSubscribeToLbRequest: Subscriber ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3921,7 +3993,7 @@ class ZonedApiUnsubscribeFromLbRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3949,7 +4021,7 @@ class ZonedApiUpdateAclRequest: Priority of this ACL (ACLs are applied in ascending order, 0 is the first ACL executed). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4002,7 +4074,7 @@ class ZonedApiUpdateBackendRequest: Cookie name for cookie-based sticky sessions. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4039,7 +4111,7 @@ class ZonedApiUpdateBackendRequest: failover_host: Optional[str] """ - Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. """ ssl_bridging: Optional[bool] @@ -4085,7 +4157,7 @@ class ZonedApiUpdateCertificateRequest: Certificate name. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4118,7 +4190,7 @@ class ZonedApiUpdateFrontendRequest: Defines whether to enable HTTP/3 protocol on the frontend. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4138,6 +4210,11 @@ class ZonedApiUpdateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class ZonedApiUpdateHealthCheckRequest: @@ -4161,7 +4238,7 @@ class ZonedApiUpdateHealthCheckRequest: Defines whether proxy protocol should be activated for the health check. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4203,7 +4280,7 @@ class ZonedApiUpdateIpRequest: IP address ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4218,6 +4295,11 @@ class ZonedApiUpdateIpRequest: ID of the server on which to attach the flexible IP. """ + tags: Optional[List[str]] + """ + List of tags for the IP. + """ + @dataclass class ZonedApiUpdateLbRequest: @@ -4236,7 +4318,7 @@ class ZonedApiUpdateLbRequest: Load Balancer description. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4264,7 +4346,7 @@ class ZonedApiUpdateRouteRequest: ID of the target backend for the route. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4287,7 +4369,7 @@ class ZonedApiUpdateSubscriberRequest: Subscriber name. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway-async/scaleway_async/marketplace/v2/api.py b/scaleway-async/scaleway_async/marketplace/v2/api.py index d96e7408..be32e1f0 100644 --- a/scaleway-async/scaleway_async/marketplace/v2/api.py +++ b/scaleway-async/scaleway_async/marketplace/v2/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( OneOfPossibility, @@ -40,7 +40,9 @@ class MarketplaceV2API(API): - """ """ + """ + This API allows you to find available images for use when launching a Scaleway Instance. + """ async def list_images( self, @@ -267,29 +269,29 @@ async def get_version( async def list_local_images( self, *, - image_id: Optional[str] = None, - version_id: Optional[str] = None, page_size: Optional[int] = None, page: Optional[int] = None, order_by: Optional[ListLocalImagesRequestOrderBy] = None, + zone: Optional[ScwZone] = None, + image_id: Optional[str] = None, + version_id: Optional[str] = None, image_label: Optional[str] = None, - zone: Optional[Zone] = None, type_: Optional[LocalImageType] = None, ) -> ListLocalImagesResponse: """ List local images from a specific image or version. List information about local images in a specific Availability Zone, specified by its `image_id` (UUID format), `version_id` (UUID format) or `image_label`. Only one of these three parameters may be set. - :param image_id: + :param page_size: A positive integer lower or equal to 100 to select the number of items to display. + :param page: A positive integer to choose the page to display. + :param order_by: Ordering to use. + :param zone: Filter local images available on this Availability Zone. + :param image_id: Filter by image id. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param version_id: + :param version_id: Filter by version id. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param page_size: - :param page: - :param order_by: - :param image_label: + :param image_label: Filter by image label. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param zone: Zone to target. If none is passed will use default zone from the config. - :param type_: + :param type_: Filter by type. :return: :class:`ListLocalImagesResponse ` Usage: @@ -323,29 +325,29 @@ async def list_local_images( async def list_local_images_all( self, *, - image_id: Optional[str] = None, - version_id: Optional[str] = None, page_size: Optional[int] = None, page: Optional[int] = None, order_by: Optional[ListLocalImagesRequestOrderBy] = None, + zone: Optional[ScwZone] = None, + image_id: Optional[str] = None, + version_id: Optional[str] = None, image_label: Optional[str] = None, - zone: Optional[Zone] = None, type_: Optional[LocalImageType] = None, ) -> List[LocalImage]: """ List local images from a specific image or version. List information about local images in a specific Availability Zone, specified by its `image_id` (UUID format), `version_id` (UUID format) or `image_label`. Only one of these three parameters may be set. - :param image_id: + :param page_size: A positive integer lower or equal to 100 to select the number of items to display. + :param page: A positive integer to choose the page to display. + :param order_by: Ordering to use. + :param zone: Filter local images available on this Availability Zone. + :param image_id: Filter by image id. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param version_id: + :param version_id: Filter by version id. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param page_size: - :param page: - :param order_by: - :param image_label: + :param image_label: Filter by image label. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param zone: Zone to target. If none is passed will use default zone from the config. - :param type_: + :param type_: Filter by type. :return: :class:`List[LocalImage] ` Usage: diff --git a/scaleway-async/scaleway_async/marketplace/v2/marshalling.py b/scaleway-async/scaleway_async/marketplace/v2/marshalling.py index eb495e08..c3c22a3e 100644 --- a/scaleway-async/scaleway_async/marketplace/v2/marshalling.py +++ b/scaleway-async/scaleway_async/marketplace/v2/marshalling.py @@ -74,16 +74,22 @@ def unmarshal_Image(data: Any) -> Image: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("valid_until", None) if field is not None: args["valid_until"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["valid_until"] = None return Image(**args) @@ -116,7 +122,7 @@ def unmarshal_LocalImage(data: Any) -> LocalImage: if field is not None: args["label"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -142,16 +148,22 @@ def unmarshal_Version(data: Any) -> Version: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("published_at", None) if field is not None: args["published_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["published_at"] = None return Version(**args) diff --git a/scaleway-async/scaleway_async/marketplace/v2/types.py b/scaleway-async/scaleway_async/marketplace/v2/types.py index 5c1ebd10..fd972c3a 100644 --- a/scaleway-async/scaleway_async/marketplace/v2/types.py +++ b/scaleway-async/scaleway_async/marketplace/v2/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -28,6 +28,8 @@ def __str__(self) -> str: class ListLocalImagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + TYPE_ASC = "type_asc" + TYPE_DESC = "type_desc" CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -91,6 +93,7 @@ class Image: label: str """ Typically an identifier for a distribution (ex. "ubuntu_focal"). +This label can be used in the image field of the server creation request. """ created_at: Optional[datetime] @@ -126,14 +129,14 @@ class LocalImage: Supported architecture for this local image. """ - zone: Zone + zone: ScwZone """ Availability Zone where this local image is available. """ label: str """ - Image label this image belongs to. + This label can be used in the image field of the server creation request. """ type_: LocalImageType @@ -250,17 +253,29 @@ class ListImagesResponse: @dataclass class ListLocalImagesRequest: page_size: Optional[int] + """ + A positive integer lower or equal to 100 to select the number of items to display. + """ page: Optional[int] + """ + A positive integer to choose the page to display. + """ order_by: Optional[ListLocalImagesRequestOrderBy] + """ + Ordering to use. + """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ - Zone to target. If none is passed will use default zone from the config. + Filter local images available on this Availability Zone. """ type_: Optional[LocalImageType] + """ + Filter by type. + """ image_id: Optional[str] diff --git a/scaleway-async/scaleway_async/mnq/v1beta1/api.py b/scaleway-async/scaleway_async/mnq/v1beta1/api.py index d8c8407f..bd5e942c 100644 --- a/scaleway-async/scaleway_async/mnq/v1beta1/api.py +++ b/scaleway-async/scaleway_async/mnq/v1beta1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( random_name, @@ -68,13 +68,13 @@ class MnqV1Beta1NatsAPI(API): """ - This API allows you to manage Scaleway Messaging and Queueing NATS accounts. + This API allows you to manage Scaleway NATS accounts. """ async def create_nats_account( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, project_id: Optional[str] = None, ) -> NatsAccount: @@ -116,7 +116,7 @@ async def delete_nats_account( self, *, nats_account_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a NATS account. @@ -148,7 +148,7 @@ async def update_nats_account( self, *, nats_account_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, ) -> NatsAccount: """ @@ -192,7 +192,7 @@ async def get_nats_account( self, *, nats_account_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> NatsAccount: """ Get a NATS account. @@ -225,7 +225,7 @@ async def get_nats_account( async def list_nats_accounts( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -268,7 +268,7 @@ async def list_nats_accounts( async def list_nats_accounts_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -307,7 +307,7 @@ async def create_nats_credentials( self, *, nats_account_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, ) -> NatsCredentials: """ @@ -350,7 +350,7 @@ async def delete_nats_credentials( self, *, nats_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete NATS credentials. @@ -384,7 +384,7 @@ async def get_nats_credentials( self, *, nats_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> NatsCredentials: """ Get NATS credentials. @@ -419,7 +419,8 @@ async def get_nats_credentials( async def list_nats_credentials( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, nats_account_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -429,6 +430,7 @@ async def list_nats_credentials( List NATS credentials. List existing credentials in the specified NATS account. The response contains only the metadata for the credentials, not the credentials themselves, which are only returned after a **Create Credentials** call. :param region: Region to target. If none is passed will use default region from the config. + :param project_id: Include only NATS accounts in this Project. :param nats_account_id: Include only credentials for this NATS account. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. @@ -453,6 +455,7 @@ async def list_nats_credentials( "order_by": order_by, "page": page, "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, }, ) @@ -462,7 +465,8 @@ async def list_nats_credentials( async def list_nats_credentials_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, nats_account_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -472,6 +476,7 @@ async def list_nats_credentials_all( List NATS credentials. List existing credentials in the specified NATS account. The response contains only the metadata for the credentials, not the credentials themselves, which are only returned after a **Create Credentials** call. :param region: Region to target. If none is passed will use default region from the config. + :param project_id: Include only NATS accounts in this Project. :param nats_account_id: Include only credentials for this NATS account. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. @@ -490,6 +495,7 @@ async def list_nats_credentials_all( fetcher=self.list_nats_credentials, args={ "region": region, + "project_id": project_id, "nats_account_id": nats_account_id, "page": page, "page_size": page_size, @@ -500,20 +506,20 @@ async def list_nats_credentials_all( class MnqV1Beta1SnsAPI(API): """ - This API allows you to manage Scaleway Messaging and Queueing SNS brokers. + This API allows you to manage your Scaleway Topics and Events. """ async def activate_sns( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SnsInfo: """ - Activate SNS. - Activate SNS for the specified Project ID. SNS must be activated before any usage. Activating SNS does not trigger any billing, and you can deactivate at any time. + Activate Topics and Events. + Activate Topics and Events for the specified Project ID. Topics and Events must be activated before any usage. Activating Topics and Events does not trigger any billing, and you can deactivate at any time. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project on which to activate the SNS service. + :param project_id: Project on which to activate the Topics and Events service. :return: :class:`SnsInfo ` Usage: @@ -544,14 +550,14 @@ async def activate_sns( async def get_sns_info( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SnsInfo: """ - Get SNS info. - Retrieve the SNS information of the specified Project ID. Informations include the activation status and the SNS API endpoint URL. + Get Topics and Events info. + Retrieve the Topics and Events information of the specified Project ID. Informations include the activation status and the Topics and Events API endpoint URL. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project to retrieve SNS info from. + :param project_id: Project to retrieve Topics and Events info from. :return: :class:`SnsInfo ` Usage: @@ -578,14 +584,14 @@ async def get_sns_info( async def deactivate_sns( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SnsInfo: """ - Deactivate SNS. - Deactivate SNS for the specified Project ID.You must delete all topics and credentials before this call or you need to set the force_delete parameter. + Deactivate Topics and Events. + Deactivate Topics and Events for the specified Project ID. You must delete all topics and credentials before this call or you need to set the force_delete parameter. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project on which to deactivate the SNS service. + :param project_id: Project on which to deactivate the Topics and Events service. :return: :class:`SnsInfo ` Usage: @@ -616,16 +622,16 @@ async def deactivate_sns( async def create_sns_credentials( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, name: Optional[str] = None, permissions: Optional[SnsPermissions] = None, ) -> SnsCredentials: """ - Create SNS credentials. - Create a set of credentials for SNS, specified by a Project ID. Credentials give the bearer access to topics, and the level of permissions can be defined granularly. + Create Topics and Events credentials. + Create a set of credentials for Topics and Events, specified by a Project ID. Credentials give the bearer access to topics, and the level of permissions can be defined granularly. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project containing the SNS credentials. + :param project_id: Project containing the Topics and Events credentials. :param name: Name of the credentials. :param permissions: Permissions associated with these credentials. :return: :class:`SnsCredentials ` @@ -661,11 +667,11 @@ async def delete_sns_credentials( self, *, sns_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ - Delete SNS credentials. - Delete a set of SNS credentials, specified by their credentials ID. Deleting credentials is irreversible and cannot be undone. The credentials can then no longer be used to access SNS. + Delete Topics and Events credentials. + Delete a set of Topics and Events credentials, specified by their credentials ID. Deleting credentials is irreversible and cannot be undone. The credentials can then no longer be used to access Topics and Events. :param sns_credentials_id: ID of the credentials to delete. :param region: Region to target. If none is passed will use default region from the config. @@ -695,14 +701,14 @@ async def update_sns_credentials( self, *, sns_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, permissions: Optional[SnsPermissions] = None, ) -> SnsCredentials: """ - Update SNS credentials. - Update a set of SNS credentials. You can update the credentials' name, or their permissions. - :param sns_credentials_id: ID of the SNS credentials to update. + Update Topics and Events credentials. + Update a set of Topics and Events credentials. You can update the credentials' name, or their permissions. + :param sns_credentials_id: ID of the Topics and Events credentials to update. :param region: Region to target. If none is passed will use default region from the config. :param name: Name of the credentials. :param permissions: Permissions associated with these credentials. @@ -744,12 +750,12 @@ async def get_sns_credentials( self, *, sns_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SnsCredentials: """ - Get SNS credentials. + Get Topics and Events credentials. Retrieve an existing set of credentials, identified by the `credentials_id`. The credentials themselves, as well as their metadata (name, project ID etc), are returned in the response. - :param sns_credentials_id: ID of the SNS credentials to get. + :param sns_credentials_id: ID of the Topics and Events credentials to get. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`SnsCredentials ` @@ -779,17 +785,17 @@ async def get_sns_credentials( async def list_sns_credentials( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSnsCredentialsRequestOrderBy] = None, ) -> ListSnsCredentialsResponse: """ - List SNS credentials. - List existing SNS credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. + List Topics and Events credentials. + List existing Topics and Events credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Include only SNS credentials in this Project. + :param project_id: Include only Topics and Events credentials in this Project. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. :param order_by: Order in which to return results. @@ -822,17 +828,17 @@ async def list_sns_credentials( async def list_sns_credentials_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSnsCredentialsRequestOrderBy] = None, ) -> List[SnsCredentials]: """ - List SNS credentials. - List existing SNS credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. + List Topics and Events credentials. + List existing Topics and Events credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Include only SNS credentials in this Project. + :param project_id: Include only Topics and Events credentials in this Project. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. :param order_by: Order in which to return results. @@ -860,20 +866,20 @@ async def list_sns_credentials_all( class MnqV1Beta1SqsAPI(API): """ - This API allows you to manage Scaleway Messaging and Queueing SQS brokers. + This API allows you to manage your Scaleway Queues. """ async def activate_sqs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SqsInfo: """ - Activate SQS. - Activate SQS for the specified Project ID. SQS must be activated before any usage such as creating credentials and queues. Activating SQS does not trigger any billing, and you can deactivate at any time. + Activate Queues. + Activate Queues for the specified Project ID. Queues must be activated before any usage such as creating credentials and queues. Activating Queues does not trigger any billing, and you can deactivate at any time. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project on which to activate the SQS service. + :param project_id: Project on which to activate the Queues service. :return: :class:`SqsInfo ` Usage: @@ -904,14 +910,14 @@ async def activate_sqs( async def get_sqs_info( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SqsInfo: """ - Get SQS info. - Retrieve the SQS information of the specified Project ID. Informations include the activation status and the SQS API endpoint URL. + Get Queues info. + Retrieve the Queues information of the specified Project ID. Informations include the activation status and the Queues API endpoint URL. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project to retrieve SQS info from. + :param project_id: Project to retrieve Queues info from. :return: :class:`SqsInfo ` Usage: @@ -938,14 +944,14 @@ async def get_sqs_info( async def deactivate_sqs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SqsInfo: """ - Deactivate SQS. - Deactivate SQS for the specified Project ID. You must delete all queues and credentials before this call or you need to set the force_delete parameter. + Deactivate Queues. + Deactivate Queues for the specified Project ID. You must delete all queues and credentials before this call or you need to set the force_delete parameter. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project on which to deactivate the SQS service. + :param project_id: Project on which to deactivate the Queues service. :return: :class:`SqsInfo ` Usage: @@ -976,16 +982,16 @@ async def deactivate_sqs( async def create_sqs_credentials( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, name: Optional[str] = None, permissions: Optional[SqsPermissions] = None, ) -> SqsCredentials: """ - Create SQS credentials. - Create a set of credentials for SQS, specified by a Project ID. Credentials give the bearer access to queues, and the level of permissions can be defined granularly. + Create Queues credentials. + Create a set of credentials for Queues, specified by a Project ID. Credentials give the bearer access to queues, and the level of permissions can be defined granularly. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project containing the SQS credentials. + :param project_id: Project containing the Queues credentials. :param name: Name of the credentials. :param permissions: Permissions associated with these credentials. :return: :class:`SqsCredentials ` @@ -1021,11 +1027,11 @@ async def delete_sqs_credentials( self, *, sqs_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ - Delete SQS credentials. - Delete a set of SQS credentials, specified by their credentials ID. Deleting credentials is irreversible and cannot be undone. The credentials can then no longer be used to access SQS. + Delete Queues credentials. + Delete a set of Queues credentials, specified by their credentials ID. Deleting credentials is irreversible and cannot be undone. The credentials can then no longer be used to access Queues. :param sqs_credentials_id: ID of the credentials to delete. :param region: Region to target. If none is passed will use default region from the config. @@ -1055,14 +1061,14 @@ async def update_sqs_credentials( self, *, sqs_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, permissions: Optional[SqsPermissions] = None, ) -> SqsCredentials: """ - Update SQS credentials. - Update a set of SQS credentials. You can update the credentials' name, or their permissions. - :param sqs_credentials_id: ID of the SQS credentials to update. + Update Queues credentials. + Update a set of Queues credentials. You can update the credentials' name, or their permissions. + :param sqs_credentials_id: ID of the Queues credentials to update. :param region: Region to target. If none is passed will use default region from the config. :param name: Name of the credentials. :param permissions: Permissions associated with these credentials. @@ -1104,12 +1110,12 @@ async def get_sqs_credentials( self, *, sqs_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SqsCredentials: """ - Get SQS credentials. + Get Queues credentials. Retrieve an existing set of credentials, identified by the `credentials_id`. The credentials themselves, as well as their metadata (name, project ID etc), are returned in the response. - :param sqs_credentials_id: ID of the SQS credentials to get. + :param sqs_credentials_id: ID of the Queues credentials to get. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`SqsCredentials ` @@ -1139,17 +1145,17 @@ async def get_sqs_credentials( async def list_sqs_credentials( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSqsCredentialsRequestOrderBy] = None, ) -> ListSqsCredentialsResponse: """ - List SQS credentials. - List existing SQS credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. + List Queues credentials. + List existing Queues credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Include only SQS credentials in this Project. + :param project_id: Include only Queues credentials in this Project. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. :param order_by: Order in which to return results. @@ -1182,17 +1188,17 @@ async def list_sqs_credentials( async def list_sqs_credentials_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSqsCredentialsRequestOrderBy] = None, ) -> List[SqsCredentials]: """ - List SQS credentials. - List existing SQS credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. + List Queues credentials. + List existing Queues credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Include only SQS credentials in this Project. + :param project_id: Include only Queues credentials in this Project. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. :param order_by: Order in which to return results. diff --git a/scaleway-async/scaleway_async/mnq/v1beta1/marshalling.py b/scaleway-async/scaleway_async/mnq/v1beta1/marshalling.py index 1ffebec4..a61ebfcb 100644 --- a/scaleway-async/scaleway_async/mnq/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/mnq/v1beta1/marshalling.py @@ -64,10 +64,14 @@ def unmarshal_NatsAccount(data: Any) -> NatsAccount: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return NatsAccount(**args) @@ -118,14 +122,20 @@ def unmarshal_NatsCredentials(data: Any) -> NatsCredentials: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("credentials", None) if field is not None: args["credentials"] = unmarshal_File(field) + else: + args["credentials"] = None return NatsCredentials(**args) @@ -141,14 +151,20 @@ def unmarshal_SnsPermissions(data: Any) -> SnsPermissions: field = data.get("can_publish", None) if field is not None: args["can_publish"] = field + else: + args["can_publish"] = None field = data.get("can_receive", None) if field is not None: args["can_receive"] = field + else: + args["can_receive"] = None field = data.get("can_manage", None) if field is not None: args["can_manage"] = field + else: + args["can_manage"] = None return SnsPermissions(**args) @@ -192,14 +208,20 @@ def unmarshal_SnsCredentials(data: Any) -> SnsCredentials: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("permissions", None) if field is not None: args["permissions"] = unmarshal_SnsPermissions(field) + else: + args["permissions"] = None return SnsCredentials(**args) @@ -215,14 +237,20 @@ def unmarshal_SqsPermissions(data: Any) -> SqsPermissions: field = data.get("can_publish", None) if field is not None: args["can_publish"] = field + else: + args["can_publish"] = None field = data.get("can_receive", None) if field is not None: args["can_receive"] = field + else: + args["can_receive"] = None field = data.get("can_manage", None) if field is not None: args["can_manage"] = field + else: + args["can_manage"] = None return SqsPermissions(**args) @@ -266,14 +294,20 @@ def unmarshal_SqsCredentials(data: Any) -> SqsCredentials: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("permissions", None) if field is not None: args["permissions"] = unmarshal_SqsPermissions(field) + else: + args["permissions"] = None return SqsCredentials(**args) @@ -389,10 +423,14 @@ def unmarshal_SnsInfo(data: Any) -> SnsInfo: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return SnsInfo(**args) @@ -424,10 +462,14 @@ def unmarshal_SqsInfo(data: Any) -> SqsInfo: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return SqsInfo(**args) @@ -517,7 +559,7 @@ def marshal_SnsApiCreateSnsCredentialsRequest( output["name"] = request.name if request.permissions is not None: - output["permissions"] = (marshal_SnsPermissions(request.permissions, defaults),) + output["permissions"] = marshal_SnsPermissions(request.permissions, defaults) return output @@ -544,7 +586,7 @@ def marshal_SnsApiUpdateSnsCredentialsRequest( output["name"] = request.name if request.permissions is not None: - output["permissions"] = (marshal_SnsPermissions(request.permissions, defaults),) + output["permissions"] = marshal_SnsPermissions(request.permissions, defaults) return output @@ -592,7 +634,7 @@ def marshal_SqsApiCreateSqsCredentialsRequest( output["name"] = request.name if request.permissions is not None: - output["permissions"] = (marshal_SqsPermissions(request.permissions, defaults),) + output["permissions"] = marshal_SqsPermissions(request.permissions, defaults) return output @@ -619,6 +661,6 @@ def marshal_SqsApiUpdateSqsCredentialsRequest( output["name"] = request.name if request.permissions is not None: - output["permissions"] = (marshal_SqsPermissions(request.permissions, defaults),) + output["permissions"] = marshal_SqsPermissions(request.permissions, defaults) return output diff --git a/scaleway-async/scaleway_async/mnq/v1beta1/types.py b/scaleway-async/scaleway_async/mnq/v1beta1/types.py index d41c5607..29a4a641 100644 --- a/scaleway-async/scaleway_async/mnq/v1beta1/types.py +++ b/scaleway-async/scaleway_async/mnq/v1beta1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -98,7 +98,7 @@ class File: class SnsPermissions: can_publish: Optional[bool] """ - Defines whether the credentials bearer can publish messages to the service (publish to SNS topics). + Defines whether the credentials bearer can publish messages to the service (publish to Topics and Events topics). """ can_receive: Optional[bool] @@ -108,7 +108,7 @@ class SnsPermissions: can_manage: Optional[bool] """ - Defines whether the credentials bearer can manage the associated SNS topics or subscriptions. + Defines whether the credentials bearer can manage the associated Topics and Events topics or subscriptions. """ @@ -116,17 +116,17 @@ class SnsPermissions: class SqsPermissions: can_publish: Optional[bool] """ - Defines whether the credentials bearer can publish messages to the service (send messages to SQS queues). + Defines whether the credentials bearer can publish messages to the service (send messages to Queues queues). """ can_receive: Optional[bool] """ - Defines whether the credentials bearer can receive messages from SQS queues. + Defines whether the credentials bearer can receive messages from Queues queues. """ can_manage: Optional[bool] """ - Defines whether the credentials bearer can manage the associated SQS queues. + Defines whether the credentials bearer can manage the associated Queues queues. """ @@ -152,7 +152,7 @@ class NatsAccount: Project ID of the Project containing the NATS account. """ - region: Region + region: ScwRegion """ Region where the NATS account is deployed. """ @@ -223,7 +223,7 @@ class SnsCredentials: Project ID of the Project containing the credentials. """ - region: Region + region: ScwRegion """ Region where the credentials exists. """ @@ -235,7 +235,7 @@ class SnsCredentials: secret_key: str """ - Secret key ID (Only returned by **Create SNS Credentials** call). + Secret key ID (Only returned by **Create Topics and Events Credentials** call). """ secret_checksum: str @@ -276,7 +276,7 @@ class SqsCredentials: Project ID of the Project containing the credentials. """ - region: Region + region: ScwRegion """ Region where the credentials exists. """ @@ -288,7 +288,7 @@ class SqsCredentials: secret_key: str """ - Secret key ID (Only returned by **Create SQS Credentials** call). + Secret key ID (Only returned by **Create Queues Credentials** call). """ secret_checksum: str @@ -347,7 +347,7 @@ class ListSnsCredentialsResponse: sns_credentials: List[SnsCredentials] """ - SNS credentials on this page. + Topics and Events credentials on this page. """ @@ -360,13 +360,13 @@ class ListSqsCredentialsResponse: sqs_credentials: List[SqsCredentials] """ - SQS credentials on this page. + Queues credentials on this page. """ @dataclass class NatsApiCreateNatsAccountRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -389,7 +389,7 @@ class NatsApiCreateNatsCredentialsRequest: NATS account containing the credentials. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -407,7 +407,7 @@ class NatsApiDeleteNatsAccountRequest: ID of the NATS account to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -420,7 +420,7 @@ class NatsApiDeleteNatsCredentialsRequest: ID of the credentials to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -433,7 +433,7 @@ class NatsApiGetNatsAccountRequest: ID of the NATS account to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -446,7 +446,7 @@ class NatsApiGetNatsCredentialsRequest: ID of the credentials to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -454,7 +454,7 @@ class NatsApiGetNatsCredentialsRequest: @dataclass class NatsApiListNatsAccountsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -482,11 +482,16 @@ class NatsApiListNatsAccountsRequest: @dataclass class NatsApiListNatsCredentialsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ + project_id: Optional[str] + """ + Include only NATS accounts in this Project. + """ + nats_account_id: Optional[str] """ Include only credentials for this NATS account. @@ -515,7 +520,7 @@ class NatsApiUpdateNatsAccountRequest: ID of the NATS account to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -528,27 +533,27 @@ class NatsApiUpdateNatsAccountRequest: @dataclass class SnsApiActivateSnsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project on which to activate the SNS service. + Project on which to activate the Topics and Events service. """ @dataclass class SnsApiCreateSnsCredentialsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project containing the SNS credentials. + Project containing the Topics and Events credentials. """ name: Optional[str] @@ -564,14 +569,14 @@ class SnsApiCreateSnsCredentialsRequest: @dataclass class SnsApiDeactivateSnsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project on which to deactivate the SNS service. + Project on which to deactivate the Topics and Events service. """ @@ -582,7 +587,7 @@ class SnsApiDeleteSnsCredentialsRequest: ID of the credentials to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -592,10 +597,10 @@ class SnsApiDeleteSnsCredentialsRequest: class SnsApiGetSnsCredentialsRequest: sns_credentials_id: str """ - ID of the SNS credentials to get. + ID of the Topics and Events credentials to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -603,27 +608,27 @@ class SnsApiGetSnsCredentialsRequest: @dataclass class SnsApiGetSnsInfoRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project to retrieve SNS info from. + Project to retrieve Topics and Events info from. """ @dataclass class SnsApiListSnsCredentialsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Include only SNS credentials in this Project. + Include only Topics and Events credentials in this Project. """ page: Optional[int] @@ -646,10 +651,10 @@ class SnsApiListSnsCredentialsRequest: class SnsApiUpdateSnsCredentialsRequest: sns_credentials_id: str """ - ID of the SNS credentials to update. + ID of the Topics and Events credentials to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -672,55 +677,55 @@ class SnsInfo: Project ID of the Project containing the service. """ - region: Region + region: ScwRegion """ Region of the service. """ status: SnsInfoStatus """ - SNS activation status. + Topics and Events activation status. """ sns_endpoint_url: str """ - Endpoint of the SNS service for this region and project. + Endpoint of the Topics and Events service for this region and project. """ created_at: Optional[datetime] """ - SNS creation date. + Topics and Events creation date. """ updated_at: Optional[datetime] """ - SNS last modification date. + Topics and Events last modification date. """ @dataclass class SqsApiActivateSqsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project on which to activate the SQS service. + Project on which to activate the Queues service. """ @dataclass class SqsApiCreateSqsCredentialsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project containing the SQS credentials. + Project containing the Queues credentials. """ name: Optional[str] @@ -736,14 +741,14 @@ class SqsApiCreateSqsCredentialsRequest: @dataclass class SqsApiDeactivateSqsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project on which to deactivate the SQS service. + Project on which to deactivate the Queues service. """ @@ -754,7 +759,7 @@ class SqsApiDeleteSqsCredentialsRequest: ID of the credentials to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -764,10 +769,10 @@ class SqsApiDeleteSqsCredentialsRequest: class SqsApiGetSqsCredentialsRequest: sqs_credentials_id: str """ - ID of the SQS credentials to get. + ID of the Queues credentials to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -775,27 +780,27 @@ class SqsApiGetSqsCredentialsRequest: @dataclass class SqsApiGetSqsInfoRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project to retrieve SQS info from. + Project to retrieve Queues info from. """ @dataclass class SqsApiListSqsCredentialsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Include only SQS credentials in this Project. + Include only Queues credentials in this Project. """ page: Optional[int] @@ -818,10 +823,10 @@ class SqsApiListSqsCredentialsRequest: class SqsApiUpdateSqsCredentialsRequest: sqs_credentials_id: str """ - ID of the SQS credentials to update. + ID of the Queues credentials to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -844,27 +849,27 @@ class SqsInfo: Project ID of the Project containing the service. """ - region: Region + region: ScwRegion """ Region of the service. """ status: SqsInfoStatus """ - SQS activation status. + Queues activation status. """ sqs_endpoint_url: str """ - Endpoint of the SQS service for this region and project. + Endpoint of the Queues service for this region and project. """ created_at: Optional[datetime] """ - SQS creation date. + Queues creation date. """ updated_at: Optional[datetime] """ - SQS last modification date. + Queues last modification date. """ diff --git a/scaleway-async/scaleway_async/mongodb/__init__.py b/scaleway-async/scaleway_async/mongodb/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway-async/scaleway_async/mongodb/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway-async/scaleway_async/mongodb/v1alpha1/__init__.py b/scaleway-async/scaleway_async/mongodb/v1alpha1/__init__.py new file mode 100644 index 00000000..697dc169 --- /dev/null +++ b/scaleway-async/scaleway_async/mongodb/v1alpha1/__init__.py @@ -0,0 +1,121 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import InstanceStatus +from .content import INSTANCE_TRANSIENT_STATUSES +from .types import ListInstancesRequestOrderBy +from .types import ListSnapshotsRequestOrderBy +from .types import ListUsersRequestOrderBy +from .types import NodeTypeStock +from .types import SettingPropertyType +from .types import SnapshotStatus +from .content import SNAPSHOT_TRANSIENT_STATUSES +from .types import UserRoleRole +from .types import VolumeType +from .types import EndpointPrivateNetworkDetails +from .types import EndpointPublicDetails +from .types import EndpointSpecPrivateNetworkDetails +from .types import EndpointSpecPublicDetails +from .types import Endpoint +from .types import InstanceSetting +from .types import Volume +from .types import NodeTypeVolumeType +from .types import SnapshotVolumeType +from .types import UserRole +from .types import Setting +from .types import EndpointSpec +from .types import CreateInstanceRequestVolumeDetails +from .types import Instance +from .types import NodeType +from .types import Snapshot +from .types import User +from .types import Version +from .types import RestoreSnapshotRequestVolumeDetails +from .types import CreateEndpointRequest +from .types import CreateInstanceRequest +from .types import CreateSnapshotRequest +from .types import CreateUserRequest +from .types import DeleteEndpointRequest +from .types import DeleteInstanceRequest +from .types import DeleteSnapshotRequest +from .types import DeleteUserRequest +from .types import GetInstanceCertificateRequest +from .types import GetInstanceRequest +from .types import GetSnapshotRequest +from .types import ListInstancesRequest +from .types import ListInstancesResponse +from .types import ListNodeTypesRequest +from .types import ListNodeTypesResponse +from .types import ListSnapshotsRequest +from .types import ListSnapshotsResponse +from .types import ListUsersRequest +from .types import ListUsersResponse +from .types import ListVersionsRequest +from .types import ListVersionsResponse +from .types import RestoreSnapshotRequest +from .types import SetUserRoleRequest +from .types import UpdateInstanceRequest +from .types import UpdateSnapshotRequest +from .types import UpdateUserRequest +from .types import UpgradeInstanceRequest +from .api import MongodbV1Alpha1API + +__all__ = [ + "InstanceStatus", + "INSTANCE_TRANSIENT_STATUSES", + "ListInstancesRequestOrderBy", + "ListSnapshotsRequestOrderBy", + "ListUsersRequestOrderBy", + "NodeTypeStock", + "SettingPropertyType", + "SnapshotStatus", + "SNAPSHOT_TRANSIENT_STATUSES", + "UserRoleRole", + "VolumeType", + "EndpointPrivateNetworkDetails", + "EndpointPublicDetails", + "EndpointSpecPrivateNetworkDetails", + "EndpointSpecPublicDetails", + "Endpoint", + "InstanceSetting", + "Volume", + "NodeTypeVolumeType", + "SnapshotVolumeType", + "UserRole", + "Setting", + "EndpointSpec", + "CreateInstanceRequestVolumeDetails", + "Instance", + "NodeType", + "Snapshot", + "User", + "Version", + "RestoreSnapshotRequestVolumeDetails", + "CreateEndpointRequest", + "CreateInstanceRequest", + "CreateSnapshotRequest", + "CreateUserRequest", + "DeleteEndpointRequest", + "DeleteInstanceRequest", + "DeleteSnapshotRequest", + "DeleteUserRequest", + "GetInstanceCertificateRequest", + "GetInstanceRequest", + "GetSnapshotRequest", + "ListInstancesRequest", + "ListInstancesResponse", + "ListNodeTypesRequest", + "ListNodeTypesResponse", + "ListSnapshotsRequest", + "ListSnapshotsResponse", + "ListUsersRequest", + "ListUsersResponse", + "ListVersionsRequest", + "ListVersionsResponse", + "RestoreSnapshotRequest", + "SetUserRoleRequest", + "UpdateInstanceRequest", + "UpdateSnapshotRequest", + "UpdateUserRequest", + "UpgradeInstanceRequest", + "MongodbV1Alpha1API", +] diff --git a/scaleway-async/scaleway_async/mongodb/v1alpha1/api.py b/scaleway-async/scaleway_async/mongodb/v1alpha1/api.py new file mode 100644 index 00000000..dc413e65 --- /dev/null +++ b/scaleway-async/scaleway_async/mongodb/v1alpha1/api.py @@ -0,0 +1,1337 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from datetime import datetime +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, + ScwFile, + unmarshal_ScwFile, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + ListInstancesRequestOrderBy, + ListSnapshotsRequestOrderBy, + ListUsersRequestOrderBy, + CreateEndpointRequest, + CreateInstanceRequest, + CreateInstanceRequestVolumeDetails, + CreateSnapshotRequest, + CreateUserRequest, + Endpoint, + EndpointSpec, + Instance, + ListInstancesResponse, + ListNodeTypesResponse, + ListSnapshotsResponse, + ListUsersResponse, + ListVersionsResponse, + NodeType, + RestoreSnapshotRequest, + RestoreSnapshotRequestVolumeDetails, + SetUserRoleRequest, + Snapshot, + UpdateInstanceRequest, + UpdateSnapshotRequest, + UpdateUserRequest, + UpgradeInstanceRequest, + User, + UserRole, + Version, +) +from .content import ( + INSTANCE_TRANSIENT_STATUSES, + SNAPSHOT_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_Endpoint, + unmarshal_Instance, + unmarshal_Snapshot, + unmarshal_User, + unmarshal_ListInstancesResponse, + unmarshal_ListNodeTypesResponse, + unmarshal_ListSnapshotsResponse, + unmarshal_ListUsersResponse, + unmarshal_ListVersionsResponse, + marshal_CreateEndpointRequest, + marshal_CreateInstanceRequest, + marshal_CreateSnapshotRequest, + marshal_CreateUserRequest, + marshal_RestoreSnapshotRequest, + marshal_SetUserRoleRequest, + marshal_UpdateInstanceRequest, + marshal_UpdateSnapshotRequest, + marshal_UpdateUserRequest, + marshal_UpgradeInstanceRequest, +) + + +class MongodbV1Alpha1API(API): + """ + This API allows you to manage your Managed Databases for MongoDB®. + """ + + async def list_node_types( + self, + *, + region: Optional[ScwRegion] = None, + include_disabled_types: Optional[bool] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListNodeTypesResponse: + """ + List available node types. + :param region: Region to target. If none is passed will use default region from the config. + :param include_disabled_types: Defines whether or not to include disabled types. + :param page: + :param page_size: + :return: :class:`ListNodeTypesResponse ` + + Usage: + :: + + result = await api.list_node_types() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/node-types", + params={ + "include_disabled_types": include_disabled_types, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListNodeTypesResponse(res.json()) + + async def list_node_types_all( + self, + *, + region: Optional[ScwRegion] = None, + include_disabled_types: Optional[bool] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[NodeType]: + """ + List available node types. + :param region: Region to target. If none is passed will use default region from the config. + :param include_disabled_types: Defines whether or not to include disabled types. + :param page: + :param page_size: + :return: :class:`List[NodeType] ` + + Usage: + :: + + result = await api.list_node_types_all() + """ + + return await fetch_all_pages_async( + type=ListNodeTypesResponse, + key="node_types", + fetcher=self.list_node_types, + args={ + "region": region, + "include_disabled_types": include_disabled_types, + "page": page, + "page_size": page_size, + }, + ) + + async def list_versions( + self, + *, + region: Optional[ScwRegion] = None, + version: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListVersionsResponse: + """ + List available MongoDB® versions. + :param region: Region to target. If none is passed will use default region from the config. + :param version: + :param page: + :param page_size: + :return: :class:`ListVersionsResponse ` + + Usage: + :: + + result = await api.list_versions() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/versions", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "version": version, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListVersionsResponse(res.json()) + + async def list_versions_all( + self, + *, + region: Optional[ScwRegion] = None, + version: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[Version]: + """ + List available MongoDB® versions. + :param region: Region to target. If none is passed will use default region from the config. + :param version: + :param page: + :param page_size: + :return: :class:`List[Version] ` + + Usage: + :: + + result = await api.list_versions_all() + """ + + return await fetch_all_pages_async( + type=ListVersionsResponse, + key="versions", + fetcher=self.list_versions, + args={ + "region": region, + "version": version, + "page": page, + "page_size": page_size, + }, + ) + + async def list_instances( + self, + *, + region: Optional[ScwRegion] = None, + tags: Optional[List[str]] = None, + name: Optional[str] = None, + order_by: Optional[ListInstancesRequestOrderBy] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListInstancesResponse: + """ + List MongoDB® Database Instances. + List all MongoDB® Database Instances in the specified region. By default, the MongoDB® Database Instances returned in the list are ordered by creation date in ascending order, though this can be modified via the order_by field. You can define additional parameters for your query, such as `tags` and `name`. For the `name` parameter, the value you include will be checked against the whole name string to see if it includes the string you put in the parameter. + :param region: Region to target. If none is passed will use default region from the config. + :param tags: List Database Instances that have a given tag. + :param name: Lists Database Instances that match a name pattern. + :param order_by: Criteria to use when ordering Database Instance listings. + :param organization_id: Organization ID of the Database Instance. + :param project_id: Project ID. + :param page: + :param page_size: + :return: :class:`ListInstancesResponse ` + + Usage: + :: + + result = await api.list_instances() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/instances", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInstancesResponse(res.json()) + + async def list_instances_all( + self, + *, + region: Optional[ScwRegion] = None, + tags: Optional[List[str]] = None, + name: Optional[str] = None, + order_by: Optional[ListInstancesRequestOrderBy] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[Instance]: + """ + List MongoDB® Database Instances. + List all MongoDB® Database Instances in the specified region. By default, the MongoDB® Database Instances returned in the list are ordered by creation date in ascending order, though this can be modified via the order_by field. You can define additional parameters for your query, such as `tags` and `name`. For the `name` parameter, the value you include will be checked against the whole name string to see if it includes the string you put in the parameter. + :param region: Region to target. If none is passed will use default region from the config. + :param tags: List Database Instances that have a given tag. + :param name: Lists Database Instances that match a name pattern. + :param order_by: Criteria to use when ordering Database Instance listings. + :param organization_id: Organization ID of the Database Instance. + :param project_id: Project ID. + :param page: + :param page_size: + :return: :class:`List[Instance] ` + + Usage: + :: + + result = await api.list_instances_all() + """ + + return await fetch_all_pages_async( + type=ListInstancesResponse, + key="instances", + fetcher=self.list_instances, + args={ + "region": region, + "tags": tags, + "name": name, + "order_by": order_by, + "organization_id": organization_id, + "project_id": project_id, + "page": page, + "page_size": page_size, + }, + ) + + async def get_instance( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + ) -> Instance: + """ + Get a MongoDB® Database Instance. + Retrieve information about a given MongoDB® Database Instance, specified by the `region` and `instance_id` parameters. Its full details, including name, status, IP address and port, are returned in the response object. + :param instance_id: UUID of the Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Instance ` + + Usage: + :: + + result = await api.get_instance( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}", + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + async def wait_for_instance( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + options: Optional[ + WaitForOptions[Instance, Union[bool, Awaitable[bool]]] + ] = None, + ) -> Instance: + """ + Get a MongoDB® Database Instance. + Retrieve information about a given MongoDB® Database Instance, specified by the `region` and `instance_id` parameters. Its full details, including name, status, IP address and port, are returned in the response object. + :param instance_id: UUID of the Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Instance ` + + Usage: + :: + + result = await api.get_instance( + instance_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in INSTANCE_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_instance, + options=options, + args={ + "instance_id": instance_id, + "region": region, + }, + ) + + async def create_instance( + self, + *, + version: str, + node_number: int, + node_type: str, + user_name: str, + password: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + volume: Optional[CreateInstanceRequestVolumeDetails] = None, + endpoints: Optional[List[EndpointSpec]] = None, + ) -> Instance: + """ + Create a MongoDB® Database Instance. + Create a new MongoDB® Database Instance. + :param version: Version of the MongoDB® engine. + :param node_number: Number of node to use for the Database Instance. + :param node_type: Type of node to use for the Database Instance. + :param user_name: Username created when the Database Instance is created. + :param password: Password of the initial user. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: The Project ID on which the Database Instance will be created. + :param name: Name of the Database Instance. + :param tags: Tags to apply to the Database Instance. + :param volume: Instance volume information. + :param endpoints: One or multiple EndpointSpec used to expose your Database Instance. + :return: :class:`Instance ` + + Usage: + :: + + result = await api.create_instance( + version="example", + node_number=1, + node_type="example", + user_name="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/instances", + body=marshal_CreateInstanceRequest( + CreateInstanceRequest( + version=version, + node_number=node_number, + node_type=node_type, + user_name=user_name, + password=password, + region=region, + project_id=project_id, + name=name or random_name(prefix="mgdb"), + tags=tags, + volume=volume, + endpoints=endpoints, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + async def update_instance( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> Instance: + """ + Update a MongoDB® Database Instance. + Update the parameters of a MongoDB® Database Instance. + :param instance_id: UUID of the Database Instance to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the Database Instance. + :param tags: Tags of a Database Instance. + :return: :class:`Instance ` + + Usage: + :: + + result = await api.update_instance( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "PATCH", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}", + body=marshal_UpdateInstanceRequest( + UpdateInstanceRequest( + instance_id=instance_id, + region=region, + name=name, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + async def delete_instance( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + ) -> Instance: + """ + Delete a MongoDB® Database Instance. + Delete a given MongoDB® Database Instance, specified by the `region` and `instance_id` parameters. Deleting a MongoDB® Database Instance is permanent, and cannot be undone. Note that upon deletion all your data will be lost. + :param instance_id: UUID of the Database Instance to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Instance ` + + Usage: + :: + + result = await api.delete_instance( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "DELETE", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}", + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + async def upgrade_instance( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + volume_size: Optional[int] = None, + ) -> Instance: + """ + Upgrade a Database Instance. + Upgrade your current Database Instance specifications like volume size. + :param instance_id: UUID of the Database Instance you want to upgrade. + :param region: Region to target. If none is passed will use default region from the config. + :param volume_size: Increase your Block Storage volume size. + One-Of ('upgrade_target'): at most one of 'volume_size' could be set. + :return: :class:`Instance ` + + Usage: + :: + + result = await api.upgrade_instance( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/upgrade", + body=marshal_UpgradeInstanceRequest( + UpgradeInstanceRequest( + instance_id=instance_id, + region=region, + volume_size=volume_size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + async def get_instance_certificate( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + ) -> ScwFile: + """ + Get the certificate of a Database Instance. + Retrieve the certificate of a given Database Instance, specified by the `instance_id` parameter. + :param instance_id: UUID of the Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ScwFile ` + + Usage: + :: + + result = await api.get_instance_certificate( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/certificate", + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + async def create_snapshot( + self, + *, + instance_id: str, + name: str, + region: Optional[ScwRegion] = None, + expires_at: Optional[datetime] = None, + ) -> Snapshot: + """ + Create a Database Instance snapshot. + Create a new snapshot of a Database Instance. You must define the `name` and `instance_id` parameters in the request. + :param instance_id: UUID of the Database Instance to snapshot. + :param name: Name of the snapshot. + :param region: Region to target. If none is passed will use default region from the config. + :param expires_at: Expiration date of the snapshot (must follow the ISO 8601 format). + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.create_snapshot( + instance_id="example", + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/snapshots", + body=marshal_CreateSnapshotRequest( + CreateSnapshotRequest( + instance_id=instance_id, + name=name, + region=region, + expires_at=expires_at, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def get_snapshot( + self, + *, + snapshot_id: str, + region: Optional[ScwRegion] = None, + ) -> Snapshot: + """ + Get a Database Instance snapshot. + Retrieve information about a given snapshot of a Database Instance. You must specify, in the endpoint, the `snapshot_id` parameter of the snapshot you want to retrieve. + :param snapshot_id: UUID of the snapshot. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.get_snapshot( + snapshot_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def wait_for_snapshot( + self, + *, + snapshot_id: str, + region: Optional[ScwRegion] = None, + options: Optional[ + WaitForOptions[Snapshot, Union[bool, Awaitable[bool]]] + ] = None, + ) -> Snapshot: + """ + Get a Database Instance snapshot. + Retrieve information about a given snapshot of a Database Instance. You must specify, in the endpoint, the `snapshot_id` parameter of the snapshot you want to retrieve. + :param snapshot_id: UUID of the snapshot. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.get_snapshot( + snapshot_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in SNAPSHOT_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_snapshot, + options=options, + args={ + "snapshot_id": snapshot_id, + "region": region, + }, + ) + + async def update_snapshot( + self, + *, + snapshot_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + expires_at: Optional[datetime] = None, + ) -> Snapshot: + """ + Update a Database Instance snapshot. + Update the parameters of a snapshot of a Database Instance. You can update the `name` and `expires_at` parameters. + :param snapshot_id: UUID of the Snapshot. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the snapshot. + :param expires_at: Expiration date of the snapshot (must follow the ISO 8601 format). + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.update_snapshot( + snapshot_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/snapshots/{param_snapshot_id}", + body=marshal_UpdateSnapshotRequest( + UpdateSnapshotRequest( + snapshot_id=snapshot_id, + region=region, + name=name, + expires_at=expires_at, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def restore_snapshot( + self, + *, + snapshot_id: str, + instance_name: str, + node_type: str, + node_number: int, + volume: RestoreSnapshotRequestVolumeDetails, + region: Optional[ScwRegion] = None, + ) -> Instance: + """ + Restore a Database Instance snapshot. + Restore a given snapshot of a Database Instance. You must specify, in the endpoint, the `snapshot_id` parameter of the snapshot you want to restore, the `instance_name` of the new Database Instance, `node_type` of the new Database Instance and `node_number` of the new Database Instance. + :param snapshot_id: UUID of the snapshot. + :param instance_name: Name of the new Database Instance. + :param node_type: Node type to use for the new Database Instance. + :param node_number: Number of nodes to use for the new Database Instance. + :param volume: Instance volume information. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Instance ` + + Usage: + :: + + result = await api.restore_snapshot( + snapshot_id="example", + instance_name="example", + node_type="example", + node_number=1, + volume=RestoreSnapshotRequestVolumeDetails(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/snapshots/{param_snapshot_id}/restore", + body=marshal_RestoreSnapshotRequest( + RestoreSnapshotRequest( + snapshot_id=snapshot_id, + instance_name=instance_name, + node_type=node_type, + node_number=node_number, + volume=volume, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + async def list_snapshots( + self, + *, + region: Optional[ScwRegion] = None, + instance_id: Optional[str] = None, + name: Optional[str] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListSnapshotsResponse: + """ + List snapshots. + List snapshots. You can include the `instance_id` or `project_id` in your query to get the list of snapshots for specific Database Instances and/or Projects. By default, the details returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param instance_id: Instance ID the snapshots belongs to. + :param name: Lists database snapshots that match a name pattern. + :param order_by: Criteria to use when ordering snapshot listings. + :param organization_id: Organization ID the snapshots belongs to. + :param project_id: Project ID to list the snapshots of. + :param page: + :param page_size: + :return: :class:`ListSnapshotsResponse ` + + Usage: + :: + + result = await api.list_snapshots() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/snapshots", + params={ + "instance_id": instance_id, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListSnapshotsResponse(res.json()) + + async def list_snapshots_all( + self, + *, + region: Optional[ScwRegion] = None, + instance_id: Optional[str] = None, + name: Optional[str] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[Snapshot]: + """ + List snapshots. + List snapshots. You can include the `instance_id` or `project_id` in your query to get the list of snapshots for specific Database Instances and/or Projects. By default, the details returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param instance_id: Instance ID the snapshots belongs to. + :param name: Lists database snapshots that match a name pattern. + :param order_by: Criteria to use when ordering snapshot listings. + :param organization_id: Organization ID the snapshots belongs to. + :param project_id: Project ID to list the snapshots of. + :param page: + :param page_size: + :return: :class:`List[Snapshot] ` + + Usage: + :: + + result = await api.list_snapshots_all() + """ + + return await fetch_all_pages_async( + type=ListSnapshotsResponse, + key="snapshots", + fetcher=self.list_snapshots, + args={ + "region": region, + "instance_id": instance_id, + "name": name, + "order_by": order_by, + "organization_id": organization_id, + "project_id": project_id, + "page": page, + "page_size": page_size, + }, + ) + + async def delete_snapshot( + self, + *, + snapshot_id: str, + region: Optional[ScwRegion] = None, + ) -> Snapshot: + """ + Delete a Database Instance snapshot. + Delete a given snapshot of a Database Instance. You must specify, in the endpoint, the `snapshot_id` parameter of the snapshot you want to delete. + :param snapshot_id: UUID of the snapshot. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = await api.delete_snapshot( + snapshot_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "DELETE", + f"/mongodb/v1alpha1/regions/{param_region}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + async def list_users( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + order_by: Optional[ListUsersRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListUsersResponse: + """ + List users of a Database Instance. + List all users of a given Database Instance. + :param instance_id: UUID of the Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the user. + :param order_by: Criteria to use when requesting user listing. + :param page: + :param page_size: + :return: :class:`ListUsersResponse ` + + Usage: + :: + + result = await api.list_users( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/users", + params={ + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListUsersResponse(res.json()) + + async def list_users_all( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + order_by: Optional[ListUsersRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[User]: + """ + List users of a Database Instance. + List all users of a given Database Instance. + :param instance_id: UUID of the Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the user. + :param order_by: Criteria to use when requesting user listing. + :param page: + :param page_size: + :return: :class:`List[User] ` + + Usage: + :: + + result = await api.list_users_all( + instance_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListUsersResponse, + key="users", + fetcher=self.list_users, + args={ + "instance_id": instance_id, + "region": region, + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size, + }, + ) + + async def create_user( + self, + *, + instance_id: str, + name: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> User: + """ + Create an user on a Database Instance. + Create an user on a Database Instance. You must define the `name`, `password` of the user and `instance_id` parameters in the request. + :param instance_id: UUID of the Database Instance the user belongs to. + :param name: Name of the database user. + :param password: Password of the database user. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`User ` + + Usage: + :: + + result = await api.create_user( + instance_id="example", + name="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/users", + body=marshal_CreateUserRequest( + CreateUserRequest( + instance_id=instance_id, + name=name, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + async def update_user( + self, + *, + instance_id: str, + name: str, + region: Optional[ScwRegion] = None, + password: Optional[str] = None, + ) -> User: + """ + Update a user on a Database Instance. + Update the parameters of a user on a Database Instance. You can update the `password` parameter, but you cannot change the name of the user. + :param instance_id: UUID of the Database Instance the user belongs to. + :param name: Name of the database user. + :param region: Region to target. If none is passed will use default region from the config. + :param password: Password of the database user. + :return: :class:`User ` + + Usage: + :: + + result = await api.update_user( + instance_id="example", + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + param_name = validate_path_param("name", name) + + res = self._request( + "PATCH", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/users/{param_name}", + body=marshal_UpdateUserRequest( + UpdateUserRequest( + instance_id=instance_id, + name=name, + region=region, + password=password, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + async def delete_user( + self, + *, + instance_id: str, + name: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a user on a Database Instance. + Delete an existing user on a Database Instance. + :param instance_id: UUID of the Database Instance the user belongs to. + :param name: Name of the database user. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_user( + instance_id="example", + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + param_name = validate_path_param("name", name) + + res = self._request( + "DELETE", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/users/{param_name}", + body={}, + ) + + self._throw_on_error(res) + + async def set_user_role( + self, + *, + instance_id: str, + user_name: str, + region: Optional[ScwRegion] = None, + roles: Optional[List[UserRole]] = None, + ) -> User: + """ + :param instance_id: UUID of the Database Instance the user belongs to. + :param user_name: Name of the database user. + :param region: Region to target. If none is passed will use default region from the config. + :param roles: List of roles assigned to the user, along with the corresponding database where each role is granted. + :return: :class:`User ` + + Usage: + :: + + result = await api.set_user_role( + instance_id="example", + user_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "PUT", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/roles", + body=marshal_SetUserRoleRequest( + SetUserRoleRequest( + instance_id=instance_id, + user_name=user_name, + region=region, + roles=roles, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + async def delete_endpoint( + self, + *, + endpoint_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a Database Instance endpoint. + Delete the endpoint of a Database Instance. You must specify the `endpoint_id` parameter of the endpoint you want to delete. Note that you might need to update any environment configurations that point to the deleted endpoint. + :param endpoint_id: UUID of the Endpoint to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_endpoint( + endpoint_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_endpoint_id = validate_path_param("endpoint_id", endpoint_id) + + res = self._request( + "DELETE", + f"/mongodb/v1alpha1/regions/{param_region}/endpoints/{param_endpoint_id}", + ) + + self._throw_on_error(res) + + async def create_endpoint( + self, + *, + instance_id: str, + endpoint: EndpointSpec, + region: Optional[ScwRegion] = None, + ) -> Endpoint: + """ + Create a new Instance endpoint. + Create a new endpoint for a MongoDB® Database Instance. You can add `public_network` or `private_network` specifications to the body of the request. + :param instance_id: UUID of the Database Instance. + :param endpoint: EndpointSpec used to expose your Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Endpoint ` + + Usage: + :: + + result = await api.create_endpoint( + instance_id="example", + endpoint=EndpointSpec(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/endpoints", + body=marshal_CreateEndpointRequest( + CreateEndpointRequest( + instance_id=instance_id, + endpoint=endpoint, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Endpoint(res.json()) diff --git a/scaleway-async/scaleway_async/mongodb/v1alpha1/content.py b/scaleway-async/scaleway_async/mongodb/v1alpha1/content.py new file mode 100644 index 00000000..8e009220 --- /dev/null +++ b/scaleway-async/scaleway_async/mongodb/v1alpha1/content.py @@ -0,0 +1,27 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + InstanceStatus, + SnapshotStatus, +) + +INSTANCE_TRANSIENT_STATUSES: List[InstanceStatus] = [ + InstanceStatus.PROVISIONING, + InstanceStatus.CONFIGURING, + InstanceStatus.DELETING, + InstanceStatus.INITIALIZING, + InstanceStatus.SNAPSHOTTING, +] +""" +Lists transient statutes of the enum :class:`InstanceStatus `. +""" +SNAPSHOT_TRANSIENT_STATUSES: List[SnapshotStatus] = [ + SnapshotStatus.CREATING, + SnapshotStatus.RESTORING, + SnapshotStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`SnapshotStatus `. +""" diff --git a/scaleway-async/scaleway_async/mongodb/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/mongodb/v1alpha1/marshalling.py new file mode 100644 index 00000000..9b267ac1 --- /dev/null +++ b/scaleway-async/scaleway_async/mongodb/v1alpha1/marshalling.py @@ -0,0 +1,903 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + EndpointPrivateNetworkDetails, + EndpointPublicDetails, + Endpoint, + InstanceSetting, + Volume, + Instance, + SnapshotVolumeType, + Snapshot, + UserRole, + User, + ListInstancesResponse, + NodeTypeVolumeType, + NodeType, + ListNodeTypesResponse, + ListSnapshotsResponse, + ListUsersResponse, + Setting, + Version, + ListVersionsResponse, + EndpointSpecPrivateNetworkDetails, + EndpointSpecPublicDetails, + EndpointSpec, + CreateEndpointRequest, + CreateInstanceRequestVolumeDetails, + CreateInstanceRequest, + CreateSnapshotRequest, + CreateUserRequest, + RestoreSnapshotRequestVolumeDetails, + RestoreSnapshotRequest, + SetUserRoleRequest, + UpdateInstanceRequest, + UpdateSnapshotRequest, + UpdateUserRequest, + UpgradeInstanceRequest, +) + + +def unmarshal_EndpointPrivateNetworkDetails(data: Any) -> EndpointPrivateNetworkDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPrivateNetworkDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + return EndpointPrivateNetworkDetails(**args) + + +def unmarshal_EndpointPublicDetails(data: Any) -> EndpointPublicDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPublicDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return EndpointPublicDetails(**args) + + +def unmarshal_Endpoint(data: Any) -> Endpoint: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Endpoint' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("ips", None) + if field is not None: + args["ips"] = field + + field = data.get("dns_records", None) + if field is not None: + args["dns_records"] = field + + field = data.get("port", None) + if field is not None: + args["port"] = field + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None + + field = data.get("public", None) + if field is not None: + args["public"] = unmarshal_EndpointPublicDetails(field) + else: + args["public"] = None + + return Endpoint(**args) + + +def unmarshal_InstanceSetting(data: Any) -> InstanceSetting: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InstanceSetting' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + return InstanceSetting(**args) + + +def unmarshal_Volume(data: Any) -> Volume: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Volume' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + return Volume(**args) + + +def unmarshal_Instance(data: Any) -> Instance: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Instance' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("settings", None) + if field is not None: + args["settings"] = ( + [unmarshal_InstanceSetting(v) for v in field] if field is not None else None + ) + + field = data.get("node_number", None) + if field is not None: + args["node_number"] = field + + field = data.get("node_type", None) + if field is not None: + args["node_type"] = field + + field = data.get("endpoints", None) + if field is not None: + args["endpoints"] = ( + [unmarshal_Endpoint(v) for v in field] if field is not None else None + ) + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("volume", None) + if field is not None: + args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + return Instance(**args) + + +def unmarshal_SnapshotVolumeType(data: Any) -> SnapshotVolumeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SnapshotVolumeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return SnapshotVolumeType(**args) + + +def unmarshal_Snapshot(data: Any) -> Snapshot: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Snapshot' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("instance_id", None) + if field is not None: + args["instance_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("instance_name", None) + if field is not None: + args["instance_name"] = field + + field = data.get("node_type", None) + if field is not None: + args["node_type"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("volume_type", None) + if field is not None: + args["volume_type"] = unmarshal_SnapshotVolumeType(field) + else: + args["volume_type"] = None + + return Snapshot(**args) + + +def unmarshal_UserRole(data: Any) -> UserRole: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'UserRole' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("role", None) + if field is not None: + args["role"] = field + + field = data.get("database", None) + if field is not None: + args["database"] = field + else: + args["database"] = None + + field = data.get("any_database", None) + if field is not None: + args["any_database"] = field + else: + args["any_database"] = None + + return UserRole(**args) + + +def unmarshal_User(data: Any) -> User: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'User' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("roles", None) + if field is not None: + args["roles"] = ( + [unmarshal_UserRole(v) for v in field] if field is not None else None + ) + + return User(**args) + + +def unmarshal_ListInstancesResponse(data: Any) -> ListInstancesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInstancesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("instances", None) + if field is not None: + args["instances"] = ( + [unmarshal_Instance(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListInstancesResponse(**args) + + +def unmarshal_NodeTypeVolumeType(data: Any) -> NodeTypeVolumeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeTypeVolumeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("min_size", None) + if field is not None: + args["min_size"] = field + + field = data.get("max_size", None) + if field is not None: + args["max_size"] = field + + field = data.get("chunk_size", None) + if field is not None: + args["chunk_size"] = field + + return NodeTypeVolumeType(**args) + + +def unmarshal_NodeType(data: Any) -> NodeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("stock_status", None) + if field is not None: + args["stock_status"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("vcpus", None) + if field is not None: + args["vcpus"] = field + + field = data.get("memory", None) + if field is not None: + args["memory"] = field + + field = data.get("available_volume_types", None) + if field is not None: + args["available_volume_types"] = ( + [unmarshal_NodeTypeVolumeType(v) for v in field] + if field is not None + else None + ) + + field = data.get("disabled", None) + if field is not None: + args["disabled"] = field + + field = data.get("beta", None) + if field is not None: + args["beta"] = field + + field = data.get("instance_range", None) + if field is not None: + args["instance_range"] = field + + return NodeType(**args) + + +def unmarshal_ListNodeTypesResponse(data: Any) -> ListNodeTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListNodeTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_types", None) + if field is not None: + args["node_types"] = ( + [unmarshal_NodeType(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListNodeTypesResponse(**args) + + +def unmarshal_ListSnapshotsResponse(data: Any) -> ListSnapshotsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSnapshotsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("snapshots", None) + if field is not None: + args["snapshots"] = ( + [unmarshal_Snapshot(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListSnapshotsResponse(**args) + + +def unmarshal_ListUsersResponse(data: Any) -> ListUsersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListUsersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("users", None) + if field is not None: + args["users"] = ( + [unmarshal_User(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListUsersResponse(**args) + + +def unmarshal_Setting(data: Any) -> Setting: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Setting' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("default_value", None) + if field is not None: + args["default_value"] = field + + field = data.get("hot_configurable", None) + if field is not None: + args["hot_configurable"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("property_type", None) + if field is not None: + args["property_type"] = field + + field = data.get("unit", None) + if field is not None: + args["unit"] = field + else: + args["unit"] = None + + field = data.get("string_constraint", None) + if field is not None: + args["string_constraint"] = field + else: + args["string_constraint"] = None + + field = data.get("int_min", None) + if field is not None: + args["int_min"] = field + else: + args["int_min"] = None + + field = data.get("int_max", None) + if field is not None: + args["int_max"] = field + else: + args["int_max"] = None + + field = data.get("float_min", None) + if field is not None: + args["float_min"] = field + else: + args["float_min"] = None + + field = data.get("float_max", None) + if field is not None: + args["float_max"] = field + else: + args["float_max"] = None + + return Setting(**args) + + +def unmarshal_Version(data: Any) -> Version: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Version' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("available_settings", None) + if field is not None: + args["available_settings"] = ( + [unmarshal_Setting(v) for v in field] if field is not None else None + ) + + field = data.get("end_of_life_at", None) + if field is not None: + args["end_of_life_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["end_of_life_at"] = None + + return Version(**args) + + +def unmarshal_ListVersionsResponse(data: Any) -> ListVersionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListVersionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("versions", None) + if field is not None: + args["versions"] = ( + [unmarshal_Version(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListVersionsResponse(**args) + + +def marshal_EndpointSpecPrivateNetworkDetails( + request: EndpointSpecPrivateNetworkDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + return output + + +def marshal_EndpointSpecPublicDetails( + request: EndpointSpecPublicDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_EndpointSpec( + request: EndpointSpec, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("public", request.public), + OneOfPossibility("private_network", request.private_network), + ] + ), + ) + + return output + + +def marshal_CreateEndpointRequest( + request: CreateEndpointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.instance_id is not None: + output["instance_id"] = request.instance_id + + if request.endpoint is not None: + output["endpoint"] = marshal_EndpointSpec(request.endpoint, defaults) + + return output + + +def marshal_CreateInstanceRequestVolumeDetails( + request: CreateInstanceRequestVolumeDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.volume_size is not None: + output["volume_size"] = request.volume_size + + if request.volume_type is not None: + output["volume_type"] = str(request.volume_type) + + return output + + +def marshal_CreateInstanceRequest( + request: CreateInstanceRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.version is not None: + output["version"] = request.version + + if request.node_number is not None: + output["node_number"] = request.node_number + + if request.node_type is not None: + output["node_type"] = request.node_type + + if request.user_name is not None: + output["user_name"] = request.user_name + + if request.password is not None: + output["password"] = request.password + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.volume is not None: + output["volume"] = marshal_CreateInstanceRequestVolumeDetails( + request.volume, defaults + ) + + if request.endpoints is not None: + output["endpoints"] = [ + marshal_EndpointSpec(item, defaults) for item in request.endpoints + ] + + return output + + +def marshal_CreateSnapshotRequest( + request: CreateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.expires_at is not None: + output["expires_at"] = request.expires_at.isoformat() + + return output + + +def marshal_CreateUserRequest( + request: CreateUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_RestoreSnapshotRequestVolumeDetails( + request: RestoreSnapshotRequestVolumeDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.volume_type is not None: + output["volume_type"] = str(request.volume_type) + + return output + + +def marshal_RestoreSnapshotRequest( + request: RestoreSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.instance_name is not None: + output["instance_name"] = request.instance_name + + if request.node_type is not None: + output["node_type"] = request.node_type + + if request.node_number is not None: + output["node_number"] = request.node_number + + if request.volume is not None: + output["volume"] = marshal_RestoreSnapshotRequestVolumeDetails( + request.volume, defaults + ) + + return output + + +def marshal_UserRole( + request: UserRole, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("database", request.database), + OneOfPossibility("any_database", request.any_database), + ] + ), + ) + + if request.role is not None: + output["role"] = str(request.role) + + return output + + +def marshal_SetUserRoleRequest( + request: SetUserRoleRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.user_name is not None: + output["user_name"] = request.user_name + + if request.roles is not None: + output["roles"] = [marshal_UserRole(item, defaults) for item in request.roles] + + return output + + +def marshal_UpdateInstanceRequest( + request: UpdateInstanceRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_UpdateSnapshotRequest( + request: UpdateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.expires_at is not None: + output["expires_at"] = request.expires_at.isoformat() + + return output + + +def marshal_UpdateUserRequest( + request: UpdateUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_UpgradeInstanceRequest( + request: UpgradeInstanceRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("volume_size", request.volume_size), + ] + ), + ) + + return output diff --git a/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py b/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py new file mode 100644 index 00000000..200da384 --- /dev/null +++ b/scaleway-async/scaleway_async/mongodb/v1alpha1/types.py @@ -0,0 +1,1091 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class InstanceStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + PROVISIONING = "provisioning" + CONFIGURING = "configuring" + DELETING = "deleting" + ERROR = "error" + INITIALIZING = "initializing" + LOCKED = "locked" + SNAPSHOTTING = "snapshotting" + + def __str__(self) -> str: + return str(self.value) + + +class ListInstancesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListSnapshotsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + EXPIRES_AT_ASC = "expires_at_asc" + EXPIRES_AT_DESC = "expires_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListUsersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class NodeTypeStock(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STOCK = "unknown_stock" + LOW_STOCK = "low_stock" + OUT_OF_STOCK = "out_of_stock" + AVAILABLE = "available" + + def __str__(self) -> str: + return str(self.value) + + +class SettingPropertyType(str, Enum, metaclass=StrEnumMeta): + BOOLEAN = "boolean" + INT = "int" + STRING = "string" + FLOAT = "float" + + def __str__(self) -> str: + return str(self.value) + + +class SnapshotStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + READY = "ready" + RESTORING = "restoring" + DELETING = "deleting" + ERROR = "error" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class UserRoleRole(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ROLE = "unknown_role" + READ = "read" + READ_WRITE = "read_write" + DB_ADMIN = "db_admin" + SYNC = "sync" + + def __str__(self) -> str: + return str(self.value) + + +class VolumeType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + SBS_5K = "sbs_5k" + SBS_15K = "sbs_15k" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class EndpointPrivateNetworkDetails: + """ + Private Network details. + """ + + private_network_id: str + """ + UUID of the Private Network. + """ + + +@dataclass +class EndpointPublicDetails: + pass + + +@dataclass +class EndpointSpecPrivateNetworkDetails: + private_network_id: str + """ + UUID of the Private Network. + """ + + +@dataclass +class EndpointSpecPublicDetails: + pass + + +@dataclass +class Endpoint: + id: str + """ + UUID of the endpoint. + """ + + ips: List[str] + """ + List of IPv4 addresses of the endpoint. + """ + + dns_records: List[str] + """ + List of DNS records of the endpoint. + """ + + port: int + """ + TCP port of the endpoint. + """ + + private_network: Optional[EndpointPrivateNetworkDetails] + + public: Optional[EndpointPublicDetails] + + +@dataclass +class InstanceSetting: + name: str + """ + Name of the settings. + """ + + value: str + """ + Value of the settings. + """ + + +@dataclass +class Volume: + type_: VolumeType + """ + Type of volume where data is stored. + """ + + size: int + """ + Volume size. + """ + + +@dataclass +class NodeTypeVolumeType: + type_: VolumeType + """ + Volume Type. + """ + + description: str + """ + The description of the volume. + """ + + min_size: int + """ + Minimum size required for the volume. + """ + + max_size: int + """ + Maximum size required for the volume. + """ + + chunk_size: int + """ + Minimum increment level for a Block Storage volume size. + """ + + +@dataclass +class SnapshotVolumeType: + type_: VolumeType + + +@dataclass +class UserRole: + role: UserRoleRole + + database: Optional[str] + + any_database: Optional[bool] + + +@dataclass +class Setting: + name: str + """ + Setting name from the database engine. + """ + + default_value: str + """ + Value set when not specified. + """ + + hot_configurable: bool + """ + Setting can be applied without restarting. + """ + + description: str + """ + Setting description. + """ + + property_type: SettingPropertyType + """ + Setting type. + """ + + unit: Optional[str] + """ + Setting base unit. + """ + + string_constraint: Optional[str] + """ + Validation regex for string type settings. + """ + + int_min: Optional[int] + """ + Minimum value for int types. + """ + + int_max: Optional[int] + """ + Maximum value for int types. + """ + + float_min: Optional[float] + """ + Minimum value for float types. + """ + + float_max: Optional[float] + """ + Maximum value for float types. + """ + + +@dataclass +class EndpointSpec: + public: Optional[EndpointSpecPublicDetails] + + private_network: Optional[EndpointSpecPrivateNetworkDetails] + + +@dataclass +class CreateInstanceRequestVolumeDetails: + volume_size: int + """ + Volume size. + """ + + volume_type: VolumeType + """ + Type of volume where data is stored. + """ + + +@dataclass +class Instance: + id: str + """ + UUID of the Database Instance. + """ + + name: str + """ + Name of the Database Instance. + """ + + project_id: str + """ + Project ID the Database Instance belongs to. + """ + + status: InstanceStatus + """ + Status of the Database Instance. + """ + + version: str + """ + MongoDB® engine version of the Database Instance. + """ + + tags: List[str] + """ + List of tags applied to the Database Instance. + """ + + settings: List[InstanceSetting] + """ + Advanced settings of the Database Instance. + """ + + node_number: int + """ + Number of node in the Database Instance. + """ + + node_type: str + """ + Node type of the Database Instance. + """ + + endpoints: List[Endpoint] + """ + List of Database Instance endpoints. + """ + + region: ScwRegion + """ + Region the Database Instance is in. + """ + + volume: Optional[Volume] + """ + Volumes of the Database Instance. + """ + + created_at: Optional[datetime] + """ + Creation date (must follow the ISO 8601 format). + """ + + +@dataclass +class NodeType: + name: str + """ + Node type name identifier. + """ + + stock_status: NodeTypeStock + """ + Current stock status for the node type. + """ + + description: str + """ + Current specs of the offer. + """ + + vcpus: int + """ + Number of virtual CPUs. + """ + + memory: int + """ + Quantity of RAM. + """ + + available_volume_types: List[NodeTypeVolumeType] + """ + Available storage options for the node type. + """ + + disabled: bool + """ + The node type is currently disabled. + """ + + beta: bool + """ + The node type is currently in beta. + """ + + instance_range: str + """ + Instance range associated with the node type offer. + """ + + +@dataclass +class Snapshot: + id: str + """ + UUID of the snapshot. + """ + + instance_id: str + """ + UUID of the Database Instance. + """ + + name: str + """ + Name of the snapshot. + """ + + status: SnapshotStatus + """ + Status of the snapshot. + """ + + size: int + """ + Size of the snapshot. + """ + + instance_name: str + """ + Name of the Database Instance of the snapshot. + """ + + node_type: str + """ + Source node type. + """ + + region: ScwRegion + """ + Region of the snapshot. + """ + + expires_at: Optional[datetime] + """ + Expiration date (must follow the ISO 8601 format). + """ + + created_at: Optional[datetime] + """ + Creation date (must follow the ISO 8601 format). + """ + + updated_at: Optional[datetime] + """ + Updated date (must follow the ISO 8601 format). + """ + + volume_type: Optional[SnapshotVolumeType] + """ + Type of volume where data is stored - sbs_5k or sbs_15k. + """ + + +@dataclass +class User: + name: str + """ + Name of the user (Length must be between 1 and 63 characters. First character must be an alphabet character (a-zA-Z). Only a-zA-Z0-9_$- characters are accepted). + """ + + roles: List[UserRole] + """ + List of roles assigned to the user, along with the corresponding database where each role is granted. + """ + + +@dataclass +class Version: + version: str + """ + MongoDB® engine version. + """ + + available_settings: List[Setting] + """ + Instance settings available to be updated. + """ + + end_of_life_at: Optional[datetime] + """ + Date of End of Life. + """ + + +@dataclass +class RestoreSnapshotRequestVolumeDetails: + volume_type: VolumeType + """ + Type of volume where data is stored. + """ + + +@dataclass +class CreateEndpointRequest: + instance_id: str + """ + UUID of the Database Instance. + """ + + endpoint: EndpointSpec + """ + EndpointSpec used to expose your Database Instance. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateInstanceRequest: + version: str + """ + Version of the MongoDB® engine. + """ + + node_number: int + """ + Number of node to use for the Database Instance. + """ + + node_type: str + """ + Type of node to use for the Database Instance. + """ + + user_name: str + """ + Username created when the Database Instance is created. + """ + + password: str + """ + Password of the initial user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + The Project ID on which the Database Instance will be created. + """ + + name: Optional[str] + """ + Name of the Database Instance. + """ + + tags: Optional[List[str]] + """ + Tags to apply to the Database Instance. + """ + + volume: Optional[CreateInstanceRequestVolumeDetails] + """ + Instance volume information. + """ + + endpoints: Optional[List[EndpointSpec]] + """ + One or multiple EndpointSpec used to expose your Database Instance. + """ + + +@dataclass +class CreateSnapshotRequest: + instance_id: str + """ + UUID of the Database Instance to snapshot. + """ + + name: str + """ + Name of the snapshot. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + expires_at: Optional[datetime] + """ + Expiration date of the snapshot (must follow the ISO 8601 format). + """ + + +@dataclass +class CreateUserRequest: + instance_id: str + """ + UUID of the Database Instance the user belongs to. + """ + + name: str + """ + Name of the database user. + """ + + password: str + """ + Password of the database user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteEndpointRequest: + endpoint_id: str + """ + UUID of the Endpoint to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteInstanceRequest: + instance_id: str + """ + UUID of the Database Instance to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteUserRequest: + instance_id: str + """ + UUID of the Database Instance the user belongs to. + """ + + name: str + """ + Name of the database user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetInstanceCertificateRequest: + instance_id: str + """ + UUID of the Database Instance. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetInstanceRequest: + instance_id: str + """ + UUID of the Database Instance. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListInstancesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + tags: Optional[List[str]] + """ + List Database Instances that have a given tag. + """ + + name: Optional[str] + """ + Lists Database Instances that match a name pattern. + """ + + order_by: Optional[ListInstancesRequestOrderBy] + """ + Criteria to use when ordering Database Instance listings. + """ + + organization_id: Optional[str] + """ + Organization ID of the Database Instance. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListInstancesResponse: + instances: List[Instance] + """ + List of all Database Instances available in an Organization or Project. + """ + + total_count: int + """ + Total count of Database Instances available in an Organization or Project. + """ + + +@dataclass +class ListNodeTypesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + include_disabled_types: Optional[bool] + """ + Defines whether or not to include disabled types. + """ + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListNodeTypesResponse: + node_types: List[NodeType] + """ + Types of the node. + """ + + total_count: int + """ + Total count of node-types available. + """ + + +@dataclass +class ListSnapshotsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + instance_id: Optional[str] + """ + Instance ID the snapshots belongs to. + """ + + name: Optional[str] + """ + Lists database snapshots that match a name pattern. + """ + + order_by: Optional[ListSnapshotsRequestOrderBy] + """ + Criteria to use when ordering snapshot listings. + """ + + organization_id: Optional[str] + """ + Organization ID the snapshots belongs to. + """ + + project_id: Optional[str] + """ + Project ID to list the snapshots of. + """ + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListSnapshotsResponse: + snapshots: List[Snapshot] + """ + List of all database snapshots available in an Organization or Project. + """ + + total_count: int + """ + Total count of database snapshots available in a Organization or Project. + """ + + +@dataclass +class ListUsersRequest: + instance_id: str + """ + UUID of the Database Instance. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the user. + """ + + order_by: Optional[ListUsersRequestOrderBy] + """ + Criteria to use when requesting user listing. + """ + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListUsersResponse: + users: List[User] + """ + List of users in a Database Instance. + """ + + total_count: int + """ + Total count of users present on a Database Instance. + """ + + +@dataclass +class ListVersionsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + version: Optional[str] + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListVersionsResponse: + versions: List[Version] + """ + Available MongoDB® engine version. + """ + + total_count: int + """ + Total count of MongoDB® engine version available. + """ + + +@dataclass +class RestoreSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + instance_name: str + """ + Name of the new Database Instance. + """ + + node_type: str + """ + Node type to use for the new Database Instance. + """ + + node_number: int + """ + Number of nodes to use for the new Database Instance. + """ + + volume: RestoreSnapshotRequestVolumeDetails + """ + Instance volume information. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SetUserRoleRequest: + instance_id: str + """ + UUID of the Database Instance the user belongs to. + """ + + user_name: str + """ + Name of the database user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + roles: Optional[List[UserRole]] + """ + List of roles assigned to the user, along with the corresponding database where each role is granted. + """ + + +@dataclass +class UpdateInstanceRequest: + instance_id: str + """ + UUID of the Database Instance to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the Database Instance. + """ + + tags: Optional[List[str]] + """ + Tags of a Database Instance. + """ + + +@dataclass +class UpdateSnapshotRequest: + snapshot_id: str + """ + UUID of the Snapshot. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the snapshot. + """ + + expires_at: Optional[datetime] + """ + Expiration date of the snapshot (must follow the ISO 8601 format). + """ + + +@dataclass +class UpdateUserRequest: + instance_id: str + """ + UUID of the Database Instance the user belongs to. + """ + + name: str + """ + Name of the database user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + password: Optional[str] + """ + Password of the database user. + """ + + +@dataclass +class UpgradeInstanceRequest: + instance_id: str + """ + UUID of the Database Instance you want to upgrade. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + volume_size: Optional[int] diff --git a/scaleway-async/scaleway_async/product_catalog/__init__.py b/scaleway-async/scaleway_async/product_catalog/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway-async/scaleway_async/product_catalog/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway-async/scaleway_async/product_catalog/v2alpha1/__init__.py b/scaleway-async/scaleway_async/product_catalog/v2alpha1/__init__.py new file mode 100644 index 00000000..323b1122 --- /dev/null +++ b/scaleway-async/scaleway_async/product_catalog/v2alpha1/__init__.py @@ -0,0 +1,53 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import PublicCatalogProductPropertiesHardwareCPUArch +from .types import PublicCatalogProductStatus +from .types import PublicCatalogProductUnitOfMeasureCountableUnit +from .types import PublicCatalogProductPropertiesHardwareCPUPhysical +from .types import PublicCatalogProductPropertiesHardwareCPUVirtual +from .types import PublicCatalogProductPropertiesHardwareCPU +from .types import PublicCatalogProductPropertiesHardwareGPU +from .types import PublicCatalogProductPropertiesHardwareNetwork +from .types import PublicCatalogProductPropertiesHardwareRAM +from .types import PublicCatalogProductPropertiesHardwareStorage +from .types import PublicCatalogProductPropertiesAppleSilicon +from .types import PublicCatalogProductPropertiesDedibox +from .types import PublicCatalogProductPropertiesElasticMetal +from .types import PublicCatalogProductPropertiesHardware +from .types import PublicCatalogProductPropertiesInstance +from .types import PublicCatalogProductEnvironmentalImpactEstimation +from .types import PublicCatalogProductLocality +from .types import PublicCatalogProductPrice +from .types import PublicCatalogProductProperties +from .types import PublicCatalogProductUnitOfMeasure +from .types import PublicCatalogProduct +from .types import ListPublicCatalogProductsResponse +from .types import PublicCatalogApiListPublicCatalogProductsRequest +from .api import ProductCatalogV2Alpha1PublicCatalogAPI + +__all__ = [ + "PublicCatalogProductPropertiesHardwareCPUArch", + "PublicCatalogProductStatus", + "PublicCatalogProductUnitOfMeasureCountableUnit", + "PublicCatalogProductPropertiesHardwareCPUPhysical", + "PublicCatalogProductPropertiesHardwareCPUVirtual", + "PublicCatalogProductPropertiesHardwareCPU", + "PublicCatalogProductPropertiesHardwareGPU", + "PublicCatalogProductPropertiesHardwareNetwork", + "PublicCatalogProductPropertiesHardwareRAM", + "PublicCatalogProductPropertiesHardwareStorage", + "PublicCatalogProductPropertiesAppleSilicon", + "PublicCatalogProductPropertiesDedibox", + "PublicCatalogProductPropertiesElasticMetal", + "PublicCatalogProductPropertiesHardware", + "PublicCatalogProductPropertiesInstance", + "PublicCatalogProductEnvironmentalImpactEstimation", + "PublicCatalogProductLocality", + "PublicCatalogProductPrice", + "PublicCatalogProductProperties", + "PublicCatalogProductUnitOfMeasure", + "PublicCatalogProduct", + "ListPublicCatalogProductsResponse", + "PublicCatalogApiListPublicCatalogProductsRequest", + "ProductCatalogV2Alpha1PublicCatalogAPI", +] diff --git a/scaleway-async/scaleway_async/product_catalog/v2alpha1/api.py b/scaleway-async/scaleway_async/product_catalog/v2alpha1/api.py new file mode 100644 index 00000000..64c2db73 --- /dev/null +++ b/scaleway-async/scaleway_async/product_catalog/v2alpha1/api.py @@ -0,0 +1,80 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.utils import ( + fetch_all_pages_async, +) +from .types import ( + ListPublicCatalogProductsResponse, + PublicCatalogProduct, +) +from .marshalling import ( + unmarshal_ListPublicCatalogProductsResponse, +) + + +class ProductCatalogV2Alpha1PublicCatalogAPI(API): + """ """ + + async def list_public_catalog_products( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListPublicCatalogProductsResponse: + """ + List all available products. + List all available products in the Scaleway catalog. Returns a complete list of products with their corresponding description, locations, prices and properties. You can define the `page` number and `page_size` for your query in the request. + :param page: Number of the page. Value must be greater or equal to 1. + :param page_size: The number of products per page. Value must be greater or equal to 1. + :return: :class:`ListPublicCatalogProductsResponse ` + + Usage: + :: + + result = await api.list_public_catalog_products() + """ + + res = self._request( + "GET", + "/product-catalog/v2alpha1/public-catalog/products", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPublicCatalogProductsResponse(res.json()) + + async def list_public_catalog_products_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[PublicCatalogProduct]: + """ + List all available products. + List all available products in the Scaleway catalog. Returns a complete list of products with their corresponding description, locations, prices and properties. You can define the `page` number and `page_size` for your query in the request. + :param page: Number of the page. Value must be greater or equal to 1. + :param page_size: The number of products per page. Value must be greater or equal to 1. + :return: :class:`List[PublicCatalogProduct] ` + + Usage: + :: + + result = await api.list_public_catalog_products_all() + """ + + return await fetch_all_pages_async( + type=ListPublicCatalogProductsResponse, + key="products", + fetcher=self.list_public_catalog_products, + args={ + "page": page, + "page_size": page_size, + }, + ) diff --git a/scaleway-async/scaleway_async/product_catalog/v2alpha1/marshalling.py b/scaleway-async/scaleway_async/product_catalog/v2alpha1/marshalling.py new file mode 100644 index 00000000..e1f552a6 --- /dev/null +++ b/scaleway-async/scaleway_async/product_catalog/v2alpha1/marshalling.py @@ -0,0 +1,589 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.bridge import ( + unmarshal_Money, +) +from .types import ( + PublicCatalogProductPropertiesHardwareCPUPhysical, + PublicCatalogProductPropertiesHardwareCPUVirtual, + PublicCatalogProductPropertiesHardwareCPU, + PublicCatalogProductPropertiesHardwareGPU, + PublicCatalogProductPropertiesHardwareNetwork, + PublicCatalogProductPropertiesHardwareRAM, + PublicCatalogProductPropertiesHardwareStorage, + PublicCatalogProductPropertiesAppleSilicon, + PublicCatalogProductPropertiesDedibox, + PublicCatalogProductPropertiesElasticMetal, + PublicCatalogProductPropertiesHardware, + PublicCatalogProductPropertiesInstance, + PublicCatalogProductEnvironmentalImpactEstimation, + PublicCatalogProductLocality, + PublicCatalogProductPrice, + PublicCatalogProductProperties, + PublicCatalogProductUnitOfMeasure, + PublicCatalogProduct, + ListPublicCatalogProductsResponse, +) + + +def unmarshal_PublicCatalogProductPropertiesHardwareCPUPhysical( + data: Any, +) -> PublicCatalogProductPropertiesHardwareCPUPhysical: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareCPUPhysical' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sockets", None) + if field is not None: + args["sockets"] = field + + field = data.get("cores_per_socket", None) + if field is not None: + args["cores_per_socket"] = field + + field = data.get("threads_per_core", None) + if field is not None: + args["threads_per_core"] = field + + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + + field = data.get("benchmark", None) + if field is not None: + args["benchmark"] = field + + return PublicCatalogProductPropertiesHardwareCPUPhysical(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareCPUVirtual( + data: Any, +) -> PublicCatalogProductPropertiesHardwareCPUVirtual: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareCPUVirtual' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("count", None) + if field is not None: + args["count"] = field + + return PublicCatalogProductPropertiesHardwareCPUVirtual(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareCPU( + data: Any, +) -> PublicCatalogProductPropertiesHardwareCPU: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareCPU' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("arch", None) + if field is not None: + args["arch"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("threads", None) + if field is not None: + args["threads"] = field + + field = data.get("virtual", None) + if field is not None: + args["virtual"] = unmarshal_PublicCatalogProductPropertiesHardwareCPUVirtual( + field + ) + else: + args["virtual"] = None + + field = data.get("physical", None) + if field is not None: + args["physical"] = unmarshal_PublicCatalogProductPropertiesHardwareCPUPhysical( + field + ) + else: + args["physical"] = None + + return PublicCatalogProductPropertiesHardwareCPU(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareGPU( + data: Any, +) -> PublicCatalogProductPropertiesHardwareGPU: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareGPU' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("count", None) + if field is not None: + args["count"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return PublicCatalogProductPropertiesHardwareGPU(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareNetwork( + data: Any, +) -> PublicCatalogProductPropertiesHardwareNetwork: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareNetwork' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("internal_bandwidth", None) + if field is not None: + args["internal_bandwidth"] = field + + field = data.get("public_bandwidth", None) + if field is not None: + args["public_bandwidth"] = field + + field = data.get("max_public_bandwidth", None) + if field is not None: + args["max_public_bandwidth"] = field + + return PublicCatalogProductPropertiesHardwareNetwork(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareRAM( + data: Any, +) -> PublicCatalogProductPropertiesHardwareRAM: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareRAM' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return PublicCatalogProductPropertiesHardwareRAM(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareStorage( + data: Any, +) -> PublicCatalogProductPropertiesHardwareStorage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareStorage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("total", None) + if field is not None: + args["total"] = field + + return PublicCatalogProductPropertiesHardwareStorage(**args) + + +def unmarshal_PublicCatalogProductPropertiesAppleSilicon( + data: Any, +) -> PublicCatalogProductPropertiesAppleSilicon: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesAppleSilicon' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("range", None) + if field is not None: + args["range"] = field + + return PublicCatalogProductPropertiesAppleSilicon(**args) + + +def unmarshal_PublicCatalogProductPropertiesDedibox( + data: Any, +) -> PublicCatalogProductPropertiesDedibox: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesDedibox' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("range", None) + if field is not None: + args["range"] = field + + return PublicCatalogProductPropertiesDedibox(**args) + + +def unmarshal_PublicCatalogProductPropertiesElasticMetal( + data: Any, +) -> PublicCatalogProductPropertiesElasticMetal: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesElasticMetal' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("range", None) + if field is not None: + args["range"] = field + + return PublicCatalogProductPropertiesElasticMetal(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardware( + data: Any, +) -> PublicCatalogProductPropertiesHardware: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardware' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("cpu", None) + if field is not None: + args["cpu"] = unmarshal_PublicCatalogProductPropertiesHardwareCPU(field) + else: + args["cpu"] = None + + field = data.get("ram", None) + if field is not None: + args["ram"] = unmarshal_PublicCatalogProductPropertiesHardwareRAM(field) + else: + args["ram"] = None + + field = data.get("storage", None) + if field is not None: + args["storage"] = unmarshal_PublicCatalogProductPropertiesHardwareStorage(field) + else: + args["storage"] = None + + field = data.get("network", None) + if field is not None: + args["network"] = unmarshal_PublicCatalogProductPropertiesHardwareNetwork(field) + else: + args["network"] = None + + field = data.get("gpu", None) + if field is not None: + args["gpu"] = unmarshal_PublicCatalogProductPropertiesHardwareGPU(field) + else: + args["gpu"] = None + + return PublicCatalogProductPropertiesHardware(**args) + + +def unmarshal_PublicCatalogProductPropertiesInstance( + data: Any, +) -> PublicCatalogProductPropertiesInstance: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesInstance' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("range", None) + if field is not None: + args["range"] = field + + field = data.get("offer_id", None) + if field is not None: + args["offer_id"] = field + + field = data.get("recommended_replacement_offer_ids", None) + if field is not None: + args["recommended_replacement_offer_ids"] = field + + return PublicCatalogProductPropertiesInstance(**args) + + +def unmarshal_PublicCatalogProductEnvironmentalImpactEstimation( + data: Any, +) -> PublicCatalogProductEnvironmentalImpactEstimation: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductEnvironmentalImpactEstimation' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("kg_co2_equivalent", None) + if field is not None: + args["kg_co2_equivalent"] = field + else: + args["kg_co2_equivalent"] = None + + field = data.get("m3_water_usage", None) + if field is not None: + args["m3_water_usage"] = field + else: + args["m3_water_usage"] = None + + return PublicCatalogProductEnvironmentalImpactEstimation(**args) + + +def unmarshal_PublicCatalogProductLocality(data: Any) -> PublicCatalogProductLocality: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductLocality' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("global", None) + if field is not None: + args["global_"] = field + else: + args["global_"] = None + + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("datacenter", None) + if field is not None: + args["datacenter"] = field + else: + args["datacenter"] = None + + return PublicCatalogProductLocality(**args) + + +def unmarshal_PublicCatalogProductPrice(data: Any) -> PublicCatalogProductPrice: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPrice' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("retail_price", None) + if field is not None: + args["retail_price"] = unmarshal_Money(field) + else: + args["retail_price"] = None + + return PublicCatalogProductPrice(**args) + + +def unmarshal_PublicCatalogProductProperties( + data: Any, +) -> PublicCatalogProductProperties: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductProperties' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("hardware", None) + if field is not None: + args["hardware"] = unmarshal_PublicCatalogProductPropertiesHardware(field) + else: + args["hardware"] = None + + field = data.get("dedibox", None) + if field is not None: + args["dedibox"] = unmarshal_PublicCatalogProductPropertiesDedibox(field) + else: + args["dedibox"] = None + + field = data.get("elastic_metal", None) + if field is not None: + args["elastic_metal"] = unmarshal_PublicCatalogProductPropertiesElasticMetal( + field + ) + else: + args["elastic_metal"] = None + + field = data.get("apple_silicon", None) + if field is not None: + args["apple_silicon"] = unmarshal_PublicCatalogProductPropertiesAppleSilicon( + field + ) + else: + args["apple_silicon"] = None + + field = data.get("instance", None) + if field is not None: + args["instance"] = unmarshal_PublicCatalogProductPropertiesInstance(field) + else: + args["instance"] = None + + return PublicCatalogProductProperties(**args) + + +def unmarshal_PublicCatalogProductUnitOfMeasure( + data: Any, +) -> PublicCatalogProductUnitOfMeasure: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductUnitOfMeasure' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("unit", None) + if field is not None: + args["unit"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + return PublicCatalogProductUnitOfMeasure(**args) + + +def unmarshal_PublicCatalogProduct(data: Any) -> PublicCatalogProduct: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProduct' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sku", None) + if field is not None: + args["sku"] = field + + field = data.get("service_category", None) + if field is not None: + args["service_category"] = field + + field = data.get("product", None) + if field is not None: + args["product"] = field + + field = data.get("variant", None) + if field is not None: + args["variant"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("locality", None) + if field is not None: + args["locality"] = unmarshal_PublicCatalogProductLocality(field) + else: + args["locality"] = None + + field = data.get("price", None) + if field is not None: + args["price"] = unmarshal_PublicCatalogProductPrice(field) + else: + args["price"] = None + + field = data.get("properties", None) + if field is not None: + args["properties"] = unmarshal_PublicCatalogProductProperties(field) + else: + args["properties"] = None + + field = data.get("environmental_impact_estimation", None) + if field is not None: + args["environmental_impact_estimation"] = ( + unmarshal_PublicCatalogProductEnvironmentalImpactEstimation(field) + ) + else: + args["environmental_impact_estimation"] = None + + field = data.get("unit_of_measure", None) + if field is not None: + args["unit_of_measure"] = unmarshal_PublicCatalogProductUnitOfMeasure(field) + else: + args["unit_of_measure"] = None + + field = data.get("end_of_life_at", None) + if field is not None: + args["end_of_life_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["end_of_life_at"] = None + + return PublicCatalogProduct(**args) + + +def unmarshal_ListPublicCatalogProductsResponse( + data: Any, +) -> ListPublicCatalogProductsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPublicCatalogProductsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("products", None) + if field is not None: + args["products"] = ( + [unmarshal_PublicCatalogProduct(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPublicCatalogProductsResponse(**args) diff --git a/scaleway-async/scaleway_async/product_catalog/v2alpha1/types.py b/scaleway-async/scaleway_async/product_catalog/v2alpha1/types.py new file mode 100644 index 00000000..0e1043d8 --- /dev/null +++ b/scaleway-async/scaleway_async/product_catalog/v2alpha1/types.py @@ -0,0 +1,417 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Money, + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class PublicCatalogProductPropertiesHardwareCPUArch(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ARCH = "unknown_arch" + X64 = "x64" + ARM64 = "arm64" + RISCV = "riscv" + APPLE_SILICON = "apple_silicon" + + def __str__(self) -> str: + return str(self.value) + + +class PublicCatalogProductStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + PUBLIC_BETA = "public_beta" + PREVIEW = "preview" + GENERAL_AVAILABILITY = "general_availability" + END_OF_DEPLOYMENT = "end_of_deployment" + END_OF_SUPPORT = "end_of_support" + + def __str__(self) -> str: + return str(self.value) + + +class PublicCatalogProductUnitOfMeasureCountableUnit(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_COUNTABLE_UNIT = "unknown_countable_unit" + CHUNK = "chunk" + CORE = "core" + CURRENCY = "currency" + DEVICE = "device" + DOMAIN = "domain" + EMAIL = "email" + GB_S = "gb_s" + GIGABYTE = "gigabyte" + HOUR = "hour" + IOPS_GIGABYTE = "iops_gigabyte" + IP = "ip" + MONTH = "month" + NODE = "node" + PLAN = "plan" + QUERY = "query" + REQUEST = "request" + SESSION = "session" + VCPU_S = "vcpu_s" + VERSION = "version" + YEAR = "year" + KEY = "key" + TOKEN = "token" + MINUTE = "minute" + SETUP = "setup" + DAY = "day" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class PublicCatalogProductPropertiesHardwareCPUPhysical: + sockets: int + """ + The number of sockets of the CPU. + """ + + cores_per_socket: int + """ + The number of cores per socket. + """ + + threads_per_core: int + """ + The number of threads per core. + """ + + frequency: int + """ + The frequency of the CPU in Hertz. + """ + + benchmark: int + """ + The benchmark score of the CPU. + """ + + +@dataclass +class PublicCatalogProductPropertiesHardwareCPUVirtual: + count: int + """ + The number of vCPUs. + """ + + +@dataclass +class PublicCatalogProductPropertiesHardwareCPU: + description: str + """ + A human readable description of the CPU. + """ + + arch: PublicCatalogProductPropertiesHardwareCPUArch + """ + The architecture of the CPU. + """ + + type_: str + """ + The type of the CPU. + """ + + threads: int + """ + The total number of threads. + """ + + virtual: Optional[PublicCatalogProductPropertiesHardwareCPUVirtual] + + physical: Optional[PublicCatalogProductPropertiesHardwareCPUPhysical] + + +@dataclass +class PublicCatalogProductPropertiesHardwareGPU: + description: str + """ + A human-readable description of the GPU. + """ + + count: int + """ + The number of GPUs. + """ + + type_: str + """ + The type of the GPU. + """ + + +@dataclass +class PublicCatalogProductPropertiesHardwareNetwork: + description: str + """ + A human-readable description of the network. + """ + + internal_bandwidth: int + """ + The internal bandwidth in bits per second. + """ + + public_bandwidth: int + """ + The default public bandwidth in bits per second. + """ + + max_public_bandwidth: int + """ + The maximum public bandwidth in bits per second (may require subscription to options). + """ + + +@dataclass +class PublicCatalogProductPropertiesHardwareRAM: + description: str + """ + A human-readable description of the RAM. + """ + + size: int + """ + The size of the RAM in bytes. + """ + + type_: str + """ + The type of the RAM. + """ + + +@dataclass +class PublicCatalogProductPropertiesHardwareStorage: + description: str + """ + A human-readable description of the storage. + """ + + total: int + """ + The total size of the storage in bytes. + """ + + +@dataclass +class PublicCatalogProductPropertiesAppleSilicon: + range: str + """ + The range of the Apple Silicon server. + """ + + +@dataclass +class PublicCatalogProductPropertiesDedibox: + range: str + """ + The range of the Dedibox server. + """ + + +@dataclass +class PublicCatalogProductPropertiesElasticMetal: + range: str + """ + The range of the Elastic Metal server. + """ + + +@dataclass +class PublicCatalogProductPropertiesHardware: + cpu: Optional[PublicCatalogProductPropertiesHardwareCPU] + """ + The CPU hardware properties. + """ + + ram: Optional[PublicCatalogProductPropertiesHardwareRAM] + """ + The RAM hardware properties. + """ + + storage: Optional[PublicCatalogProductPropertiesHardwareStorage] + """ + The storage hardware properties. + """ + + network: Optional[PublicCatalogProductPropertiesHardwareNetwork] + """ + The network hardware properties. + """ + + gpu: Optional[PublicCatalogProductPropertiesHardwareGPU] + """ + The GPU hardware properties. + """ + + +@dataclass +class PublicCatalogProductPropertiesInstance: + range: str + """ + The range of the Instance server. + """ + + offer_id: str + """ + The offer ID of the Instance server. + """ + + recommended_replacement_offer_ids: List[str] + """ + The recommended replacement offer IDs of the Instance server. + """ + + +@dataclass +class PublicCatalogProductEnvironmentalImpactEstimation: + kg_co2_equivalent: Optional[float] + + m3_water_usage: Optional[float] + + +@dataclass +class PublicCatalogProductLocality: + global_: Optional[bool] + + region: Optional[ScwRegion] + + zone: Optional[ScwZone] + + datacenter: Optional[str] + + +@dataclass +class PublicCatalogProductPrice: + retail_price: Optional[Money] + """ + The retail price of the product. + """ + + +@dataclass +class PublicCatalogProductProperties: + hardware: Optional[PublicCatalogProductPropertiesHardware] + """ + The hardware properties of the product (if supported). + """ + + dedibox: Optional[PublicCatalogProductPropertiesDedibox] + + elastic_metal: Optional[PublicCatalogProductPropertiesElasticMetal] + + apple_silicon: Optional[PublicCatalogProductPropertiesAppleSilicon] + + instance: Optional[PublicCatalogProductPropertiesInstance] + + +@dataclass +class PublicCatalogProductUnitOfMeasure: + unit: PublicCatalogProductUnitOfMeasureCountableUnit + + size: int + + +@dataclass +class PublicCatalogProduct: + sku: str + """ + The unique identifier of the product. + """ + + service_category: str + """ + The category of the product. + """ + + product: str + """ + The product name. + """ + + variant: str + """ + The product variant. + """ + + description: str + """ + The product description. + """ + + status: PublicCatalogProductStatus + """ + The status of the product. + """ + + locality: Optional[PublicCatalogProductLocality] + """ + The locality of the product. + """ + + price: Optional[PublicCatalogProductPrice] + """ + The price of the product. + """ + + properties: Optional[PublicCatalogProductProperties] + """ + The properties of the product. + """ + + environmental_impact_estimation: Optional[ + PublicCatalogProductEnvironmentalImpactEstimation + ] + """ + The environmental impact estimation of the product. + """ + + unit_of_measure: Optional[PublicCatalogProductUnitOfMeasure] + """ + The unit of measure of the product. + """ + + end_of_life_at: Optional[datetime] + """ + The end of life date of the product. + """ + + +@dataclass +class ListPublicCatalogProductsResponse: + products: List[PublicCatalogProduct] + """ + The list of products. + """ + + total_count: int + """ + The total number of products in the catalog. + """ + + +@dataclass +class PublicCatalogApiListPublicCatalogProductsRequest: + page: Optional[int] + """ + Number of the page. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + The number of products per page. Value must be greater or equal to 1. + """ diff --git a/scaleway-async/scaleway_async/qaas/v1alpha1/__init__.py b/scaleway-async/scaleway_async/qaas/v1alpha1/__init__.py index db40cd45..eb2ff39c 100644 --- a/scaleway-async/scaleway_async/qaas/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/qaas/v1alpha1/__init__.py @@ -11,6 +11,7 @@ from .types import ListProcessesRequestOrderBy from .types import ListSessionACLsRequestOrderBy from .types import ListSessionsRequestOrderBy +from .types import PlatformAvailability from .types import PlatformTechnology from .types import PlatformType from .types import ProcessStatus @@ -19,6 +20,7 @@ from .types import SessionOriginType from .types import SessionStatus from .content import SESSION_TRANSIENT_STATUSES +from .types import PlatformHardware from .types import JobCircuit from .types import Application from .types import JobResult @@ -75,6 +77,7 @@ "ListProcessesRequestOrderBy", "ListSessionACLsRequestOrderBy", "ListSessionsRequestOrderBy", + "PlatformAvailability", "PlatformTechnology", "PlatformType", "ProcessStatus", @@ -83,6 +86,7 @@ "SessionOriginType", "SessionStatus", "SESSION_TRANSIENT_STATUSES", + "PlatformHardware", "JobCircuit", "Application", "JobResult", diff --git a/scaleway-async/scaleway_async/qaas/v1alpha1/api.py b/scaleway-async/scaleway_async/qaas/v1alpha1/api.py index d3ced01e..9e4d25ec 100644 --- a/scaleway-async/scaleway_async/qaas/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/qaas/v1alpha1/api.py @@ -521,6 +521,7 @@ async def list_platforms( self, *, provider_name: Optional[str] = None, + backend_name: Optional[str] = None, name: Optional[str] = None, platform_type: Optional[PlatformType] = None, platform_technology: Optional[PlatformTechnology] = None, @@ -532,6 +533,7 @@ async def list_platforms( List all available platforms. Retrieve information about all platforms. :param provider_name: List platforms with this provider name. + :param backend_name: List platforms with this backend name. :param name: List platforms with this name. :param platform_type: List platforms with this type. :param platform_technology: List platforms with this technology. @@ -550,6 +552,7 @@ async def list_platforms( "GET", "/qaas/v1alpha1/platforms", params={ + "backend_name": backend_name, "name": name, "order_by": order_by, "page": page, @@ -567,6 +570,7 @@ async def list_platforms_all( self, *, provider_name: Optional[str] = None, + backend_name: Optional[str] = None, name: Optional[str] = None, platform_type: Optional[PlatformType] = None, platform_technology: Optional[PlatformTechnology] = None, @@ -578,6 +582,7 @@ async def list_platforms_all( List all available platforms. Retrieve information about all platforms. :param provider_name: List platforms with this provider name. + :param backend_name: List platforms with this backend name. :param name: List platforms with this name. :param platform_type: List platforms with this type. :param platform_technology: List platforms with this technology. @@ -598,6 +603,7 @@ async def list_platforms_all( fetcher=self.list_platforms, args={ "provider_name": provider_name, + "backend_name": backend_name, "name": name, "platform_type": platform_type, "platform_technology": platform_technology, diff --git a/scaleway-async/scaleway_async/qaas/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/qaas/v1alpha1/marshalling.py index 7ea0ec5d..e8ad932f 100644 --- a/scaleway-async/scaleway_async/qaas/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/qaas/v1alpha1/marshalling.py @@ -5,6 +5,9 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) from scaleway_core.utils import ( OneOfPossibility, resolve_one_of, @@ -14,6 +17,7 @@ JobCircuit, Application, Job, + PlatformHardware, Platform, Process, Session, @@ -47,10 +51,14 @@ def unmarshal_JobCircuit(data: Any) -> JobCircuit: field = data.get("perceval_circuit", None) if field is not None: args["perceval_circuit"] = field + else: + args["perceval_circuit"] = None field = data.get("qiskit_circuit", None) if field is not None: args["qiskit_circuit"] = field + else: + args["qiskit_circuit"] = None return JobCircuit(**args) @@ -71,7 +79,7 @@ def unmarshal_Application(data: Any) -> Application: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -113,34 +121,83 @@ def unmarshal_Job(data: Any) -> Job: field = data.get("tags", None) if field is not None: args["tags"] = field + else: + args["tags"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("progress_message", None) if field is not None: args["progress_message"] = field + else: + args["progress_message"] = None field = data.get("job_duration", None) if field is not None: args["job_duration"] = field + else: + args["job_duration"] = None field = data.get("result_distribution", None) if field is not None: args["result_distribution"] = field + else: + args["result_distribution"] = None return Job(**args) +def unmarshal_PlatformHardware(data: Any) -> PlatformHardware: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlatformHardware' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("vcpus", None) + if field is not None: + args["vcpus"] = field + + field = data.get("gpus", None) + if field is not None: + args["gpus"] = field + + field = data.get("gpus_network", None) + if field is not None: + args["gpus_network"] = field + + field = data.get("ram", None) + if field is not None: + args["ram"] = field + + field = data.get("vram", None) + if field is not None: + args["vram"] = field + + return PlatformHardware(**args) + + def unmarshal_Platform(data: Any) -> Platform: if not isinstance(data, dict): raise TypeError( @@ -165,7 +222,11 @@ def unmarshal_Platform(data: Any) -> Platform: if field is not None: args["provider_name"] = field - field = data.get("type_", None) + field = data.get("backend_name", None) + if field is not None: + args["backend_name"] = field + + field = data.get("type", None) if field is not None: args["type_"] = field @@ -177,10 +238,46 @@ def unmarshal_Platform(data: Any) -> Platform: if field is not None: args["max_qubit_count"] = field + field = data.get("max_shot_count", None) + if field is not None: + args["max_shot_count"] = field + + field = data.get("max_circuit_count", None) + if field is not None: + args["max_circuit_count"] = field + + field = data.get("availability", None) + if field is not None: + args["availability"] = field + field = data.get("metadata", None) if field is not None: args["metadata"] = field + field = data.get("price_per_hour", None) + if field is not None: + args["price_per_hour"] = unmarshal_Money(field) + else: + args["price_per_hour"] = None + + field = data.get("price_per_shot", None) + if field is not None: + args["price_per_shot"] = unmarshal_Money(field) + else: + args["price_per_shot"] = None + + field = data.get("price_per_circuit", None) + if field is not None: + args["price_per_circuit"] = unmarshal_Money(field) + else: + args["price_per_circuit"] = None + + field = data.get("hardware", None) + if field is not None: + args["hardware"] = unmarshal_PlatformHardware(field) + else: + args["hardware"] = None + return Platform(**args) @@ -207,6 +304,8 @@ def unmarshal_Process(data: Any) -> Process: field = data.get("application_id", None) if field is not None: args["application_id"] = field + else: + args["application_id"] = None field = data.get("status", None) if field is not None: @@ -223,36 +322,52 @@ def unmarshal_Process(data: Any) -> Process: field = data.get("platform_id", None) if field is not None: args["platform_id"] = field + else: + args["platform_id"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("finished_at", None) if field is not None: args["finished_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["finished_at"] = None field = data.get("progress", None) if field is not None: args["progress"] = field + else: + args["progress"] = None field = data.get("progress_message", None) if field is not None: args["progress_message"] = field + else: + args["progress_message"] = None field = data.get("input", None) if field is not None: args["input"] = field + else: + args["input"] = None return Process(**args) @@ -284,6 +399,8 @@ def unmarshal_Session(data: Any) -> Session: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("finished_job_count", None) if field is not None: @@ -308,32 +425,52 @@ def unmarshal_Session(data: Any) -> Session: field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("terminated_at", None) if field is not None: args["terminated_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["terminated_at"] = None field = data.get("max_idle_duration", None) if field is not None: args["max_idle_duration"] = field + else: + args["max_idle_duration"] = None field = data.get("max_duration", None) if field is not None: args["max_duration"] = field + else: + args["max_duration"] = None field = data.get("tags", None) if field is not None: args["tags"] = field + else: + args["tags"] = None field = data.get("origin_id", None) if field is not None: args["origin_id"] = field + else: + args["origin_id"] = None + + field = data.get("progress_message", None) + if field is not None: + args["progress_message"] = field + else: + args["progress_message"] = None return Session(**args) @@ -374,14 +511,20 @@ def unmarshal_JobResult(data: Any) -> JobResult: field = data.get("result", None) if field is not None: args["result"] = field + else: + args["result"] = None field = data.get("url", None) if field is not None: args["url"] = field + else: + args["url"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return JobResult(**args) @@ -466,6 +609,8 @@ def unmarshal_ProcessResult(data: Any) -> ProcessResult: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return ProcessResult(**args) @@ -582,7 +727,7 @@ def marshal_CreateJobRequest( output["session_id"] = request.session_id if request.circuit is not None: - output["circuit"] = (marshal_JobCircuit(request.circuit, defaults),) + output["circuit"] = marshal_JobCircuit(request.circuit, defaults) if request.tags is not None: output["tags"] = request.tags diff --git a/scaleway-async/scaleway_async/qaas/v1alpha1/types.py b/scaleway-async/scaleway_async/qaas/v1alpha1/types.py index e97fdfe5..ccb14a04 100644 --- a/scaleway-async/scaleway_async/qaas/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/qaas/v1alpha1/types.py @@ -7,6 +7,9 @@ from enum import Enum from typing import List, Optional +from scaleway_core.bridge import ( + Money, +) from scaleway_core.utils import ( StrEnumMeta, ) @@ -76,6 +79,8 @@ class ListPlatformsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): TYPE_DESC = "type_desc" TECHNOLOGY_ASC = "technology_asc" TECHNOLOGY_DESC = "technology_desc" + BACKEND_NAME_ASC = "backend_name_asc" + BACKEND_NAME_DESC = "backend_name_desc" def __str__(self) -> str: return str(self.value) @@ -125,10 +130,23 @@ def __str__(self) -> str: return str(self.value) +class PlatformAvailability(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_AVAILABILITY = "unknown_availability" + AVAILABLE = "available" + SHORTAGE = "shortage" + SCARCE = "scarce" + MAINTENANCE = "maintenance" + + def __str__(self) -> str: + return str(self.value) + + class PlatformTechnology(str, Enum, metaclass=StrEnumMeta): UNKNOWN_TECHNOLOGY = "unknown_technology" PHOTONIC = "photonic" GENERAL_PURPOSE = "general_purpose" + TRAPPED_ION = "trapped_ion" + SUPERCONDUCTING = "superconducting" def __str__(self) -> str: return str(self.value) @@ -190,6 +208,39 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class PlatformHardware: + name: str + """ + Product name of the hardware. + """ + + vcpus: int + """ + Number of vCPUs available. + """ + + gpus: int + """ + Number of GPUs available (0 if no GPU). + """ + + gpus_network: str + """ + Network topology of GPUs (PCIe, NVLink...). + """ + + ram: int + """ + Amount of RAM available in byte. + """ + + vram: int + """ + Amount of VRAM available in byte (0 if no GPU). + """ + + @dataclass class JobCircuit: perceval_circuit: Optional[str] @@ -315,7 +366,7 @@ class Platform: version: str """ - Verison of the platform. + Version of the platform. """ name: str @@ -328,6 +379,11 @@ class Platform: Provider name of the platform. """ + backend_name: str + """ + Name of the running backend over the platform (ascella, qsim, aer...). + """ + type_: PlatformType """ Type of the platform. @@ -340,7 +396,22 @@ class Platform: max_qubit_count: int """ - Maximum number of qubits supported by the platform. + Estimated maximum number of qubits supported by the platform. + """ + + max_shot_count: int + """ + Maximum number of shots during a circuit execution. + """ + + max_circuit_count: int + """ + Maximum number of circuit that can be executed in one call. + """ + + availability: PlatformAvailability + """ + Availability of the platform. """ metadata: str @@ -348,6 +419,26 @@ class Platform: Metadata provided by the platform. """ + price_per_hour: Optional[Money] + """ + Price to be paid per hour (excluding free tiers). + """ + + price_per_shot: Optional[Money] + """ + Price to be paid per shot (excluding free tiers). + """ + + price_per_circuit: Optional[Money] + """ + Price to be paid per circuit setup before its execution (excluding free tiers). + """ + + hardware: Optional[PlatformHardware] + """ + Specifications of the underlying hardware. + """ + @dataclass class ProcessResult: @@ -532,6 +623,11 @@ class Session: Unique ID of the session's origin resource (if exists). """ + progress_message: Optional[str] + """ + Any progress of the session. + """ + @dataclass class CancelJobRequest: @@ -844,6 +940,11 @@ class ListPlatformsRequest: List platforms with this provider name. """ + backend_name: Optional[str] + """ + List platforms with this backend name. + """ + name: Optional[str] """ List platforms with this name. diff --git a/scaleway-async/scaleway_async/rdb/v1/__init__.py b/scaleway-async/scaleway_async/rdb/v1/__init__.py index f2affddf..1ba2fa88 100644 --- a/scaleway-async/scaleway_async/rdb/v1/__init__.py +++ b/scaleway-async/scaleway_async/rdb/v1/__init__.py @@ -5,6 +5,7 @@ from .types import ACLRuleProtocol from .types import DatabaseBackupStatus from .content import DATABASE_BACKUP_TRANSIENT_STATUSES +from .types import EndpointPrivateNetworkDetailsProvisioningMode from .types import EngineSettingPropertyType from .types import InstanceLogStatus from .content import INSTANCE_LOG_TRANSIENT_STATUSES @@ -41,6 +42,7 @@ from .types import ReadReplicaEndpointSpecPrivateNetwork from .types import EngineVersion from .types import BackupSchedule +from .types import EncryptionAtRest from .types import InstanceSetting from .types import LogsPolicy from .types import Maintenance @@ -150,6 +152,7 @@ "ACLRuleProtocol", "DatabaseBackupStatus", "DATABASE_BACKUP_TRANSIENT_STATUSES", + "EndpointPrivateNetworkDetailsProvisioningMode", "EngineSettingPropertyType", "InstanceLogStatus", "INSTANCE_LOG_TRANSIENT_STATUSES", @@ -186,6 +189,7 @@ "ReadReplicaEndpointSpecPrivateNetwork", "EngineVersion", "BackupSchedule", + "EncryptionAtRest", "InstanceSetting", "LogsPolicy", "Maintenance", diff --git a/scaleway-async/scaleway_async/rdb/v1/api.py b/scaleway-async/scaleway_async/rdb/v1/api.py index cc3c88f2..27236160 100644 --- a/scaleway-async/scaleway_async/rdb/v1/api.py +++ b/scaleway-async/scaleway_async/rdb/v1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ScwFile, unmarshal_ScwFile, ) @@ -50,6 +50,7 @@ DeleteInstanceACLRulesResponse, DeleteInstanceSettingsRequest, DeleteInstanceSettingsResponse, + EncryptionAtRest, Endpoint, EndpointSpec, Instance, @@ -159,12 +160,14 @@ class RdbV1API(API): - """ """ + """ + This API allows you to manage your Managed Databases for PostgreSQL and MySQL. + """ async def list_database_engines( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, version: Optional[str] = None, page: Optional[int] = None, @@ -207,7 +210,7 @@ async def list_database_engines( async def list_database_engines_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, version: Optional[str] = None, page: Optional[int] = None, @@ -246,7 +249,7 @@ async def list_node_types( self, *, include_disabled_types: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListNodeTypesResponse: @@ -288,7 +291,7 @@ async def list_node_types_all( self, *, include_disabled_types: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[NodeType]: @@ -324,7 +327,7 @@ async def list_node_types_all( async def list_database_backups( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListDatabaseBackupsRequestOrderBy] = None, instance_id: Optional[str] = None, @@ -377,7 +380,7 @@ async def list_database_backups( async def list_database_backups_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListDatabaseBackupsRequestOrderBy] = None, instance_id: Optional[str] = None, @@ -426,7 +429,7 @@ async def create_database_backup( *, instance_id: str, database_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, expires_at: Optional[datetime] = None, ) -> DatabaseBackup: @@ -475,7 +478,7 @@ async def get_database_backup( self, *, database_backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DatabaseBackup: """ Get a database backup. @@ -511,7 +514,7 @@ async def wait_for_database_backup( self, *, database_backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[DatabaseBackup, Union[bool, Awaitable[bool]]] ] = None, @@ -552,7 +555,7 @@ async def update_database_backup( self, *, database_backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, expires_at: Optional[datetime] = None, ) -> DatabaseBackup: @@ -601,7 +604,7 @@ async def delete_database_backup( self, *, database_backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DatabaseBackup: """ Delete a database backup. @@ -638,7 +641,7 @@ async def restore_database_backup( *, database_backup_id: str, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, database_name: Optional[str] = None, ) -> DatabaseBackup: """ @@ -687,7 +690,7 @@ async def export_database_backup( self, *, database_backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DatabaseBackup: """ Export a database backup. @@ -724,7 +727,7 @@ async def upgrade_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, node_type: Optional[str] = None, enable_ha: Optional[bool] = None, volume_size: Optional[int] = None, @@ -733,6 +736,7 @@ async def upgrade_instance( major_upgrade_workflow: Optional[ UpgradeInstanceRequestMajorUpgradeWorkflow ] = None, + enable_encryption: Optional[bool] = None, ) -> Instance: """ Upgrade a Database Instance. @@ -740,17 +744,19 @@ async def upgrade_instance( :param instance_id: UUID of the Database Instance you want to upgrade. :param region: Region to target. If none is passed will use default region from the config. :param node_type: Node type of the Database Instance you want to upgrade to. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :param enable_ha: Defines whether or not high availability should be enabled on the Database Instance. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :param volume_size: Increase your block storage volume size. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :param volume_type: Change your Database Instance storage type. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :param upgradable_version_id: This will create a new Database Instance with same specifications as the current one and perform a Database Engine upgrade. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :param major_upgrade_workflow: Upgrade your database engine to a new major version including instance endpoints. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. + :param enable_encryption: Defines whether or not encryption should be enabled on the Database Instance. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :return: :class:`Instance ` Usage: @@ -779,6 +785,7 @@ async def upgrade_instance( volume_type=volume_type, upgradable_version_id=upgradable_version_id, major_upgrade_workflow=major_upgrade_workflow, + enable_encryption=enable_encryption, ), self.client, ), @@ -790,7 +797,7 @@ async def upgrade_instance( async def list_instances( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, tags: Optional[List[str]] = None, name: Optional[str] = None, order_by: Optional[ListInstancesRequestOrderBy] = None, @@ -843,7 +850,7 @@ async def list_instances( async def list_instances_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, tags: Optional[List[str]] = None, name: Optional[str] = None, order_by: Optional[ListInstancesRequestOrderBy] = None, @@ -891,7 +898,7 @@ async def get_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Instance: """ Get a Database Instance. @@ -925,7 +932,7 @@ async def wait_for_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[Instance, Union[bool, Awaitable[bool]]] ] = None, @@ -967,7 +974,7 @@ async def create_instance( user_name: str, password: str, node_type: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, name: Optional[str] = None, @@ -979,13 +986,14 @@ async def create_instance( init_settings: Optional[List[InstanceSetting]] = None, volume_type: Optional[VolumeType] = None, init_endpoints: Optional[List[EndpointSpec]] = None, + encryption: Optional[EncryptionAtRest] = None, ) -> Instance: """ Create a Database Instance. Create a new Database Instance. You must set the `engine`, `user_name`, `password` and `node_type` parameters. Optionally, you can specify the volume type and size. :param engine: Database engine of the Database Instance (PostgreSQL, MySQL, ...). :param user_name: Username created when the Database Instance is created. - :param password: Password of the user. + :param password: Password of the user. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. :param node_type: Type of node to use for the Database Instance. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Please use project_id instead. @@ -1001,6 +1009,7 @@ async def create_instance( :param init_settings: List of engine settings to be set upon Database Instance initialization. :param volume_type: Type of volume where data is stored (lssd, bssd, ...). :param init_endpoints: One or multiple EndpointSpec used to expose your Database Instance. A load_balancer public endpoint is systematically created. + :param encryption: Encryption at rest settings for your Database Instance. :return: :class:`Instance ` Usage: @@ -1041,6 +1050,7 @@ async def create_instance( init_settings=init_settings, volume_type=volume_type, init_endpoints=init_endpoints, + encryption=encryption, project_id=project_id, organization_id=organization_id, ), @@ -1055,7 +1065,7 @@ async def update_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, backup_schedule_frequency: Optional[int] = None, backup_schedule_retention: Optional[int] = None, is_backup_schedule_disabled: Optional[bool] = None, @@ -1120,7 +1130,7 @@ async def delete_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Instance: """ Delete a Database Instance. @@ -1155,7 +1165,7 @@ async def clone_instance( *, instance_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, node_type: Optional[str] = None, ) -> Instance: """ @@ -1202,7 +1212,7 @@ async def restart_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Instance: """ Restart Database Instance. @@ -1237,7 +1247,7 @@ async def get_instance_certificate( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ScwFile: """ Get the TLS certificate of a Database Instance. @@ -1271,7 +1281,7 @@ async def renew_instance_certificate( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Renew the TLS certificate of a Database Instance. @@ -1304,7 +1314,7 @@ async def get_instance_metrics( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, start_date: Optional[datetime] = None, end_date: Optional[datetime] = None, metric_name: Optional[str] = None, @@ -1349,7 +1359,7 @@ async def create_read_replica( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, endpoint_spec: Optional[List[ReadReplicaEndpointSpec]] = None, same_zone: Optional[bool] = None, ) -> ReadReplica: @@ -1395,7 +1405,7 @@ async def get_read_replica( self, *, read_replica_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ReadReplica: """ Get a Read Replica. @@ -1429,7 +1439,7 @@ async def wait_for_read_replica( self, *, read_replica_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[ReadReplica, Union[bool, Awaitable[bool]]] ] = None, @@ -1468,7 +1478,7 @@ async def delete_read_replica( self, *, read_replica_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ReadReplica: """ Delete a Read Replica. @@ -1502,7 +1512,7 @@ async def reset_read_replica( self, *, read_replica_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ReadReplica: """ Resync a Read Replica. @@ -1538,7 +1548,7 @@ async def promote_read_replica( self, *, read_replica_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Instance: """ Promote a Read Replica. @@ -1574,7 +1584,7 @@ async def create_read_replica_endpoint( *, read_replica_id: str, endpoint_spec: List[ReadReplicaEndpointSpec], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ReadReplica: """ Create an endpoint for a Read Replica. @@ -1618,7 +1628,7 @@ async def prepare_instance_logs( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, start_date: Optional[datetime] = None, end_date: Optional[datetime] = None, ) -> PrepareInstanceLogsResponse: @@ -1665,7 +1675,7 @@ async def list_instance_logs( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListInstanceLogsRequestOrderBy] = None, ) -> ListInstanceLogsResponse: """ @@ -1704,7 +1714,7 @@ async def get_instance_log( self, *, instance_log_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> InstanceLog: """ Get given logs of a Database Instance. @@ -1738,7 +1748,7 @@ async def wait_for_instance_log( self, *, instance_log_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[InstanceLog, Union[bool, Awaitable[bool]]] ] = None, @@ -1777,7 +1787,7 @@ async def purge_instance_logs( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, log_name: Optional[str] = None, ) -> None: """ @@ -1819,7 +1829,7 @@ async def list_instance_logs_details( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListInstanceLogsDetailsResponse: """ List remote Database Instance logs details. @@ -1854,7 +1864,7 @@ async def add_instance_settings( *, instance_id: str, settings: List[InstanceSetting], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> AddInstanceSettingsResponse: """ Add Database Instance advanced settings. @@ -1899,7 +1909,7 @@ async def delete_instance_settings( *, instance_id: str, setting_names: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DeleteInstanceSettingsResponse: """ Delete Database Instance advanced settings. @@ -1944,11 +1954,11 @@ async def set_instance_settings( *, instance_id: str, settings: List[InstanceSetting], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SetInstanceSettingsResponse: """ Set Database Instance advanced settings. - Update an advanced setting for a Database Instance. Settings added upon database engine initalization can only be defined once, and cannot, therefore, be updated. + Update an advanced setting for a Database Instance. Settings added upon database engine initialization can only be defined once, and cannot, therefore, be updated. :param instance_id: UUID of the Database Instance where the settings must be set. :param settings: Settings to define for the Database Instance. :param region: Region to target. If none is passed will use default region from the config. @@ -1988,7 +1998,7 @@ async def list_instance_acl_rules( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListInstanceACLRulesResponse: @@ -2030,7 +2040,7 @@ async def list_instance_acl_rules_all( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[ACLRule]: @@ -2068,7 +2078,7 @@ async def add_instance_acl_rules( *, instance_id: str, rules: List[ACLRuleRequest], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> AddInstanceACLRulesResponse: """ Add an ACL rule to a Database Instance. @@ -2113,7 +2123,7 @@ async def set_instance_acl_rules( *, instance_id: str, rules: List[ACLRuleRequest], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SetInstanceACLRulesResponse: """ Set ACL rules for a Database Instance. @@ -2158,7 +2168,7 @@ async def delete_instance_acl_rules( *, instance_id: str, acl_rule_ips: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DeleteInstanceACLRulesResponse: """ Delete ACL rules of a Database Instance. @@ -2202,7 +2212,7 @@ async def list_users( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListUsersRequestOrderBy] = None, page: Optional[int] = None, @@ -2250,7 +2260,7 @@ async def list_users_all( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListUsersRequestOrderBy] = None, page: Optional[int] = None, @@ -2296,14 +2306,14 @@ async def create_user( name: str, password: str, is_admin: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> User: """ Create a user for a Database Instance. Create a new user for a Database Instance. You must define the `name`, `password` and `is_admin` parameters. :param instance_id: UUID of the Database Instance in which you want to create a user. :param name: Name of the user you want to create. - :param password: Password of the user you want to create. + :param password: Password of the user you want to create. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. :param is_admin: Defines whether the user will have administrative privileges. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`User ` @@ -2347,7 +2357,7 @@ async def update_user( *, instance_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, password: Optional[str] = None, is_admin: Optional[bool] = None, ) -> User: @@ -2357,7 +2367,7 @@ async def update_user( :param instance_id: UUID of the Database Instance the user belongs to. :param name: Name of the database user. :param region: Region to target. If none is passed will use default region from the config. - :param password: Password of the database user. + :param password: Password of the database user. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. :param is_admin: Defines whether or not this user got administrative privileges. :return: :class:`User ` @@ -2399,7 +2409,7 @@ async def delete_user( *, instance_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a user on a Database Instance. @@ -2434,7 +2444,7 @@ async def list_databases( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, managed: Optional[bool] = None, owner: Optional[str] = None, @@ -2488,7 +2498,7 @@ async def list_databases_all( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, managed: Optional[bool] = None, owner: Optional[str] = None, @@ -2538,7 +2548,7 @@ async def create_database( *, instance_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Database: """ Create a database in a Database Instance. @@ -2583,7 +2593,7 @@ async def delete_database( *, instance_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a database in a Database Instance. @@ -2618,7 +2628,7 @@ async def list_privileges( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivilegesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2669,7 +2679,7 @@ async def list_privileges_all( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivilegesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2717,7 +2727,7 @@ async def set_privilege( instance_id: str, database_name: str, user_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, permission: Optional[Permission] = None, ) -> Privilege: """ @@ -2766,7 +2776,7 @@ async def set_privilege( async def list_snapshots( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListSnapshotsRequestOrderBy] = None, instance_id: Optional[str] = None, @@ -2819,7 +2829,7 @@ async def list_snapshots( async def list_snapshots_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListSnapshotsRequestOrderBy] = None, instance_id: Optional[str] = None, @@ -2867,7 +2877,7 @@ async def get_snapshot( self, *, snapshot_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Snapshot: """ Get a Database Instance snapshot. @@ -2901,7 +2911,7 @@ async def wait_for_snapshot( self, *, snapshot_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[Snapshot, Union[bool, Awaitable[bool]]] ] = None, @@ -2940,7 +2950,7 @@ async def create_snapshot( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, expires_at: Optional[datetime] = None, ) -> Snapshot: @@ -2987,7 +2997,7 @@ async def update_snapshot( self, *, snapshot_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, expires_at: Optional[datetime] = None, ) -> Snapshot: @@ -3034,7 +3044,7 @@ async def delete_snapshot( self, *, snapshot_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Snapshot: """ Delete a Database Instance snapshot. @@ -3069,7 +3079,7 @@ async def create_instance_from_snapshot( *, snapshot_id: str, instance_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, is_ha_cluster: Optional[bool] = None, node_type: Optional[str] = None, ) -> Instance: @@ -3119,7 +3129,7 @@ async def create_endpoint( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, endpoint_spec: Optional[EndpointSpec] = None, ) -> Endpoint: """ @@ -3163,7 +3173,7 @@ async def delete_endpoint( self, *, endpoint_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a Database Instance endpoint. @@ -3195,7 +3205,7 @@ async def get_endpoint( self, *, endpoint_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Endpoint: """ Get a Database Instance endpoint. @@ -3230,7 +3240,7 @@ async def migrate_endpoint( *, endpoint_id: str, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Endpoint: """ Migrate an existing instance endpoint to another instance. @@ -3273,7 +3283,7 @@ async def apply_instance_maintenance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Maintenance: """ Apply Database Instance maintenance. diff --git a/scaleway-async/scaleway_async/rdb/v1/marshalling.py b/scaleway-async/scaleway_async/rdb/v1/marshalling.py index a480738f..6ae68f62 100644 --- a/scaleway-async/scaleway_async/rdb/v1/marshalling.py +++ b/scaleway-async/scaleway_async/rdb/v1/marshalling.py @@ -23,6 +23,7 @@ Database, InstanceLog, BackupSchedule, + EncryptionAtRest, InstanceSetting, LogsPolicy, UpgradableVersion, @@ -140,6 +141,10 @@ def unmarshal_EndpointPrivateNetworkDetails(data: Any) -> EndpointPrivateNetwork if field is not None: args["zone"] = field + field = data.get("provisioning_mode", None) + if field is not None: + args["provisioning_mode"] = field + return EndpointPrivateNetworkDetails(**args) @@ -162,26 +167,38 @@ def unmarshal_Endpoint(data: Any) -> Endpoint: field = data.get("ip", None) if field is not None: args["ip"] = field + else: + args["ip"] = None field = data.get("name", None) if field is not None: args["name"] = field + else: + args["name"] = None field = data.get("private_network", None) if field is not None: args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None field = data.get("load_balancer", None) if field is not None: args["load_balancer"] = unmarshal_EndpointLoadBalancerDetails(field) + else: + args["load_balancer"] = None field = data.get("direct_access", None) if field is not None: args["direct_access"] = unmarshal_EndpointDirectAccessDetails(field) + else: + args["direct_access"] = None field = data.get("hostname", None) if field is not None: args["hostname"] = field + else: + args["hostname"] = None return Endpoint(**args) @@ -205,18 +222,26 @@ def unmarshal_Maintenance(data: Any) -> Maintenance: field = data.get("starts_at", None) if field is not None: args["starts_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["starts_at"] = None field = data.get("stops_at", None) if field is not None: args["stops_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stops_at"] = None field = data.get("closed_at", None) if field is not None: args["closed_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["closed_at"] = None field = data.get("forced_at", None) if field is not None: args["forced_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["forced_at"] = None return Maintenance(**args) @@ -289,18 +314,26 @@ def unmarshal_DatabaseBackup(data: Any) -> DatabaseBackup: field = data.get("size", None) if field is not None: args["size"] = field + else: + args["size"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("instance_name", None) if field is not None: @@ -317,12 +350,16 @@ def unmarshal_DatabaseBackup(data: Any) -> DatabaseBackup: field = data.get("download_url", None) if field is not None: args["download_url"] = field + else: + args["download_url"] = None field = data.get("download_url_expires_at", None) if field is not None: args["download_url_expires_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["download_url_expires_at"] = None return DatabaseBackup(**args) @@ -381,14 +418,20 @@ def unmarshal_InstanceLog(data: Any) -> InstanceLog: field = data.get("download_url", None) if field is not None: args["download_url"] = field + else: + args["download_url"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return InstanceLog(**args) @@ -418,10 +461,27 @@ def unmarshal_BackupSchedule(data: Any) -> BackupSchedule: args["next_run_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["next_run_at"] = None return BackupSchedule(**args) +def unmarshal_EncryptionAtRest(data: Any) -> EncryptionAtRest: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EncryptionAtRest' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + return EncryptionAtRest(**args) + + def unmarshal_InstanceSetting(data: Any) -> InstanceSetting: if not isinstance(data, dict): raise TypeError( @@ -452,10 +512,14 @@ def unmarshal_LogsPolicy(data: Any) -> LogsPolicy: field = data.get("max_age_retention", None) if field is not None: args["max_age_retention"] = field + else: + args["max_age_retention"] = None field = data.get("total_disk_retention", None) if field is not None: args["total_disk_retention"] = field + else: + args["total_disk_retention"] = None return LogsPolicy(**args) @@ -495,7 +559,7 @@ def unmarshal_Volume(data: Any) -> Volume: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -503,7 +567,7 @@ def unmarshal_Volume(data: Any) -> Volume: if field is not None: args["size"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -537,10 +601,14 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None field = data.get("project_id", None) if field is not None: @@ -579,10 +647,14 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("endpoint", None) if field is not None: args["endpoint"] = unmarshal_Endpoint(field) + else: + args["endpoint"] = None field = data.get("backup_schedule", None) if field is not None: args["backup_schedule"] = unmarshal_BackupSchedule(field) + else: + args["backup_schedule"] = None field = data.get("read_replicas", None) if field is not None: @@ -619,6 +691,14 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("logs_policy", None) if field is not None: args["logs_policy"] = unmarshal_LogsPolicy(field) + else: + args["logs_policy"] = None + + field = data.get("encryption", None) + if field is not None: + args["encryption"] = unmarshal_EncryptionAtRest(field) + else: + args["encryption"] = None return Instance(**args) @@ -654,11 +734,11 @@ def unmarshal_SnapshotVolumeType(data: Any) -> SnapshotVolumeType: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -704,22 +784,32 @@ def unmarshal_Snapshot(data: Any) -> Snapshot: field = data.get("size", None) if field is not None: args["size"] = field + else: + args["size"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("volume_type", None) if field is not None: args["volume_type"] = unmarshal_SnapshotVolumeType(field) + else: + args["volume_type"] = None return Snapshot(**args) @@ -774,6 +864,8 @@ def unmarshal_ACLRule(data: Any) -> ACLRule: field = data.get("port", None) if field is not None: args["port"] = field + else: + args["port"] = None return ACLRule(**args) @@ -919,26 +1011,38 @@ def unmarshal_EngineSetting(data: Any) -> EngineSetting: field = data.get("unit", None) if field is not None: args["unit"] = field + else: + args["unit"] = None field = data.get("string_constraint", None) if field is not None: args["string_constraint"] = field + else: + args["string_constraint"] = None field = data.get("int_min", None) if field is not None: args["int_min"] = field + else: + args["int_min"] = None field = data.get("int_max", None) if field is not None: args["int_max"] = field + else: + args["int_max"] = None field = data.get("float_min", None) if field is not None: args["float_min"] = field + else: + args["float_min"] = None field = data.get("float_max", None) if field is not None: args["float_max"] = field + else: + args["float_max"] = None return EngineSetting(**args) @@ -984,6 +1088,8 @@ def unmarshal_EngineVersion(data: Any) -> EngineVersion: args["end_of_life"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["end_of_life"] = None return EngineVersion(**args) @@ -1190,7 +1296,7 @@ def unmarshal_NodeTypeVolumeType(data: Any) -> NodeTypeVolumeType: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -1210,7 +1316,7 @@ def unmarshal_NodeTypeVolumeType(data: Any) -> NodeTypeVolumeType: if field is not None: args["chunk_size"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -1256,10 +1362,14 @@ def unmarshal_NodeType(data: Any) -> NodeType: field = data.get("volume_constraint", None) if field is not None: args["volume_constraint"] = unmarshal_NodeTypeVolumeConstraintSizes(field) + else: + args["volume_constraint"] = None field = data.get("is_bssd_compatible", None) if field is not None: args["is_bssd_compatible"] = field + else: + args["is_bssd_compatible"] = None field = data.get("available_volume_types", None) if field is not None: @@ -1512,7 +1622,7 @@ def marshal_CreateDatabaseBackupRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -1591,9 +1701,7 @@ def marshal_CreateEndpointRequest( output: Dict[str, Any] = {} if request.endpoint_spec is not None: - output["endpoint_spec"] = ( - marshal_EndpointSpec(request.endpoint_spec, defaults), - ) + output["endpoint_spec"] = marshal_EndpointSpec(request.endpoint_spec, defaults) return output @@ -1616,6 +1724,18 @@ def marshal_CreateInstanceFromSnapshotRequest( return output +def marshal_EncryptionAtRest( + request: EncryptionAtRest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.enabled is not None: + output["enabled"] = request.enabled + + return output + + def marshal_CreateInstanceRequest( request: CreateInstanceRequest, defaults: ProfileDefaults, @@ -1679,6 +1799,9 @@ def marshal_CreateInstanceRequest( marshal_EndpointSpec(item, defaults) for item in request.init_endpoints ] + if request.encryption is not None: + output["encryption"] = marshal_EncryptionAtRest(request.encryption, defaults) + return output @@ -1783,7 +1906,7 @@ def marshal_CreateSnapshotRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -1849,10 +1972,10 @@ def marshal_PrepareInstanceLogsRequest( output: Dict[str, Any] = {} if request.start_date is not None: - output["start_date"] = request.start_date + output["start_date"] = request.start_date.isoformat() if request.end_date is not None: - output["end_date"] = request.end_date + output["end_date"] = request.end_date.isoformat() return output @@ -1940,7 +2063,7 @@ def marshal_UpdateDatabaseBackupRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -1982,7 +2105,7 @@ def marshal_UpdateInstanceRequest( output["tags"] = request.tags if request.logs_policy is not None: - output["logs_policy"] = (marshal_LogsPolicy(request.logs_policy, defaults),) + output["logs_policy"] = marshal_LogsPolicy(request.logs_policy, defaults) if request.backup_same_region is not None: output["backup_same_region"] = request.backup_same_region @@ -2003,7 +2126,7 @@ def marshal_UpdateSnapshotRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -2056,6 +2179,7 @@ def marshal_UpgradeInstanceRequest( OneOfPossibility( "major_upgrade_workflow", request.major_upgrade_workflow ), + OneOfPossibility("enable_encryption", request.enable_encryption), ] ), ) diff --git a/scaleway-async/scaleway_async/rdb/v1/types.py b/scaleway-async/scaleway_async/rdb/v1/types.py index ef41a5e2..2b86e74a 100644 --- a/scaleway-async/scaleway_async/rdb/v1/types.py +++ b/scaleway-async/scaleway_async/rdb/v1/types.py @@ -8,9 +8,9 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, TimeSeries, - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -56,6 +56,14 @@ def __str__(self) -> str: return str(self.value) +class EndpointPrivateNetworkDetailsProvisioningMode(str, Enum, metaclass=StrEnumMeta): + STATIC = "static" + IPAM = "ipam" + + def __str__(self) -> str: + return str(self.value) + + class EngineSettingPropertyType(str, Enum, metaclass=StrEnumMeta): BOOLEAN = "boolean" INT = "int" @@ -281,11 +289,16 @@ class EndpointPrivateNetworkDetails: CIDR notation of the endpoint IPv4 address. """ - zone: Zone + zone: ScwZone """ Private network zone. """ + provisioning_mode: EndpointPrivateNetworkDetailsProvisioningMode + """ + How endpoint ips are provisioned. + """ + @dataclass class EndpointSpecPrivateNetworkIpamConfig: @@ -478,6 +491,11 @@ class BackupSchedule: """ +@dataclass +class EncryptionAtRest: + enabled: bool + + @dataclass class InstanceSetting: name: str @@ -548,7 +566,7 @@ class ReadReplica: Read replica status. """ - region: Region + region: ScwRegion """ Region the Read Replica is in. """ @@ -588,7 +606,7 @@ class Volume: class NodeTypeVolumeConstraintSizes: min_size: int """ - [deprecated] Mimimum size required for the Volume. + [deprecated] Minimum size required for the Volume. """ max_size: int @@ -611,7 +629,7 @@ class NodeTypeVolumeType: min_size: int """ - Mimimum size required for the Volume. + Minimum size required for the Volume. """ max_size: int @@ -725,7 +743,7 @@ class DatabaseBackup: Name of the Database Instance of the backup. """ - region: Region + region: ScwRegion """ Region of the database backup. """ @@ -763,7 +781,7 @@ class DatabaseEngine: Available versions. """ - region: Region + region: ScwRegion """ Region of this Database Instance. """ @@ -816,14 +834,14 @@ class InstanceLog: Name of the underlying node. """ - region: Region + region: ScwRegion """ Region the Database Instance is in. """ download_url: Optional[str] """ - Presigned S3 URL to download your log file. + Presigned Object Storage URL to download your log file. """ expires_at: Optional[datetime] @@ -839,7 +857,7 @@ class InstanceLog: @dataclass class Instance: - region: Region + region: ScwRegion """ Region the Database Instance is in. """ @@ -949,6 +967,11 @@ class Instance: Logs policy of the Database Instance. """ + encryption: Optional[EncryptionAtRest] + """ + Encryption at rest settings for your Database Instance. + """ + @dataclass class NodeType: @@ -1017,7 +1040,7 @@ class NodeType: Instance range associated with the NodeType offer. """ - region: Region + region: ScwRegion """ Region the Node Type is in. """ @@ -1073,7 +1096,7 @@ class Snapshot: Source node type. """ - region: Region + region: ScwRegion """ Region of this snapshot. """ @@ -1142,7 +1165,7 @@ class AddInstanceACLRulesRequest: ACL rules to add to the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1168,7 +1191,7 @@ class AddInstanceSettingsRequest: Settings to add to the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1189,7 +1212,7 @@ class ApplyInstanceMaintenanceRequest: UUID of the Database Instance you want to apply maintenance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1207,7 +1230,7 @@ class CloneInstanceRequest: Name of the Database Instance clone. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1230,7 +1253,7 @@ class CreateDatabaseBackupRequest: Name of the database you want to back up. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1258,7 +1281,7 @@ class CreateDatabaseRequest: Name of the database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1271,7 +1294,7 @@ class CreateEndpointRequest: UUID of the Database Instance you to which you want to add an endpoint. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1294,7 +1317,7 @@ class CreateInstanceFromSnapshotRequest: Name of the Database Instance created with the snapshot. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1324,7 +1347,7 @@ class CreateInstanceRequest: password: str """ - Password of the user. + Password of the user. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. """ node_type: str @@ -1332,7 +1355,7 @@ class CreateInstanceRequest: Type of node to use for the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1382,6 +1405,11 @@ class CreateInstanceRequest: One or multiple EndpointSpec used to expose your Database Instance. A load_balancer public endpoint is systematically created. """ + encryption: Optional[EncryptionAtRest] + """ + Encryption at rest settings for your Database Instance. + """ + project_id: Optional[str] organization_id: Optional[str] @@ -1399,7 +1427,7 @@ class CreateReadReplicaEndpointRequest: Specification of the endpoint you want to create. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1412,7 +1440,7 @@ class CreateReadReplicaRequest: UUID of the Database Instance you want to create a Read Replica from. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1435,7 +1463,7 @@ class CreateSnapshotRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1465,7 +1493,7 @@ class CreateUserRequest: password: str """ - Password of the user you want to create. + Password of the user you want to create. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. """ is_admin: bool @@ -1473,7 +1501,7 @@ class CreateUserRequest: Defines whether the user will have administrative privileges. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1486,7 +1514,7 @@ class DeleteDatabaseBackupRequest: UUID of the database backup to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1504,7 +1532,7 @@ class DeleteDatabaseRequest: Name of the database to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1517,7 +1545,7 @@ class DeleteEndpointRequest: This endpoint can also be used to delete a Read Replica endpoint. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1535,7 +1563,7 @@ class DeleteInstanceACLRulesRequest: IP addresses defined in the ACL rules of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1556,7 +1584,7 @@ class DeleteInstanceRequest: UUID of the Database Instance to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1574,7 +1602,7 @@ class DeleteInstanceSettingsRequest: Settings names to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1595,7 +1623,7 @@ class DeleteReadReplicaRequest: UUID of the Read Replica. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1608,7 +1636,7 @@ class DeleteSnapshotRequest: UUID of the snapshot to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1626,7 +1654,7 @@ class DeleteUserRequest: Name of the user. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1639,7 +1667,7 @@ class ExportDatabaseBackupRequest: UUID of the database backup you want to export. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1652,7 +1680,7 @@ class GetDatabaseBackupRequest: UUID of the database backup. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1665,7 +1693,7 @@ class GetEndpointRequest: UUID of the endpoint you want to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1678,7 +1706,7 @@ class GetInstanceCertificateRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1691,7 +1719,7 @@ class GetInstanceLogRequest: UUID of the instance_log you want. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1704,7 +1732,7 @@ class GetInstanceMetricsRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1732,7 +1760,7 @@ class GetInstanceRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1745,7 +1773,7 @@ class GetReadReplicaRequest: UUID of the Read Replica. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1758,7 +1786,7 @@ class GetSnapshotRequest: UUID of the snapshot. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1774,7 +1802,7 @@ class InstanceMetrics: @dataclass class ListDatabaseBackupsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1824,7 +1852,7 @@ class ListDatabaseBackupsResponse: @dataclass class ListDatabaseEnginesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1864,7 +1892,7 @@ class ListDatabasesRequest: UUID of the Database Instance to list the databases of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1914,7 +1942,7 @@ class ListInstanceACLRulesRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1944,7 +1972,7 @@ class ListInstanceLogsDetailsRequest: UUID of the Database Instance you want logs of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1965,7 +1993,7 @@ class ListInstanceLogsRequest: UUID of the Database Instance you want logs of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1986,7 +2014,7 @@ class ListInstanceLogsResponse: @dataclass class ListInstancesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2041,7 +2069,7 @@ class ListNodeTypesRequest: Defines whether or not to include disabled types. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2071,7 +2099,7 @@ class ListPrivilegesRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2111,7 +2139,7 @@ class ListPrivilegesResponse: @dataclass class ListSnapshotsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2166,7 +2194,7 @@ class ListUsersRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2211,7 +2239,7 @@ class MigrateEndpointRequest: UUID of the instance you want to attach the endpoint to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2224,7 +2252,7 @@ class PrepareInstanceLogsRequest: UUID of the Database Instance you want logs of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2255,7 +2283,7 @@ class PromoteReadReplicaRequest: UUID of the Read Replica. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2268,7 +2296,7 @@ class PurgeInstanceLogsRequest: UUID of the Database Instance you want logs of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2286,7 +2314,7 @@ class RenewInstanceCertificateRequest: UUID of the Database Instance you want logs of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2299,7 +2327,7 @@ class ResetReadReplicaRequest: UUID of the Read Replica. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2312,7 +2340,7 @@ class RestartInstanceRequest: UUID of the Database Instance you want to restart. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2330,7 +2358,7 @@ class RestoreDatabaseBackupRequest: Defines the Database Instance where the backup has to be restored. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2353,7 +2381,7 @@ class SetInstanceACLRulesRequest: ACL rules to define for the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2379,7 +2407,7 @@ class SetInstanceSettingsRequest: Settings to define for the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2410,7 +2438,7 @@ class SetPrivilegeRequest: Name of the user. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2428,7 +2456,7 @@ class UpdateDatabaseBackupRequest: UUID of the database backup to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2451,7 +2479,7 @@ class UpdateInstanceRequest: UUID of the Database Instance to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2504,7 +2532,7 @@ class UpdateSnapshotRequest: UUID of the snapshot to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2532,14 +2560,14 @@ class UpdateUserRequest: Name of the database user. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ password: Optional[str] """ - Password of the database user. + Password of the database user. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. """ is_admin: Optional[bool] @@ -2555,7 +2583,7 @@ class UpgradeInstanceRequest: UUID of the Database Instance you want to upgrade. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2571,3 +2599,5 @@ class UpgradeInstanceRequest: upgradable_version_id: Optional[str] major_upgrade_workflow: Optional[UpgradeInstanceRequestMajorUpgradeWorkflow] + + enable_encryption: Optional[bool] diff --git a/scaleway-async/scaleway_async/redis/v1/api.py b/scaleway-async/scaleway_async/redis/v1/api.py index a64ce881..badef9c9 100644 --- a/scaleway-async/scaleway_async/redis/v1/api.py +++ b/scaleway-async/scaleway_async/redis/v1/api.py @@ -7,7 +7,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( ScwFile, - Zone, + Zone as ScwZone, unmarshal_ScwFile, ) from scaleway_core.utils import ( @@ -79,14 +79,16 @@ class RedisV1API(API): - """ """ + """ + This API allows you to manage your Managed Databases for Redis™. + """ async def create_cluster( self, *, version: str, node_type: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project_id: Optional[str] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, @@ -160,7 +162,7 @@ async def update_cluster( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, user_name: Optional[str] = None, @@ -211,7 +213,7 @@ async def get_cluster( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Get a Redis™ Database Instance. @@ -243,7 +245,7 @@ async def wait_for_cluster( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Cluster, Union[bool, Awaitable[bool]]]] = None, ) -> Cluster: """ @@ -279,7 +281,7 @@ async def wait_for_cluster( async def list_clusters( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, name: Optional[str] = None, order_by: Optional[ListClustersRequestOrderBy] = None, @@ -333,7 +335,7 @@ async def list_clusters( async def list_clusters_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, name: Optional[str] = None, order_by: Optional[ListClustersRequestOrderBy] = None, @@ -384,7 +386,7 @@ async def migrate_cluster( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, version: Optional[str] = None, node_type: Optional[str] = None, cluster_size: Optional[int] = None, @@ -435,7 +437,7 @@ async def delete_cluster( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Delete a Redis™ Database Instance. @@ -467,7 +469,7 @@ async def get_cluster_metrics( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, start_at: Optional[datetime] = None, end_at: Optional[datetime] = None, metric_name: Optional[str] = None, @@ -510,7 +512,7 @@ async def list_node_types( self, *, include_disabled_types: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListNodeTypesResponse: @@ -550,7 +552,7 @@ async def list_node_types_all( self, *, include_disabled_types: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[NodeType]: @@ -589,7 +591,7 @@ async def list_cluster_versions( include_disabled: bool, include_beta: bool, include_deprecated: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, version: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -640,7 +642,7 @@ async def list_cluster_versions_all( include_disabled: bool, include_beta: bool, include_deprecated: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, version: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -686,7 +688,7 @@ async def get_cluster_certificate( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ScwFile: """ Get the TLS certificate of a cluster. @@ -718,7 +720,7 @@ async def renew_cluster_certificate( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Renew the TLS certificate of a cluster. @@ -752,7 +754,7 @@ async def add_cluster_settings( *, cluster_id: str, settings: List[ClusterSetting], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ClusterSettingsResponse: """ Add advanced settings. @@ -795,7 +797,7 @@ async def delete_cluster_setting( *, cluster_id: str, setting_name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Delete advanced setting. @@ -831,11 +833,11 @@ async def set_cluster_settings( *, cluster_id: str, settings: List[ClusterSetting], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ClusterSettingsResponse: """ Set advanced settings. - Update an advanced setting for a Redis™ Database Instance (Redis™ cluster). Settings added upon database engine initalization can only be defined once, and cannot, therefore, be updated. + Update an advanced setting for a Redis™ Database Instance (Redis™ cluster). Settings added upon database engine initialization can only be defined once, and cannot, therefore, be updated. :param cluster_id: UUID of the Database Instance where the settings must be set. :param settings: Settings to define for the Database Instance. :param zone: Zone to target. If none is passed will use default zone from the config. @@ -874,7 +876,7 @@ async def set_acl_rules( *, cluster_id: str, acl_rules: List[ACLRuleSpec], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetAclRulesResponse: """ Set ACL rules for a cluster. @@ -917,7 +919,7 @@ async def add_acl_rules( *, cluster_id: str, acl_rules: List[ACLRuleSpec], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> AddAclRulesResponse: """ Add ACL rules for a cluster. @@ -959,7 +961,7 @@ async def delete_acl_rule( self, *, acl_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Delete an ACL rule for a cluster. @@ -991,7 +993,7 @@ async def get_acl_rule( self, *, acl_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ACLRule: """ Get an ACL rule. @@ -1024,7 +1026,7 @@ async def set_endpoints( *, cluster_id: str, endpoints: List[EndpointSpec], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetEndpointsResponse: """ Set endpoints for a cluster. @@ -1067,7 +1069,7 @@ async def add_endpoints( *, cluster_id: str, endpoints: List[EndpointSpec], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> AddEndpointsResponse: """ Add endpoints for a cluster. @@ -1109,7 +1111,7 @@ async def delete_endpoint( self, *, endpoint_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Delete an endpoint for a cluster. @@ -1141,7 +1143,7 @@ async def get_endpoint( self, *, endpoint_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Endpoint: """ Get an endpoint. @@ -1173,7 +1175,7 @@ async def update_endpoint( self, *, endpoint_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, private_network: Optional[EndpointSpecPrivateNetworkSpec] = None, public_network: Optional[EndpointSpecPublicNetworkSpec] = None, ) -> Endpoint: diff --git a/scaleway-async/scaleway_async/redis/v1/marshalling.py b/scaleway-async/scaleway_async/redis/v1/marshalling.py index f72dabcb..91b1befd 100644 --- a/scaleway-async/scaleway_async/redis/v1/marshalling.py +++ b/scaleway-async/scaleway_async/redis/v1/marshalling.py @@ -64,10 +64,14 @@ def unmarshal_ACLRule(data: Any) -> ACLRule: field = data.get("ip_cidr", None) if field is not None: args["ip_cidr"] = field + else: + args["ip_cidr"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None return ACLRule(**args) @@ -133,10 +137,14 @@ def unmarshal_Endpoint(data: Any) -> Endpoint: field = data.get("private_network", None) if field is not None: args["private_network"] = unmarshal_PrivateNetwork(field) + else: + args["private_network"] = None field = data.get("public_network", None) if field is not None: args["public_network"] = unmarshal_PublicNetwork(field) + else: + args["public_network"] = None return Endpoint(**args) @@ -215,10 +223,14 @@ def unmarshal_Cluster(data: Any) -> Cluster: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("acl_rules", None) if field is not None: @@ -333,7 +345,7 @@ def unmarshal_AvailableClusterSetting(data: Any) -> AvailableClusterSetting: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -348,18 +360,26 @@ def unmarshal_AvailableClusterSetting(data: Any) -> AvailableClusterSetting: field = data.get("default_value", None) if field is not None: args["default_value"] = field + else: + args["default_value"] = None field = data.get("max_value", None) if field is not None: args["max_value"] = field + else: + args["max_value"] = None field = data.get("min_value", None) if field is not None: args["min_value"] = field + else: + args["min_value"] = None field = data.get("regex", None) if field is not None: args["regex"] = field + else: + args["regex"] = None return AvailableClusterSetting(**args) @@ -397,6 +417,8 @@ def unmarshal_ClusterVersion(data: Any) -> ClusterVersion: args["end_of_life_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["end_of_life_at"] = None return ClusterVersion(**args) @@ -621,10 +643,8 @@ def marshal_EndpointSpecPrivateNetworkSpec( output["service_ips"] = request.service_ips if request.ipam_config is not None: - output["ipam_config"] = ( - marshal_EndpointSpecPrivateNetworkSpecIpamConfig( - request.ipam_config, defaults - ), + output["ipam_config"] = marshal_EndpointSpecPrivateNetworkSpecIpamConfig( + request.ipam_config, defaults ) return output diff --git a/scaleway-async/scaleway_async/redis/v1/types.py b/scaleway-async/scaleway_async/redis/v1/types.py index 108a9712..a4a9c8ea 100644 --- a/scaleway-async/scaleway_async/redis/v1/types.py +++ b/scaleway-async/scaleway_async/redis/v1/types.py @@ -9,7 +9,7 @@ from scaleway_core.bridge import ( TimeSeries, - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -87,7 +87,7 @@ class PrivateNetwork: List of IPv4 CIDR notation addresses of the endpoint. """ - zone: Zone + zone: ScwZone """ Zone of the Private Network. """ @@ -259,7 +259,7 @@ class ClusterVersion: Redis™ logo url. """ - zone: Zone + zone: ScwZone """ Zone of the Redis™ Database Instance. """ @@ -342,7 +342,7 @@ class Cluster: Number of nodes of the Database Instance cluster. """ - zone: Zone + zone: ScwZone """ Zone of the Database Instance. """ @@ -395,7 +395,7 @@ class NodeType: Defines whether node type is currently in beta. """ - zone: Zone + zone: ScwZone """ Zone of the node type. """ @@ -413,7 +413,7 @@ class AddAclRulesRequest: ACLs rules to add to the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -444,7 +444,7 @@ class AddClusterSettingsRequest: Settings to add to the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -462,7 +462,7 @@ class AddEndpointsRequest: Endpoints to add to the Database Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -509,7 +509,7 @@ class CreateClusterRequest: Type of node to use for the Database Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -572,7 +572,7 @@ class DeleteAclRuleRequest: UUID of the ACL rule you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -585,7 +585,7 @@ class DeleteClusterRequest: UUID of the Database Instance to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -603,7 +603,7 @@ class DeleteClusterSettingRequest: Setting name to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -616,7 +616,7 @@ class DeleteEndpointRequest: UUID of the endpoint you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -629,7 +629,7 @@ class GetAclRuleRequest: UUID of the ACL rule you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -642,7 +642,7 @@ class GetClusterCertificateRequest: UUID of the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -655,7 +655,7 @@ class GetClusterMetricsRequest: UUID of the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -683,7 +683,7 @@ class GetClusterRequest: UUID of the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -696,7 +696,7 @@ class GetEndpointRequest: UUID of the endpoint you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -719,7 +719,7 @@ class ListClusterVersionsRequest: Defines whether or not to include deprecated Redis™ engine versions. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -749,7 +749,7 @@ class ListClusterVersionsResponse: @dataclass class ListClustersRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -809,7 +809,7 @@ class ListNodeTypesRequest: Defines whether or not to include disabled types. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -839,7 +839,7 @@ class MigrateClusterRequest: UUID of the Database Instance to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -858,7 +858,7 @@ class RenewClusterCertificateRequest: UUID of the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -876,7 +876,7 @@ class SetAclRulesRequest: ACLs rules to define for the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -902,7 +902,7 @@ class SetClusterSettingsRequest: Settings to define for the Database Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -920,7 +920,7 @@ class SetEndpointsRequest: Endpoints to define for the Database Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -941,7 +941,7 @@ class UpdateClusterRequest: UUID of the Database Instance to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -974,7 +974,7 @@ class UpdateEndpointRequest: UUID of the endpoint you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway-async/scaleway_async/registry/v1/api.py b/scaleway-async/scaleway_async/registry/v1/api.py index 258a0558..0b0e3db6 100644 --- a/scaleway-async/scaleway_async/registry/v1/api.py +++ b/scaleway-async/scaleway_async/registry/v1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( WaitForOptions, @@ -49,13 +49,13 @@ class RegistryV1API(API): """ - Container Registry API. + This API allows you to manage your Container Registry resources. """ async def list_namespaces( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -105,7 +105,7 @@ async def list_namespaces( async def list_namespaces_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -150,7 +150,7 @@ async def get_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Get a namespace. @@ -184,7 +184,7 @@ async def wait_for_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[Namespace, Union[bool, Awaitable[bool]]] ] = None, @@ -224,7 +224,7 @@ async def create_namespace( *, description: str, is_public: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, @@ -278,7 +278,7 @@ async def update_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, is_public: Optional[bool] = None, ) -> Namespace: @@ -325,7 +325,7 @@ async def delete_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Delete a namespace. @@ -358,7 +358,7 @@ async def delete_namespace( async def list_images( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListImagesRequestOrderBy] = None, @@ -411,7 +411,7 @@ async def list_images( async def list_images_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListImagesRequestOrderBy] = None, @@ -459,7 +459,7 @@ async def get_image( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Image: """ Get an image. @@ -493,7 +493,7 @@ async def wait_for_image( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Image, Union[bool, Awaitable[bool]]]] = None, ) -> Image: """ @@ -530,7 +530,7 @@ async def update_image( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, visibility: Optional[ImageVisibility] = None, ) -> Image: """ @@ -574,7 +574,7 @@ async def delete_image( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Image: """ Delete an image. @@ -608,7 +608,7 @@ async def list_tags( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTagsRequestOrderBy] = None, @@ -656,7 +656,7 @@ async def list_tags_all( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTagsRequestOrderBy] = None, @@ -699,7 +699,7 @@ async def get_tag( self, *, tag_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Tag: """ Get a tag. @@ -733,7 +733,7 @@ async def wait_for_tag( self, *, tag_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Tag, Union[bool, Awaitable[bool]]]] = None, ) -> Tag: """ @@ -770,7 +770,7 @@ async def delete_tag( self, *, tag_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, force: Optional[bool] = None, ) -> Tag: """ diff --git a/scaleway-async/scaleway_async/registry/v1/marshalling.py b/scaleway-async/scaleway_async/registry/v1/marshalling.py index d720c137..1ffa9c7f 100644 --- a/scaleway-async/scaleway_async/registry/v1/marshalling.py +++ b/scaleway-async/scaleway_async/registry/v1/marshalling.py @@ -61,14 +61,20 @@ def unmarshal_Image(data: Any) -> Image: field = data.get("status_message", None) if field is not None: args["status_message"] = field + else: + args["status_message"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Image(**args) @@ -132,10 +138,14 @@ def unmarshal_Namespace(data: Any) -> Namespace: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Namespace(**args) @@ -171,10 +181,14 @@ def unmarshal_Tag(data: Any) -> Tag: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Tag(**args) diff --git a/scaleway-async/scaleway_async/registry/v1/types.py b/scaleway-async/scaleway_async/registry/v1/types.py index 8caf3e1f..e5e425da 100644 --- a/scaleway-async/scaleway_async/registry/v1/types.py +++ b/scaleway-async/scaleway_async/registry/v1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -152,7 +152,7 @@ class Namespace: name: str """ - Name of the namespace, unique in a region accross all organizations. + Name of the namespace, unique in a region across all organizations. """ description: str @@ -200,7 +200,7 @@ class Namespace: Number of images in the namespace. """ - region: Region + region: ScwRegion """ Region the namespace belongs to. """ @@ -266,7 +266,7 @@ class CreateNamespaceRequest: Defines whether or not namespace is public. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -288,7 +288,7 @@ class DeleteImageRequest: UUID of the image. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -301,7 +301,7 @@ class DeleteNamespaceRequest: UUID of the namespace. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -314,7 +314,7 @@ class DeleteTagRequest: UUID of the tag. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -332,7 +332,7 @@ class GetImageRequest: UUID of the image. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -345,7 +345,7 @@ class GetNamespaceRequest: UUID of the namespace. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -358,7 +358,7 @@ class GetTagRequest: UUID of the tag. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -366,7 +366,7 @@ class GetTagRequest: @dataclass class ListImagesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -422,7 +422,7 @@ class ListImagesResponse: @dataclass class ListNamespacesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -478,7 +478,7 @@ class ListTagsRequest: UUID of the image. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -524,7 +524,7 @@ class UpdateImageRequest: ID of the image to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -542,7 +542,7 @@ class UpdateNamespaceRequest: ID of the namespace to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway-async/scaleway_async/secret/v1alpha1/api.py b/scaleway-async/scaleway_async/secret/v1alpha1/api.py index 797e11e5..87483f25 100644 --- a/scaleway-async/scaleway_async/secret/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/secret/v1alpha1/api.py @@ -57,7 +57,7 @@ class SecretV1Alpha1API(API): """ - This API allows you to conveniently store, access and share sensitive data. + This API allows you to manage your Secret Manager services, for storing, accessing and sharing sensitive data such as passwords, API keys and certificates. """ async def create_secret( diff --git a/scaleway-async/scaleway_async/secret/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/secret/v1alpha1/marshalling.py index 6c6efd10..8be5c217 100644 --- a/scaleway-async/scaleway_async/secret/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/secret/v1alpha1/marshalling.py @@ -58,6 +58,8 @@ def unmarshal_Folder(data: Any) -> Folder: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return Folder(**args) @@ -77,10 +79,14 @@ def unmarshal_EphemeralProperties(data: Any) -> EphemeralProperties: field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("expires_once_accessed", None) if field is not None: args["expires_once_accessed"] = field + else: + args["expires_once_accessed"] = None return EphemeralProperties(**args) @@ -112,18 +118,26 @@ def unmarshal_SecretVersion(data: Any) -> SecretVersion: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("ephemeral_properties", None) if field is not None: args["ephemeral_properties"] = unmarshal_EphemeralProperties(field) + else: + args["ephemeral_properties"] = None return SecretVersion(**args) @@ -143,10 +157,14 @@ def unmarshal_EphemeralPolicy(data: Any) -> EphemeralPolicy: field = data.get("time_to_live", None) if field is not None: args["time_to_live"] = field + else: + args["time_to_live"] = None field = data.get("expires_once_accessed", None) if field is not None: args["expires_once_accessed"] = field + else: + args["expires_once_accessed"] = None return EphemeralPolicy(**args) @@ -178,10 +196,14 @@ def unmarshal_Secret(data: Any) -> Secret: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("tags", None) if field is not None: @@ -199,7 +221,7 @@ def unmarshal_Secret(data: Any) -> Secret: if field is not None: args["is_protected"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -214,10 +236,14 @@ def unmarshal_Secret(data: Any) -> Secret: field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("ephemeral_policy", None) if field is not None: args["ephemeral_policy"] = unmarshal_EphemeralPolicy(field) + else: + args["ephemeral_policy"] = None return Secret(**args) @@ -245,6 +271,8 @@ def unmarshal_AccessSecretVersionResponse(data: Any) -> AccessSecretVersionRespo field = data.get("data_crc32", None) if field is not None: args["data_crc32"] = field + else: + args["data_crc32"] = None return AccessSecretVersionResponse(**args) @@ -410,8 +438,8 @@ def marshal_CreateSecretRequest( output["path"] = request.path if request.ephemeral_policy is not None: - output["ephemeral_policy"] = ( - marshal_EphemeralPolicy(request.ephemeral_policy, defaults), + output["ephemeral_policy"] = marshal_EphemeralPolicy( + request.ephemeral_policy, defaults ) return output @@ -457,8 +485,8 @@ def marshal_CreateSecretVersionRequest( output["disable_previous"] = request.disable_previous if request.password_generation is not None: - output["password_generation"] = ( - marshal_PasswordGenerationParams(request.password_generation, defaults), + output["password_generation"] = marshal_PasswordGenerationParams( + request.password_generation, defaults ) if request.data_crc32 is not None: @@ -516,8 +544,8 @@ def marshal_UpdateSecretRequest( output["path"] = request.path if request.ephemeral_policy is not None: - output["ephemeral_policy"] = ( - marshal_EphemeralPolicy(request.ephemeral_policy, defaults), + output["ephemeral_policy"] = marshal_EphemeralPolicy( + request.ephemeral_policy, defaults ) return output @@ -533,7 +561,7 @@ def marshal_EphemeralProperties( output["action"] = str(request.action) if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() if request.expires_once_accessed is not None: output["expires_once_accessed"] = request.expires_once_accessed @@ -551,8 +579,8 @@ def marshal_UpdateSecretVersionRequest( output["description"] = request.description if request.ephemeral_properties is not None: - output["ephemeral_properties"] = ( - marshal_EphemeralProperties(request.ephemeral_properties, defaults), + output["ephemeral_properties"] = marshal_EphemeralProperties( + request.ephemeral_properties, defaults ) return output diff --git a/scaleway-async/scaleway_async/secret/v1beta1/__init__.py b/scaleway-async/scaleway_async/secret/v1beta1/__init__.py index b00f3efc..531ccc83 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/__init__.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/__init__.py @@ -14,19 +14,24 @@ from .types import BrowseSecretsResponseItem from .types import SecretVersion from .types import Secret +from .types import AccessSecretVersionByPathRequest from .types import AccessSecretVersionRequest from .types import AccessSecretVersionResponse from .types import AddSecretOwnerRequest +from .types import BasicCredentials from .types import BrowseSecretsRequest from .types import BrowseSecretsResponse from .types import CreateSecretRequest from .types import CreateSecretVersionRequest +from .types import DatabaseCredentials from .types import DeleteSecretRequest from .types import DeleteSecretVersionRequest from .types import DisableSecretVersionRequest from .types import EnableSecretVersionRequest from .types import GetSecretRequest from .types import GetSecretVersionRequest +from .types import ListSecretTypesRequest +from .types import ListSecretTypesResponse from .types import ListSecretVersionsRequest from .types import ListSecretVersionsResponse from .types import ListSecretsRequest @@ -34,6 +39,9 @@ from .types import ListTagsRequest from .types import ListTagsResponse from .types import ProtectSecretRequest +from .types import RestoreSecretRequest +from .types import RestoreSecretVersionRequest +from .types import SSHKey from .types import UnprotectSecretRequest from .types import UpdateSecretRequest from .types import UpdateSecretVersionRequest @@ -54,19 +62,24 @@ "BrowseSecretsResponseItem", "SecretVersion", "Secret", + "AccessSecretVersionByPathRequest", "AccessSecretVersionRequest", "AccessSecretVersionResponse", "AddSecretOwnerRequest", + "BasicCredentials", "BrowseSecretsRequest", "BrowseSecretsResponse", "CreateSecretRequest", "CreateSecretVersionRequest", + "DatabaseCredentials", "DeleteSecretRequest", "DeleteSecretVersionRequest", "DisableSecretVersionRequest", "EnableSecretVersionRequest", "GetSecretRequest", "GetSecretVersionRequest", + "ListSecretTypesRequest", + "ListSecretTypesResponse", "ListSecretVersionsRequest", "ListSecretVersionsResponse", "ListSecretsRequest", @@ -74,6 +87,9 @@ "ListTagsRequest", "ListTagsResponse", "ProtectSecretRequest", + "RestoreSecretRequest", + "RestoreSecretVersionRequest", + "SSHKey", "UnprotectSecretRequest", "UpdateSecretRequest", "UpdateSecretVersionRequest", diff --git a/scaleway-async/scaleway_async/secret/v1beta1/api.py b/scaleway-async/scaleway_async/secret/v1beta1/api.py index 9f53f77b..b45fd612 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/api.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( validate_path_param, @@ -24,6 +24,7 @@ CreateSecretVersionRequest, EphemeralPolicy, EphemeralProperties, + ListSecretTypesResponse, ListSecretVersionsResponse, ListSecretsResponse, ListTagsResponse, @@ -37,6 +38,7 @@ unmarshal_Secret, unmarshal_AccessSecretVersionResponse, unmarshal_BrowseSecretsResponse, + unmarshal_ListSecretTypesResponse, unmarshal_ListSecretVersionsResponse, unmarshal_ListSecretsResponse, unmarshal_ListTagsResponse, @@ -50,7 +52,7 @@ class SecretV1Beta1API(API): """ - This API allows you to conveniently store, access and share sensitive data such as passwords, API keys and certificates. + This API allows you to manage your Secret Manager services, for storing, accessing and sharing sensitive data such as passwords, API keys and certificates. """ async def create_secret( @@ -58,26 +60,28 @@ async def create_secret( *, name: str, protected: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, description: Optional[str] = None, type_: Optional[SecretType] = None, path: Optional[str] = None, ephemeral_policy: Optional[EphemeralPolicy] = None, + key_id: Optional[str] = None, ) -> Secret: """ Create a secret. - You must specify the `region` to create a secret. + Create a secret in a given region specified by the `region` parameter. :param name: Name of the secret. :param protected: A protected secret cannot be deleted. :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the Project containing the secret. :param tags: List of the secret's tags. :param description: Description of the secret. - :param type_: (Optional.) See `Secret.Type` enum for description of values. If not specified, the type is `Opaque`. + :param type_: (Optional.) See the `Secret.Type` enum for a description of values. If not specified, the type is `Opaque`. :param path: (Optional.) Location of the secret in the directory structure. If not specified, the path is `/`. :param ephemeral_policy: (Optional.) Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions. + :param key_id: (Optional.) The Scaleway Key Manager key ID will be used to encrypt and decrypt secret versions. If not specified, Secret Manager will use a Key Manager internal key. :return: :class:`Secret ` Usage: @@ -107,6 +111,7 @@ async def create_secret( type_=type_, path=path, ephemeral_policy=ephemeral_policy, + key_id=key_id, ), self.client, ), @@ -119,7 +124,7 @@ async def get_secret( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Secret: """ Get metadata using the secret's ID. @@ -153,7 +158,7 @@ async def update_secret( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, description: Optional[str] = None, @@ -209,7 +214,7 @@ async def delete_secret( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a secret. @@ -240,7 +245,8 @@ async def delete_secret( async def list_secrets( self, *, - region: Optional[Region] = None, + scheduled_for_deletion: bool, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, order_by: Optional[ListSecretsRequestOrderBy] = None, @@ -255,6 +261,7 @@ async def list_secrets( """ List secrets. Retrieve the list of secrets created within an Organization and/or Project. You must specify either the `organization_id` or the `project_id` and the `region`. + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by Organization ID (optional). :param project_id: Filter by Project ID (optional). @@ -271,7 +278,9 @@ async def list_secrets( Usage: :: - result = await api.list_secrets() + result = await api.list_secrets( + scheduled_for_deletion=False, + ) """ param_region = validate_path_param( @@ -291,6 +300,7 @@ async def list_secrets( "page_size": page_size or self.client.default_page_size, "path": path, "project_id": project_id or self.client.default_project_id, + "scheduled_for_deletion": scheduled_for_deletion, "tags": tags, "type": type_, }, @@ -302,7 +312,8 @@ async def list_secrets( async def list_secrets_all( self, *, - region: Optional[Region] = None, + scheduled_for_deletion: bool, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, order_by: Optional[ListSecretsRequestOrderBy] = None, @@ -317,6 +328,7 @@ async def list_secrets_all( """ List secrets. Retrieve the list of secrets created within an Organization and/or Project. You must specify either the `organization_id` or the `project_id` and the `region`. + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by Organization ID (optional). :param project_id: Filter by Project ID (optional). @@ -333,7 +345,9 @@ async def list_secrets_all( Usage: :: - result = await api.list_secrets_all() + result = await api.list_secrets_all( + scheduled_for_deletion=False, + ) """ return await fetch_all_pages_async( @@ -341,6 +355,7 @@ async def list_secrets_all( key="secrets", fetcher=self.list_secrets, args={ + "scheduled_for_deletion": scheduled_for_deletion, "region": region, "organization_id": organization_id, "project_id": project_id, @@ -359,12 +374,13 @@ async def browse_secrets( self, *, prefix: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, order_by: Optional[BrowseSecretsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, tags: Optional[List[str]] = None, + type_: Optional[SecretType] = None, ) -> BrowseSecretsResponse: """ Browse secrets. @@ -376,6 +392,7 @@ async def browse_secrets( :param page: :param page_size: :param tags: Filter secrets by tags. + :param type_: Filter by secret type (optional). :return: :class:`BrowseSecretsResponse ` Usage: @@ -400,6 +417,7 @@ async def browse_secrets( "prefix": prefix, "project_id": project_id or self.client.default_project_id, "tags": tags, + "type": type_, }, ) @@ -410,7 +428,7 @@ async def protect_secret( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Secret: """ Enable secret protection. @@ -445,7 +463,7 @@ async def unprotect_secret( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Secret: """ Disable secret protection. @@ -480,7 +498,7 @@ async def add_secret_owner( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, product: Optional[Product] = None, ) -> None: """ @@ -522,7 +540,7 @@ async def create_secret_version( *, secret_id: str, data: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, disable_previous: Optional[bool] = None, data_crc32: Optional[int] = None, @@ -576,7 +594,7 @@ async def get_secret_version( *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SecretVersion: """ Get metadata of a secret's version using the secret's ID. @@ -617,7 +635,7 @@ async def update_secret_version( *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, ephemeral_properties: Optional[EphemeralProperties] = None, ) -> SecretVersion: @@ -672,7 +690,7 @@ async def delete_secret_version( *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a version. @@ -710,7 +728,7 @@ async def list_secret_versions( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, status: Optional[List[SecretVersionStatus]] = None, @@ -755,7 +773,7 @@ async def list_secret_versions_all( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, status: Optional[List[SecretVersionStatus]] = None, @@ -796,7 +814,7 @@ async def access_secret_version( *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> AccessSecretVersionResponse: """ Access a secret's version using the secret's ID. @@ -832,12 +850,62 @@ async def access_secret_version( self._throw_on_error(res) return unmarshal_AccessSecretVersionResponse(res.json()) + async def access_secret_version_by_path( + self, + *, + secret_path: str, + secret_name: str, + revision: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AccessSecretVersionResponse: + """ + Access a secret's version using the secret's name and path. + Access sensitive data in a secret's version specified by the `region`, `secret_name`, `secret_path` and `revision` parameters. + :param secret_path: Secret's path. + :param secret_name: Secret's name. + :param revision: The first version of the secret is numbered 1, and all subsequent revisions augment by 1. Value can be either: + - an integer (the revision number) + - "latest" (the latest revision) + - "latest_enabled" (the latest enabled revision). + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to target. + :return: :class:`AccessSecretVersionResponse ` + + Usage: + :: + + result = await api.access_secret_version_by_path( + secret_path="example", + secret_name="example", + revision="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_revision = validate_path_param("revision", revision) + + res = self._request( + "GET", + f"/secret-manager/v1beta1/regions/{param_region}/secrets-by-path/versions/{param_revision}/access", + params={ + "project_id": project_id or self.client.default_project_id, + "secret_name": secret_name, + "secret_path": secret_path, + }, + ) + + self._throw_on_error(res) + return unmarshal_AccessSecretVersionResponse(res.json()) + async def enable_secret_version( self, *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SecretVersion: """ Enable a version. @@ -879,7 +947,7 @@ async def disable_secret_version( *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SecretVersion: """ Disable a version. @@ -919,7 +987,7 @@ async def disable_secret_version( async def list_tags( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -959,7 +1027,7 @@ async def list_tags( async def list_tags_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -990,3 +1058,152 @@ async def list_tags_all( "page_size": page_size, }, ) + + async def list_secret_types( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListSecretTypesResponse: + """ + List secret types. + List all secret types created within a given Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to target. + :param page: + :param page_size: + :return: :class:`ListSecretTypesResponse ` + + Usage: + :: + + result = await api.list_secret_types() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/secret-manager/v1beta1/regions/{param_region}/secret-types", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListSecretTypesResponse(res.json()) + + async def list_secret_types_all( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[SecretType]: + """ + List secret types. + List all secret types created within a given Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to target. + :param page: + :param page_size: + :return: :class:`List[SecretType] ` + + Usage: + :: + + result = await api.list_secret_types_all() + """ + + return await fetch_all_pages_async( + type=ListSecretTypesResponse, + key="types", + fetcher=self.list_secret_types, + args={ + "region": region, + "project_id": project_id, + "page": page, + "page_size": page_size, + }, + ) + + async def restore_secret_version( + self, + *, + secret_id: str, + revision: str, + region: Optional[ScwRegion] = None, + ) -> SecretVersion: + """ + Restore a version. + Restore a secret's version specified by the `region`, `secret_id` and `revision` parameters. + :param secret_id: + :param revision: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`SecretVersion ` + + Usage: + :: + + result = await api.restore_secret_version( + secret_id="example", + revision="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_secret_id = validate_path_param("secret_id", secret_id) + param_revision = validate_path_param("revision", revision) + + res = self._request( + "POST", + f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/versions/{param_revision}/restore", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_SecretVersion(res.json()) + + async def restore_secret( + self, + *, + secret_id: str, + region: Optional[ScwRegion] = None, + ) -> Secret: + """ + Restore a secret. + Restore a secret and all its versions scheduled for deletion specified by the `region` and `secret_id` parameters. + :param secret_id: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Secret ` + + Usage: + :: + + result = await api.restore_secret( + secret_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_secret_id = validate_path_param("secret_id", secret_id) + + res = self._request( + "POST", + f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/restore", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Secret(res.json()) diff --git a/scaleway-async/scaleway_async/secret/v1beta1/marshalling.py b/scaleway-async/scaleway_async/secret/v1beta1/marshalling.py index c38b8cbe..3bf186c9 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/marshalling.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/marshalling.py @@ -6,6 +6,8 @@ from scaleway_core.profile import ProfileDefaults from .types import ( + Product, + SecretType, EphemeralProperties, SecretVersion, EphemeralPolicy, @@ -15,6 +17,7 @@ BrowseSecretsResponseItemSecretDetails, BrowseSecretsResponseItem, BrowseSecretsResponse, + ListSecretTypesResponse, ListSecretVersionsResponse, ListSecretsResponse, ListTagsResponse, @@ -41,10 +44,14 @@ def unmarshal_EphemeralProperties(data: Any) -> EphemeralProperties: field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("expires_once_accessed", None) if field is not None: args["expires_once_accessed"] = field + else: + args["expires_once_accessed"] = None return EphemeralProperties(**args) @@ -76,18 +83,40 @@ def unmarshal_SecretVersion(data: Any) -> SecretVersion: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("deleted_at", None) + if field is not None: + args["deleted_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["deleted_at"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("ephemeral_properties", None) if field is not None: args["ephemeral_properties"] = unmarshal_EphemeralProperties(field) + else: + args["ephemeral_properties"] = None + + field = data.get("deletion_requested_at", None) + if field is not None: + args["deletion_requested_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["deletion_requested_at"] = None return SecretVersion(**args) @@ -107,10 +136,14 @@ def unmarshal_EphemeralPolicy(data: Any) -> EphemeralPolicy: field = data.get("time_to_live", None) if field is not None: args["time_to_live"] = field + else: + args["time_to_live"] = None field = data.get("expires_once_accessed", None) if field is not None: args["expires_once_accessed"] = field + else: + args["expires_once_accessed"] = None return EphemeralPolicy(**args) @@ -139,14 +172,6 @@ def unmarshal_Secret(data: Any) -> Secret: if field is not None: args["status"] = field - field = data.get("created_at", None) - if field is not None: - args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field - - field = data.get("updated_at", None) - if field is not None: - args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field - field = data.get("tags", None) if field is not None: args["tags"] = field @@ -163,7 +188,7 @@ def unmarshal_Secret(data: Any) -> Secret: if field is not None: args["protected"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -171,17 +196,51 @@ def unmarshal_Secret(data: Any) -> Secret: if field is not None: args["path"] = field + field = data.get("used_by", None) + if field is not None: + args["used_by"] = [Product(v) for v in field] if field is not None else None + field = data.get("region", None) if field is not None: args["region"] = field + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("ephemeral_policy", None) if field is not None: args["ephemeral_policy"] = unmarshal_EphemeralPolicy(field) + else: + args["ephemeral_policy"] = None + + field = data.get("deletion_requested_at", None) + if field is not None: + args["deletion_requested_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["deletion_requested_at"] = None + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + else: + args["key_id"] = None return Secret(**args) @@ -206,9 +265,15 @@ def unmarshal_AccessSecretVersionResponse(data: Any) -> AccessSecretVersionRespo if field is not None: args["data"] = field + field = data.get("type", None) + if field is not None: + args["type_"] = field + field = data.get("data_crc32", None) if field is not None: args["data_crc32"] = field + else: + args["data_crc32"] = None return AccessSecretVersionResponse(**args) @@ -252,9 +317,15 @@ def unmarshal_BrowseSecretsResponseItemSecretDetails( if field is not None: args["protected"] = field + field = data.get("type", None) + if field is not None: + args["type_"] = field + field = data.get("ephemeral_policy", None) if field is not None: args["ephemeral_policy"] = unmarshal_EphemeralPolicy(field) + else: + args["ephemeral_policy"] = None return BrowseSecretsResponseItemSecretDetails(**args) @@ -274,18 +345,26 @@ def unmarshal_BrowseSecretsResponseItem(data: Any) -> BrowseSecretsResponseItem: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("secret", None) if field is not None: args["secret"] = unmarshal_BrowseSecretsResponseItemSecretDetails(field) + else: + args["secret"] = None field = data.get("folder", None) if field is not None: args["folder"] = unmarshal_BrowseSecretsResponseItemFolderDetails(field) + else: + args["folder"] = None return BrowseSecretsResponseItem(**args) @@ -317,6 +396,25 @@ def unmarshal_BrowseSecretsResponse(data: Any) -> BrowseSecretsResponse: return BrowseSecretsResponse(**args) +def unmarshal_ListSecretTypesResponse(data: Any) -> ListSecretTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSecretTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("types", None) + if field is not None: + args["types"] = [SecretType(v) for v in field] if field is not None else None + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListSecretTypesResponse(**args) + + def unmarshal_ListSecretVersionsResponse(data: Any) -> ListSecretVersionsResponse: if not isinstance(data, dict): raise TypeError( @@ -436,10 +534,13 @@ def marshal_CreateSecretRequest( output["path"] = request.path if request.ephemeral_policy is not None: - output["ephemeral_policy"] = ( - marshal_EphemeralPolicy(request.ephemeral_policy, defaults), + output["ephemeral_policy"] = marshal_EphemeralPolicy( + request.ephemeral_policy, defaults ) + if request.key_id is not None: + output["key_id"] = request.key_id + return output @@ -483,8 +584,8 @@ def marshal_UpdateSecretRequest( output["path"] = request.path if request.ephemeral_policy is not None: - output["ephemeral_policy"] = ( - marshal_EphemeralPolicy(request.ephemeral_policy, defaults), + output["ephemeral_policy"] = marshal_EphemeralPolicy( + request.ephemeral_policy, defaults ) return output @@ -500,7 +601,7 @@ def marshal_EphemeralProperties( output["action"] = str(request.action) if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() if request.expires_once_accessed is not None: output["expires_once_accessed"] = request.expires_once_accessed @@ -518,8 +619,8 @@ def marshal_UpdateSecretVersionRequest( output["description"] = request.description if request.ephemeral_properties is not None: - output["ephemeral_properties"] = ( - marshal_EphemeralProperties(request.ephemeral_properties, defaults), + output["ephemeral_properties"] = marshal_EphemeralProperties( + request.ephemeral_properties, defaults ) return output diff --git a/scaleway-async/scaleway_async/secret/v1beta1/types.py b/scaleway-async/scaleway_async/secret/v1beta1/types.py index a03d231f..aa5423e8 100644 --- a/scaleway-async/scaleway_async/secret/v1beta1/types.py +++ b/scaleway-async/scaleway_async/secret/v1beta1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -83,6 +83,7 @@ class SecretVersionStatus(str, Enum, metaclass=StrEnumMeta): ENABLED = "enabled" DISABLED = "disabled" DELETED = "deleted" + SCHEDULED_FOR_DELETION = "scheduled_for_deletion" def __str__(self) -> str: return str(self.value) @@ -121,6 +122,8 @@ class BrowseSecretsResponseItemSecretDetails: protected: bool + type_: SecretType + ephemeral_policy: Optional[EphemeralPolicy] @@ -169,9 +172,10 @@ class SecretVersion: status: SecretVersionStatus """ - * `unknown`: the version is in an invalid state. + * `unknown_status`: the version is in an invalid state. * `enabled`: the version is accessible. * `disabled`: the version is not accessible but can be enabled. +* `scheduled_for_deletion`: the version is scheduled for deletion. It will be deleted in 7 days. * `deleted`: the version is permanently deleted. It is not possible to recover it. """ @@ -190,6 +194,11 @@ class SecretVersion: Last update of the version. """ + deleted_at: Optional[datetime] + """ + Date and time of the version's deletion. + """ + description: Optional[str] """ Description of the version. @@ -200,6 +209,11 @@ class SecretVersion: Returns the version's expiration date, whether it expires after being accessed once, and the action to perform (disable or delete) once the version expires. """ + deletion_requested_at: Optional[datetime] + """ + Returns the time at which deletion was requested. + """ + @dataclass class Secret: @@ -224,16 +238,6 @@ class Secret: * `locked`: no action can be performed on the secret. This status can only be applied and removed by Scaleway. """ - created_at: Optional[datetime] - """ - Date and time of the secret's creation. - """ - - updated_at: Optional[datetime] - """ - Last update of the secret. - """ - tags: List[str] """ List of the secret's tags. @@ -256,7 +260,7 @@ class Secret: type_: SecretType """ - See `Secret.Type` enum for description of values. + See the `Secret.Type` enum for a description of values. """ path: str @@ -264,11 +268,26 @@ class Secret: Location of the secret in the directory structure. """ - region: Region + used_by: List[Product] + """ + List of Scaleway resources that can access and manage the secret. + """ + + region: ScwRegion """ Region of the secret. """ + created_at: Optional[datetime] + """ + Date and time of the secret's creation. + """ + + updated_at: Optional[datetime] + """ + Last update of the secret. + """ + description: Optional[str] """ Updated description of the secret. @@ -279,6 +298,47 @@ class Secret: (Optional.) Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions. """ + deletion_requested_at: Optional[datetime] + """ + Returns the time at which deletion was requested. + """ + + key_id: Optional[str] + """ + (Optional.) The Scaleway Key Manager key ID used to encrypt and decrypt secret versions. + """ + + +@dataclass +class AccessSecretVersionByPathRequest: + secret_path: str + """ + Secret's path. + """ + + secret_name: str + """ + Secret's name. + """ + + revision: str + """ + The first version of the secret is numbered 1, and all subsequent revisions augment by 1. Value can be either: +- an integer (the revision number) +- "latest" (the latest revision) +- "latest_enabled" (the latest enabled revision). + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + @dataclass class AccessSecretVersionRequest: @@ -295,7 +355,7 @@ class AccessSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -318,6 +378,11 @@ class AccessSecretVersionResponse: The base64-encoded secret payload of the version. """ + type_: SecretType + """ + See the `Secret.Type` enum for a description of values. + """ + data_crc32: Optional[int] """ This field is only available if a CRC32 was supplied during the creation of the version. @@ -331,7 +396,7 @@ class AddSecretOwnerRequest: ID of the secret. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -342,6 +407,19 @@ class AddSecretOwnerRequest: """ +@dataclass +class BasicCredentials: + username: str + """ + The username or identifier associated with the credentials. + """ + + password: str + """ + The password associated with the credentials. + """ + + @dataclass class BrowseSecretsRequest: prefix: str @@ -349,7 +427,7 @@ class BrowseSecretsRequest: Filter secrets and folders for a given prefix (default /). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -370,6 +448,11 @@ class BrowseSecretsRequest: Filter secrets by tags. """ + type_: Optional[SecretType] + """ + Filter by secret type (optional). + """ + @dataclass class BrowseSecretsResponse: @@ -401,7 +484,7 @@ class CreateSecretRequest: A protected secret cannot be deleted. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -423,7 +506,7 @@ class CreateSecretRequest: type_: Optional[SecretType] """ - (Optional.) See `Secret.Type` enum for description of values. If not specified, the type is `Opaque`. + (Optional.) See the `Secret.Type` enum for a description of values. If not specified, the type is `Opaque`. """ path: Optional[str] @@ -436,6 +519,11 @@ class CreateSecretRequest: (Optional.) Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions. """ + key_id: Optional[str] + """ + (Optional.) The Scaleway Key Manager key ID will be used to encrypt and decrypt secret versions. If not specified, Secret Manager will use a Key Manager internal key. + """ + @dataclass class CreateSecretVersionRequest: @@ -449,7 +537,7 @@ class CreateSecretVersionRequest: The base64-encoded secret payload of the version. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -470,6 +558,39 @@ class CreateSecretVersionRequest: """ +@dataclass +class DatabaseCredentials: + engine: str + """ + Supported database engines are: 'postgres', 'mysql', 'other'. + """ + + username: str + """ + The username used to authenticate to the database server. + """ + + password: str + """ + The password used to authenticate to the database server. + """ + + host: str + """ + The hostname or resolvable DNS name of the database server. + """ + + dbname: str + """ + The name of the database to connect to. + """ + + port: str + """ + The port must be an integer ranging from 0 to 65535. + """ + + @dataclass class DeleteSecretRequest: secret_id: str @@ -477,7 +598,7 @@ class DeleteSecretRequest: ID of the secret. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -498,7 +619,7 @@ class DeleteSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -519,7 +640,7 @@ class DisableSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -540,7 +661,7 @@ class EnableSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -553,7 +674,7 @@ class GetSecretRequest: ID of the secret. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -574,12 +695,42 @@ class GetSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class ListSecretTypesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListSecretTypesResponse: + types: List[SecretType] + """ + List of secret types. + """ + + total_count: int + """ + Count of all secret types matching the requested criteria. + """ + + @dataclass class ListSecretVersionsRequest: secret_id: str @@ -587,7 +738,7 @@ class ListSecretVersionsRequest: ID of the secret. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -617,7 +768,12 @@ class ListSecretVersionsResponse: @dataclass class ListSecretsRequest: - region: Optional[Region] + scheduled_for_deletion: bool + """ + Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -679,7 +835,7 @@ class ListSecretsResponse: @dataclass class ListTagsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -714,12 +870,42 @@ class ProtectSecretRequest: ID of the secret to enable secret protection for. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class RestoreSecretRequest: + secret_id: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RestoreSecretVersionRequest: + secret_id: str + + revision: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SSHKey: + ssh_private_key: str + """ + The private SSH key. + """ + + @dataclass class UnprotectSecretRequest: secret_id: str @@ -727,7 +913,7 @@ class UnprotectSecretRequest: ID of the secret to disable secret protection for. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -740,7 +926,7 @@ class UpdateSecretRequest: ID of the secret. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -786,7 +972,7 @@ class UpdateSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/api.py b/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/api.py index 0a07ce5e..b4f4c606 100644 --- a/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( WaitForOptions, @@ -40,7 +40,7 @@ class ServerlessSqldbV1Alpha1API(API): """ - This API allows you to manage your Serverless SQL DB databases. + This API allows you to manage your Serverless SQL Databases. """ async def create_database( @@ -49,7 +49,7 @@ async def create_database( name: str, cpu_min: int, cpu_max: int, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, from_backup_id: Optional[str] = None, ) -> Database: @@ -101,7 +101,7 @@ async def get_database( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Database: """ Get a database information. @@ -135,7 +135,7 @@ async def wait_for_database( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[ WaitForOptions[Database, Union[bool, Awaitable[bool]]] ] = None, @@ -174,7 +174,7 @@ async def delete_database( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Database: """ Delete a database. @@ -207,7 +207,7 @@ async def delete_database( async def list_databases( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, page: Optional[int] = None, @@ -257,7 +257,7 @@ async def list_databases( async def list_databases_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, page: Optional[int] = None, @@ -302,7 +302,7 @@ async def update_database( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, cpu_min: Optional[int] = None, cpu_max: Optional[int] = None, ) -> Database: @@ -350,7 +350,7 @@ async def restore_database_from_backup( *, database_id: str, backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Database: """ Restore a database from a backup. @@ -394,7 +394,7 @@ async def get_database_backup( self, *, backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DatabaseBackup: """ Get a database backup information. @@ -428,7 +428,7 @@ async def list_database_backups( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, page: Optional[int] = None, @@ -437,7 +437,7 @@ async def list_database_backups( ) -> ListDatabaseBackupsResponse: """ List your Serverless SQL Database backups. - List all Serverless SQL Database backups for a given Scaleway Project or Database. By default, the backups returned in the list are ordered by creation date in ascending order, though this can be modified via the order_by field. + List all Serverless SQL Database backups for a given Scaleway Project or Database. By default, the backups returned in the list are ordered by creation date in descending order, though this can be modified via the order_by field. :param database_id: Filter by the UUID of the Serverless SQL Database. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by the UUID of the Scaleway organization. @@ -480,7 +480,7 @@ async def list_database_backups_all( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, page: Optional[int] = None, @@ -489,7 +489,7 @@ async def list_database_backups_all( ) -> List[DatabaseBackup]: """ List your Serverless SQL Database backups. - List all Serverless SQL Database backups for a given Scaleway Project or Database. By default, the backups returned in the list are ordered by creation date in ascending order, though this can be modified via the order_by field. + List all Serverless SQL Database backups for a given Scaleway Project or Database. By default, the backups returned in the list are ordered by creation date in descending order, though this can be modified via the order_by field. :param database_id: Filter by the UUID of the Serverless SQL Database. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by the UUID of the Scaleway organization. @@ -526,7 +526,7 @@ async def export_database_backup( self, *, backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DatabaseBackup: """ Export a database backup. diff --git a/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/marshalling.py index 88f441a6..13a841b1 100644 --- a/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/marshalling.py @@ -51,24 +51,40 @@ def unmarshal_DatabaseBackup(data: Any) -> DatabaseBackup: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("size", None) if field is not None: args["size"] = field + else: + args["size"] = None + + field = data.get("db_size", None) + if field is not None: + args["db_size"] = field + else: + args["db_size"] = None field = data.get("download_url", None) if field is not None: args["download_url"] = field + else: + args["download_url"] = None field = data.get("download_url_expires_at", None) if field is not None: args["download_url_expires_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["download_url_expires_at"] = None return DatabaseBackup(**args) @@ -132,6 +148,8 @@ def unmarshal_Database(data: Any) -> Database: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return Database(**args) diff --git a/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/types.py b/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/types.py index d7b885d7..6ec7e725 100644 --- a/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/serverless_sqldb/v1alpha1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -39,8 +39,8 @@ def __str__(self) -> str: class ListDatabaseBackupsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): - CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" def __str__(self) -> str: return str(self.value) @@ -83,7 +83,7 @@ class DatabaseBackup: UUID of the source Serverless SQL Database the backup is created from. """ - region: Region + region: ScwRegion """ Region of the database backup. """ @@ -100,7 +100,12 @@ class DatabaseBackup: size: Optional[int] """ - Size of the database backup. + Size (in bytes) of the database backup file. + """ + + db_size: Optional[int] + """ + Size (in bytes) of the database when backup has been done. """ download_url: Optional[str] @@ -146,7 +151,7 @@ class Database: Project ID the database belongs to. """ - region: Region + region: ScwRegion """ Region of the database. """ @@ -199,7 +204,7 @@ class CreateDatabaseRequest: The maximum number of CPU units for your Serverless SQL Database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -222,7 +227,7 @@ class DeleteDatabaseRequest: UUID of the Serverless SQL Database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -235,7 +240,7 @@ class ExportDatabaseBackupRequest: UUID of the Serverless SQL Database backup. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -248,7 +253,7 @@ class GetDatabaseBackupRequest: UUID of the Serverless SQL Database backup. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -261,7 +266,7 @@ class GetDatabaseRequest: UUID of the Serverless SQL DB database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -274,7 +279,7 @@ class ListDatabaseBackupsRequest: Filter by the UUID of the Serverless SQL Database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -320,7 +325,7 @@ class ListDatabaseBackupsResponse: @dataclass class ListDatabasesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -381,7 +386,7 @@ class RestoreDatabaseFromBackupRequest: UUID of the Serverless SQL Database backup to restore. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -394,7 +399,7 @@ class UpdateDatabaseRequest: UUID of the Serverless SQL Database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/__init__.py b/scaleway-async/scaleway_async/tem/v1alpha1/__init__.py index 19db4a37..53ba0d7c 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/__init__.py @@ -1,5 +1,7 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import BlocklistType +from .types import DomainLastStatusAutoconfigStateReason from .types import DomainLastStatusRecordStatus from .types import DomainReputationStatus from .types import DomainStatus @@ -8,39 +10,84 @@ from .types import EmailRcptType from .types import EmailStatus from .content import EMAIL_TRANSIENT_STATUSES +from .types import ListBlocklistsRequestOrderBy from .types import ListEmailsRequestOrderBy +from .types import ListWebhookEventsRequestOrderBy +from .types import ListWebhooksRequestOrderBy +from .types import OfferName +from .types import PoolStatus +from .types import ProjectSettingsPeriodicReportFrequency +from .types import WebhookEventStatus +from .types import WebhookEventType from .types import DomainRecordsDMARC from .types import EmailTry from .types import DomainRecords from .types import DomainReputation from .types import DomainStatistics +from .types import Blocklist from .types import CreateEmailRequestAddress from .types import CreateEmailRequestAttachment from .types import CreateEmailRequestHeader from .types import Email +from .types import DomainLastStatusAutoconfigState from .types import DomainLastStatusDkimRecord from .types import DomainLastStatusDmarcRecord from .types import DomainLastStatusSpfRecord from .types import Domain +from .types import OfferSubscription +from .types import Offer +from .types import Pool +from .types import WebhookEvent +from .types import Webhook +from .types import ProjectSettingsPeriodicReport +from .types import UpdateProjectSettingsRequestUpdatePeriodicReport +from .types import BulkCreateBlocklistsRequest +from .types import BulkCreateBlocklistsResponse from .types import CancelEmailRequest from .types import CheckDomainRequest from .types import CreateDomainRequest from .types import CreateEmailRequest from .types import CreateEmailResponse +from .types import CreateWebhookRequest +from .types import DeleteBlocklistRequest +from .types import DeleteWebhookRequest from .types import DomainLastStatus from .types import GetDomainLastStatusRequest from .types import GetDomainRequest from .types import GetEmailRequest +from .types import GetProjectConsumptionRequest +from .types import GetProjectSettingsRequest from .types import GetStatisticsRequest +from .types import GetWebhookRequest +from .types import ListBlocklistsRequest +from .types import ListBlocklistsResponse from .types import ListDomainsRequest from .types import ListDomainsResponse from .types import ListEmailsRequest from .types import ListEmailsResponse +from .types import ListOfferSubscriptionsRequest +from .types import ListOfferSubscriptionsResponse +from .types import ListOffersRequest +from .types import ListOffersResponse +from .types import ListPoolsRequest +from .types import ListPoolsResponse +from .types import ListWebhookEventsRequest +from .types import ListWebhookEventsResponse +from .types import ListWebhooksRequest +from .types import ListWebhooksResponse +from .types import ProjectConsumption +from .types import ProjectSettings from .types import RevokeDomainRequest from .types import Statistics +from .types import UpdateDomainRequest +from .types import UpdateOfferSubscriptionRequest +from .types import UpdateProjectSettingsRequest +from .types import UpdateWebhookRequest from .api import TemV1Alpha1API __all__ = [ + "BlocklistType", + "DomainLastStatusAutoconfigStateReason", "DomainLastStatusRecordStatus", "DomainReputationStatus", "DomainStatus", @@ -49,35 +96,78 @@ "EmailRcptType", "EmailStatus", "EMAIL_TRANSIENT_STATUSES", + "ListBlocklistsRequestOrderBy", "ListEmailsRequestOrderBy", + "ListWebhookEventsRequestOrderBy", + "ListWebhooksRequestOrderBy", + "OfferName", + "PoolStatus", + "ProjectSettingsPeriodicReportFrequency", + "WebhookEventStatus", + "WebhookEventType", "DomainRecordsDMARC", "EmailTry", "DomainRecords", "DomainReputation", "DomainStatistics", + "Blocklist", "CreateEmailRequestAddress", "CreateEmailRequestAttachment", "CreateEmailRequestHeader", "Email", + "DomainLastStatusAutoconfigState", "DomainLastStatusDkimRecord", "DomainLastStatusDmarcRecord", "DomainLastStatusSpfRecord", "Domain", + "OfferSubscription", + "Offer", + "Pool", + "WebhookEvent", + "Webhook", + "ProjectSettingsPeriodicReport", + "UpdateProjectSettingsRequestUpdatePeriodicReport", + "BulkCreateBlocklistsRequest", + "BulkCreateBlocklistsResponse", "CancelEmailRequest", "CheckDomainRequest", "CreateDomainRequest", "CreateEmailRequest", "CreateEmailResponse", + "CreateWebhookRequest", + "DeleteBlocklistRequest", + "DeleteWebhookRequest", "DomainLastStatus", "GetDomainLastStatusRequest", "GetDomainRequest", "GetEmailRequest", + "GetProjectConsumptionRequest", + "GetProjectSettingsRequest", "GetStatisticsRequest", + "GetWebhookRequest", + "ListBlocklistsRequest", + "ListBlocklistsResponse", "ListDomainsRequest", "ListDomainsResponse", "ListEmailsRequest", "ListEmailsResponse", + "ListOfferSubscriptionsRequest", + "ListOfferSubscriptionsResponse", + "ListOffersRequest", + "ListOffersResponse", + "ListPoolsRequest", + "ListPoolsResponse", + "ListWebhookEventsRequest", + "ListWebhookEventsResponse", + "ListWebhooksRequest", + "ListWebhooksResponse", + "ProjectConsumption", + "ProjectSettings", "RevokeDomainRequest", "Statistics", + "UpdateDomainRequest", + "UpdateOfferSubscriptionRequest", + "UpdateProjectSettingsRequest", + "UpdateWebhookRequest", "TemV1Alpha1API", ] diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/api.py b/scaleway-async/scaleway_async/tem/v1alpha1/api.py index eb7f29a0..5d2f8269 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( WaitForOptions, @@ -15,22 +15,50 @@ wait_for_resource_async, ) from .types import ( + BlocklistType, DomainStatus, EmailFlag, EmailStatus, + ListBlocklistsRequestOrderBy, ListEmailsRequestOrderBy, + ListWebhookEventsRequestOrderBy, + ListWebhooksRequestOrderBy, + OfferName, + WebhookEventStatus, + WebhookEventType, + Blocklist, + BulkCreateBlocklistsRequest, + BulkCreateBlocklistsResponse, CreateDomainRequest, CreateEmailRequest, CreateEmailRequestAddress, CreateEmailRequestAttachment, CreateEmailRequestHeader, CreateEmailResponse, + CreateWebhookRequest, Domain, DomainLastStatus, Email, + ListBlocklistsResponse, ListDomainsResponse, ListEmailsResponse, + ListOfferSubscriptionsResponse, + ListOffersResponse, + ListPoolsResponse, + ListWebhookEventsResponse, + ListWebhooksResponse, + OfferSubscription, + Pool, + ProjectConsumption, + ProjectSettings, Statistics, + UpdateDomainRequest, + UpdateOfferSubscriptionRequest, + UpdateProjectSettingsRequest, + UpdateProjectSettingsRequestUpdatePeriodicReport, + UpdateWebhookRequest, + Webhook, + WebhookEvent, ) from .content import ( DOMAIN_TRANSIENT_STATUSES, @@ -39,27 +67,46 @@ from .marshalling import ( unmarshal_Email, unmarshal_Domain, + unmarshal_OfferSubscription, + unmarshal_Webhook, + unmarshal_BulkCreateBlocklistsResponse, unmarshal_CreateEmailResponse, unmarshal_DomainLastStatus, + unmarshal_ListBlocklistsResponse, unmarshal_ListDomainsResponse, unmarshal_ListEmailsResponse, + unmarshal_ListOfferSubscriptionsResponse, + unmarshal_ListOffersResponse, + unmarshal_ListPoolsResponse, + unmarshal_ListWebhookEventsResponse, + unmarshal_ListWebhooksResponse, + unmarshal_ProjectConsumption, + unmarshal_ProjectSettings, unmarshal_Statistics, + marshal_BulkCreateBlocklistsRequest, marshal_CreateDomainRequest, marshal_CreateEmailRequest, + marshal_CreateWebhookRequest, + marshal_UpdateDomainRequest, + marshal_UpdateOfferSubscriptionRequest, + marshal_UpdateProjectSettingsRequest, + marshal_UpdateWebhookRequest, ) class TemV1Alpha1API(API): - """ """ + """ + This API allows you to manage your Transactional Email services. + """ async def create_email( self, *, + from_: CreateEmailRequestAddress, subject: str, text: str, html: str, - region: Optional[Region] = None, - from_: Optional[CreateEmailRequestAddress] = None, + region: Optional[ScwRegion] = None, to: Optional[List[CreateEmailRequestAddress]] = None, cc: Optional[List[CreateEmailRequestAddress]] = None, bcc: Optional[List[CreateEmailRequestAddress]] = None, @@ -71,11 +118,11 @@ async def create_email( """ Send an email. You must specify the `region`, the sender and the recipient's information and the `project_id` to send an email from a checked domain. The subject of the email must contain at least 6 characters. + :param from_: Sender information. Must be from a checked domain declared in the Project. :param subject: Subject of the email. :param text: Text content. :param html: HTML content. :param region: Region to target. If none is passed will use default region from the config. - :param from_: Sender information. Must be from a checked domain declared in the Project. :param to: An array of the primary recipient's information. :param cc: An array of the carbon copy recipient's information. :param bcc: An array of the blind carbon copy recipient's information. @@ -89,6 +136,7 @@ async def create_email( :: result = await api.create_email( + from=CreateEmailRequestAddress(), subject="example", text="example", html="example", @@ -104,11 +152,11 @@ async def create_email( f"/transactional-email/v1alpha1/regions/{param_region}/emails", body=marshal_CreateEmailRequest( CreateEmailRequest( + from_=from_, subject=subject, text=text, html=html, region=region, - from_=from_, to=to, cc=cc, bcc=bcc, @@ -128,7 +176,7 @@ async def get_email( self, *, email_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Email: """ Get an email. @@ -162,7 +210,7 @@ async def wait_for_email( self, *, email_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Email, Union[bool, Awaitable[bool]]]] = None, ) -> Email: """ @@ -198,7 +246,7 @@ async def wait_for_email( async def list_emails( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, @@ -227,7 +275,7 @@ async def list_emails( :param since: (Optional) List emails created after this date. :param until: (Optional) List emails created before this date. :param mail_from: (Optional) List emails sent with this sender's email address. - :param mail_to: List emails sent to this recipient's email address. + :param mail_to: Deprecated. List emails sent to this recipient's email address. :param mail_rcpt: (Optional) List emails sent to this recipient's email address. :param statuses: (Optional) List emails with any of these statuses. :param subject: (Optional) List emails with this subject. @@ -274,7 +322,7 @@ async def list_emails( async def list_emails_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, @@ -303,7 +351,7 @@ async def list_emails_all( :param since: (Optional) List emails created after this date. :param until: (Optional) List emails created before this date. :param mail_from: (Optional) List emails sent with this sender's email address. - :param mail_to: List emails sent to this recipient's email address. + :param mail_to: Deprecated. List emails sent to this recipient's email address. :param mail_rcpt: (Optional) List emails sent to this recipient's email address. :param statuses: (Optional) List emails with any of these statuses. :param subject: (Optional) List emails with this subject. @@ -345,7 +393,7 @@ async def list_emails_all( async def get_statistics( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, domain_id: Optional[str] = None, since: Optional[datetime] = None, @@ -392,7 +440,7 @@ async def cancel_email( self, *, email_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Email: """ Cancel an email. @@ -427,17 +475,19 @@ async def create_domain( self, *, domain_name: str, - accept_tos: bool, - region: Optional[Region] = None, + autoconfig: bool, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, + accept_tos: Optional[bool] = None, ) -> Domain: """ Register a domain in a project. You must specify the `region`, `project_id` and `domain_name` to register a domain in a specific Project. :param domain_name: Fully qualified domain dame. - :param accept_tos: Accept Scaleway's Terms of Service. + :param autoconfig: Activate auto-configuration of the domain's DNS zone. :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the project to which the domain belongs. + :param accept_tos: Deprecated. Accept Scaleway's Terms of Service. :return: :class:`Domain ` Usage: @@ -445,7 +495,7 @@ async def create_domain( result = await api.create_domain( domain_name="example", - accept_tos=False, + autoconfig=False, ) """ @@ -459,9 +509,10 @@ async def create_domain( body=marshal_CreateDomainRequest( CreateDomainRequest( domain_name=domain_name, - accept_tos=accept_tos, + autoconfig=autoconfig, region=region, project_id=project_id, + accept_tos=accept_tos, ), self.client, ), @@ -474,7 +525,7 @@ async def get_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Get information about a domain. @@ -508,7 +559,7 @@ async def wait_for_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Domain, Union[bool, Awaitable[bool]]]] = None, ) -> Domain: """ @@ -544,7 +595,7 @@ async def wait_for_domain( async def list_domains( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, @@ -557,11 +608,11 @@ async def list_domains( Retrieve domains in a specific Project or in a specific Organization using the `region` parameter. :param region: Region to target. If none is passed will use default region from the config. :param page: Requested page number. Value must be greater or equal to 1. - :param page_size: Page size. - :param project_id: - :param status: - :param organization_id: - :param name: + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: (Optional) ID of the Project in which to list the domains. + :param status: (Optional) List domains under specific statuses. + :param organization_id: (Optional) ID of the Organization in which to list the domains. + :param name: (Optional) Names of the domains to list. :return: :class:`ListDomainsResponse ` Usage: @@ -594,7 +645,7 @@ async def list_domains( async def list_domains_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, @@ -607,11 +658,11 @@ async def list_domains_all( Retrieve domains in a specific Project or in a specific Organization using the `region` parameter. :param region: Region to target. If none is passed will use default region from the config. :param page: Requested page number. Value must be greater or equal to 1. - :param page_size: Page size. - :param project_id: - :param status: - :param organization_id: - :param name: + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: (Optional) ID of the Project in which to list the domains. + :param status: (Optional) List domains under specific statuses. + :param organization_id: (Optional) ID of the Organization in which to list the domains. + :param name: (Optional) Names of the domains to list. :return: :class:`List[Domain] ` Usage: @@ -639,7 +690,7 @@ async def revoke_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Delete a domain. @@ -674,7 +725,7 @@ async def check_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Domain DNS check. @@ -709,7 +760,7 @@ async def get_domain_last_status( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DomainLastStatus: """ Display SPF and DKIM records status and potential errors. @@ -738,3 +789,908 @@ async def get_domain_last_status( self._throw_on_error(res) return unmarshal_DomainLastStatus(res.json()) + + async def update_domain( + self, + *, + domain_id: str, + region: Optional[ScwRegion] = None, + autoconfig: Optional[bool] = None, + ) -> Domain: + """ + Update a domain. + Update a domain auto-configuration. + :param domain_id: ID of the domain to update. + :param region: Region to target. If none is passed will use default region from the config. + :param autoconfig: (Optional) If set to true, activate auto-configuration of the domain's DNS zone. + :return: :class:`Domain ` + + Usage: + :: + + result = await api.update_domain( + domain_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain_id = validate_path_param("domain_id", domain_id) + + res = self._request( + "PATCH", + f"/transactional-email/v1alpha1/regions/{param_region}/domains/{param_domain_id}", + body=marshal_UpdateDomainRequest( + UpdateDomainRequest( + domain_id=domain_id, + region=region, + autoconfig=autoconfig, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Domain(res.json()) + + async def create_webhook( + self, + *, + domain_id: str, + name: str, + sns_arn: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + event_types: Optional[List[WebhookEventType]] = None, + ) -> Webhook: + """ + Create a Webhook. + Create a new Webhook triggered by a list of event types and pushed to a Scaleway SNS ARN. + :param domain_id: ID of the Domain to watch for triggering events. + :param name: Name of the Webhook. + :param sns_arn: Scaleway SNS ARN topic to push the events to. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project to which the Webhook belongs. + :param event_types: List of event types that will trigger an event. + :return: :class:`Webhook ` + + Usage: + :: + + result = await api.create_webhook( + domain_id="example", + name="example", + sns_arn="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks", + body=marshal_CreateWebhookRequest( + CreateWebhookRequest( + domain_id=domain_id, + name=name, + sns_arn=sns_arn, + region=region, + project_id=project_id, + event_types=event_types, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Webhook(res.json()) + + async def list_webhooks( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListWebhooksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + domain_id: Optional[str] = None, + ) -> ListWebhooksResponse: + """ + List Webhooks. + Retrieve Webhooks in a specific Project or in a specific Organization using the `region` parameter. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List Webhooks corresponding to specific criteria. + :param page: (Optional) Requested page number. Value must be greater or equal to 1. + :param page_size: (Optional) Requested page size. Value must be between 1 and 100. + :param project_id: (Optional) ID of the Project for which to list the Webhooks. + :param organization_id: (Optional) ID of the Organization for which to list the Webhooks. + :param domain_id: (Optional) ID of the Domain for which to list the Webhooks. + :return: :class:`ListWebhooksResponse ` + + Usage: + :: + + result = await api.list_webhooks() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks", + params={ + "domain_id": domain_id, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWebhooksResponse(res.json()) + + async def list_webhooks_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListWebhooksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + domain_id: Optional[str] = None, + ) -> List[Webhook]: + """ + List Webhooks. + Retrieve Webhooks in a specific Project or in a specific Organization using the `region` parameter. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List Webhooks corresponding to specific criteria. + :param page: (Optional) Requested page number. Value must be greater or equal to 1. + :param page_size: (Optional) Requested page size. Value must be between 1 and 100. + :param project_id: (Optional) ID of the Project for which to list the Webhooks. + :param organization_id: (Optional) ID of the Organization for which to list the Webhooks. + :param domain_id: (Optional) ID of the Domain for which to list the Webhooks. + :return: :class:`List[Webhook] ` + + Usage: + :: + + result = await api.list_webhooks_all() + """ + + return await fetch_all_pages_async( + type=ListWebhooksResponse, + key="webhooks", + fetcher=self.list_webhooks, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "organization_id": organization_id, + "domain_id": domain_id, + }, + ) + + async def get_webhook( + self, + *, + webhook_id: str, + region: Optional[ScwRegion] = None, + ) -> Webhook: + """ + Get information about a Webhook. + Retrieve information about a specific Webhook using the `webhook_id` and `region` parameters. + :param webhook_id: ID of the Webhook to check. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Webhook ` + + Usage: + :: + + result = await api.get_webhook( + webhook_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_webhook_id = validate_path_param("webhook_id", webhook_id) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks/{param_webhook_id}", + ) + + self._throw_on_error(res) + return unmarshal_Webhook(res.json()) + + async def update_webhook( + self, + *, + webhook_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + event_types: Optional[List[WebhookEventType]] = None, + sns_arn: Optional[str] = None, + ) -> Webhook: + """ + Update a Webhook. + Update a Webhook events type, SNS ARN or name. + :param webhook_id: ID of the Webhook to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the Webhook to update. + :param event_types: List of event types to update. + :param sns_arn: Scaleway SNS ARN topic to update. + :return: :class:`Webhook ` + + Usage: + :: + + result = await api.update_webhook( + webhook_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_webhook_id = validate_path_param("webhook_id", webhook_id) + + res = self._request( + "PATCH", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks/{param_webhook_id}", + body=marshal_UpdateWebhookRequest( + UpdateWebhookRequest( + webhook_id=webhook_id, + region=region, + name=name, + event_types=event_types, + sns_arn=sns_arn, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Webhook(res.json()) + + async def delete_webhook( + self, + *, + webhook_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a Webhook. + You must specify the Webhook you want to delete by the `region` and `webhook_id`. Deleting a Webhook is permanent and cannot be undone. + :param webhook_id: ID of the Webhook to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_webhook( + webhook_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_webhook_id = validate_path_param("webhook_id", webhook_id) + + res = self._request( + "DELETE", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks/{param_webhook_id}", + ) + + self._throw_on_error(res) + + async def list_webhook_events( + self, + *, + webhook_id: str, + region: Optional[ScwRegion] = None, + order_by: Optional[ListWebhookEventsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + email_id: Optional[str] = None, + event_types: Optional[List[WebhookEventType]] = None, + statuses: Optional[List[WebhookEventStatus]] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + domain_id: Optional[str] = None, + ) -> ListWebhookEventsResponse: + """ + List Webhook triggered events. + Retrieve the list of Webhook events triggered from a specific Webhook or for a specific Project or Organization. You must specify the `region`. + :param webhook_id: ID of the Webhook linked to the events. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List Webhook events corresponding to specific criteria. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 100. + :param email_id: ID of the email linked to the events. + :param event_types: List of event types linked to the events. + :param statuses: List of event statuses. + :param project_id: ID of the webhook Project. + :param organization_id: ID of the webhook Organization. + :param domain_id: ID of the domain to watch for triggering events. + :return: :class:`ListWebhookEventsResponse ` + + Usage: + :: + + result = await api.list_webhook_events( + webhook_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_webhook_id = validate_path_param("webhook_id", webhook_id) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks/{param_webhook_id}/events", + params={ + "domain_id": domain_id, + "email_id": email_id, + "event_types": event_types, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "statuses": statuses, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWebhookEventsResponse(res.json()) + + async def list_webhook_events_all( + self, + *, + webhook_id: str, + region: Optional[ScwRegion] = None, + order_by: Optional[ListWebhookEventsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + email_id: Optional[str] = None, + event_types: Optional[List[WebhookEventType]] = None, + statuses: Optional[List[WebhookEventStatus]] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + domain_id: Optional[str] = None, + ) -> List[WebhookEvent]: + """ + List Webhook triggered events. + Retrieve the list of Webhook events triggered from a specific Webhook or for a specific Project or Organization. You must specify the `region`. + :param webhook_id: ID of the Webhook linked to the events. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List Webhook events corresponding to specific criteria. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 100. + :param email_id: ID of the email linked to the events. + :param event_types: List of event types linked to the events. + :param statuses: List of event statuses. + :param project_id: ID of the webhook Project. + :param organization_id: ID of the webhook Organization. + :param domain_id: ID of the domain to watch for triggering events. + :return: :class:`List[WebhookEvent] ` + + Usage: + :: + + result = await api.list_webhook_events_all( + webhook_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListWebhookEventsResponse, + key="webhook_events", + fetcher=self.list_webhook_events, + args={ + "webhook_id": webhook_id, + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "email_id": email_id, + "event_types": event_types, + "statuses": statuses, + "project_id": project_id, + "organization_id": organization_id, + "domain_id": domain_id, + }, + ) + + async def get_project_settings( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> ProjectSettings: + """ + List project settings. + Retrieve the project settings including periodic reports. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project. + :return: :class:`ProjectSettings ` + + Usage: + :: + + result = await api.get_project_settings() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/project/{param_project_id}/settings", + ) + + self._throw_on_error(res) + return unmarshal_ProjectSettings(res.json()) + + async def update_project_settings( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + periodic_report: Optional[ + UpdateProjectSettingsRequestUpdatePeriodicReport + ] = None, + ) -> ProjectSettings: + """ + Update project settings. + Update the project settings including periodic reports. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project. + :param periodic_report: Periodic report update details - all fields are optional. + :return: :class:`ProjectSettings ` + + Usage: + :: + + result = await api.update_project_settings() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "PATCH", + f"/transactional-email/v1alpha1/regions/{param_region}/project/{param_project_id}/settings", + body=marshal_UpdateProjectSettingsRequest( + UpdateProjectSettingsRequest( + region=region, + project_id=project_id, + periodic_report=periodic_report, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ProjectSettings(res.json()) + + async def list_blocklists( + self, + *, + domain_id: str, + region: Optional[ScwRegion] = None, + order_by: Optional[ListBlocklistsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + email: Optional[str] = None, + type_: Optional[BlocklistType] = None, + custom: Optional[bool] = None, + ) -> ListBlocklistsResponse: + """ + List blocklists. + Retrieve the list of blocklists. + :param domain_id: (Optional) Filter by a domain ID. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List blocklist corresponding to specific criteria. + :param page: (Optional) Requested page number. Value must be greater or equal to 1. + :param page_size: (Optional) Requested page size. Value must be between 1 and 100. + :param email: (Optional) Filter by an email address. + :param type_: (Optional) Filter by a blocklist type. + :param custom: (Optional) Filter by custom blocklist (true) or automatic Transactional Email blocklist (false). + :return: :class:`ListBlocklistsResponse ` + + Usage: + :: + + result = await api.list_blocklists( + domain_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/blocklists", + params={ + "custom": custom, + "domain_id": domain_id, + "email": email, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "type": type_, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBlocklistsResponse(res.json()) + + async def list_blocklists_all( + self, + *, + domain_id: str, + region: Optional[ScwRegion] = None, + order_by: Optional[ListBlocklistsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + email: Optional[str] = None, + type_: Optional[BlocklistType] = None, + custom: Optional[bool] = None, + ) -> List[Blocklist]: + """ + List blocklists. + Retrieve the list of blocklists. + :param domain_id: (Optional) Filter by a domain ID. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List blocklist corresponding to specific criteria. + :param page: (Optional) Requested page number. Value must be greater or equal to 1. + :param page_size: (Optional) Requested page size. Value must be between 1 and 100. + :param email: (Optional) Filter by an email address. + :param type_: (Optional) Filter by a blocklist type. + :param custom: (Optional) Filter by custom blocklist (true) or automatic Transactional Email blocklist (false). + :return: :class:`List[Blocklist] ` + + Usage: + :: + + result = await api.list_blocklists_all( + domain_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListBlocklistsResponse, + key="blocklists", + fetcher=self.list_blocklists, + args={ + "domain_id": domain_id, + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "email": email, + "type_": type_, + "custom": custom, + }, + ) + + async def bulk_create_blocklists( + self, + *, + domain_id: str, + region: Optional[ScwRegion] = None, + emails: Optional[List[str]] = None, + type_: Optional[BlocklistType] = None, + reason: Optional[str] = None, + ) -> BulkCreateBlocklistsResponse: + """ + Bulk create blocklists. + Create multiple blocklists in a specific Project or Organization using the `region` parameter. + :param domain_id: Domain ID linked to the blocklist. + :param region: Region to target. If none is passed will use default region from the config. + :param emails: Email blocked by the blocklist. + :param type_: Type of blocklist. + :param reason: Reason to block the email. + :return: :class:`BulkCreateBlocklistsResponse ` + + Usage: + :: + + result = await api.bulk_create_blocklists( + domain_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/transactional-email/v1alpha1/regions/{param_region}/blocklists", + body=marshal_BulkCreateBlocklistsRequest( + BulkCreateBlocklistsRequest( + domain_id=domain_id, + region=region, + emails=emails, + type_=type_, + reason=reason, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BulkCreateBlocklistsResponse(res.json()) + + async def delete_blocklist( + self, + *, + blocklist_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a blocklist. + You must specify the blocklist you want to delete by the `region` and `blocklist_id`. + :param blocklist_id: ID of the blocklist to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_blocklist( + blocklist_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_blocklist_id = validate_path_param("blocklist_id", blocklist_id) + + res = self._request( + "DELETE", + f"/transactional-email/v1alpha1/regions/{param_region}/blocklists/{param_blocklist_id}", + ) + + self._throw_on_error(res) + + async def list_offer_subscriptions( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> ListOfferSubscriptionsResponse: + """ + Get information about subscribed offers. + Retrieve information about the offers you are subscribed to using the `project_id` and `region` parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :return: :class:`ListOfferSubscriptionsResponse ` + + Usage: + :: + + result = await api.list_offer_subscriptions() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/offer-subscriptions", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListOfferSubscriptionsResponse(res.json()) + + async def update_offer_subscription( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + name: Optional[OfferName] = None, + ) -> OfferSubscription: + """ + Update a subscribed offer. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :param name: Name of the offer-subscription. + :return: :class:`OfferSubscription ` + + Usage: + :: + + result = await api.update_offer_subscription() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "PATCH", + f"/transactional-email/v1alpha1/regions/{param_region}/offer-subscriptions", + body=marshal_UpdateOfferSubscriptionRequest( + UpdateOfferSubscriptionRequest( + region=region, + project_id=project_id, + name=name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_OfferSubscription(res.json()) + + async def list_offers( + self, + *, + region: Optional[ScwRegion] = None, + ) -> ListOffersResponse: + """ + List the available offers. + Retrieve the list of the available and free-of-charge offers you can subscribe to. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ListOffersResponse ` + + Usage: + :: + + result = await api.list_offers() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/offers", + ) + + self._throw_on_error(res) + return unmarshal_ListOffersResponse(res.json()) + + async def list_pools( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> ListPoolsResponse: + """ + Get information about a sending pool. + Retrieve information about a sending pool, including its creation status and configuration parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: ID of the Project. + :return: :class:`ListPoolsResponse ` + + Usage: + :: + + result = await api.list_pools() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/pools", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPoolsResponse(res.json()) + + async def list_pools_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> List[Pool]: + """ + Get information about a sending pool. + Retrieve information about a sending pool, including its creation status and configuration parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: ID of the Project. + :return: :class:`List[Pool] ` + + Usage: + :: + + result = await api.list_pools_all() + """ + + return await fetch_all_pages_async( + type=ListPoolsResponse, + key="pools", + fetcher=self.list_pools, + args={ + "region": region, + "page": page, + "page_size": page_size, + "project_id": project_id, + }, + ) + + async def get_project_consumption( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> ProjectConsumption: + """ + Get project resource consumption. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project. + :return: :class:`ProjectConsumption ` + + Usage: + :: + + result = await api.get_project_consumption() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/project-consumption", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ProjectConsumption(res.json()) diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/content.py b/scaleway-async/scaleway_async/tem/v1alpha1/content.py index 3ae5890b..80c9895d 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/content.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/content.py @@ -9,6 +9,7 @@ DOMAIN_TRANSIENT_STATUSES: List[DomainStatus] = [ DomainStatus.PENDING, + DomainStatus.AUTOCONFIGURING, ] """ Lists transient statutes of the enum :class:`DomainStatus `. diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py index 5d15e237..522b5dec 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/marshalling.py @@ -7,6 +7,7 @@ from scaleway_core.profile import ProfileDefaults from .types import ( EmailFlag, + WebhookEventType, EmailTry, Email, DomainRecordsDMARC, @@ -14,19 +15,43 @@ DomainReputation, DomainStatistics, Domain, + OfferSubscription, + Webhook, + Blocklist, + BulkCreateBlocklistsResponse, CreateEmailResponse, + DomainLastStatusAutoconfigState, DomainLastStatusDkimRecord, DomainLastStatusDmarcRecord, DomainLastStatusSpfRecord, DomainLastStatus, + ListBlocklistsResponse, ListDomainsResponse, ListEmailsResponse, + ListOfferSubscriptionsResponse, + Offer, + ListOffersResponse, + Pool, + ListPoolsResponse, + WebhookEvent, + ListWebhookEventsResponse, + ListWebhooksResponse, + ProjectConsumption, + ProjectSettingsPeriodicReport, + ProjectSettings, Statistics, + BulkCreateBlocklistsRequest, CreateDomainRequest, CreateEmailRequestAddress, CreateEmailRequestAttachment, CreateEmailRequestHeader, CreateEmailRequest, + CreateWebhookRequest, + UpdateDomainRequest, + UpdateOfferSubscriptionRequest, + UpdateProjectSettingsRequestUpdatePeriodicReport, + UpdateProjectSettingsRequest, + UpdateWebhookRequest, ) @@ -53,6 +78,8 @@ def unmarshal_EmailTry(data: Any) -> EmailTry: field = data.get("tried_at", None) if field is not None: args["tried_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["tried_at"] = None return EmailTry(**args) @@ -88,6 +115,8 @@ def unmarshal_Email(data: Any) -> Email: field = data.get("rcpt_to", None) if field is not None: args["rcpt_to"] = field + else: + args["rcpt_to"] = None field = data.get("rcpt_type", None) if field is not None: @@ -118,14 +147,20 @@ def unmarshal_Email(data: Any) -> Email: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("status_details", None) if field is not None: args["status_details"] = field + else: + args["status_details"] = None return Email(**args) @@ -160,6 +195,8 @@ def unmarshal_DomainRecords(data: Any) -> DomainRecords: field = data.get("dmarc", None) if field is not None: args["dmarc"] = unmarshal_DomainRecordsDMARC(field) + else: + args["dmarc"] = None return DomainRecords(**args) @@ -183,16 +220,22 @@ def unmarshal_DomainReputation(data: Any) -> DomainReputation: field = data.get("scored_at", None) if field is not None: args["scored_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["scored_at"] = None field = data.get("previous_score", None) if field is not None: args["previous_score"] = field + else: + args["previous_score"] = None field = data.get("previous_scored_at", None) if field is not None: args["previous_scored_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["previous_scored_at"] = None return DomainReputation(**args) @@ -256,25 +299,35 @@ def unmarshal_Domain(data: Any) -> Domain: if field is not None: args["spf_config"] = field + field = data.get("dkim_config", None) + if field is not None: + args["dkim_config"] = field + field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("next_check_at", None) if field is not None: args["next_check_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["next_check_at"] = None field = data.get("last_valid_at", None) if field is not None: args["last_valid_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_valid_at"] = None - field = data.get("dkim_config", None) + field = data.get("autoconfig", None) if field is not None: - args["dkim_config"] = field + args["autoconfig"] = field field = data.get("region", None) if field is not None: @@ -283,26 +336,222 @@ def unmarshal_Domain(data: Any) -> Domain: field = data.get("revoked_at", None) if field is not None: args["revoked_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["revoked_at"] = None field = data.get("last_error", None) if field is not None: args["last_error"] = field + else: + args["last_error"] = None field = data.get("statistics", None) if field is not None: args["statistics"] = unmarshal_DomainStatistics(field) + else: + args["statistics"] = None field = data.get("reputation", None) if field is not None: args["reputation"] = unmarshal_DomainReputation(field) + else: + args["reputation"] = None field = data.get("records", None) if field is not None: args["records"] = unmarshal_DomainRecords(field) + else: + args["records"] = None return Domain(**args) +def unmarshal_OfferSubscription(data: Any) -> OfferSubscription: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferSubscription' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("sla", None) + if field is not None: + args["sla"] = field + + field = data.get("max_domains", None) + if field is not None: + args["max_domains"] = field + + field = data.get("max_dedicated_ips", None) + if field is not None: + args["max_dedicated_ips"] = field + + field = data.get("max_webhooks_per_domain", None) + if field is not None: + args["max_webhooks_per_domain"] = field + + field = data.get("max_custom_blocklists_per_domain", None) + if field is not None: + args["max_custom_blocklists_per_domain"] = field + + field = data.get("included_monthly_emails", None) + if field is not None: + args["included_monthly_emails"] = field + + field = data.get("subscribed_at", None) + if field is not None: + args["subscribed_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["subscribed_at"] = None + + field = data.get("cancellation_available_at", None) + if field is not None: + args["cancellation_available_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["cancellation_available_at"] = None + + return OfferSubscription(**args) + + +def unmarshal_Webhook(data: Any) -> Webhook: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Webhook' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("domain_id", None) + if field is not None: + args["domain_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("event_types", None) + if field is not None: + args["event_types"] = ( + [WebhookEventType(v) for v in field] if field is not None else None + ) + + field = data.get("sns_arn", None) + if field is not None: + args["sns_arn"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Webhook(**args) + + +def unmarshal_Blocklist(data: Any) -> Blocklist: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Blocklist' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("domain_id", None) + if field is not None: + args["domain_id"] = field + + field = data.get("email", None) + if field is not None: + args["email"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("reason", None) + if field is not None: + args["reason"] = field + + field = data.get("custom", None) + if field is not None: + args["custom"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("ends_at", None) + if field is not None: + args["ends_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["ends_at"] = None + + return Blocklist(**args) + + +def unmarshal_BulkCreateBlocklistsResponse(data: Any) -> BulkCreateBlocklistsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BulkCreateBlocklistsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("blocklists", None) + if field is not None: + args["blocklists"] = ( + [unmarshal_Blocklist(v) for v in field] if field is not None else None + ) + + return BulkCreateBlocklistsResponse(**args) + + def unmarshal_CreateEmailResponse(data: Any) -> CreateEmailResponse: if not isinstance(data, dict): raise TypeError( @@ -320,6 +569,33 @@ def unmarshal_CreateEmailResponse(data: Any) -> CreateEmailResponse: return CreateEmailResponse(**args) +def unmarshal_DomainLastStatusAutoconfigState( + data: Any, +) -> DomainLastStatusAutoconfigState: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DomainLastStatusAutoconfigState' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + field = data.get("autoconfigurable", None) + if field is not None: + args["autoconfigurable"] = field + + field = data.get("reason", None) + if field is not None: + args["reason"] = field + else: + args["reason"] = None + + return DomainLastStatusAutoconfigState(**args) + + def unmarshal_DomainLastStatusDkimRecord(data: Any) -> DomainLastStatusDkimRecord: if not isinstance(data, dict): raise TypeError( @@ -337,10 +613,14 @@ def unmarshal_DomainLastStatusDkimRecord(data: Any) -> DomainLastStatusDkimRecor args["last_valid_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_valid_at"] = None field = data.get("error", None) if field is not None: args["error"] = field + else: + args["error"] = None return DomainLastStatusDkimRecord(**args) @@ -362,10 +642,14 @@ def unmarshal_DomainLastStatusDmarcRecord(data: Any) -> DomainLastStatusDmarcRec args["last_valid_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_valid_at"] = None field = data.get("error", None) if field is not None: args["error"] = field + else: + args["error"] = None return DomainLastStatusDmarcRecord(**args) @@ -387,10 +671,14 @@ def unmarshal_DomainLastStatusSpfRecord(data: Any) -> DomainLastStatusSpfRecord: args["last_valid_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_valid_at"] = None field = data.get("error", None) if field is not None: args["error"] = field + else: + args["error"] = None return DomainLastStatusSpfRecord(**args) @@ -414,18 +702,51 @@ def unmarshal_DomainLastStatus(data: Any) -> DomainLastStatus: field = data.get("spf_record", None) if field is not None: args["spf_record"] = unmarshal_DomainLastStatusSpfRecord(field) + else: + args["spf_record"] = None field = data.get("dkim_record", None) if field is not None: args["dkim_record"] = unmarshal_DomainLastStatusDkimRecord(field) + else: + args["dkim_record"] = None field = data.get("dmarc_record", None) if field is not None: args["dmarc_record"] = unmarshal_DomainLastStatusDmarcRecord(field) + else: + args["dmarc_record"] = None + + field = data.get("autoconfig_state", None) + if field is not None: + args["autoconfig_state"] = unmarshal_DomainLastStatusAutoconfigState(field) + else: + args["autoconfig_state"] = None return DomainLastStatus(**args) +def unmarshal_ListBlocklistsResponse(data: Any) -> ListBlocklistsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListBlocklistsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("blocklists", None) + if field is not None: + args["blocklists"] = ( + [unmarshal_Blocklist(v) for v in field] if field is not None else None + ) + + return ListBlocklistsResponse(**args) + + def unmarshal_ListDomainsResponse(data: Any) -> ListDomainsResponse: if not isinstance(data, dict): raise TypeError( @@ -468,6 +789,347 @@ def unmarshal_ListEmailsResponse(data: Any) -> ListEmailsResponse: return ListEmailsResponse(**args) +def unmarshal_ListOfferSubscriptionsResponse( + data: Any, +) -> ListOfferSubscriptionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOfferSubscriptionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offer_subscriptions", None) + if field is not None: + args["offer_subscriptions"] = ( + [unmarshal_OfferSubscription(v) for v in field] + if field is not None + else None + ) + + return ListOfferSubscriptionsResponse(**args) + + +def unmarshal_Offer(data: Any) -> Offer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Offer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("sla", None) + if field is not None: + args["sla"] = field + + field = data.get("max_domains", None) + if field is not None: + args["max_domains"] = field + + field = data.get("max_dedicated_ips", None) + if field is not None: + args["max_dedicated_ips"] = field + + field = data.get("included_monthly_emails", None) + if field is not None: + args["included_monthly_emails"] = field + + field = data.get("max_webhooks_per_domain", None) + if field is not None: + args["max_webhooks_per_domain"] = field + + field = data.get("max_custom_blocklists_per_domain", None) + if field is not None: + args["max_custom_blocklists_per_domain"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("commitment_period", None) + if field is not None: + args["commitment_period"] = field + else: + args["commitment_period"] = None + + return Offer(**args) + + +def unmarshal_ListOffersResponse(data: Any) -> ListOffersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOffersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offers", None) + if field is not None: + args["offers"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return ListOffersResponse(**args) + + +def unmarshal_Pool(data: Any) -> Pool: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pool' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("ips", None) + if field is not None: + args["ips"] = field + + field = data.get("details", None) + if field is not None: + args["details"] = field + else: + args["details"] = None + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("reverse", None) + if field is not None: + args["reverse"] = field + else: + args["reverse"] = None + + return Pool(**args) + + +def unmarshal_ListPoolsResponse(data: Any) -> ListPoolsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPoolsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("pools", None) + if field is not None: + args["pools"] = ( + [unmarshal_Pool(v) for v in field] if field is not None else None + ) + + return ListPoolsResponse(**args) + + +def unmarshal_WebhookEvent(data: Any) -> WebhookEvent: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'WebhookEvent' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("webhook_id", None) + if field is not None: + args["webhook_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("domain_id", None) + if field is not None: + args["domain_id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("data", None) + if field is not None: + args["data"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("email_id", None) + if field is not None: + args["email_id"] = field + else: + args["email_id"] = None + + return WebhookEvent(**args) + + +def unmarshal_ListWebhookEventsResponse(data: Any) -> ListWebhookEventsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListWebhookEventsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("webhook_events", None) + if field is not None: + args["webhook_events"] = ( + [unmarshal_WebhookEvent(v) for v in field] if field is not None else None + ) + + return ListWebhookEventsResponse(**args) + + +def unmarshal_ListWebhooksResponse(data: Any) -> ListWebhooksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListWebhooksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("webhooks", None) + if field is not None: + args["webhooks"] = ( + [unmarshal_Webhook(v) for v in field] if field is not None else None + ) + + return ListWebhooksResponse(**args) + + +def unmarshal_ProjectConsumption(data: Any) -> ProjectConsumption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectConsumption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("domains_count", None) + if field is not None: + args["domains_count"] = field + + field = data.get("dedicated_ips_count", None) + if field is not None: + args["dedicated_ips_count"] = field + + field = data.get("monthly_emails_count", None) + if field is not None: + args["monthly_emails_count"] = field + + field = data.get("webhooks_count", None) + if field is not None: + args["webhooks_count"] = field + + field = data.get("custom_blocklists_count", None) + if field is not None: + args["custom_blocklists_count"] = field + + return ProjectConsumption(**args) + + +def unmarshal_ProjectSettingsPeriodicReport(data: Any) -> ProjectSettingsPeriodicReport: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectSettingsPeriodicReport' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + + field = data.get("sending_hour", None) + if field is not None: + args["sending_hour"] = field + + field = data.get("sending_day", None) + if field is not None: + args["sending_day"] = field + + return ProjectSettingsPeriodicReport(**args) + + +def unmarshal_ProjectSettings(data: Any) -> ProjectSettings: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectSettings' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("periodic_report", None) + if field is not None: + args["periodic_report"] = unmarshal_ProjectSettingsPeriodicReport(field) + else: + args["periodic_report"] = None + + return ProjectSettings(**args) + + def unmarshal_Statistics(data: Any) -> Statistics: if not isinstance(data, dict): raise TypeError( @@ -503,6 +1165,27 @@ def unmarshal_Statistics(data: Any) -> Statistics: return Statistics(**args) +def marshal_BulkCreateBlocklistsRequest( + request: BulkCreateBlocklistsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain_id is not None: + output["domain_id"] = request.domain_id + + if request.emails is not None: + output["emails"] = request.emails + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.reason is not None: + output["reason"] = request.reason + + return output + + def marshal_CreateDomainRequest( request: CreateDomainRequest, defaults: ProfileDefaults, @@ -512,12 +1195,15 @@ def marshal_CreateDomainRequest( if request.domain_name is not None: output["domain_name"] = request.domain_name - if request.accept_tos is not None: - output["accept_tos"] = request.accept_tos + if request.autoconfig is not None: + output["autoconfig"] = request.autoconfig if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id + if request.accept_tos is not None: + output["accept_tos"] = request.accept_tos + return output @@ -575,6 +1261,9 @@ def marshal_CreateEmailRequest( ) -> Dict[str, Any]: output: Dict[str, Any] = {} + if request.from_ is not None: + output["from"] = marshal_CreateEmailRequestAddress(request.from_, defaults) + if request.subject is not None: output["subject"] = request.subject @@ -584,9 +1273,6 @@ def marshal_CreateEmailRequest( if request.html is not None: output["html"] = request.html - if request.from_ is not None: - output["from"] = (marshal_CreateEmailRequestAddress(request.from_, defaults),) - if request.to is not None: output["to"] = [ marshal_CreateEmailRequestAddress(item, defaults) for item in request.to @@ -612,7 +1298,7 @@ def marshal_CreateEmailRequest( ] if request.send_before is not None: - output["send_before"] = request.send_before + output["send_before"] = request.send_before.isoformat() if request.additional_headers is not None: output["additional_headers"] = [ @@ -621,3 +1307,109 @@ def marshal_CreateEmailRequest( ] return output + + +def marshal_CreateWebhookRequest( + request: CreateWebhookRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain_id is not None: + output["domain_id"] = request.domain_id + + if request.name is not None: + output["name"] = request.name + + if request.sns_arn is not None: + output["sns_arn"] = request.sns_arn + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.event_types is not None: + output["event_types"] = [str(item) for item in request.event_types] + + return output + + +def marshal_UpdateDomainRequest( + request: UpdateDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.autoconfig is not None: + output["autoconfig"] = request.autoconfig + + return output + + +def marshal_UpdateOfferSubscriptionRequest( + request: UpdateOfferSubscriptionRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.name is not None: + output["name"] = str(request.name) + + return output + + +def marshal_UpdateProjectSettingsRequestUpdatePeriodicReport( + request: UpdateProjectSettingsRequestUpdatePeriodicReport, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.enabled is not None: + output["enabled"] = request.enabled + + if request.frequency is not None: + output["frequency"] = str(request.frequency) + + if request.sending_hour is not None: + output["sending_hour"] = request.sending_hour + + if request.sending_day is not None: + output["sending_day"] = request.sending_day + + return output + + +def marshal_UpdateProjectSettingsRequest( + request: UpdateProjectSettingsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.periodic_report is not None: + output["periodic_report"] = ( + marshal_UpdateProjectSettingsRequestUpdatePeriodicReport( + request.periodic_report, defaults + ) + ) + + return output + + +def marshal_UpdateWebhookRequest( + request: UpdateWebhookRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.event_types is not None: + output["event_types"] = [str(item) for item in request.event_types] + + if request.sns_arn is not None: + output["sns_arn"] = request.sns_arn + + return output diff --git a/scaleway-async/scaleway_async/tem/v1alpha1/types.py b/scaleway-async/scaleway_async/tem/v1alpha1/types.py index a8dfc4a3..0f40682c 100644 --- a/scaleway-async/scaleway_async/tem/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/tem/v1alpha1/types.py @@ -8,13 +8,32 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, ) +class BlocklistType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + MAILBOX_FULL = "mailbox_full" + MAILBOX_NOT_FOUND = "mailbox_not_found" + + def __str__(self) -> str: + return str(self.value) + + +class DomainLastStatusAutoconfigStateReason(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_REASON = "unknown_reason" + PERMISSION_DENIED = "permission_denied" + DOMAIN_NOT_FOUND = "domain_not_found" + + def __str__(self) -> str: + return str(self.value) + + class DomainLastStatusRecordStatus(str, Enum, metaclass=StrEnumMeta): UNKNOWN_RECORD_STATUS = "unknown_record_status" VALID = "valid" @@ -44,6 +63,7 @@ class DomainStatus(str, Enum, metaclass=StrEnumMeta): LOCKED = "locked" REVOKED = "revoked" PENDING = "pending" + AUTOCONFIGURING = "autoconfiguring" def __str__(self) -> str: return str(self.value) @@ -58,6 +78,7 @@ class EmailFlag(str, Enum, metaclass=StrEnumMeta): MAILBOX_NOT_FOUND = "mailbox_not_found" GREYLISTED = "greylisted" SEND_BEFORE_EXPIRATION = "send_before_expiration" + BLOCKLISTED = "blocklisted" def __str__(self) -> str: return str(self.value) @@ -85,6 +106,16 @@ def __str__(self) -> str: return str(self.value) +class ListBlocklistsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + ENDS_AT_DESC = "ends_at_desc" + ENDS_AT_ASC = "ends_at_asc" + + def __str__(self) -> str: + return str(self.value) + + class ListEmailsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_DESC = "created_at_desc" CREATED_AT_ASC = "created_at_asc" @@ -103,6 +134,77 @@ def __str__(self) -> str: return str(self.value) +class ListWebhookEventsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ListWebhooksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class OfferName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + ESSENTIAL = "essential" + SCALE = "scale" + + def __str__(self) -> str: + return str(self.value) + + +class PoolStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DISABLED = "disabled" + CREATING = "creating" + READY = "ready" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class ProjectSettingsPeriodicReportFrequency(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_FREQUENCY = "unknown_frequency" + MONTHLY = "monthly" + WEEKLY = "weekly" + DAILY = "daily" + + def __str__(self) -> str: + return str(self.value) + + +class WebhookEventStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + SENDING = "sending" + SENT = "sent" + FAILED = "failed" + + def __str__(self) -> str: + return str(self.value) + + +class WebhookEventType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + EMAIL_QUEUED = "email_queued" + EMAIL_DROPPED = "email_dropped" + EMAIL_DEFERRED = "email_deferred" + EMAIL_DELIVERED = "email_delivered" + EMAIL_SPAM = "email_spam" + EMAIL_MAILBOX_NOT_FOUND = "email_mailbox_not_found" + EMAIL_BLOCKLISTED = "email_blocklisted" + BLOCKLIST_CREATED = "blocklist_created" + + def __str__(self) -> str: + return str(self.value) + + @dataclass class DomainRecordsDMARC: name: str @@ -186,6 +288,54 @@ class DomainStatistics: canceled_count: int +@dataclass +class Blocklist: + id: str + """ + ID of the blocklist. + """ + + domain_id: str + """ + Domain ID linked to the blocklist. + """ + + email: str + """ + Email blocked by the blocklist. + """ + + type_: BlocklistType + """ + Type of block for this email. + """ + + reason: str + """ + Reason to block this email. + """ + + custom: bool + """ + True if this blocklist was created manually. False for an automatic Transactional Email blocklist. + """ + + created_at: Optional[datetime] + """ + Date and time of the blocklist creation. + """ + + updated_at: Optional[datetime] + """ + Date and time of the blocklist's last update. + """ + + ends_at: Optional[datetime] + """ + Date and time when the blocklist ends. Empty if the blocklist has no end. + """ + + @dataclass class CreateEmailRequestAddress: email: str @@ -259,7 +409,7 @@ class Email: rcpt_to: Optional[str] """ - Email address of the recipient. + Deprecated. Email address of the recipient. """ rcpt_type: EmailRcptType @@ -308,6 +458,24 @@ class Email: """ +@dataclass +class DomainLastStatusAutoconfigState: + enabled: bool + """ + Enable or disable the auto-configuration of domain DNS records. + """ + + autoconfigurable: bool + """ + Whether the domain can be auto-configured or not. + """ + + reason: Optional[DomainLastStatusAutoconfigStateReason] + """ + The reason that the domain cannot be auto-configurable. + """ + + @dataclass class DomainLastStatusDkimRecord: status: DomainLastStatusRecordStatus @@ -394,6 +562,11 @@ class Domain: Snippet of the SPF record to register in the DNS zone. """ + dkim_config: str + """ + DKIM public key to record in the DNS zone. + """ + created_at: Optional[datetime] """ Date and time of domain creation. @@ -409,12 +582,12 @@ class Domain: Date and time the domain was last valid. """ - dkim_config: str + autoconfig: bool """ - DKIM public key to record in the DNS zone. + Status of auto-configuration for the domain's DNS zone. """ - region: Region + region: ScwRegion """ Region to target. If none is passed will use default region from the config. """ @@ -426,7 +599,7 @@ class Domain: last_error: Optional[str] """ - Error message returned if the last check failed. + Deprecated. Error message returned if the last check failed. """ statistics: Optional[DomainStatistics] @@ -446,266 +619,772 @@ class Domain: @dataclass -class CancelEmailRequest: - email_id: str +class OfferSubscription: + organization_id: str """ - ID of the email to cancel. + ID of the offer-subscription Organization. """ - region: Optional[Region] + project_id: str """ - Region to target. If none is passed will use default region from the config. + ID of the offer-subscription Project. """ + offer_name: OfferName + """ + Name of the offer associated with the Project. + """ -@dataclass -class CheckDomainRequest: - domain_id: str + sla: float """ - ID of the domain to check. + Service Level Agreement percentage of the offer-subscription. """ - region: Optional[Region] + max_domains: int """ - Region to target. If none is passed will use default region from the config. + Max number of domains that can be associated with the offer-subscription for a particular Project. """ + max_dedicated_ips: int + """ + Max number of dedicated IPs that can be associated with the offer-subscription for a particular Project. + """ -@dataclass -class CreateDomainRequest: - domain_name: str + max_webhooks_per_domain: int """ - Fully qualified domain dame. + Max number of webhooks that can be associated with the offer-subscription for a particular Project. """ - accept_tos: bool + max_custom_blocklists_per_domain: int """ - Accept Scaleway's Terms of Service. + Max number of custom blocklists that can be associated with the offer-subscription for a particular Project. """ - region: Optional[Region] + included_monthly_emails: int """ - Region to target. If none is passed will use default region from the config. + Number of emails included in the offer-subscription per month. """ - project_id: Optional[str] + subscribed_at: Optional[datetime] """ - ID of the project to which the domain belongs. + Date and time of the subscription. + """ + + cancellation_available_at: Optional[datetime] + """ + Date and time of the end of the offer-subscription commitment. """ @dataclass -class CreateEmailRequest: - subject: str +class Offer: + name: OfferName """ - Subject of the email. + Name of the offer. """ - text: str + sla: float """ - Text content. + Service Level Agreement percentage of the offer. """ - html: str + max_domains: int """ - HTML content. + Max number of checked domains that can be associated with the offer. """ - region: Optional[Region] + max_dedicated_ips: int """ - Region to target. If none is passed will use default region from the config. + Max number of dedicated IPs that can be associated with the offer. """ - from_: Optional[CreateEmailRequestAddress] + included_monthly_emails: int """ - Sender information. Must be from a checked domain declared in the Project. + Number of emails included in the offer per month. """ - to: Optional[List[CreateEmailRequestAddress]] + max_webhooks_per_domain: int """ - An array of the primary recipient's information. + Max number of webhooks that can be associated with the offer. """ - cc: Optional[List[CreateEmailRequestAddress]] + max_custom_blocklists_per_domain: int """ - An array of the carbon copy recipient's information. + Max number of active custom blocklists that can be associated with the offer. """ - bcc: Optional[List[CreateEmailRequestAddress]] + created_at: Optional[datetime] """ - An array of the blind carbon copy recipient's information. + Date and time of the offer creation. """ - project_id: Optional[str] + commitment_period: Optional[str] """ - ID of the Project in which to create the email. + Period of commitment. """ - attachments: Optional[List[CreateEmailRequestAttachment]] + +@dataclass +class Pool: + project_id: str """ - Array of attachments. + ID of the Project. """ - send_before: Optional[datetime] + status: PoolStatus """ - Maximum date to deliver the email. + Status of the pool. """ - additional_headers: Optional[List[CreateEmailRequestHeader]] + ips: List[str] """ - Array of additional headers as key-value. + IPs of the pool. """ + details: Optional[str] + """ + Details of the pool. + """ -@dataclass -class CreateEmailResponse: - emails: List[Email] + zone: Optional[ScwZone] """ - Single page of emails matching the requested criteria. + Zone of the pool. + """ + + reverse: Optional[str] + """ + Reverse hostname of all IPs of the pool. """ @dataclass -class DomainLastStatus: - domain_id: str +class WebhookEvent: + id: str """ - The ID of the domain. + ID of the Webhook Event. """ - domain_name: str + webhook_id: str """ - The domain name (example.com). + ID of the Webhook that triggers the Event. """ - spf_record: Optional[DomainLastStatusSpfRecord] + organization_id: str """ - The SPF record verification data. + ID of the Webhook Event Organization. """ - dkim_record: Optional[DomainLastStatusDkimRecord] + project_id: str """ - The DKIM record verification data. + ID of the Webhook Event Project. """ - dmarc_record: Optional[DomainLastStatusDmarcRecord] + domain_id: str """ - The DMARC record verification data. + ID of the webhook event domain. """ + type_: WebhookEventType + """ + Type of the Webhook Event. + """ -@dataclass -class GetDomainLastStatusRequest: - domain_id: str + status: WebhookEventStatus """ - ID of the domain to delete. + Status of the Webhook Event. """ - region: Optional[Region] + data: str """ - Region to target. If none is passed will use default region from the config. + Data sent to the Webhook destination. """ + created_at: Optional[datetime] + """ + Date and time of the Webhook Event creation. + """ -@dataclass -class GetDomainRequest: - domain_id: str + updated_at: Optional[datetime] """ - ID of the domain. + Date and time of last Webhook Event updates. """ - region: Optional[Region] + email_id: Optional[str] """ - Region to target. If none is passed will use default region from the config. + Optional Email ID if the event is triggered by an Email resource. """ @dataclass -class GetEmailRequest: - email_id: str +class Webhook: + id: str """ - ID of the email to retrieve. + ID of the Webhook. """ - region: Optional[Region] + domain_id: str """ - Region to target. If none is passed will use default region from the config. + ID of the Domain to watch for triggering events. """ + organization_id: str + """ + ID of the Webhook Organization. + """ -@dataclass -class GetStatisticsRequest: - region: Optional[Region] + project_id: str """ - Region to target. If none is passed will use default region from the config. + ID of the Webhook Project. """ - project_id: Optional[str] + name: str """ - (Optional) Number of emails for this Project. + Name of the Webhook. """ - domain_id: Optional[str] + event_types: List[WebhookEventType] """ - (Optional) Number of emails sent from this domain (must be coherent with the `project_id` and the `organization_id`). + List of event types that will trigger a Webhook Event. """ - since: Optional[datetime] + sns_arn: str """ - (Optional) Number of emails created after this date. + Scaleway SNS ARN topic to push the events to. """ - until: Optional[datetime] + created_at: Optional[datetime] """ - (Optional) Number of emails created before this date. + Date and time of the Webhook creation. """ - mail_from: Optional[str] + updated_at: Optional[datetime] """ - (Optional) Number of emails sent with this sender's email address. + Date and time of last Webhook updates. """ @dataclass -class ListDomainsRequest: - region: Optional[Region] +class ProjectSettingsPeriodicReport: + enabled: bool """ - Region to target. If none is passed will use default region from the config. + Enable or disable periodic report notifications. """ - page: Optional[int] + frequency: ProjectSettingsPeriodicReportFrequency """ - Requested page number. Value must be greater or equal to 1. + At which frequency you receive periodic report notifications. """ - page_size: Optional[int] + sending_hour: int """ - Page size. + At which hour you receive periodic report notifications. """ - project_id: Optional[str] - - status: Optional[List[DomainStatus]] - - organization_id: Optional[str] - - name: Optional[str] - - -@dataclass -class ListDomainsResponse: - total_count: int + sending_day: int """ - Number of domains that match the request (without pagination). + On which day you receive periodic report notifications (1-7 weekly, 1-28 monthly). """ - domains: List[Domain] - @dataclass -class ListEmailsRequest: - region: Optional[Region] +class UpdateProjectSettingsRequestUpdatePeriodicReport: + enabled: Optional[bool] """ - Region to target. If none is passed will use default region from the config. + (Optional) Enable or disable periodic report notifications. + """ + + frequency: Optional[ProjectSettingsPeriodicReportFrequency] + """ + (Optional) Frequency at which you receive periodic report notifications. + """ + + sending_hour: Optional[int] + """ + (Optional) Hour at which you receive periodic report notifications. + """ + + sending_day: Optional[int] + """ + (Optional) On which day you receive periodic report notifications (1-7 weekly, 1-28 monthly). + """ + + +@dataclass +class BulkCreateBlocklistsRequest: + domain_id: str + """ + Domain ID linked to the blocklist. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + emails: Optional[List[str]] + """ + Email blocked by the blocklist. + """ + + type_: Optional[BlocklistType] + """ + Type of blocklist. + """ + + reason: Optional[str] + """ + Reason to block the email. + """ + + +@dataclass +class BulkCreateBlocklistsResponse: + blocklists: List[Blocklist] + """ + List of blocklist created. + """ + + +@dataclass +class CancelEmailRequest: + email_id: str + """ + ID of the email to cancel. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CheckDomainRequest: + domain_id: str + """ + ID of the domain to check. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateDomainRequest: + domain_name: str + """ + Fully qualified domain dame. + """ + + autoconfig: bool + """ + Activate auto-configuration of the domain's DNS zone. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project to which the domain belongs. + """ + + accept_tos: Optional[bool] + """ + Deprecated. Accept Scaleway's Terms of Service. + """ + + +@dataclass +class CreateEmailRequest: + from_: CreateEmailRequestAddress + """ + Sender information. Must be from a checked domain declared in the Project. + """ + + subject: str + """ + Subject of the email. + """ + + text: str + """ + Text content. + """ + + html: str + """ + HTML content. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + to: Optional[List[CreateEmailRequestAddress]] + """ + An array of the primary recipient's information. + """ + + cc: Optional[List[CreateEmailRequestAddress]] + """ + An array of the carbon copy recipient's information. + """ + + bcc: Optional[List[CreateEmailRequestAddress]] + """ + An array of the blind carbon copy recipient's information. + """ + + project_id: Optional[str] + """ + ID of the Project in which to create the email. + """ + + attachments: Optional[List[CreateEmailRequestAttachment]] + """ + Array of attachments. + """ + + send_before: Optional[datetime] + """ + Maximum date to deliver the email. + """ + + additional_headers: Optional[List[CreateEmailRequestHeader]] + """ + Array of additional headers as key-value. + """ + + +@dataclass +class CreateEmailResponse: + emails: List[Email] + """ + Single page of emails matching the requested criteria. + """ + + +@dataclass +class CreateWebhookRequest: + domain_id: str + """ + ID of the Domain to watch for triggering events. + """ + + name: str + """ + Name of the Webhook. + """ + + sns_arn: str + """ + Scaleway SNS ARN topic to push the events to. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project to which the Webhook belongs. + """ + + event_types: Optional[List[WebhookEventType]] + """ + List of event types that will trigger an event. + """ + + +@dataclass +class DeleteBlocklistRequest: + blocklist_id: str + """ + ID of the blocklist to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteWebhookRequest: + webhook_id: str + """ + ID of the Webhook to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DomainLastStatus: + domain_id: str + """ + The ID of the domain. + """ + + domain_name: str + """ + The domain name (example.com). + """ + + spf_record: Optional[DomainLastStatusSpfRecord] + """ + The SPF record verification data. + """ + + dkim_record: Optional[DomainLastStatusDkimRecord] + """ + The DKIM record verification data. + """ + + dmarc_record: Optional[DomainLastStatusDmarcRecord] + """ + The DMARC record verification data. + """ + + autoconfig_state: Optional[DomainLastStatusAutoconfigState] + """ + The verification state of domain auto-configuration. + """ + + +@dataclass +class GetDomainLastStatusRequest: + domain_id: str + """ + ID of the domain to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDomainRequest: + domain_id: str + """ + ID of the domain. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetEmailRequest: + email_id: str + """ + ID of the email to retrieve. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetProjectConsumptionRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project. + """ + + +@dataclass +class GetProjectSettingsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project. + """ + + +@dataclass +class GetStatisticsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + (Optional) Number of emails for this Project. + """ + + domain_id: Optional[str] + """ + (Optional) Number of emails sent from this domain (must be coherent with the `project_id` and the `organization_id`). + """ + + since: Optional[datetime] + """ + (Optional) Number of emails created after this date. + """ + + until: Optional[datetime] + """ + (Optional) Number of emails created before this date. + """ + + mail_from: Optional[str] + """ + (Optional) Number of emails sent with this sender's email address. + """ + + +@dataclass +class GetWebhookRequest: + webhook_id: str + """ + ID of the Webhook to check. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListBlocklistsRequest: + domain_id: str + """ + (Optional) Filter by a domain ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListBlocklistsRequestOrderBy] + """ + (Optional) List blocklist corresponding to specific criteria. + """ + + page: Optional[int] + """ + (Optional) Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + (Optional) Requested page size. Value must be between 1 and 100. + """ + + email: Optional[str] + """ + (Optional) Filter by an email address. + """ + + type_: Optional[BlocklistType] + """ + (Optional) Filter by a blocklist type. + """ + + custom: Optional[bool] + """ + (Optional) Filter by custom blocklist (true) or automatic Transactional Email blocklist (false). + """ + + +@dataclass +class ListBlocklistsResponse: + total_count: int + """ + Number of blocklists matching the requested criteria. + """ + + blocklists: List[Blocklist] + """ + Single page of blocklists matching the requested criteria. + """ + + +@dataclass +class ListDomainsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + Requested page size. Value must be between 1 and 1000. + """ + + project_id: Optional[str] + """ + (Optional) ID of the Project in which to list the domains. + """ + + status: Optional[List[DomainStatus]] + """ + (Optional) List domains under specific statuses. + """ + + organization_id: Optional[str] + """ + (Optional) ID of the Organization in which to list the domains. + """ + + name: Optional[str] + """ + (Optional) Names of the domains to list. + """ + + +@dataclass +class ListDomainsResponse: + total_count: int + """ + Number of domains that match the request (without pagination). + """ + + domains: List[Domain] + """ + Single page of domains matching the requested criteria. + """ + + +@dataclass +class ListEmailsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. """ page: Optional[int] @@ -744,7 +1423,7 @@ class ListEmailsRequest: mail_to: Optional[str] """ - List emails sent to this recipient's email address. + Deprecated. List emails sent to this recipient's email address. """ mail_rcpt: Optional[str] @@ -791,6 +1470,252 @@ class ListEmailsResponse: """ +@dataclass +class ListOfferSubscriptionsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class ListOfferSubscriptionsResponse: + total_count: int + """ + Number of offer-subscriptions matching the requested criteria. + """ + + offer_subscriptions: List[OfferSubscription] + """ + Single page of offer-subscriptions matching the requested criteria. + """ + + +@dataclass +class ListOffersRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListOffersResponse: + total_count: int + """ + Number of offers matching the requested criteria. + """ + + offers: List[Offer] + """ + Single page of offers matching the requested criteria. + """ + + +@dataclass +class ListPoolsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + Requested page size. Value must be between 1 and 1000. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class ListPoolsResponse: + total_count: int + """ + Number of pools matching the requested criteria. + """ + + pools: List[Pool] + """ + Single page of pools matching the requested criteria. + """ + + +@dataclass +class ListWebhookEventsRequest: + webhook_id: str + """ + ID of the Webhook linked to the events. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListWebhookEventsRequestOrderBy] + """ + (Optional) List Webhook events corresponding to specific criteria. + """ + + page: Optional[int] + """ + Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + Requested page size. Value must be between 1 and 100. + """ + + email_id: Optional[str] + """ + ID of the email linked to the events. + """ + + event_types: Optional[List[WebhookEventType]] + """ + List of event types linked to the events. + """ + + statuses: Optional[List[WebhookEventStatus]] + """ + List of event statuses. + """ + + project_id: Optional[str] + """ + ID of the webhook Project. + """ + + organization_id: Optional[str] + """ + ID of the webhook Organization. + """ + + domain_id: Optional[str] + """ + ID of the domain to watch for triggering events. + """ + + +@dataclass +class ListWebhookEventsResponse: + total_count: int + """ + Number of Webhook events matching the requested criteria. + """ + + webhook_events: List[WebhookEvent] + """ + Single page of Webhook events matching the requested criteria. + """ + + +@dataclass +class ListWebhooksRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListWebhooksRequestOrderBy] + """ + (Optional) List Webhooks corresponding to specific criteria. + """ + + page: Optional[int] + """ + (Optional) Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + (Optional) Requested page size. Value must be between 1 and 100. + """ + + project_id: Optional[str] + """ + (Optional) ID of the Project for which to list the Webhooks. + """ + + organization_id: Optional[str] + """ + (Optional) ID of the Organization for which to list the Webhooks. + """ + + domain_id: Optional[str] + """ + (Optional) ID of the Domain for which to list the Webhooks. + """ + + +@dataclass +class ListWebhooksResponse: + total_count: int + """ + Number of Webhooks matching the requested criteria. + """ + + webhooks: List[Webhook] + """ + Single page of Webhooks matching the requested criteria. + """ + + +@dataclass +class ProjectConsumption: + project_id: str + """ + ID of the project. + """ + + domains_count: int + """ + Number of domains in the project. + """ + + dedicated_ips_count: int + """ + Number of dedicated IP in the project. + """ + + monthly_emails_count: int + """ + Number of emails sent during the current month in the project. + """ + + webhooks_count: int + """ + Number of webhooks in the project. + """ + + custom_blocklists_count: int + """ + Number of custom blocklists in the project. + """ + + +@dataclass +class ProjectSettings: + periodic_report: Optional[ProjectSettingsPeriodicReport] + """ + Information about your periodic report. + """ + + @dataclass class RevokeDomainRequest: domain_id: str @@ -798,7 +1723,7 @@ class RevokeDomainRequest: ID of the domain to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -835,3 +1760,85 @@ class Statistics: """ Number of emails in the final `canceled` state. This means emails that have been canceled upon request. """ + + +@dataclass +class UpdateDomainRequest: + domain_id: str + """ + ID of the domain to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + autoconfig: Optional[bool] + """ + (Optional) If set to true, activate auto-configuration of the domain's DNS zone. + """ + + +@dataclass +class UpdateOfferSubscriptionRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + name: Optional[OfferName] + """ + Name of the offer-subscription. + """ + + +@dataclass +class UpdateProjectSettingsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project. + """ + + periodic_report: Optional[UpdateProjectSettingsRequestUpdatePeriodicReport] + """ + Periodic report update details - all fields are optional. + """ + + +@dataclass +class UpdateWebhookRequest: + webhook_id: str + """ + ID of the Webhook to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the Webhook to update. + """ + + event_types: Optional[List[WebhookEventType]] + """ + List of event types to update. + """ + + sns_arn: Optional[str] + """ + Scaleway SNS ARN topic to update. + """ diff --git a/scaleway-async/scaleway_async/test/v1/marshalling.py b/scaleway-async/scaleway_async/test/v1/marshalling.py index 357241bf..6c3c3e84 100644 --- a/scaleway-async/scaleway_async/test/v1/marshalling.py +++ b/scaleway-async/scaleway_async/test/v1/marshalling.py @@ -58,10 +58,14 @@ def unmarshal_Human(data: Any) -> Human: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("hair_count", None) if field is not None: diff --git a/scaleway-async/scaleway_async/vpc/v1/api.py b/scaleway-async/scaleway_async/vpc/v1/api.py index d2ba7217..e6a1ab27 100644 --- a/scaleway-async/scaleway_async/vpc/v1/api.py +++ b/scaleway-async/scaleway_async/vpc/v1/api.py @@ -29,7 +29,7 @@ class VpcV1API(API): """ - VPC API. + This API allows you to manage your Virtual Private Clouds (VPCs) and Private Networks. """ async def list_private_networks( diff --git a/scaleway-async/scaleway_async/vpc/v1/marshalling.py b/scaleway-async/scaleway_async/vpc/v1/marshalling.py index 32514e39..b67881a3 100644 --- a/scaleway-async/scaleway_async/vpc/v1/marshalling.py +++ b/scaleway-async/scaleway_async/vpc/v1/marshalling.py @@ -52,10 +52,14 @@ def unmarshal_PrivateNetwork(data: Any) -> PrivateNetwork: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return PrivateNetwork(**args) diff --git a/scaleway-async/scaleway_async/vpc/v2/__init__.py b/scaleway-async/scaleway_async/vpc/v2/__init__.py index 9ab28205..81cbc5da 100644 --- a/scaleway-async/scaleway_async/vpc/v2/__init__.py +++ b/scaleway-async/scaleway_async/vpc/v2/__init__.py @@ -1,57 +1,83 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import AclRuleProtocol +from .types import Action from .types import ListPrivateNetworksRequestOrderBy +from .types import ListSubnetsRequestOrderBy from .types import ListVPCsRequestOrderBy from .types import Subnet from .types import PrivateNetwork +from .types import Route +from .types import AclRule from .types import VPC from .types import AddSubnetsRequest from .types import AddSubnetsResponse from .types import CreatePrivateNetworkRequest +from .types import CreateRouteRequest from .types import CreateVPCRequest from .types import DeletePrivateNetworkRequest +from .types import DeleteRouteRequest from .types import DeleteSubnetsRequest from .types import DeleteSubnetsResponse from .types import DeleteVPCRequest from .types import EnableDHCPRequest +from .types import EnableRoutingRequest +from .types import GetAclRequest +from .types import GetAclResponse from .types import GetPrivateNetworkRequest +from .types import GetRouteRequest from .types import GetVPCRequest from .types import ListPrivateNetworksRequest from .types import ListPrivateNetworksResponse +from .types import ListSubnetsRequest +from .types import ListSubnetsResponse from .types import ListVPCsRequest from .types import ListVPCsResponse -from .types import MigrateZonalPrivateNetworksRequest -from .types import SetSubnetsRequest -from .types import SetSubnetsResponse +from .types import SetAclRequest +from .types import SetAclResponse from .types import UpdatePrivateNetworkRequest +from .types import UpdateRouteRequest from .types import UpdateVPCRequest from .api import VpcV2API __all__ = [ + "AclRuleProtocol", + "Action", "ListPrivateNetworksRequestOrderBy", + "ListSubnetsRequestOrderBy", "ListVPCsRequestOrderBy", "Subnet", "PrivateNetwork", + "Route", + "AclRule", "VPC", "AddSubnetsRequest", "AddSubnetsResponse", "CreatePrivateNetworkRequest", + "CreateRouteRequest", "CreateVPCRequest", "DeletePrivateNetworkRequest", + "DeleteRouteRequest", "DeleteSubnetsRequest", "DeleteSubnetsResponse", "DeleteVPCRequest", "EnableDHCPRequest", + "EnableRoutingRequest", + "GetAclRequest", + "GetAclResponse", "GetPrivateNetworkRequest", + "GetRouteRequest", "GetVPCRequest", "ListPrivateNetworksRequest", "ListPrivateNetworksResponse", + "ListSubnetsRequest", + "ListSubnetsResponse", "ListVPCsRequest", "ListVPCsResponse", - "MigrateZonalPrivateNetworksRequest", - "SetSubnetsRequest", - "SetSubnetsResponse", + "SetAclRequest", + "SetAclResponse", "UpdatePrivateNetworkRequest", + "UpdateRouteRequest", "UpdateVPCRequest", "VpcV2API", ] diff --git a/scaleway-async/scaleway_async/vpc/v2/api.py b/scaleway-async/scaleway_async/vpc/v2/api.py index 226f46f1..c76c382d 100644 --- a/scaleway-async/scaleway_async/vpc/v2/api.py +++ b/scaleway-async/scaleway_async/vpc/v2/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( random_name, @@ -13,52 +13,64 @@ fetch_all_pages_async, ) from .types import ( + Action, ListPrivateNetworksRequestOrderBy, + ListSubnetsRequestOrderBy, ListVPCsRequestOrderBy, + AclRule, AddSubnetsRequest, AddSubnetsResponse, CreatePrivateNetworkRequest, + CreateRouteRequest, CreateVPCRequest, DeleteSubnetsRequest, DeleteSubnetsResponse, + GetAclResponse, ListPrivateNetworksResponse, + ListSubnetsResponse, ListVPCsResponse, - MigrateZonalPrivateNetworksRequest, PrivateNetwork, - SetSubnetsRequest, - SetSubnetsResponse, + Route, + SetAclRequest, + SetAclResponse, + Subnet, UpdatePrivateNetworkRequest, + UpdateRouteRequest, UpdateVPCRequest, VPC, ) from .marshalling import ( unmarshal_PrivateNetwork, + unmarshal_Route, unmarshal_VPC, unmarshal_AddSubnetsResponse, unmarshal_DeleteSubnetsResponse, + unmarshal_GetAclResponse, unmarshal_ListPrivateNetworksResponse, + unmarshal_ListSubnetsResponse, unmarshal_ListVPCsResponse, - unmarshal_SetSubnetsResponse, + unmarshal_SetAclResponse, marshal_AddSubnetsRequest, marshal_CreatePrivateNetworkRequest, + marshal_CreateRouteRequest, marshal_CreateVPCRequest, marshal_DeleteSubnetsRequest, - marshal_MigrateZonalPrivateNetworksRequest, - marshal_SetSubnetsRequest, + marshal_SetAclRequest, marshal_UpdatePrivateNetworkRequest, + marshal_UpdateRouteRequest, marshal_UpdateVPCRequest, ) class VpcV2API(API): """ - VPC API. + This API allows you to manage your Virtual Private Clouds (VPCs) and Private Networks. """ async def list_vp_cs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListVPCsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -77,7 +89,7 @@ async def list_vp_cs( :param page: Page number to return, from the paginated results. :param page_size: Maximum number of VPCs to return per page. :param name: Name to filter for. Only VPCs with names containing this string will be returned. - :param tags: Tags to filter for. Only VPCs with one more more matching tags will be returned. + :param tags: Tags to filter for. Only VPCs with one or more matching tags will be returned. :param organization_id: Organization ID to filter for. Only VPCs belonging to this Organization will be returned. :param project_id: Project ID to filter for. Only VPCs belonging to this Project will be returned. :param is_default: Defines whether to filter only for VPCs which are the default one for their Project. @@ -117,7 +129,7 @@ async def list_vp_cs( async def list_vp_cs_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListVPCsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -136,7 +148,7 @@ async def list_vp_cs_all( :param page: Page number to return, from the paginated results. :param page_size: Maximum number of VPCs to return per page. :param name: Name to filter for. Only VPCs with names containing this string will be returned. - :param tags: Tags to filter for. Only VPCs with one more more matching tags will be returned. + :param tags: Tags to filter for. Only VPCs with one or more matching tags will be returned. :param organization_id: Organization ID to filter for. Only VPCs belonging to this Organization will be returned. :param project_id: Project ID to filter for. Only VPCs belonging to this Project will be returned. :param is_default: Defines whether to filter only for VPCs which are the default one for their Project. @@ -171,7 +183,7 @@ async def create_vpc( self, *, enable_routing: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, @@ -220,7 +232,7 @@ async def get_vpc( self, *, vpc_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> VPC: """ Get a VPC. @@ -254,7 +266,7 @@ async def update_vpc( self, *, vpc_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, ) -> VPC: @@ -301,7 +313,7 @@ async def delete_vpc( self, *, vpc_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a VPC. @@ -332,7 +344,7 @@ async def delete_vpc( async def list_private_networks( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -394,7 +406,7 @@ async def list_private_networks( async def list_private_networks_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -450,7 +462,8 @@ async def list_private_networks_all( async def create_private_network( self, *, - region: Optional[Region] = None, + default_route_propagation_enabled: bool, + region: Optional[ScwRegion] = None, name: Optional[str] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, @@ -460,6 +473,7 @@ async def create_private_network( """ Create a Private Network. Create a new Private Network. Once created, you can attach Scaleway resources which are in the same region. + :param default_route_propagation_enabled: Defines whether default v4 and v6 routes are propagated for this Private Network. :param region: Region to target. If none is passed will use default region from the config. :param name: Name for the Private Network. :param project_id: Scaleway Project in which to create the Private Network. @@ -471,7 +485,9 @@ async def create_private_network( Usage: :: - result = await api.create_private_network() + result = await api.create_private_network( + default_route_propagation_enabled=False, + ) """ param_region = validate_path_param( @@ -483,6 +499,7 @@ async def create_private_network( f"/vpc/v2/regions/{param_region}/private-networks", body=marshal_CreatePrivateNetworkRequest( CreatePrivateNetworkRequest( + default_route_propagation_enabled=default_route_propagation_enabled, region=region, name=name or random_name(prefix="pn"), project_id=project_id, @@ -501,7 +518,7 @@ async def get_private_network( self, *, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> PrivateNetwork: """ Get a Private Network. @@ -537,9 +554,10 @@ async def update_private_network( self, *, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, + default_route_propagation_enabled: Optional[bool] = None, ) -> PrivateNetwork: """ Update Private Network. @@ -548,6 +566,7 @@ async def update_private_network( :param region: Region to target. If none is passed will use default region from the config. :param name: Name for the Private Network. :param tags: Tags for the Private Network. + :param default_route_propagation_enabled: Defines whether default v4 and v6 routes are propagated for this Private Network. :return: :class:`PrivateNetwork ` Usage: @@ -574,6 +593,7 @@ async def update_private_network( region=region, name=name, tags=tags, + default_route_propagation_enabled=default_route_propagation_enabled, ), self.client, ), @@ -586,7 +606,7 @@ async def delete_private_network( self, *, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a Private Network. @@ -616,138 +636,183 @@ async def delete_private_network( self._throw_on_error(res) - async def migrate_zonal_private_networks( + async def enable_dhcp( self, *, - region: Optional[Region] = None, - organization_id: Optional[str] = None, - project_id: Optional[str] = None, - private_network_ids: Optional[List[str]] = None, - ) -> None: + private_network_id: str, + region: Optional[ScwRegion] = None, + ) -> PrivateNetwork: """ - Migrate Private Networks from zoned to regional. - Transform multiple existing zoned Private Networks (scoped to a single Availability Zone) into regional Private Networks, scoped to an entire region. You can transform one or many Private Networks (specified by their Private Network IDs) within a single Scaleway Organization or Project, with the same call. + Enable DHCP on a Private Network. + Enable DHCP managed on an existing Private Network. Note that you will not be able to deactivate it afterwards. + :param private_network_id: Private Network ID. :param region: Region to target. If none is passed will use default region from the config. - :param organization_id: Organization ID to target. The specified zoned Private Networks within this Organization will be migrated to regional. - One-Of ('scope'): at most one of 'organization_id', 'project_id' could be set. - :param project_id: Project to target. The specified zoned Private Networks within this Project will be migrated to regional. - One-Of ('scope'): at most one of 'organization_id', 'project_id' could be set. - :param private_network_ids: IDs of the Private Networks to migrate. + :return: :class:`PrivateNetwork ` Usage: :: - result = await api.migrate_zonal_private_networks() + result = await api.enable_dhcp( + private_network_id="example", + ) """ param_region = validate_path_param( "region", region or self.client.default_region ) + param_private_network_id = validate_path_param( + "private_network_id", private_network_id + ) res = self._request( "POST", - f"/vpc/v2/regions/{param_region}/private-networks/migrate-zonal", - body=marshal_MigrateZonalPrivateNetworksRequest( - MigrateZonalPrivateNetworksRequest( - region=region, - private_network_ids=private_network_ids, - organization_id=organization_id, - project_id=project_id, - ), - self.client, - ), + f"/vpc/v2/regions/{param_region}/private-networks/{param_private_network_id}/enable-dhcp", + body={}, ) self._throw_on_error(res) + return unmarshal_PrivateNetwork(res.json()) - async def enable_dhcp( + async def enable_routing( self, *, - private_network_id: str, - region: Optional[Region] = None, - ) -> PrivateNetwork: + vpc_id: str, + region: Optional[ScwRegion] = None, + ) -> VPC: """ - Enable DHCP on a Private Network. - Enable DHCP managed on an existing Private Network. Note that you will not be able to deactivate it afterwards. - :param private_network_id: Private Network ID. + Enable routing on a VPC. + Enable routing on an existing VPC. Note that you will not be able to deactivate it afterwards. + :param vpc_id: VPC ID. :param region: Region to target. If none is passed will use default region from the config. - :return: :class:`PrivateNetwork ` + :return: :class:`VPC ` Usage: :: - result = await api.enable_dhcp( - private_network_id="example", + result = await api.enable_routing( + vpc_id="example", ) """ param_region = validate_path_param( "region", region or self.client.default_region ) - param_private_network_id = validate_path_param( - "private_network_id", private_network_id - ) + param_vpc_id = validate_path_param("vpc_id", vpc_id) res = self._request( "POST", - f"/vpc/v2/regions/{param_region}/private-networks/{param_private_network_id}/enable-dhcp", + f"/vpc/v2/regions/{param_region}/vpcs/{param_vpc_id}/enable-routing", body={}, ) self._throw_on_error(res) - return unmarshal_PrivateNetwork(res.json()) + return unmarshal_VPC(res.json()) - async def set_subnets( + async def list_subnets( self, *, - private_network_id: str, - region: Optional[Region] = None, - subnets: Optional[List[str]] = None, - ) -> SetSubnetsResponse: + region: Optional[ScwRegion] = None, + order_by: Optional[ListSubnetsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + subnet_ids: Optional[List[str]] = None, + vpc_id: Optional[str] = None, + ) -> ListSubnetsResponse: """ - Set the subnets of a Private Network. - Set subnets for an existing Private Network. Note that the method is PUT and not PATCH. Any existing subnets will be removed in favor of the new specified set of subnets. - :param private_network_id: Private Network ID. + List subnets. + List any Private Network's subnets. See ListPrivateNetworks to list a specific Private Network's subnets. :param region: Region to target. If none is passed will use default region from the config. - :param subnets: Private Network subnets CIDR. - :return: :class:`SetSubnetsResponse ` + :param order_by: Sort order of the returned subnets. + :param page: Page number to return, from the paginated results. + :param page_size: Maximum number of Private Networks to return per page. + :param organization_id: Organization ID to filter for. Only subnets belonging to this Organization will be returned. + :param project_id: Project ID to filter for. Only subnets belonging to this Project will be returned. + :param subnet_ids: Subnet IDs to filter for. Only subnets matching the specified IDs will be returned. + :param vpc_id: VPC ID to filter for. Only subnets belonging to this VPC will be returned. + :return: :class:`ListSubnetsResponse ` Usage: :: - result = await api.set_subnets( - private_network_id="example", - ) + result = await api.list_subnets() """ param_region = validate_path_param( "region", region or self.client.default_region ) - param_private_network_id = validate_path_param( - "private_network_id", private_network_id - ) res = self._request( - "PUT", - f"/vpc/v2/regions/{param_region}/private-networks/{param_private_network_id}/subnets", - body=marshal_SetSubnetsRequest( - SetSubnetsRequest( - private_network_id=private_network_id, - region=region, - subnets=subnets, - ), - self.client, - ), + "GET", + f"/vpc/v2/regions/{param_region}/subnets", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "subnet_ids": subnet_ids, + "vpc_id": vpc_id, + }, ) self._throw_on_error(res) - return unmarshal_SetSubnetsResponse(res.json()) + return unmarshal_ListSubnetsResponse(res.json()) + + async def list_subnets_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListSubnetsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + subnet_ids: Optional[List[str]] = None, + vpc_id: Optional[str] = None, + ) -> List[Subnet]: + """ + List subnets. + List any Private Network's subnets. See ListPrivateNetworks to list a specific Private Network's subnets. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Sort order of the returned subnets. + :param page: Page number to return, from the paginated results. + :param page_size: Maximum number of Private Networks to return per page. + :param organization_id: Organization ID to filter for. Only subnets belonging to this Organization will be returned. + :param project_id: Project ID to filter for. Only subnets belonging to this Project will be returned. + :param subnet_ids: Subnet IDs to filter for. Only subnets matching the specified IDs will be returned. + :param vpc_id: VPC ID to filter for. Only subnets belonging to this VPC will be returned. + :return: :class:`List[Subnet] ` + + Usage: + :: + + result = await api.list_subnets_all() + """ + + return await fetch_all_pages_async( + type=ListSubnetsResponse, + key="subnets", + fetcher=self.list_subnets, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "subnet_ids": subnet_ids, + "vpc_id": vpc_id, + }, + ) async def add_subnets( self, *, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, subnets: Optional[List[str]] = None, ) -> AddSubnetsResponse: """ @@ -793,7 +858,7 @@ async def delete_subnets( self, *, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, subnets: Optional[List[str]] = None, ) -> DeleteSubnetsResponse: """ @@ -834,3 +899,275 @@ async def delete_subnets( self._throw_on_error(res) return unmarshal_DeleteSubnetsResponse(res.json()) + + async def create_route( + self, + *, + description: str, + vpc_id: str, + destination: str, + region: Optional[ScwRegion] = None, + tags: Optional[List[str]] = None, + nexthop_resource_id: Optional[str] = None, + nexthop_private_network_id: Optional[str] = None, + ) -> Route: + """ + Create a Route. + Create a new custom Route. + :param description: Route description. + :param vpc_id: VPC the Route belongs to. + :param destination: Destination of the Route. + :param region: Region to target. If none is passed will use default region from the config. + :param tags: Tags of the Route. + :param nexthop_resource_id: ID of the nexthop resource. + :param nexthop_private_network_id: ID of the nexthop private network. + :return: :class:`Route ` + + Usage: + :: + + result = await api.create_route( + description="example", + vpc_id="example", + destination="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/vpc/v2/regions/{param_region}/routes", + body=marshal_CreateRouteRequest( + CreateRouteRequest( + description=description, + vpc_id=vpc_id, + destination=destination, + region=region, + tags=tags, + nexthop_resource_id=nexthop_resource_id, + nexthop_private_network_id=nexthop_private_network_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Route(res.json()) + + async def get_route( + self, + *, + route_id: str, + region: Optional[ScwRegion] = None, + ) -> Route: + """ + Get a Route. + Retrieve details of an existing Route, specified by its Route ID. + :param route_id: Route ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Route ` + + Usage: + :: + + result = await api.get_route( + route_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_route_id = validate_path_param("route_id", route_id) + + res = self._request( + "GET", + f"/vpc/v2/regions/{param_region}/routes/{param_route_id}", + ) + + self._throw_on_error(res) + return unmarshal_Route(res.json()) + + async def update_route( + self, + *, + route_id: str, + region: Optional[ScwRegion] = None, + description: Optional[str] = None, + tags: Optional[List[str]] = None, + destination: Optional[str] = None, + nexthop_resource_id: Optional[str] = None, + nexthop_private_network_id: Optional[str] = None, + ) -> Route: + """ + Update Route. + Update parameters of the specified Route. + :param route_id: Route ID. + :param region: Region to target. If none is passed will use default region from the config. + :param description: Route description. + :param tags: Tags of the Route. + :param destination: Destination of the Route. + :param nexthop_resource_id: ID of the nexthop resource. + :param nexthop_private_network_id: ID of the nexthop private network. + :return: :class:`Route ` + + Usage: + :: + + result = await api.update_route( + route_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_route_id = validate_path_param("route_id", route_id) + + res = self._request( + "PATCH", + f"/vpc/v2/regions/{param_region}/routes/{param_route_id}", + body=marshal_UpdateRouteRequest( + UpdateRouteRequest( + route_id=route_id, + region=region, + description=description, + tags=tags, + destination=destination, + nexthop_resource_id=nexthop_resource_id, + nexthop_private_network_id=nexthop_private_network_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Route(res.json()) + + async def delete_route( + self, + *, + route_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a Route. + Delete a Route specified by its Route ID. + :param route_id: Route ID. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = await api.delete_route( + route_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_route_id = validate_path_param("route_id", route_id) + + res = self._request( + "DELETE", + f"/vpc/v2/regions/{param_region}/routes/{param_route_id}", + ) + + self._throw_on_error(res) + + async def get_acl( + self, + *, + vpc_id: str, + is_ipv6: bool, + region: Optional[ScwRegion] = None, + ) -> GetAclResponse: + """ + Get ACL Rules for VPC. + Retrieve a list of ACL rules for a VPC, specified by its VPC ID. + :param vpc_id: ID of the Network ACL's VPC. + :param is_ipv6: Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`GetAclResponse ` + + Usage: + :: + + result = await api.get_acl( + vpc_id="example", + is_ipv6=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_vpc_id = validate_path_param("vpc_id", vpc_id) + + res = self._request( + "GET", + f"/vpc/v2/regions/{param_region}/vpcs/{param_vpc_id}/acl-rules", + params={ + "is_ipv6": is_ipv6, + }, + ) + + self._throw_on_error(res) + return unmarshal_GetAclResponse(res.json()) + + async def set_acl( + self, + *, + vpc_id: str, + rules: List[AclRule], + is_ipv6: bool, + default_policy: Action, + region: Optional[ScwRegion] = None, + ) -> SetAclResponse: + """ + Set VPC ACL rules. + Set the list of ACL rules and the default routing policy for a VPC. + :param vpc_id: ID of the Network ACL's VPC. + :param rules: List of Network ACL rules. + :param is_ipv6: Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + :param default_policy: Action to take for packets which do not match any rules. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`SetAclResponse ` + + Usage: + :: + + result = await api.set_acl( + vpc_id="example", + rules=[], + is_ipv6=False, + default_policy=Action.unknown_action, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_vpc_id = validate_path_param("vpc_id", vpc_id) + + res = self._request( + "PUT", + f"/vpc/v2/regions/{param_region}/vpcs/{param_vpc_id}/acl-rules", + body=marshal_SetAclRequest( + SetAclRequest( + vpc_id=vpc_id, + rules=rules, + is_ipv6=is_ipv6, + default_policy=default_policy, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetAclResponse(res.json()) diff --git a/scaleway-async/scaleway_async/vpc/v2/marshalling.py b/scaleway-async/scaleway_async/vpc/v2/marshalling.py index 760ec692..9229bba7 100644 --- a/scaleway-async/scaleway_async/vpc/v2/marshalling.py +++ b/scaleway-async/scaleway_async/vpc/v2/marshalling.py @@ -5,26 +5,27 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults -from scaleway_core.utils import ( - OneOfPossibility, - resolve_one_of, -) from .types import ( Subnet, PrivateNetwork, + Route, VPC, AddSubnetsResponse, DeleteSubnetsResponse, + AclRule, + GetAclResponse, ListPrivateNetworksResponse, + ListSubnetsResponse, ListVPCsResponse, - SetSubnetsResponse, + SetAclResponse, AddSubnetsRequest, CreatePrivateNetworkRequest, + CreateRouteRequest, CreateVPCRequest, DeleteSubnetsRequest, - MigrateZonalPrivateNetworksRequest, - SetSubnetsRequest, + SetAclRequest, UpdatePrivateNetworkRequest, + UpdateRouteRequest, UpdateVPCRequest, ) @@ -45,13 +46,29 @@ def unmarshal_Subnet(data: Any) -> Subnet: if field is not None: args["subnet"] = field + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + field = data.get("vpc_id", None) + if field is not None: + args["vpc_id"] = field + field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Subnet(**args) @@ -102,17 +119,88 @@ def unmarshal_PrivateNetwork(data: Any) -> PrivateNetwork: if field is not None: args["dhcp_enabled"] = field + field = data.get("default_route_propagation_enabled", None) + if field is not None: + args["default_route_propagation_enabled"] = field + field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return PrivateNetwork(**args) +def unmarshal_Route(data: Any) -> Route: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Route' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("vpc_id", None) + if field is not None: + args["vpc_id"] = field + + field = data.get("destination", None) + if field is not None: + args["destination"] = field + + field = data.get("is_read_only", None) + if field is not None: + args["is_read_only"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("nexthop_resource_id", None) + if field is not None: + args["nexthop_resource_id"] = field + else: + args["nexthop_resource_id"] = None + + field = data.get("nexthop_private_network_id", None) + if field is not None: + args["nexthop_private_network_id"] = field + else: + args["nexthop_private_network_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Route(**args) + + def unmarshal_VPC(data: Any) -> VPC: if not isinstance(data, dict): raise TypeError( @@ -160,10 +248,14 @@ def unmarshal_VPC(data: Any) -> VPC: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return VPC(**args) @@ -198,6 +290,76 @@ def unmarshal_DeleteSubnetsResponse(data: Any) -> DeleteSubnetsResponse: return DeleteSubnetsResponse(**args) +def unmarshal_AclRule(data: Any) -> AclRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AclRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("protocol", None) + if field is not None: + args["protocol"] = field + + field = data.get("source", None) + if field is not None: + args["source"] = field + + field = data.get("src_port_low", None) + if field is not None: + args["src_port_low"] = field + + field = data.get("src_port_high", None) + if field is not None: + args["src_port_high"] = field + + field = data.get("destination", None) + if field is not None: + args["destination"] = field + + field = data.get("dst_port_low", None) + if field is not None: + args["dst_port_low"] = field + + field = data.get("dst_port_high", None) + if field is not None: + args["dst_port_high"] = field + + field = data.get("action", None) + if field is not None: + args["action"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + else: + args["description"] = None + + return AclRule(**args) + + +def unmarshal_GetAclResponse(data: Any) -> GetAclResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetAclResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_AclRule(v) for v in field] if field is not None else None + ) + + field = data.get("default_policy", None) + if field is not None: + args["default_policy"] = field + + return GetAclResponse(**args) + + def unmarshal_ListPrivateNetworksResponse(data: Any) -> ListPrivateNetworksResponse: if not isinstance(data, dict): raise TypeError( @@ -219,6 +381,27 @@ def unmarshal_ListPrivateNetworksResponse(data: Any) -> ListPrivateNetworksRespo return ListPrivateNetworksResponse(**args) +def unmarshal_ListSubnetsResponse(data: Any) -> ListSubnetsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSubnetsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("subnets", None) + if field is not None: + args["subnets"] = ( + [unmarshal_Subnet(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListSubnetsResponse(**args) + + def unmarshal_ListVPCsResponse(data: Any) -> ListVPCsResponse: if not isinstance(data, dict): raise TypeError( @@ -238,19 +421,25 @@ def unmarshal_ListVPCsResponse(data: Any) -> ListVPCsResponse: return ListVPCsResponse(**args) -def unmarshal_SetSubnetsResponse(data: Any) -> SetSubnetsResponse: +def unmarshal_SetAclResponse(data: Any) -> SetAclResponse: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'SetSubnetsResponse' failed as data isn't a dictionary." + "Unmarshalling the type 'SetAclResponse' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} - field = data.get("subnets", None) + field = data.get("rules", None) if field is not None: - args["subnets"] = field + args["rules"] = ( + [unmarshal_AclRule(v) for v in field] if field is not None else None + ) + + field = data.get("default_policy", None) + if field is not None: + args["default_policy"] = field - return SetSubnetsResponse(**args) + return SetAclResponse(**args) def marshal_AddSubnetsRequest( @@ -271,6 +460,11 @@ def marshal_CreatePrivateNetworkRequest( ) -> Dict[str, Any]: output: Dict[str, Any] = {} + if request.default_route_propagation_enabled is not None: + output["default_route_propagation_enabled"] = ( + request.default_route_propagation_enabled + ) + if request.name is not None: output["name"] = request.name @@ -289,6 +483,33 @@ def marshal_CreatePrivateNetworkRequest( return output +def marshal_CreateRouteRequest( + request: CreateRouteRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.description is not None: + output["description"] = request.description + + if request.vpc_id is not None: + output["vpc_id"] = request.vpc_id + + if request.destination is not None: + output["destination"] = request.destination + + if request.tags is not None: + output["tags"] = request.tags + + if request.nexthop_resource_id is not None: + output["nexthop_resource_id"] = request.nexthop_resource_id + + if request.nexthop_private_network_id is not None: + output["nexthop_private_network_id"] = request.nexthop_private_network_id + + return output + + def marshal_CreateVPCRequest( request: CreateVPCRequest, defaults: ProfileDefaults, @@ -322,40 +543,56 @@ def marshal_DeleteSubnetsRequest( return output -def marshal_MigrateZonalPrivateNetworksRequest( - request: MigrateZonalPrivateNetworksRequest, +def marshal_AclRule( + request: AclRule, defaults: ProfileDefaults, ) -> Dict[str, Any]: output: Dict[str, Any] = {} - output.update( - resolve_one_of( - [ - OneOfPossibility( - "organization_id", - request.organization_id, - defaults.default_organization_id, - ), - OneOfPossibility( - "project_id", request.project_id, defaults.default_project_id - ), - ] - ), - ) - - if request.private_network_ids is not None: - output["private_network_ids"] = request.private_network_ids + + if request.protocol is not None: + output["protocol"] = str(request.protocol) + + if request.source is not None: + output["source"] = request.source + + if request.src_port_low is not None: + output["src_port_low"] = request.src_port_low + + if request.src_port_high is not None: + output["src_port_high"] = request.src_port_high + + if request.destination is not None: + output["destination"] = request.destination + + if request.dst_port_low is not None: + output["dst_port_low"] = request.dst_port_low + + if request.dst_port_high is not None: + output["dst_port_high"] = request.dst_port_high + + if request.action is not None: + output["action"] = str(request.action) + + if request.description is not None: + output["description"] = request.description return output -def marshal_SetSubnetsRequest( - request: SetSubnetsRequest, +def marshal_SetAclRequest( + request: SetAclRequest, defaults: ProfileDefaults, ) -> Dict[str, Any]: output: Dict[str, Any] = {} - if request.subnets is not None: - output["subnets"] = request.subnets + if request.rules is not None: + output["rules"] = [marshal_AclRule(item, defaults) for item in request.rules] + + if request.is_ipv6 is not None: + output["is_ipv6"] = request.is_ipv6 + + if request.default_policy is not None: + output["default_policy"] = str(request.default_policy) return output @@ -372,6 +609,35 @@ def marshal_UpdatePrivateNetworkRequest( if request.tags is not None: output["tags"] = request.tags + if request.default_route_propagation_enabled is not None: + output["default_route_propagation_enabled"] = ( + request.default_route_propagation_enabled + ) + + return output + + +def marshal_UpdateRouteRequest( + request: UpdateRouteRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.description is not None: + output["description"] = request.description + + if request.tags is not None: + output["tags"] = request.tags + + if request.destination is not None: + output["destination"] = request.destination + + if request.nexthop_resource_id is not None: + output["nexthop_resource_id"] = request.nexthop_resource_id + + if request.nexthop_private_network_id is not None: + output["nexthop_private_network_id"] = request.nexthop_private_network_id + return output diff --git a/scaleway-async/scaleway_async/vpc/v2/types.py b/scaleway-async/scaleway_async/vpc/v2/types.py index c74e7bd3..09a06570 100644 --- a/scaleway-async/scaleway_async/vpc/v2/types.py +++ b/scaleway-async/scaleway_async/vpc/v2/types.py @@ -8,13 +8,32 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, ) +class AclRuleProtocol(str, Enum, metaclass=StrEnumMeta): + ANY = "any" + TCP = "tcp" + UDP = "udp" + ICMP = "icmp" + + def __str__(self) -> str: + return str(self.value) + + +class Action(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + ACCEPT = "accept" + DROP = "drop" + + def __str__(self) -> str: + return str(self.value) + + class ListPrivateNetworksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -25,6 +44,14 @@ def __str__(self) -> str: return str(self.value) +class ListSubnetsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + class ListVPCsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -47,6 +74,21 @@ class Subnet: Subnet CIDR. """ + project_id: str + """ + Scaleway Project the subnet belongs to. + """ + + private_network_id: str + """ + Private Network the subnet belongs to. + """ + + vpc_id: str + """ + VPC the subnet belongs to. + """ + created_at: Optional[datetime] """ Subnet creation date. @@ -80,7 +122,7 @@ class PrivateNetwork: Scaleway Project the Private Network belongs to. """ - region: Region + region: ScwRegion """ Region in which the Private Network is available. """ @@ -105,6 +147,11 @@ class PrivateNetwork: Defines whether managed DHCP is enabled for this Private Network. """ + default_route_propagation_enabled: bool + """ + Defines whether default v4 and v6 routes are propagated for this Private Network. + """ + created_at: Optional[datetime] """ Date the Private Network was created. @@ -116,6 +163,112 @@ class PrivateNetwork: """ +@dataclass +class Route: + id: str + """ + Route ID. + """ + + description: str + """ + Route description. + """ + + tags: List[str] + """ + Tags of the Route. + """ + + vpc_id: str + """ + VPC the Route belongs to. + """ + + destination: str + """ + Destination of the Route. + """ + + is_read_only: bool + """ + Defines whether the route can be modified or deleted by the user. + """ + + region: ScwRegion + """ + Region of the Route. + """ + + nexthop_resource_id: Optional[str] + """ + ID of the nexthop resource. + """ + + nexthop_private_network_id: Optional[str] + """ + ID of the nexthop private network. + """ + + created_at: Optional[datetime] + """ + Date the Route was created. + """ + + updated_at: Optional[datetime] + """ + Date the Route was last modified. + """ + + +@dataclass +class AclRule: + protocol: AclRuleProtocol + """ + Protocol to which this rule applies. + """ + + source: str + """ + Source IP range to which this rule applies (CIDR notation with subnet mask). + """ + + src_port_low: int + """ + Starting port of the source port range to which this rule applies (inclusive). + """ + + src_port_high: int + """ + Ending port of the source port range to which this rule applies (inclusive). + """ + + destination: str + """ + Destination IP range to which this rule applies (CIDR notation with subnet mask). + """ + + dst_port_low: int + """ + Starting port of the destination port range to which this rule applies (inclusive). + """ + + dst_port_high: int + """ + Ending port of the destination port range to which this rule applies (inclusive). + """ + + action: Action + """ + Policy to apply to the packet. + """ + + description: Optional[str] + """ + Rule description. + """ + + @dataclass class VPC: id: str @@ -138,7 +291,7 @@ class VPC: Scaleway Project the VPC belongs to. """ - region: Region + region: ScwRegion """ Region of the VPC. """ @@ -181,7 +334,7 @@ class AddSubnetsRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -199,7 +352,12 @@ class AddSubnetsResponse: @dataclass class CreatePrivateNetworkRequest: - region: Optional[Region] + default_route_propagation_enabled: bool + """ + Defines whether default v4 and v6 routes are propagated for this Private Network. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -230,6 +388,44 @@ class CreatePrivateNetworkRequest: """ +@dataclass +class CreateRouteRequest: + description: str + """ + Route description. + """ + + vpc_id: str + """ + VPC the Route belongs to. + """ + + destination: str + """ + Destination of the Route. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + tags: Optional[List[str]] + """ + Tags of the Route. + """ + + nexthop_resource_id: Optional[str] + """ + ID of the nexthop resource. + """ + + nexthop_private_network_id: Optional[str] + """ + ID of the nexthop private network. + """ + + @dataclass class CreateVPCRequest: enable_routing: bool @@ -237,7 +433,7 @@ class CreateVPCRequest: Enable routing between Private Networks in the VPC. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -265,7 +461,20 @@ class DeletePrivateNetworkRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteRouteRequest: + route_id: str + """ + Route ID. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -278,7 +487,7 @@ class DeleteSubnetsRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -301,7 +510,7 @@ class DeleteVPCRequest: VPC ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -314,12 +523,50 @@ class EnableDHCPRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class EnableRoutingRequest: + vpc_id: str + """ + VPC ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetAclRequest: + vpc_id: str + """ + ID of the Network ACL's VPC. + """ + + is_ipv6: bool + """ + Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetAclResponse: + rules: List[AclRule] + + default_policy: Action + + @dataclass class GetPrivateNetworkRequest: private_network_id: str @@ -327,7 +574,20 @@ class GetPrivateNetworkRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetRouteRequest: + route_id: str + """ + Route ID. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -340,7 +600,7 @@ class GetVPCRequest: VPC ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -348,7 +608,7 @@ class GetVPCRequest: @dataclass class ListPrivateNetworksRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -411,9 +671,59 @@ class ListPrivateNetworksResponse: total_count: int +@dataclass +class ListSubnetsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListSubnetsRequestOrderBy] + """ + Sort order of the returned subnets. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Maximum number of Private Networks to return per page. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. Only subnets belonging to this Organization will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for. Only subnets belonging to this Project will be returned. + """ + + subnet_ids: Optional[List[str]] + """ + Subnet IDs to filter for. Only subnets matching the specified IDs will be returned. + """ + + vpc_id: Optional[str] + """ + VPC ID to filter for. Only subnets belonging to this VPC will be returned. + """ + + +@dataclass +class ListSubnetsResponse: + subnets: List[Subnet] + + total_count: int + + @dataclass class ListVPCsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -440,7 +750,7 @@ class ListVPCsRequest: tags: Optional[List[str]] """ - Tags to filter for. Only VPCs with one more more matching tags will be returned. + Tags to filter for. Only VPCs with one or more matching tags will be returned. """ organization_id: Optional[str] @@ -472,43 +782,38 @@ class ListVPCsResponse: @dataclass -class MigrateZonalPrivateNetworksRequest: - region: Optional[Region] +class SetAclRequest: + vpc_id: str """ - Region to target. If none is passed will use default region from the config. + ID of the Network ACL's VPC. """ - private_network_ids: Optional[List[str]] + rules: List[AclRule] """ - IDs of the Private Networks to migrate. + List of Network ACL rules. """ - organization_id: Optional[str] - - project_id: Optional[str] - - -@dataclass -class SetSubnetsRequest: - private_network_id: str + is_ipv6: bool """ - Private Network ID. + Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. """ - region: Optional[Region] + default_policy: Action """ - Region to target. If none is passed will use default region from the config. + Action to take for packets which do not match any rules. """ - subnets: Optional[List[str]] + region: Optional[ScwRegion] """ - Private Network subnets CIDR. + Region to target. If none is passed will use default region from the config. """ @dataclass -class SetSubnetsResponse: - subnets: List[str] +class SetAclResponse: + rules: List[AclRule] + + default_policy: Action @dataclass @@ -518,7 +823,7 @@ class UpdatePrivateNetworkRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -533,6 +838,49 @@ class UpdatePrivateNetworkRequest: Tags for the Private Network. """ + default_route_propagation_enabled: Optional[bool] + """ + Defines whether default v4 and v6 routes are propagated for this Private Network. + """ + + +@dataclass +class UpdateRouteRequest: + route_id: str + """ + Route ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + description: Optional[str] + """ + Route description. + """ + + tags: Optional[List[str]] + """ + Tags of the Route. + """ + + destination: Optional[str] + """ + Destination of the Route. + """ + + nexthop_resource_id: Optional[str] + """ + ID of the nexthop resource. + """ + + nexthop_private_network_id: Optional[str] + """ + ID of the nexthop private network. + """ + @dataclass class UpdateVPCRequest: @@ -541,7 +889,7 @@ class UpdateVPCRequest: VPC ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway-async/scaleway_async/vpcgw/v1/__init__.py b/scaleway-async/scaleway_async/vpcgw/v1/__init__.py index d02eb818..99525258 100644 --- a/scaleway-async/scaleway_async/vpcgw/v1/__init__.py +++ b/scaleway-async/scaleway_async/vpcgw/v1/__init__.py @@ -57,6 +57,7 @@ from .types import ListIPsResponse from .types import ListPATRulesRequest from .types import ListPATRulesResponse +from .types import MigrateToV2Request from .types import RefreshSSHKeysRequest from .types import SetDHCPEntriesRequest from .types import SetDHCPEntriesResponse @@ -129,6 +130,7 @@ "ListIPsResponse", "ListPATRulesRequest", "ListPATRulesResponse", + "MigrateToV2Request", "RefreshSSHKeysRequest", "SetDHCPEntriesRequest", "SetDHCPEntriesResponse", diff --git a/scaleway-async/scaleway_async/vpcgw/v1/api.py b/scaleway-async/scaleway_async/vpcgw/v1/api.py index a0d89c8b..6d81509b 100644 --- a/scaleway-async/scaleway_async/vpcgw/v1/api.py +++ b/scaleway-async/scaleway_async/vpcgw/v1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, @@ -58,6 +58,7 @@ UpdateGatewayRequest, UpdateIPRequest, UpdatePATRuleRequest, + UpgradeGatewayRequest, ) from .content import ( GATEWAY_NETWORK_TRANSIENT_STATUSES, @@ -93,18 +94,19 @@ marshal_UpdateGatewayRequest, marshal_UpdateIPRequest, marshal_UpdatePATRuleRequest, + marshal_UpgradeGatewayRequest, ) class VpcgwV1API(API): """ - Public Gateways API. + This API allows you to manage your Public Gateways. """ async def list_gateways( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListGatewaysRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -131,6 +133,7 @@ async def list_gateways( :param status: Filter for gateways with this current status. Use `unknown` to include all statuses. :param private_network_id: Filter for gateways attached to this Private nNetwork. :return: :class:`ListGatewaysResponse ` + :deprecated Usage: :: @@ -164,7 +167,7 @@ async def list_gateways( async def list_gateways_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListGatewaysRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -191,6 +194,7 @@ async def list_gateways_all( :param status: Filter for gateways with this current status. Use `unknown` to include all statuses. :param private_network_id: Filter for gateways attached to this Private nNetwork. :return: :class:`List[Gateway] ` + :deprecated Usage: :: @@ -221,7 +225,7 @@ async def get_gateway( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Gateway: """ Get a Public Gateway. @@ -229,6 +233,7 @@ async def get_gateway( :param gateway_id: ID of the gateway to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`Gateway ` + :deprecated Usage: :: @@ -253,7 +258,7 @@ async def wait_for_gateway( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Gateway, Union[bool, Awaitable[bool]]]] = None, ) -> Gateway: """ @@ -262,6 +267,7 @@ async def wait_for_gateway( :param gateway_id: ID of the gateway to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`Gateway ` + :deprecated Usage: :: @@ -292,7 +298,7 @@ async def create_gateway( type_: str, enable_smtp: bool, enable_bastion: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project_id: Optional[str] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, @@ -314,6 +320,7 @@ async def create_gateway( :param ip_id: Existing IP address to attach to the gateway. :param bastion_port: Port of the SSH bastion. :return: :class:`Gateway ` + :deprecated Usage: :: @@ -354,7 +361,7 @@ async def update_gateway( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, upstream_dns_servers: Optional[List[str]] = None, @@ -374,6 +381,7 @@ async def update_gateway( :param bastion_port: Port of the SSH bastion. :param enable_smtp: Defines whether SMTP traffic should be allowed to pass through the gateway. :return: :class:`Gateway ` + :deprecated Usage: :: @@ -412,7 +420,7 @@ async def delete_gateway( *, gateway_id: str, cleanup_dhcp: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a Public Gateway. @@ -420,6 +428,7 @@ async def delete_gateway( :param gateway_id: ID of the gateway to delete. :param cleanup_dhcp: Defines whether to clean up attached DHCP configurations (if any, and if not attached to another Gateway Network). :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -447,14 +456,17 @@ async def upgrade_gateway( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, + type_: Optional[str] = None, ) -> Gateway: """ - Upgrade a Public Gateway to the latest version. - Upgrade a given Public Gateway to the newest software version. This applies the latest bugfixes and features to your Public Gateway, but its service will be interrupted during the update. + Upgrade a Public Gateway to the latest version and/or to a different commercial offer type. + Upgrade a given Public Gateway to the newest software version or to a different commercial offer type. This applies the latest bugfixes and features to your Public Gateway. Note that gateway service will be interrupted during the update. :param gateway_id: ID of the gateway to upgrade. :param zone: Zone to target. If none is passed will use default zone from the config. + :param type_: Gateway type (commercial offer). :return: :class:`Gateway ` + :deprecated Usage: :: @@ -470,7 +482,14 @@ async def upgrade_gateway( res = self._request( "POST", f"/vpc-gw/v1/zones/{param_zone}/gateways/{param_gateway_id}/upgrade", - body={}, + body=marshal_UpgradeGatewayRequest( + UpgradeGatewayRequest( + gateway_id=gateway_id, + zone=zone, + type_=type_, + ), + self.client, + ), ) self._throw_on_error(res) @@ -480,13 +499,14 @@ async def enable_ip_mobility( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Upgrade a Public Gateway to IP mobility. Upgrade a Public Gateway to IP mobility (move from NAT IP to routed IP). This is idempotent: repeated calls after the first will return no error but have no effect. :param gateway_id: ID of the gateway to upgrade to IP mobility. :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -510,7 +530,7 @@ async def enable_ip_mobility( async def list_gateway_networks( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListGatewayNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -533,6 +553,7 @@ async def list_gateway_networks( :param dhcp_id: Filter for GatewayNetworks using this DHCP configuration. :param status: Filter for GatewayNetworks with this current status this status. Use `unknown` to include all statuses. :return: :class:`ListGatewayNetworksResponse ` + :deprecated Usage: :: @@ -563,7 +584,7 @@ async def list_gateway_networks( async def list_gateway_networks_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListGatewayNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -586,6 +607,7 @@ async def list_gateway_networks_all( :param dhcp_id: Filter for GatewayNetworks using this DHCP configuration. :param status: Filter for GatewayNetworks with this current status this status. Use `unknown` to include all statuses. :return: :class:`List[GatewayNetwork] ` + :deprecated Usage: :: @@ -614,7 +636,7 @@ async def get_gateway_network( self, *, gateway_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GatewayNetwork: """ Get a Public Gateway connection to a Private Network. @@ -622,6 +644,7 @@ async def get_gateway_network( :param gateway_network_id: ID of the GatewayNetwork to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`GatewayNetwork ` + :deprecated Usage: :: @@ -648,7 +671,7 @@ async def wait_for_gateway_network( self, *, gateway_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[ WaitForOptions[GatewayNetwork, Union[bool, Awaitable[bool]]] ] = None, @@ -659,6 +682,7 @@ async def wait_for_gateway_network( :param gateway_network_id: ID of the GatewayNetwork to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`GatewayNetwork ` + :deprecated Usage: :: @@ -691,7 +715,7 @@ async def create_gateway_network( gateway_id: str, private_network_id: str, enable_masquerade: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, enable_dhcp: Optional[bool] = None, dhcp_id: Optional[str] = None, dhcp: Optional[CreateDHCPRequest] = None, @@ -711,11 +735,12 @@ async def create_gateway_network( One-Of ('ip_config'): at most one of 'dhcp_id', 'dhcp', 'address', 'ipam_config' could be set. :param dhcp: New DHCP configuration object to use for this GatewayNetwork. One-Of ('ip_config'): at most one of 'dhcp_id', 'dhcp', 'address', 'ipam_config' could be set. - :param address: Static IP address in CIDR format to to use without DHCP. + :param address: Static IP address in CIDR format to use without DHCP. One-Of ('ip_config'): at most one of 'dhcp_id', 'dhcp', 'address', 'ipam_config' could be set. :param ipam_config: Note: all or none of the GatewayNetworks for a single gateway can use the IPAM. DHCP and IPAM configurations cannot be mixed. Some products may require that the Public Gateway uses the IPAM, to ensure correct functionality. One-Of ('ip_config'): at most one of 'dhcp_id', 'dhcp', 'address', 'ipam_config' could be set. :return: :class:`GatewayNetwork ` + :deprecated Usage: :: @@ -755,7 +780,7 @@ async def update_gateway_network( self, *, gateway_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, enable_masquerade: Optional[bool] = None, enable_dhcp: Optional[bool] = None, dhcp_id: Optional[str] = None, @@ -777,6 +802,7 @@ async def update_gateway_network( :param ipam_config: Note: all or none of the GatewayNetworks for a single gateway can use the IPAM. DHCP and IPAM configurations cannot be mixed. Some products may require that the Public Gateway uses the IPAM, to ensure correct functionality. One-Of ('ip_config'): at most one of 'dhcp_id', 'address', 'ipam_config' could be set. :return: :class:`GatewayNetwork ` + :deprecated Usage: :: @@ -816,7 +842,7 @@ async def delete_gateway_network( *, gateway_network_id: str, cleanup_dhcp: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Detach a Public Gateway from a Private Network. @@ -824,6 +850,7 @@ async def delete_gateway_network( :param gateway_network_id: ID of the GatewayNetwork to delete. :param cleanup_dhcp: Defines whether to clean up attached DHCP configurations (if any, and if not attached to another Gateway Network). :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -852,7 +879,7 @@ async def delete_gateway_network( async def list_dhc_ps( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListDHCPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -873,6 +900,7 @@ async def list_dhc_ps( :param address: Filter for DHCP configuration objects with this DHCP server IP address (the gateway's address in the Private Network). :param has_address: Filter for DHCP configuration objects with subnets containing this IP address. :return: :class:`ListDHCPsResponse ` + :deprecated Usage: :: @@ -903,7 +931,7 @@ async def list_dhc_ps( async def list_dhc_ps_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListDHCPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -924,6 +952,7 @@ async def list_dhc_ps_all( :param address: Filter for DHCP configuration objects with this DHCP server IP address (the gateway's address in the Private Network). :param has_address: Filter for DHCP configuration objects with subnets containing this IP address. :return: :class:`List[DHCP] ` + :deprecated Usage: :: @@ -951,7 +980,7 @@ async def get_dhcp( self, *, dhcp_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> DHCP: """ Get a DHCP configuration. @@ -959,6 +988,7 @@ async def get_dhcp( :param dhcp_id: ID of the DHCP configuration to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`DHCP ` + :deprecated Usage: :: @@ -983,7 +1013,7 @@ async def create_dhcp( self, *, subnet: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project_id: Optional[str] = None, address: Optional[str] = None, pool_low: Optional[str] = None, @@ -1017,6 +1047,7 @@ async def create_dhcp( :param dns_search: Array of search paths in addition to the pushed DNS configuration. :param dns_local_name: TLD given to hostnames in the Private Network. Allowed characters are `a-z0-9-.`. Defaults to the slugified Private Network name if created along a GatewayNetwork, or else to `priv`. :return: :class:`DHCP ` + :deprecated Usage: :: @@ -1060,7 +1091,7 @@ async def update_dhcp( self, *, dhcp_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, subnet: Optional[str] = None, address: Optional[str] = None, pool_low: Optional[str] = None, @@ -1094,6 +1125,7 @@ async def update_dhcp( :param dns_search: Array of search paths in addition to the pushed DNS configuration. :param dns_local_name: TLD given to hostnames in the Private Networks. If an instance with hostname `foo` gets a lease, and this is set to `bar`, `foo.bar` will resolve. Allowed characters are `a-z0-9-.`. :return: :class:`DHCP ` + :deprecated Usage: :: @@ -1138,13 +1170,14 @@ async def delete_dhcp( self, *, dhcp_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a DHCP configuration. Delete a DHCP configuration object, identified by its DHCP ID. Note that you cannot delete a DHCP configuration object that is currently being used by a Gateway Network. :param dhcp_id: DHCP configuration ID to delete. :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -1167,7 +1200,7 @@ async def delete_dhcp( async def list_dhcp_entries( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListDHCPEntriesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1190,6 +1223,7 @@ async def list_dhcp_entries( :param hostname: Filter for entries with this hostname substring. :param type_: Filter for entries of this type. :return: :class:`ListDHCPEntriesResponse ` + :deprecated Usage: :: @@ -1220,7 +1254,7 @@ async def list_dhcp_entries( async def list_dhcp_entries_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListDHCPEntriesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1243,6 +1277,7 @@ async def list_dhcp_entries_all( :param hostname: Filter for entries with this hostname substring. :param type_: Filter for entries of this type. :return: :class:`List[DHCPEntry] ` + :deprecated Usage: :: @@ -1271,7 +1306,7 @@ async def get_dhcp_entry( self, *, dhcp_entry_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> DHCPEntry: """ Get a DHCP entry. @@ -1279,6 +1314,7 @@ async def get_dhcp_entry( :param dhcp_entry_id: ID of the DHCP entry to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`DHCPEntry ` + :deprecated Usage: :: @@ -1305,7 +1341,7 @@ async def create_dhcp_entry( gateway_network_id: str, mac_address: str, ip_address: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> DHCPEntry: """ Create a DHCP entry. @@ -1315,6 +1351,7 @@ async def create_dhcp_entry( :param ip_address: IP address to give to the device. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`DHCPEntry ` + :deprecated Usage: :: @@ -1349,7 +1386,7 @@ async def update_dhcp_entry( self, *, dhcp_entry_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ip_address: Optional[str] = None, ) -> DHCPEntry: """ @@ -1359,6 +1396,7 @@ async def update_dhcp_entry( :param zone: Zone to target. If none is passed will use default zone from the config. :param ip_address: New IP address to give to the device. :return: :class:`DHCPEntry ` + :deprecated Usage: :: @@ -1391,7 +1429,7 @@ async def set_dhcp_entries( self, *, gateway_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, dhcp_entries: Optional[List[SetDHCPEntriesRequestEntry]] = None, ) -> SetDHCPEntriesResponse: """ @@ -1401,6 +1439,7 @@ async def set_dhcp_entries( :param zone: Zone to target. If none is passed will use default zone from the config. :param dhcp_entries: New list of DHCP reservations. :return: :class:`SetDHCPEntriesResponse ` + :deprecated Usage: :: @@ -1432,13 +1471,14 @@ async def delete_dhcp_entry( self, *, dhcp_entry_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a DHCP entry. Delete a static DHCP reservation, identified by its DHCP entry ID. Note that you cannot delete DHCP entries of type `lease`, these are deleted automatically when their time-to-live expires. :param dhcp_entry_id: ID of the DHCP entry to delete. :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -1461,7 +1501,7 @@ async def delete_dhcp_entry( async def list_pat_rules( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListPATRulesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1480,6 +1520,7 @@ async def list_pat_rules( :param private_ip: Filter for PAT rules targeting this private ip. :param protocol: Filter for PAT rules with this protocol. :return: :class:`ListPATRulesResponse ` + :deprecated Usage: :: @@ -1508,7 +1549,7 @@ async def list_pat_rules( async def list_pat_rules_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListPATRulesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1527,6 +1568,7 @@ async def list_pat_rules_all( :param private_ip: Filter for PAT rules targeting this private ip. :param protocol: Filter for PAT rules with this protocol. :return: :class:`List[PATRule] ` + :deprecated Usage: :: @@ -1553,7 +1595,7 @@ async def get_pat_rule( self, *, pat_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> PATRule: """ Get a PAT rule. @@ -1561,6 +1603,7 @@ async def get_pat_rule( :param pat_rule_id: ID of the PAT rule to get. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`PATRule ` + :deprecated Usage: :: @@ -1588,7 +1631,7 @@ async def create_pat_rule( public_port: int, private_ip: str, private_port: int, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, protocol: Optional[PATRuleProtocol] = None, ) -> PATRule: """ @@ -1601,6 +1644,7 @@ async def create_pat_rule( :param zone: Zone to target. If none is passed will use default zone from the config. :param protocol: Protocol the rule should apply to. :return: :class:`PATRule ` + :deprecated Usage: :: @@ -1638,7 +1682,7 @@ async def update_pat_rule( self, *, pat_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, public_port: Optional[int] = None, private_ip: Optional[str] = None, private_port: Optional[int] = None, @@ -1654,6 +1698,7 @@ async def update_pat_rule( :param private_port: Private port to translate to. :param protocol: Protocol the rule should apply to. :return: :class:`PATRule ` + :deprecated Usage: :: @@ -1690,7 +1735,7 @@ async def set_pat_rules( *, gateway_id: str, pat_rules: List[SetPATRulesRequestRule], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetPATRulesResponse: """ Set all PAT rules. @@ -1699,6 +1744,7 @@ async def set_pat_rules( :param pat_rules: New list of PAT rules. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`SetPATRulesResponse ` + :deprecated Usage: :: @@ -1731,13 +1777,14 @@ async def delete_pat_rule( self, *, pat_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a PAT rule. Delete a PAT rule, identified by its PAT rule ID. This action is irreversible. :param pat_rule_id: ID of the PAT rule to delete. :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -1760,13 +1807,14 @@ async def delete_pat_rule( async def list_gateway_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ListGatewayTypesResponse: """ List Public Gateway types. List the different Public Gateway commercial offer types available at Scaleway. The response is an array of objects describing the name and technical details of each available gateway type. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`ListGatewayTypesResponse ` + :deprecated Usage: :: @@ -1787,7 +1835,7 @@ async def list_gateway_types( async def list_i_ps( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1810,6 +1858,7 @@ async def list_i_ps( :param reverse: Filter for IP addresses that have a reverse containing this string. :param is_free: Filter based on whether the IP is attached to a gateway or not. :return: :class:`ListIPsResponse ` + :deprecated Usage: :: @@ -1841,7 +1890,7 @@ async def list_i_ps( async def list_i_ps_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1864,6 +1913,7 @@ async def list_i_ps_all( :param reverse: Filter for IP addresses that have a reverse containing this string. :param is_free: Filter based on whether the IP is attached to a gateway or not. :return: :class:`List[IP] ` + :deprecated Usage: :: @@ -1892,7 +1942,7 @@ async def get_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> IP: """ Get an IP. @@ -1900,6 +1950,7 @@ async def get_ip( :param ip_id: ID of the IP address to get. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`IP ` + :deprecated Usage: :: @@ -1923,7 +1974,7 @@ async def get_ip( async def create_ip( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, ) -> IP: @@ -1934,6 +1985,7 @@ async def create_ip( :param project_id: Project to create the IP address in. :param tags: Tags to give to the IP address. :return: :class:`IP ` + :deprecated Usage: :: @@ -1963,7 +2015,7 @@ async def update_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, reverse: Optional[str] = None, gateway_id: Optional[str] = None, @@ -1977,6 +2029,7 @@ async def update_ip( :param reverse: Reverse to set on the address. Empty string to unset. :param gateway_id: Gateway to attach the IP address to. Empty string to detach. :return: :class:`IP ` + :deprecated Usage: :: @@ -2011,13 +2064,14 @@ async def delete_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an IP. Delete a flexible IP address from your account. This action is irreversible. :param ip_id: ID of the IP address to delete. :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -2041,7 +2095,7 @@ async def refresh_ssh_keys( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Gateway: """ Refresh a Public Gateway's SSH keys. @@ -2049,6 +2103,7 @@ async def refresh_ssh_keys( :param gateway_id: ID of the gateway to refresh SSH keys on. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`Gateway ` + :deprecated Usage: :: @@ -2069,3 +2124,35 @@ async def refresh_ssh_keys( self._throw_on_error(res) return unmarshal_Gateway(res.json()) + + async def migrate_to_v2( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Put a Public Gateway in IPAM mode. + Put a Public Gateway in IPAM mode, so that it can be used with the Public Gateways API v2. This call is idempotent. + :param gateway_id: ID of the gateway to put into IPAM mode. + :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated + + Usage: + :: + + result = await api.migrate_to_v2( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "POST", + f"/vpc-gw/v1/zones/{param_zone}/gateways/{param_gateway_id}/migrate-to-v2", + body={}, + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/vpcgw/v1/marshalling.py b/scaleway-async/scaleway_async/vpcgw/v1/marshalling.py index 80c04c1c..ef34334d 100644 --- a/scaleway-async/scaleway_async/vpcgw/v1/marshalling.py +++ b/scaleway-async/scaleway_async/vpcgw/v1/marshalling.py @@ -45,6 +45,7 @@ UpdateGatewayRequest, UpdateIPRequest, UpdatePATRuleRequest, + UpgradeGatewayRequest, ) @@ -83,10 +84,14 @@ def unmarshal_DHCP(data: Any) -> DHCP: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("pool_high", None) if field is not None: @@ -123,14 +128,20 @@ def unmarshal_DHCP(data: Any) -> DHCP: field = data.get("valid_lifetime", None) if field is not None: args["valid_lifetime"] = field + else: + args["valid_lifetime"] = None field = data.get("renew_timer", None) if field is not None: args["renew_timer"] = field + else: + args["renew_timer"] = None field = data.get("rebind_timer", None) if field is not None: args["rebind_timer"] = field + else: + args["rebind_timer"] = None return DHCP(**args) @@ -177,14 +188,20 @@ def unmarshal_GatewayNetwork(data: Any) -> GatewayNetwork: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("mac_address", None) if field is not None: args["mac_address"] = field + else: + args["mac_address"] = None field = data.get("enable_masquerade", None) if field is not None: @@ -205,14 +222,20 @@ def unmarshal_GatewayNetwork(data: Any) -> GatewayNetwork: field = data.get("dhcp", None) if field is not None: args["dhcp"] = unmarshal_DHCP(field) + else: + args["dhcp"] = None field = data.get("address", None) if field is not None: args["address"] = field + else: + args["address"] = None field = data.get("ipam_config", None) if field is not None: args["ipam_config"] = unmarshal_IpamConfig(field) + else: + args["ipam_config"] = None return GatewayNetwork(**args) @@ -252,18 +275,26 @@ def unmarshal_IP(data: Any) -> IP: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("reverse", None) if field is not None: args["reverse"] = field + else: + args["reverse"] = None field = data.get("gateway_id", None) if field is not None: args["gateway_id"] = field + else: + args["gateway_id"] = None return IP(**args) @@ -296,7 +327,7 @@ def unmarshal_DHCPEntry(data: Any) -> DHCPEntry: if field is not None: args["hostname"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -307,10 +338,14 @@ def unmarshal_DHCPEntry(data: Any) -> DHCPEntry: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return DHCPEntry(**args) @@ -361,14 +396,20 @@ def unmarshal_Gateway(data: Any) -> Gateway: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = unmarshal_GatewayType(field) + else: + args["type_"] = None field = data.get("status", None) if field is not None: @@ -399,14 +440,20 @@ def unmarshal_Gateway(data: Any) -> Gateway: field = data.get("ip", None) if field is not None: args["ip"] = unmarshal_IP(field) + else: + args["ip"] = None field = data.get("version", None) if field is not None: args["version"] = field + else: + args["version"] = None field = data.get("can_upgrade_to", None) if field is not None: args["can_upgrade_to"] = field + else: + args["can_upgrade_to"] = None field = data.get("bastion_port", None) if field is not None: @@ -470,10 +517,14 @@ def unmarshal_PATRule(data: Any) -> PATRule: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return PATRule(**args) @@ -1077,3 +1128,15 @@ def marshal_UpdatePATRuleRequest( output["protocol"] = str(request.protocol) return output + + +def marshal_UpgradeGatewayRequest( + request: UpgradeGatewayRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.type_ is not None: + output["type"] = request.type_ + + return output diff --git a/scaleway-async/scaleway_async/vpcgw/v1/types.py b/scaleway-async/scaleway_async/vpcgw/v1/types.py index 3fa4fd58..bb1c21bd 100644 --- a/scaleway-async/scaleway_async/vpcgw/v1/types.py +++ b/scaleway-async/scaleway_async/vpcgw/v1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -208,7 +208,7 @@ class DHCP: TLD given to hostnames in the Private Networks. If an Instance with hostname `foo` gets a lease, and this is set to `bar`, `foo.bar` will resolve. """ - zone: Zone + zone: ScwZone """ Zone of this DHCP configuration. """ @@ -289,7 +289,7 @@ class GatewayNetwork: Defines whether DHCP is enabled on the connected Private Network. """ - zone: Zone + zone: ScwZone """ Zone of the GatewayNetwork connection. """ @@ -322,7 +322,7 @@ class GatewayType: Bandwidth, in bps, of the Public Gateway. This is the public bandwidth to the outer Internet, and the internal bandwidth to each connected Private Networks. """ - zone: Zone + zone: ScwZone """ Zone the Public Gateway type is available in. """ @@ -355,7 +355,7 @@ class IP: The IP address itself. """ - zone: Zone + zone: ScwZone """ Zone of the IP address. """ @@ -388,7 +388,7 @@ class CreateDHCPRequest: Subnet for the DHCP server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -504,7 +504,7 @@ class DHCPEntry: Entry type, either static (DHCP reservation) or dynamic (DHCP lease). """ - zone: Zone + zone: ScwZone """ Zone of this DHCP entry. """ @@ -617,7 +617,7 @@ class Gateway: Defines whether the gateway uses routed IPs (IP mobility) instead of NAT IPs. """ - zone: Zone + zone: ScwZone """ Zone of the gateway. """ @@ -655,7 +655,7 @@ class PATRule: Protocol the rule applies to. """ - zone: Zone + zone: ScwZone """ Zone of the PAT rule. """ @@ -737,7 +737,7 @@ class CreateDHCPEntryRequest: IP address to give to the device. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -760,7 +760,7 @@ class CreateGatewayNetworkRequest: Note: this setting is ignored when passing `ipam_config`. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -797,7 +797,7 @@ class CreateGatewayRequest: Defines whether SSH bastion should be enabled the gateway. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -835,7 +835,7 @@ class CreateGatewayRequest: @dataclass class CreateIPRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -873,7 +873,7 @@ class CreatePATRuleRequest: Private port to translate to. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -891,7 +891,7 @@ class DeleteDHCPEntryRequest: ID of the DHCP entry to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -904,7 +904,7 @@ class DeleteDHCPRequest: DHCP configuration ID to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -922,7 +922,7 @@ class DeleteGatewayNetworkRequest: Defines whether to clean up attached DHCP configurations (if any, and if not attached to another Gateway Network). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -940,7 +940,7 @@ class DeleteGatewayRequest: Defines whether to clean up attached DHCP configurations (if any, and if not attached to another Gateway Network). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -953,7 +953,7 @@ class DeleteIPRequest: ID of the IP address to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -966,7 +966,7 @@ class DeletePATRuleRequest: ID of the PAT rule to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -979,7 +979,7 @@ class EnableIPMobilityRequest: ID of the gateway to upgrade to IP mobility. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -992,7 +992,7 @@ class GetDHCPEntryRequest: ID of the DHCP entry to fetch. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1005,7 +1005,7 @@ class GetDHCPRequest: ID of the DHCP configuration to fetch. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1018,7 +1018,7 @@ class GetGatewayNetworkRequest: ID of the GatewayNetwork to fetch. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1031,7 +1031,7 @@ class GetGatewayRequest: ID of the gateway to fetch. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1044,7 +1044,7 @@ class GetIPRequest: ID of the IP address to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1057,7 +1057,7 @@ class GetPATRuleRequest: ID of the PAT rule to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1065,7 +1065,7 @@ class GetPATRuleRequest: @dataclass class ListDHCPEntriesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1126,7 +1126,7 @@ class ListDHCPEntriesResponse: @dataclass class ListDHCPsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1182,7 +1182,7 @@ class ListDHCPsResponse: @dataclass class ListGatewayNetworksRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1243,7 +1243,7 @@ class ListGatewayNetworksResponse: @dataclass class ListGatewayTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1259,7 +1259,7 @@ class ListGatewayTypesResponse: @dataclass class ListGatewaysRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1330,7 +1330,7 @@ class ListGatewaysResponse: @dataclass class ListIPsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1391,7 +1391,7 @@ class ListIPsResponse: @dataclass class ListPATRulesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1440,6 +1440,19 @@ class ListPATRulesResponse: """ +@dataclass +class MigrateToV2Request: + gateway_id: str + """ + ID of the gateway to put into IPAM mode. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class RefreshSSHKeysRequest: gateway_id: str @@ -1447,7 +1460,7 @@ class RefreshSSHKeysRequest: ID of the gateway to refresh SSH keys on. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1460,7 +1473,7 @@ class SetDHCPEntriesRequest: ID of the Gateway Network on which to set DHCP reservation list. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1491,7 +1504,7 @@ class SetPATRulesRequest: New list of PAT rules. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1512,7 +1525,7 @@ class UpdateDHCPEntryRequest: ID of the DHCP entry to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1530,7 +1543,7 @@ class UpdateDHCPRequest: DHCP configuration to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1608,7 +1621,7 @@ class UpdateGatewayNetworkRequest: ID of the GatewayNetwork to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1638,7 +1651,7 @@ class UpdateGatewayRequest: ID of the gateway to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1681,7 +1694,7 @@ class UpdateIPRequest: ID of the IP address to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1709,7 +1722,7 @@ class UpdatePATRuleRequest: ID of the PAT rule to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1742,7 +1755,12 @@ class UpgradeGatewayRequest: ID of the gateway to upgrade. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ + + type_: Optional[str] + """ + Gateway type (commercial offer). + """ diff --git a/scaleway-async/scaleway_async/vpcgw/v2/__init__.py b/scaleway-async/scaleway_async/vpcgw/v2/__init__.py new file mode 100644 index 00000000..8856eb50 --- /dev/null +++ b/scaleway-async/scaleway_async/vpcgw/v2/__init__.py @@ -0,0 +1,107 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import GatewayNetworkStatus +from .content import GATEWAY_NETWORK_TRANSIENT_STATUSES +from .types import GatewayStatus +from .content import GATEWAY_TRANSIENT_STATUSES +from .types import ListGatewayNetworksRequestOrderBy +from .types import ListGatewaysRequestOrderBy +from .types import ListIPsRequestOrderBy +from .types import ListPatRulesRequestOrderBy +from .types import PatRuleProtocol +from .types import GatewayNetwork +from .types import IP +from .types import GatewayType +from .types import Gateway +from .types import PatRule +from .types import SetPatRulesRequestRule +from .types import AddBastionAllowedIPsRequest +from .types import AddBastionAllowedIPsResponse +from .types import CreateGatewayNetworkRequest +from .types import CreateGatewayRequest +from .types import CreateIPRequest +from .types import CreatePatRuleRequest +from .types import DeleteBastionAllowedIPsRequest +from .types import DeleteGatewayNetworkRequest +from .types import DeleteGatewayRequest +from .types import DeleteIPRequest +from .types import DeletePatRuleRequest +from .types import GetGatewayNetworkRequest +from .types import GetGatewayRequest +from .types import GetIPRequest +from .types import GetPatRuleRequest +from .types import ListGatewayNetworksRequest +from .types import ListGatewayNetworksResponse +from .types import ListGatewayTypesRequest +from .types import ListGatewayTypesResponse +from .types import ListGatewaysRequest +from .types import ListGatewaysResponse +from .types import ListIPsRequest +from .types import ListIPsResponse +from .types import ListPatRulesRequest +from .types import ListPatRulesResponse +from .types import RefreshSSHKeysRequest +from .types import SetBastionAllowedIPsRequest +from .types import SetBastionAllowedIPsResponse +from .types import SetPatRulesRequest +from .types import SetPatRulesResponse +from .types import UpdateGatewayNetworkRequest +from .types import UpdateGatewayRequest +from .types import UpdateIPRequest +from .types import UpdatePatRuleRequest +from .types import UpgradeGatewayRequest +from .api import VpcgwV2API + +__all__ = [ + "GatewayNetworkStatus", + "GATEWAY_NETWORK_TRANSIENT_STATUSES", + "GatewayStatus", + "GATEWAY_TRANSIENT_STATUSES", + "ListGatewayNetworksRequestOrderBy", + "ListGatewaysRequestOrderBy", + "ListIPsRequestOrderBy", + "ListPatRulesRequestOrderBy", + "PatRuleProtocol", + "GatewayNetwork", + "IP", + "GatewayType", + "Gateway", + "PatRule", + "SetPatRulesRequestRule", + "AddBastionAllowedIPsRequest", + "AddBastionAllowedIPsResponse", + "CreateGatewayNetworkRequest", + "CreateGatewayRequest", + "CreateIPRequest", + "CreatePatRuleRequest", + "DeleteBastionAllowedIPsRequest", + "DeleteGatewayNetworkRequest", + "DeleteGatewayRequest", + "DeleteIPRequest", + "DeletePatRuleRequest", + "GetGatewayNetworkRequest", + "GetGatewayRequest", + "GetIPRequest", + "GetPatRuleRequest", + "ListGatewayNetworksRequest", + "ListGatewayNetworksResponse", + "ListGatewayTypesRequest", + "ListGatewayTypesResponse", + "ListGatewaysRequest", + "ListGatewaysResponse", + "ListIPsRequest", + "ListIPsResponse", + "ListPatRulesRequest", + "ListPatRulesResponse", + "RefreshSSHKeysRequest", + "SetBastionAllowedIPsRequest", + "SetBastionAllowedIPsResponse", + "SetPatRulesRequest", + "SetPatRulesResponse", + "UpdateGatewayNetworkRequest", + "UpdateGatewayRequest", + "UpdateIPRequest", + "UpdatePatRuleRequest", + "UpgradeGatewayRequest", + "VpcgwV2API", +] diff --git a/scaleway-async/scaleway_async/vpcgw/v2/api.py b/scaleway-async/scaleway_async/vpcgw/v2/api.py new file mode 100644 index 00000000..049c9c6c --- /dev/null +++ b/scaleway-async/scaleway_async/vpcgw/v2/api.py @@ -0,0 +1,1512 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + GatewayNetworkStatus, + GatewayStatus, + ListGatewayNetworksRequestOrderBy, + ListGatewaysRequestOrderBy, + ListIPsRequestOrderBy, + ListPatRulesRequestOrderBy, + PatRuleProtocol, + AddBastionAllowedIPsRequest, + AddBastionAllowedIPsResponse, + CreateGatewayNetworkRequest, + CreateGatewayRequest, + CreateIPRequest, + CreatePatRuleRequest, + Gateway, + GatewayNetwork, + IP, + ListGatewayNetworksResponse, + ListGatewayTypesResponse, + ListGatewaysResponse, + ListIPsResponse, + ListPatRulesResponse, + PatRule, + SetBastionAllowedIPsRequest, + SetBastionAllowedIPsResponse, + SetPatRulesRequest, + SetPatRulesRequestRule, + SetPatRulesResponse, + UpdateGatewayNetworkRequest, + UpdateGatewayRequest, + UpdateIPRequest, + UpdatePatRuleRequest, + UpgradeGatewayRequest, +) +from .content import ( + GATEWAY_NETWORK_TRANSIENT_STATUSES, + GATEWAY_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_GatewayNetwork, + unmarshal_IP, + unmarshal_Gateway, + unmarshal_PatRule, + unmarshal_AddBastionAllowedIPsResponse, + unmarshal_ListGatewayNetworksResponse, + unmarshal_ListGatewayTypesResponse, + unmarshal_ListGatewaysResponse, + unmarshal_ListIPsResponse, + unmarshal_ListPatRulesResponse, + unmarshal_SetBastionAllowedIPsResponse, + unmarshal_SetPatRulesResponse, + marshal_AddBastionAllowedIPsRequest, + marshal_CreateGatewayNetworkRequest, + marshal_CreateGatewayRequest, + marshal_CreateIPRequest, + marshal_CreatePatRuleRequest, + marshal_SetBastionAllowedIPsRequest, + marshal_SetPatRulesRequest, + marshal_UpdateGatewayNetworkRequest, + marshal_UpdateGatewayRequest, + marshal_UpdateIPRequest, + marshal_UpdatePatRuleRequest, + marshal_UpgradeGatewayRequest, +) + + +class VpcgwV2API(API): + """ + This API allows you to manage your Public Gateways. + """ + + async def list_gateways( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListGatewaysRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + types: Optional[List[str]] = None, + status: Optional[List[GatewayStatus]] = None, + private_network_ids: Optional[List[str]] = None, + include_legacy: Optional[bool] = None, + ) -> ListGatewaysResponse: + """ + List Public Gateways. + List Public Gateways in a given Scaleway Organization or Project. By default, results are displayed in ascending order of creation date. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Gateways per page. + :param organization_id: Include only gateways in this Organization. + :param project_id: Include only gateways in this Project. + :param name: Filter for gateways which have this search term in their name. + :param tags: Filter for gateways with these tags. + :param types: Filter for gateways of these types. + :param status: Filter for gateways with these status. Use `unknown` to include all statuses. + :param private_network_ids: Filter for gateways attached to these Private Networks. + :param include_legacy: Include also legacy gateways. + :return: :class:`ListGatewaysResponse ` + + Usage: + :: + + result = await api.list_gateways() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/gateways", + params={ + "include_legacy": include_legacy, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "private_network_ids": private_network_ids, + "project_id": project_id or self.client.default_project_id, + "status": status, + "tags": tags, + "types": types, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListGatewaysResponse(res.json()) + + async def list_gateways_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListGatewaysRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + types: Optional[List[str]] = None, + status: Optional[List[GatewayStatus]] = None, + private_network_ids: Optional[List[str]] = None, + include_legacy: Optional[bool] = None, + ) -> List[Gateway]: + """ + List Public Gateways. + List Public Gateways in a given Scaleway Organization or Project. By default, results are displayed in ascending order of creation date. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Gateways per page. + :param organization_id: Include only gateways in this Organization. + :param project_id: Include only gateways in this Project. + :param name: Filter for gateways which have this search term in their name. + :param tags: Filter for gateways with these tags. + :param types: Filter for gateways of these types. + :param status: Filter for gateways with these status. Use `unknown` to include all statuses. + :param private_network_ids: Filter for gateways attached to these Private Networks. + :param include_legacy: Include also legacy gateways. + :return: :class:`List[Gateway] ` + + Usage: + :: + + result = await api.list_gateways_all() + """ + + return await fetch_all_pages_async( + type=ListGatewaysResponse, + key="gateways", + fetcher=self.list_gateways, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "name": name, + "tags": tags, + "types": types, + "status": status, + "private_network_ids": private_network_ids, + "include_legacy": include_legacy, + }, + ) + + async def get_gateway( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + ) -> Gateway: + """ + Get a Public Gateway. + Get details of a Public Gateway, specified by its gateway ID. The response object contains full details of the gateway, including its **name**, **type**, **status** and more. + :param gateway_id: ID of the gateway to fetch. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Gateway ` + + Usage: + :: + + result = await api.get_gateway( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}", + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + async def wait_for_gateway( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[Gateway, Union[bool, Awaitable[bool]]]] = None, + ) -> Gateway: + """ + Get a Public Gateway. + Get details of a Public Gateway, specified by its gateway ID. The response object contains full details of the gateway, including its **name**, **type**, **status** and more. + :param gateway_id: ID of the gateway to fetch. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Gateway ` + + Usage: + :: + + result = await api.get_gateway( + gateway_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in GATEWAY_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_gateway, + options=options, + args={ + "gateway_id": gateway_id, + "zone": zone, + }, + ) + + async def create_gateway( + self, + *, + type_: str, + enable_smtp: bool, + enable_bastion: bool, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ip_id: Optional[str] = None, + bastion_port: Optional[int] = None, + ) -> Gateway: + """ + Create a Public Gateway. + Create a new Public Gateway in the specified Scaleway Project, defining its **name**, **type** and other configuration details such as whether to enable SSH bastion. + :param type_: Gateway type (commercial offer type). + :param enable_smtp: Defines whether SMTP traffic should be allowed pass through the gateway. + :param enable_bastion: Defines whether SSH bastion should be enabled the gateway. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Scaleway Project to create the gateway in. + :param name: Name for the gateway. + :param tags: Tags for the gateway. + :param ip_id: Existing IP address to attach to the gateway. + :param bastion_port: Port of the SSH bastion. + :return: :class:`Gateway ` + + Usage: + :: + + result = await api.create_gateway( + type="example", + enable_smtp=False, + enable_bastion=False, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/gateways", + body=marshal_CreateGatewayRequest( + CreateGatewayRequest( + type_=type_, + enable_smtp=enable_smtp, + enable_bastion=enable_bastion, + zone=zone, + project_id=project_id, + name=name or random_name(prefix="gw"), + tags=tags, + ip_id=ip_id, + bastion_port=bastion_port, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + async def update_gateway( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + enable_bastion: Optional[bool] = None, + bastion_port: Optional[int] = None, + enable_smtp: Optional[bool] = None, + ) -> Gateway: + """ + Update a Public Gateway. + Update the parameters of an existing Public Gateway, for example, its **name**, **tags**, **SSH bastion configuration**, and **DNS servers**. + :param gateway_id: ID of the gateway to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name for the gateway. + :param tags: Tags for the gateway. + :param enable_bastion: Defines whether SSH bastion should be enabled the gateway. + :param bastion_port: Port of the SSH bastion. + :param enable_smtp: Defines whether SMTP traffic should be allowed to pass through the gateway. + :return: :class:`Gateway ` + + Usage: + :: + + result = await api.update_gateway( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "PATCH", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}", + body=marshal_UpdateGatewayRequest( + UpdateGatewayRequest( + gateway_id=gateway_id, + zone=zone, + name=name, + tags=tags, + enable_bastion=enable_bastion, + bastion_port=bastion_port, + enable_smtp=enable_smtp, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + async def delete_gateway( + self, + *, + gateway_id: str, + delete_ip: bool, + zone: Optional[ScwZone] = None, + ) -> Gateway: + """ + Delete a Public Gateway. + Delete an existing Public Gateway, specified by its gateway ID. This action is irreversible. + :param gateway_id: ID of the gateway to delete. + :param delete_ip: Defines whether the PGW's IP should be deleted. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Gateway ` + + Usage: + :: + + result = await api.delete_gateway( + gateway_id="example", + delete_ip=False, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "DELETE", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}", + params={ + "delete_ip": delete_ip, + }, + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + async def upgrade_gateway( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + type_: Optional[str] = None, + ) -> Gateway: + """ + Upgrade a Public Gateway to the latest version and/or to a different commercial offer type. + Upgrade a given Public Gateway to the newest software version or to a different commercial offer type. This applies the latest bugfixes and features to your Public Gateway. Note that gateway service will be interrupted during the update. + :param gateway_id: ID of the gateway to upgrade. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param type_: Gateway type (commercial offer). + :return: :class:`Gateway ` + + Usage: + :: + + result = await api.upgrade_gateway( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}/upgrade", + body=marshal_UpgradeGatewayRequest( + UpgradeGatewayRequest( + gateway_id=gateway_id, + zone=zone, + type_=type_, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + async def list_gateway_networks( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListGatewayNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + status: Optional[List[GatewayNetworkStatus]] = None, + gateway_ids: Optional[List[str]] = None, + private_network_ids: Optional[List[str]] = None, + masquerade_enabled: Optional[bool] = None, + ) -> ListGatewayNetworksResponse: + """ + List Public Gateway connections to Private Networks. + List the connections between Public Gateways and Private Networks (a connection = a GatewayNetwork). You can choose to filter by `gateway-id` to list all Private Networks attached to the specified Public Gateway, or by `private_network_id` to list all Public Gateways attached to the specified Private Network. Other query parameters are also available. The result is an array of GatewayNetwork objects, each giving details of the connection between a given Public Gateway and a given Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: GatewayNetworks per page. + :param status: Filter for GatewayNetworks with these status. Use `unknown` to include all statuses. + :param gateway_ids: Filter for GatewayNetworks connected to these gateways. + :param private_network_ids: Filter for GatewayNetworks connected to these Private Networks. + :param masquerade_enabled: Filter for GatewayNetworks with this `enable_masquerade` setting. + :return: :class:`ListGatewayNetworksResponse ` + + Usage: + :: + + result = await api.list_gateway_networks() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/gateway-networks", + params={ + "gateway_ids": gateway_ids, + "masquerade_enabled": masquerade_enabled, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "private_network_ids": private_network_ids, + "status": status, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListGatewayNetworksResponse(res.json()) + + async def list_gateway_networks_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListGatewayNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + status: Optional[List[GatewayNetworkStatus]] = None, + gateway_ids: Optional[List[str]] = None, + private_network_ids: Optional[List[str]] = None, + masquerade_enabled: Optional[bool] = None, + ) -> List[GatewayNetwork]: + """ + List Public Gateway connections to Private Networks. + List the connections between Public Gateways and Private Networks (a connection = a GatewayNetwork). You can choose to filter by `gateway-id` to list all Private Networks attached to the specified Public Gateway, or by `private_network_id` to list all Public Gateways attached to the specified Private Network. Other query parameters are also available. The result is an array of GatewayNetwork objects, each giving details of the connection between a given Public Gateway and a given Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: GatewayNetworks per page. + :param status: Filter for GatewayNetworks with these status. Use `unknown` to include all statuses. + :param gateway_ids: Filter for GatewayNetworks connected to these gateways. + :param private_network_ids: Filter for GatewayNetworks connected to these Private Networks. + :param masquerade_enabled: Filter for GatewayNetworks with this `enable_masquerade` setting. + :return: :class:`List[GatewayNetwork] ` + + Usage: + :: + + result = await api.list_gateway_networks_all() + """ + + return await fetch_all_pages_async( + type=ListGatewayNetworksResponse, + key="gateway_networks", + fetcher=self.list_gateway_networks, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "status": status, + "gateway_ids": gateway_ids, + "private_network_ids": private_network_ids, + "masquerade_enabled": masquerade_enabled, + }, + ) + + async def get_gateway_network( + self, + *, + gateway_network_id: str, + zone: Optional[ScwZone] = None, + ) -> GatewayNetwork: + """ + Get a Public Gateway connection to a Private Network. + Get details of a given connection between a Public Gateway and a Private Network (this connection = a GatewayNetwork), specified by its `gateway_network_id`. The response object contains details of the connection including the IDs of the Public Gateway and Private Network, the dates the connection was created/updated and its configuration settings. + :param gateway_network_id: ID of the GatewayNetwork to fetch. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`GatewayNetwork ` + + Usage: + :: + + result = await api.get_gateway_network( + gateway_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_network_id = validate_path_param( + "gateway_network_id", gateway_network_id + ) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/gateway-networks/{param_gateway_network_id}", + ) + + self._throw_on_error(res) + return unmarshal_GatewayNetwork(res.json()) + + async def wait_for_gateway_network( + self, + *, + gateway_network_id: str, + zone: Optional[ScwZone] = None, + options: Optional[ + WaitForOptions[GatewayNetwork, Union[bool, Awaitable[bool]]] + ] = None, + ) -> GatewayNetwork: + """ + Get a Public Gateway connection to a Private Network. + Get details of a given connection between a Public Gateway and a Private Network (this connection = a GatewayNetwork), specified by its `gateway_network_id`. The response object contains details of the connection including the IDs of the Public Gateway and Private Network, the dates the connection was created/updated and its configuration settings. + :param gateway_network_id: ID of the GatewayNetwork to fetch. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`GatewayNetwork ` + + Usage: + :: + + result = await api.get_gateway_network( + gateway_network_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in GATEWAY_NETWORK_TRANSIENT_STATUSES + ) + + return await wait_for_resource_async( + fetcher=self.get_gateway_network, + options=options, + args={ + "gateway_network_id": gateway_network_id, + "zone": zone, + }, + ) + + async def create_gateway_network( + self, + *, + gateway_id: str, + private_network_id: str, + enable_masquerade: bool, + push_default_route: bool, + zone: Optional[ScwZone] = None, + ipam_ip_id: Optional[str] = None, + ) -> GatewayNetwork: + """ + Attach a Public Gateway to a Private Network. + Attach a specific Public Gateway to a specific Private Network (create a GatewayNetwork). You can configure parameters for the connection including whether to enable masquerade (dynamic NAT), and more. + :param gateway_id: Public Gateway to connect. + :param private_network_id: Private Network to connect. + :param enable_masquerade: Defines whether to enable masquerade (dynamic NAT) on the GatewayNetwork. + :param push_default_route: Enabling the default route also enables masquerading. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param ipam_ip_id: Use this IPAM-booked IP ID as the Gateway's IP in this Private Network. + :return: :class:`GatewayNetwork ` + + Usage: + :: + + result = await api.create_gateway_network( + gateway_id="example", + private_network_id="example", + enable_masquerade=False, + push_default_route=False, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/gateway-networks", + body=marshal_CreateGatewayNetworkRequest( + CreateGatewayNetworkRequest( + gateway_id=gateway_id, + private_network_id=private_network_id, + enable_masquerade=enable_masquerade, + push_default_route=push_default_route, + zone=zone, + ipam_ip_id=ipam_ip_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_GatewayNetwork(res.json()) + + async def update_gateway_network( + self, + *, + gateway_network_id: str, + zone: Optional[ScwZone] = None, + enable_masquerade: Optional[bool] = None, + push_default_route: Optional[bool] = None, + ipam_ip_id: Optional[str] = None, + ) -> GatewayNetwork: + """ + Update a Public Gateway's connection to a Private Network. + Update the configuration parameters of a connection between a given Public Gateway and Private Network (the connection = a GatewayNetwork). Updatable parameters include whether to enable traffic masquerade (dynamic NAT). + :param gateway_network_id: ID of the GatewayNetwork to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param enable_masquerade: Defines whether to enable masquerade (dynamic NAT) on the GatewayNetwork. + :param push_default_route: Enabling the default route also enables masquerading. + :param ipam_ip_id: Use this IPAM-booked IP ID as the Gateway's IP in this Private Network. + :return: :class:`GatewayNetwork ` + + Usage: + :: + + result = await api.update_gateway_network( + gateway_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_network_id = validate_path_param( + "gateway_network_id", gateway_network_id + ) + + res = self._request( + "PATCH", + f"/vpc-gw/v2/zones/{param_zone}/gateway-networks/{param_gateway_network_id}", + body=marshal_UpdateGatewayNetworkRequest( + UpdateGatewayNetworkRequest( + gateway_network_id=gateway_network_id, + zone=zone, + enable_masquerade=enable_masquerade, + push_default_route=push_default_route, + ipam_ip_id=ipam_ip_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_GatewayNetwork(res.json()) + + async def delete_gateway_network( + self, + *, + gateway_network_id: str, + zone: Optional[ScwZone] = None, + ) -> GatewayNetwork: + """ + Detach a Public Gateway from a Private Network. + Detach a given Public Gateway from a given Private Network, i.e. delete a GatewayNetwork specified by a gateway_network_id. + :param gateway_network_id: ID of the GatewayNetwork to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`GatewayNetwork ` + + Usage: + :: + + result = await api.delete_gateway_network( + gateway_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_network_id = validate_path_param( + "gateway_network_id", gateway_network_id + ) + + res = self._request( + "DELETE", + f"/vpc-gw/v2/zones/{param_zone}/gateway-networks/{param_gateway_network_id}", + ) + + self._throw_on_error(res) + return unmarshal_GatewayNetwork(res.json()) + + async def list_pat_rules( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListPatRulesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + gateway_ids: Optional[List[str]] = None, + private_ips: Optional[List[str]] = None, + protocol: Optional[PatRuleProtocol] = None, + ) -> ListPatRulesResponse: + """ + List PAT rules. + List PAT rules. You can filter by gateway ID to list all PAT rules for a particular gateway, or filter for PAT rules targeting a specific IP address or using a specific protocol. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: PAT rules per page. + :param gateway_ids: Filter for PAT rules on these gateways. + :param private_ips: Filter for PAT rules targeting these private ips. + :param protocol: Filter for PAT rules with this protocol. + :return: :class:`ListPatRulesResponse ` + + Usage: + :: + + result = await api.list_pat_rules() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules", + params={ + "gateway_ids": gateway_ids, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "private_ips": private_ips, + "protocol": protocol, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPatRulesResponse(res.json()) + + async def list_pat_rules_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListPatRulesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + gateway_ids: Optional[List[str]] = None, + private_ips: Optional[List[str]] = None, + protocol: Optional[PatRuleProtocol] = None, + ) -> List[PatRule]: + """ + List PAT rules. + List PAT rules. You can filter by gateway ID to list all PAT rules for a particular gateway, or filter for PAT rules targeting a specific IP address or using a specific protocol. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: PAT rules per page. + :param gateway_ids: Filter for PAT rules on these gateways. + :param private_ips: Filter for PAT rules targeting these private ips. + :param protocol: Filter for PAT rules with this protocol. + :return: :class:`List[PatRule] ` + + Usage: + :: + + result = await api.list_pat_rules_all() + """ + + return await fetch_all_pages_async( + type=ListPatRulesResponse, + key="pat_rules", + fetcher=self.list_pat_rules, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "gateway_ids": gateway_ids, + "private_ips": private_ips, + "protocol": protocol, + }, + ) + + async def get_pat_rule( + self, + *, + pat_rule_id: str, + zone: Optional[ScwZone] = None, + ) -> PatRule: + """ + Get a PAT rule. + Get a PAT rule, specified by its PAT rule ID. The response object gives full details of the PAT rule, including the Public Gateway it belongs to and the configuration settings in terms of public / private ports, private IP and protocol. + :param pat_rule_id: ID of the PAT rule to get. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`PatRule ` + + Usage: + :: + + result = await api.get_pat_rule( + pat_rule_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_pat_rule_id = validate_path_param("pat_rule_id", pat_rule_id) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules/{param_pat_rule_id}", + ) + + self._throw_on_error(res) + return unmarshal_PatRule(res.json()) + + async def create_pat_rule( + self, + *, + gateway_id: str, + public_port: int, + private_ip: str, + private_port: int, + zone: Optional[ScwZone] = None, + protocol: Optional[PatRuleProtocol] = None, + ) -> PatRule: + """ + Create a PAT rule. + Create a new PAT rule on a specified Public Gateway, defining the protocol to use, public port to listen on, and private port / IP address to map to. + :param gateway_id: ID of the Gateway on which to create the rule. + :param public_port: Public port to listen on. + :param private_ip: Private IP to forward data to. + :param private_port: Private port to translate to. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param protocol: Protocol the rule should apply to. + :return: :class:`PatRule ` + + Usage: + :: + + result = await api.create_pat_rule( + gateway_id="example", + public_port=1, + private_ip="example", + private_port=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules", + body=marshal_CreatePatRuleRequest( + CreatePatRuleRequest( + gateway_id=gateway_id, + public_port=public_port, + private_ip=private_ip, + private_port=private_port, + zone=zone, + protocol=protocol, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_PatRule(res.json()) + + async def update_pat_rule( + self, + *, + pat_rule_id: str, + zone: Optional[ScwZone] = None, + public_port: Optional[int] = None, + private_ip: Optional[str] = None, + private_port: Optional[int] = None, + protocol: Optional[PatRuleProtocol] = None, + ) -> PatRule: + """ + Update a PAT rule. + Update a PAT rule, specified by its PAT rule ID. Configuration settings including private/public port, private IP address and protocol can all be updated. + :param pat_rule_id: ID of the PAT rule to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param public_port: Public port to listen on. + :param private_ip: Private IP to forward data to. + :param private_port: Private port to translate to. + :param protocol: Protocol the rule should apply to. + :return: :class:`PatRule ` + + Usage: + :: + + result = await api.update_pat_rule( + pat_rule_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_pat_rule_id = validate_path_param("pat_rule_id", pat_rule_id) + + res = self._request( + "PATCH", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules/{param_pat_rule_id}", + body=marshal_UpdatePatRuleRequest( + UpdatePatRuleRequest( + pat_rule_id=pat_rule_id, + zone=zone, + public_port=public_port, + private_ip=private_ip, + private_port=private_port, + protocol=protocol, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_PatRule(res.json()) + + async def set_pat_rules( + self, + *, + gateway_id: str, + pat_rules: List[SetPatRulesRequestRule], + zone: Optional[ScwZone] = None, + ) -> SetPatRulesResponse: + """ + Set all PAT rules. + Set a definitive list of PAT rules attached to a Public Gateway. Each rule is identified by its public port and protocol. This will sync the current PAT rule list on the gateway with the new list, creating, updating or deleting PAT rules accordingly. + :param gateway_id: ID of the gateway on which to set the PAT rules. + :param pat_rules: New list of PAT rules. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`SetPatRulesResponse ` + + Usage: + :: + + result = await api.set_pat_rules( + gateway_id="example", + pat_rules=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "PUT", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules", + body=marshal_SetPatRulesRequest( + SetPatRulesRequest( + gateway_id=gateway_id, + pat_rules=pat_rules, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetPatRulesResponse(res.json()) + + async def delete_pat_rule( + self, + *, + pat_rule_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a PAT rule. + Delete a PAT rule, identified by its PAT rule ID. This action is irreversible. + :param pat_rule_id: ID of the PAT rule to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_pat_rule( + pat_rule_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_pat_rule_id = validate_path_param("pat_rule_id", pat_rule_id) + + res = self._request( + "DELETE", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules/{param_pat_rule_id}", + ) + + self._throw_on_error(res) + + async def list_gateway_types( + self, + *, + zone: Optional[ScwZone] = None, + ) -> ListGatewayTypesResponse: + """ + List Public Gateway types. + List the different Public Gateway commercial offer types available at Scaleway. The response is an array of objects describing the name and technical details of each available gateway type. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ListGatewayTypesResponse ` + + Usage: + :: + + result = await api.list_gateway_types() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/gateway-types", + ) + + self._throw_on_error(res) + return unmarshal_ListGatewayTypesResponse(res.json()) + + async def list_i_ps( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListIPsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + reverse: Optional[str] = None, + is_free: Optional[bool] = None, + ) -> ListIPsResponse: + """ + List IPs. + List Public Gateway flexible IP addresses. A number of filter options are available for limiting results in the response. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: IP addresses per page. + :param organization_id: Include only gateways in this Organization. + :param project_id: Filter for IP addresses in this Project. + :param tags: Filter for IP addresses with these tags. + :param reverse: Filter for IP addresses that have a reverse containing this string. + :param is_free: Filter based on whether the IP is attached to a gateway or not. + :return: :class:`ListIPsResponse ` + + Usage: + :: + + result = await api.list_i_ps() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/ips", + params={ + "is_free": is_free, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "reverse": reverse, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListIPsResponse(res.json()) + + async def list_i_ps_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListIPsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + reverse: Optional[str] = None, + is_free: Optional[bool] = None, + ) -> List[IP]: + """ + List IPs. + List Public Gateway flexible IP addresses. A number of filter options are available for limiting results in the response. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: IP addresses per page. + :param organization_id: Include only gateways in this Organization. + :param project_id: Filter for IP addresses in this Project. + :param tags: Filter for IP addresses with these tags. + :param reverse: Filter for IP addresses that have a reverse containing this string. + :param is_free: Filter based on whether the IP is attached to a gateway or not. + :return: :class:`List[IP] ` + + Usage: + :: + + result = await api.list_i_ps_all() + """ + + return await fetch_all_pages_async( + type=ListIPsResponse, + key="ips", + fetcher=self.list_i_ps, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "tags": tags, + "reverse": reverse, + "is_free": is_free, + }, + ) + + async def get_ip( + self, + *, + ip_id: str, + zone: Optional[ScwZone] = None, + ) -> IP: + """ + Get an IP. + Get details of a Public Gateway flexible IP address, identified by its IP ID. The response object contains information including which (if any) Public Gateway using this IP address, the reverse and various other metadata. + :param ip_id: ID of the IP address to get. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`IP ` + + Usage: + :: + + result = await api.get_ip( + ip_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/ips/{param_ip_id}", + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + async def create_ip( + self, + *, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> IP: + """ + Reserve an IP. + Create (reserve) a new flexible IP address that can be used for a Public Gateway in a specified Scaleway Project. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project to create the IP address in. + :param tags: Tags to give to the IP address. + :return: :class:`IP ` + + Usage: + :: + + result = await api.create_ip() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/ips", + body=marshal_CreateIPRequest( + CreateIPRequest( + zone=zone, + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + async def update_ip( + self, + *, + ip_id: str, + zone: Optional[ScwZone] = None, + tags: Optional[List[str]] = None, + reverse: Optional[str] = None, + gateway_id: Optional[str] = None, + ) -> IP: + """ + Update an IP. + Update details of an existing flexible IP address, including its tags, reverse and the Public Gateway it is assigned to. + :param ip_id: ID of the IP address to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param tags: Tags to give to the IP address. + :param reverse: Reverse to set on the address. Empty string to unset. + :param gateway_id: Gateway to attach the IP address to. Empty string to detach. + :return: :class:`IP ` + + Usage: + :: + + result = await api.update_ip( + ip_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "PATCH", + f"/vpc-gw/v2/zones/{param_zone}/ips/{param_ip_id}", + body=marshal_UpdateIPRequest( + UpdateIPRequest( + ip_id=ip_id, + zone=zone, + tags=tags, + reverse=reverse, + gateway_id=gateway_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + async def delete_ip( + self, + *, + ip_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete an IP. + Delete a flexible IP address from your account. This action is irreversible. + :param ip_id: ID of the IP address to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_ip( + ip_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "DELETE", + f"/vpc-gw/v2/zones/{param_zone}/ips/{param_ip_id}", + ) + + self._throw_on_error(res) + + async def refresh_ssh_keys( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + ) -> Gateway: + """ + Refresh a Public Gateway's SSH keys. + Refresh the SSH keys of a given Public Gateway, specified by its gateway ID. This adds any new SSH keys in the gateway's Scaleway Project to the gateway itself. + :param gateway_id: ID of the gateway to refresh SSH keys on. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Gateway ` + + Usage: + :: + + result = await api.refresh_ssh_keys( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}/refresh-ssh-keys", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + async def add_bastion_allowed_i_ps( + self, + *, + gateway_id: str, + ip_range: str, + zone: Optional[ScwZone] = None, + ) -> AddBastionAllowedIPsResponse: + """ + Add allowed IP range to SSH bastion. + Add an IP range (in CIDR notation) to be allowed to connect to the SSH bastion. + :param gateway_id: ID of the gateway to add the allowed IP range to. + :param ip_range: IP range allowed to connect to the SSH bastion. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`AddBastionAllowedIPsResponse ` + + Usage: + :: + + result = await api.add_bastion_allowed_i_ps( + gateway_id="example", + ip_range="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}/bastion-allowed-ips", + body=marshal_AddBastionAllowedIPsRequest( + AddBastionAllowedIPsRequest( + gateway_id=gateway_id, + ip_range=ip_range, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AddBastionAllowedIPsResponse(res.json()) + + async def set_bastion_allowed_i_ps( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + ip_ranges: Optional[List[str]] = None, + ) -> SetBastionAllowedIPsResponse: + """ + Set all IP ranges allowed for SSH bastion. + Set a definitive list of IP ranges (in CIDR notation) allowed to connect to the SSH bastion. + :param gateway_id: ID of the gateway on which to set the allowed IP range. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param ip_ranges: New list of IP ranges (each range in CIDR notation) allowed to connect to the SSH bastion. + :return: :class:`SetBastionAllowedIPsResponse ` + + Usage: + :: + + result = await api.set_bastion_allowed_i_ps( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "PUT", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}/bastion-allowed-ips", + body=marshal_SetBastionAllowedIPsRequest( + SetBastionAllowedIPsRequest( + gateway_id=gateway_id, + zone=zone, + ip_ranges=ip_ranges, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetBastionAllowedIPsResponse(res.json()) + + async def delete_bastion_allowed_i_ps( + self, + *, + gateway_id: str, + ip_range: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete allowed IP range from SSH bastion. + Delete an IP range (defined in CIDR notation) from SSH bastion, so that it is no longer allowed to connect. + :param gateway_id: ID of the gateway on which to delete the allowed IP range. + :param ip_range: IP range to delete from SSH bastion's list of allowed IPs. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = await api.delete_bastion_allowed_i_ps( + gateway_id="example", + ip_range="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + param_ip_range = validate_path_param("ip_range", ip_range) + + res = self._request( + "DELETE", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}/bastion-allowed-ips/{param_ip_range}", + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/vpcgw/v2/content.py b/scaleway-async/scaleway_async/vpcgw/v2/content.py new file mode 100644 index 00000000..a5b8a7ac --- /dev/null +++ b/scaleway-async/scaleway_async/vpcgw/v2/content.py @@ -0,0 +1,26 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + GatewayNetworkStatus, + GatewayStatus, +) + +GATEWAY_NETWORK_TRANSIENT_STATUSES: List[GatewayNetworkStatus] = [ + GatewayNetworkStatus.ATTACHING, + GatewayNetworkStatus.CONFIGURING, + GatewayNetworkStatus.DETACHING, +] +""" +Lists transient statutes of the enum :class:`GatewayNetworkStatus `. +""" +GATEWAY_TRANSIENT_STATUSES: List[GatewayStatus] = [ + GatewayStatus.ALLOCATING, + GatewayStatus.CONFIGURING, + GatewayStatus.STOPPING, + GatewayStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`GatewayStatus `. +""" diff --git a/scaleway-async/scaleway_async/vpcgw/v2/marshalling.py b/scaleway-async/scaleway_async/vpcgw/v2/marshalling.py new file mode 100644 index 00000000..2c01ee75 --- /dev/null +++ b/scaleway-async/scaleway_async/vpcgw/v2/marshalling.py @@ -0,0 +1,729 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from .types import ( + GatewayNetwork, + IP, + Gateway, + PatRule, + AddBastionAllowedIPsResponse, + ListGatewayNetworksResponse, + GatewayType, + ListGatewayTypesResponse, + ListGatewaysResponse, + ListIPsResponse, + ListPatRulesResponse, + SetBastionAllowedIPsResponse, + SetPatRulesResponse, + AddBastionAllowedIPsRequest, + CreateGatewayNetworkRequest, + CreateGatewayRequest, + CreateIPRequest, + CreatePatRuleRequest, + SetBastionAllowedIPsRequest, + SetPatRulesRequestRule, + SetPatRulesRequest, + UpdateGatewayNetworkRequest, + UpdateGatewayRequest, + UpdateIPRequest, + UpdatePatRuleRequest, + UpgradeGatewayRequest, +) + + +def unmarshal_GatewayNetwork(data: Any) -> GatewayNetwork: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GatewayNetwork' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("gateway_id", None) + if field is not None: + args["gateway_id"] = field + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + field = data.get("masquerade_enabled", None) + if field is not None: + args["masquerade_enabled"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("push_default_route", None) + if field is not None: + args["push_default_route"] = field + + field = data.get("ipam_ip_id", None) + if field is not None: + args["ipam_ip_id"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("mac_address", None) + if field is not None: + args["mac_address"] = field + else: + args["mac_address"] = None + + return GatewayNetwork(**args) + + +def unmarshal_IP(data: Any) -> IP: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'IP' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("reverse", None) + if field is not None: + args["reverse"] = field + else: + args["reverse"] = None + + field = data.get("gateway_id", None) + if field is not None: + args["gateway_id"] = field + else: + args["gateway_id"] = None + + return IP(**args) + + +def unmarshal_Gateway(data: Any) -> Gateway: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Gateway' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("bandwidth", None) + if field is not None: + args["bandwidth"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("gateway_networks", None) + if field is not None: + args["gateway_networks"] = ( + [unmarshal_GatewayNetwork(v) for v in field] if field is not None else None + ) + + field = data.get("bastion_enabled", None) + if field is not None: + args["bastion_enabled"] = field + + field = data.get("ipv4", None) + if field is not None: + args["ipv4"] = unmarshal_IP(field) + else: + args["ipv4"] = None + + field = data.get("version", None) + if field is not None: + args["version"] = field + else: + args["version"] = None + + field = data.get("can_upgrade_to", None) + if field is not None: + args["can_upgrade_to"] = field + else: + args["can_upgrade_to"] = None + + field = data.get("bastion_port", None) + if field is not None: + args["bastion_port"] = field + + field = data.get("smtp_enabled", None) + if field is not None: + args["smtp_enabled"] = field + + field = data.get("is_legacy", None) + if field is not None: + args["is_legacy"] = field + + field = data.get("bastion_allowed_ips", None) + if field is not None: + args["bastion_allowed_ips"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + return Gateway(**args) + + +def unmarshal_PatRule(data: Any) -> PatRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PatRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("gateway_id", None) + if field is not None: + args["gateway_id"] = field + + field = data.get("public_port", None) + if field is not None: + args["public_port"] = field + + field = data.get("private_ip", None) + if field is not None: + args["private_ip"] = field + + field = data.get("private_port", None) + if field is not None: + args["private_port"] = field + + field = data.get("protocol", None) + if field is not None: + args["protocol"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return PatRule(**args) + + +def unmarshal_AddBastionAllowedIPsResponse(data: Any) -> AddBastionAllowedIPsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AddBastionAllowedIPsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("ip_ranges", None) + if field is not None: + args["ip_ranges"] = field + + return AddBastionAllowedIPsResponse(**args) + + +def unmarshal_ListGatewayNetworksResponse(data: Any) -> ListGatewayNetworksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGatewayNetworksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("gateway_networks", None) + if field is not None: + args["gateway_networks"] = ( + [unmarshal_GatewayNetwork(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListGatewayNetworksResponse(**args) + + +def unmarshal_GatewayType(data: Any) -> GatewayType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GatewayType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("bandwidth", None) + if field is not None: + args["bandwidth"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + return GatewayType(**args) + + +def unmarshal_ListGatewayTypesResponse(data: Any) -> ListGatewayTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGatewayTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("types", None) + if field is not None: + args["types"] = ( + [unmarshal_GatewayType(v) for v in field] if field is not None else None + ) + + return ListGatewayTypesResponse(**args) + + +def unmarshal_ListGatewaysResponse(data: Any) -> ListGatewaysResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGatewaysResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("gateways", None) + if field is not None: + args["gateways"] = ( + [unmarshal_Gateway(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListGatewaysResponse(**args) + + +def unmarshal_ListIPsResponse(data: Any) -> ListIPsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListIPsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("ips", None) + if field is not None: + args["ips"] = [unmarshal_IP(v) for v in field] if field is not None else None + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListIPsResponse(**args) + + +def unmarshal_ListPatRulesResponse(data: Any) -> ListPatRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPatRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pat_rules", None) + if field is not None: + args["pat_rules"] = ( + [unmarshal_PatRule(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPatRulesResponse(**args) + + +def unmarshal_SetBastionAllowedIPsResponse(data: Any) -> SetBastionAllowedIPsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetBastionAllowedIPsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("ip_ranges", None) + if field is not None: + args["ip_ranges"] = field + + return SetBastionAllowedIPsResponse(**args) + + +def unmarshal_SetPatRulesResponse(data: Any) -> SetPatRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetPatRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pat_rules", None) + if field is not None: + args["pat_rules"] = ( + [unmarshal_PatRule(v) for v in field] if field is not None else None + ) + + return SetPatRulesResponse(**args) + + +def marshal_AddBastionAllowedIPsRequest( + request: AddBastionAllowedIPsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip_range is not None: + output["ip_range"] = request.ip_range + + return output + + +def marshal_CreateGatewayNetworkRequest( + request: CreateGatewayNetworkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.gateway_id is not None: + output["gateway_id"] = request.gateway_id + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + if request.enable_masquerade is not None: + output["enable_masquerade"] = request.enable_masquerade + + if request.push_default_route is not None: + output["push_default_route"] = request.push_default_route + + if request.ipam_ip_id is not None: + output["ipam_ip_id"] = request.ipam_ip_id + + return output + + +def marshal_CreateGatewayRequest( + request: CreateGatewayRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.type_ is not None: + output["type"] = request.type_ + + if request.enable_smtp is not None: + output["enable_smtp"] = request.enable_smtp + + if request.enable_bastion is not None: + output["enable_bastion"] = request.enable_bastion + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.ip_id is not None: + output["ip_id"] = request.ip_id + + if request.bastion_port is not None: + output["bastion_port"] = request.bastion_port + + return output + + +def marshal_CreateIPRequest( + request: CreateIPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_CreatePatRuleRequest( + request: CreatePatRuleRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.gateway_id is not None: + output["gateway_id"] = request.gateway_id + + if request.public_port is not None: + output["public_port"] = request.public_port + + if request.private_ip is not None: + output["private_ip"] = request.private_ip + + if request.private_port is not None: + output["private_port"] = request.private_port + + if request.protocol is not None: + output["protocol"] = str(request.protocol) + + return output + + +def marshal_SetBastionAllowedIPsRequest( + request: SetBastionAllowedIPsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip_ranges is not None: + output["ip_ranges"] = request.ip_ranges + + return output + + +def marshal_SetPatRulesRequestRule( + request: SetPatRulesRequestRule, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.public_port is not None: + output["public_port"] = request.public_port + + if request.private_ip is not None: + output["private_ip"] = request.private_ip + + if request.private_port is not None: + output["private_port"] = request.private_port + + if request.protocol is not None: + output["protocol"] = str(request.protocol) + + return output + + +def marshal_SetPatRulesRequest( + request: SetPatRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.gateway_id is not None: + output["gateway_id"] = request.gateway_id + + if request.pat_rules is not None: + output["pat_rules"] = [ + marshal_SetPatRulesRequestRule(item, defaults) for item in request.pat_rules + ] + + return output + + +def marshal_UpdateGatewayNetworkRequest( + request: UpdateGatewayNetworkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.enable_masquerade is not None: + output["enable_masquerade"] = request.enable_masquerade + + if request.push_default_route is not None: + output["push_default_route"] = request.push_default_route + + if request.ipam_ip_id is not None: + output["ipam_ip_id"] = request.ipam_ip_id + + return output + + +def marshal_UpdateGatewayRequest( + request: UpdateGatewayRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.enable_bastion is not None: + output["enable_bastion"] = request.enable_bastion + + if request.bastion_port is not None: + output["bastion_port"] = request.bastion_port + + if request.enable_smtp is not None: + output["enable_smtp"] = request.enable_smtp + + return output + + +def marshal_UpdateIPRequest( + request: UpdateIPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.tags is not None: + output["tags"] = request.tags + + if request.reverse is not None: + output["reverse"] = request.reverse + + if request.gateway_id is not None: + output["gateway_id"] = request.gateway_id + + return output + + +def marshal_UpdatePatRuleRequest( + request: UpdatePatRuleRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.public_port is not None: + output["public_port"] = request.public_port + + if request.private_ip is not None: + output["private_ip"] = request.private_ip + + if request.private_port is not None: + output["private_port"] = request.private_port + + if request.protocol is not None: + output["protocol"] = str(request.protocol) + + return output + + +def marshal_UpgradeGatewayRequest( + request: UpgradeGatewayRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.type_ is not None: + output["type"] = request.type_ + + return output diff --git a/scaleway-async/scaleway_async/vpcgw/v2/types.py b/scaleway-async/scaleway_async/vpcgw/v2/types.py new file mode 100644 index 00000000..dfd76ccc --- /dev/null +++ b/scaleway-async/scaleway_async/vpcgw/v2/types.py @@ -0,0 +1,1156 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class GatewayNetworkStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATED = "created" + ATTACHING = "attaching" + CONFIGURING = "configuring" + READY = "ready" + DETACHING = "detaching" + + def __str__(self) -> str: + return str(self.value) + + +class GatewayStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + STOPPED = "stopped" + ALLOCATING = "allocating" + CONFIGURING = "configuring" + RUNNING = "running" + STOPPING = "stopping" + FAILED = "failed" + DELETING = "deleting" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class ListGatewayNetworksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListGatewaysRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + TYPE_ASC = "type_asc" + TYPE_DESC = "type_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListIPsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + ADDRESS_ASC = "address_asc" + ADDRESS_DESC = "address_desc" + REVERSE_ASC = "reverse_asc" + REVERSE_DESC = "reverse_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPatRulesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + PUBLIC_PORT_ASC = "public_port_asc" + PUBLIC_PORT_DESC = "public_port_desc" + + def __str__(self) -> str: + return str(self.value) + + +class PatRuleProtocol(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PROTOCOL = "unknown_protocol" + BOTH = "both" + TCP = "tcp" + UDP = "udp" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class GatewayNetwork: + id: str + """ + ID of the Public Gateway-Private Network connection. + """ + + gateway_id: str + """ + ID of the connected Public Gateway. + """ + + private_network_id: str + """ + ID of the connected Private Network. + """ + + masquerade_enabled: bool + """ + Defines whether the gateway masquerades traffic for this Private Network (Dynamic NAT). + """ + + status: GatewayNetworkStatus + """ + Current status of the Public Gateway's connection to the Private Network. + """ + + push_default_route: bool + """ + Enabling the default route also enables masquerading. + """ + + ipam_ip_id: str + """ + Use this IPAM-booked IP ID as the Gateway's IP in this Private Network. + """ + + zone: ScwZone + """ + Zone of the GatewayNetwork connection. + """ + + created_at: Optional[datetime] + """ + Connection creation date. + """ + + updated_at: Optional[datetime] + """ + Connection last modification date. + """ + + mac_address: Optional[str] + """ + MAC address of the gateway in the Private Network (if the gateway is up and running). + """ + + +@dataclass +class IP: + id: str + """ + IP address ID. + """ + + organization_id: str + """ + Owning Organization. + """ + + project_id: str + """ + Owning Project. + """ + + tags: List[str] + """ + Tags associated with the IP address. + """ + + address: str + """ + The IP address itself. + """ + + zone: ScwZone + """ + Zone of the IP address. + """ + + created_at: Optional[datetime] + """ + IP address creation date. + """ + + updated_at: Optional[datetime] + """ + IP address last modification date. + """ + + reverse: Optional[str] + """ + Reverse domain name for the IP address. + """ + + gateway_id: Optional[str] + """ + Public Gateway associated with the IP address. + """ + + +@dataclass +class GatewayType: + name: str + """ + Public Gateway type name. + """ + + bandwidth: int + """ + Bandwidth, in bps, of the Public Gateway. This is the public bandwidth to the outer Internet, and the internal bandwidth to each connected Private Networks. + """ + + zone: ScwZone + """ + Zone the Public Gateway type is available in. + """ + + +@dataclass +class Gateway: + id: str + """ + ID of the gateway. + """ + + organization_id: str + """ + Owning Organization. + """ + + project_id: str + """ + Owning Project. + """ + + type_: str + """ + Gateway type name (commercial offer). + """ + + bandwidth: int + """ + Bandwidth available of the gateway. + """ + + status: GatewayStatus + """ + Current status of the gateway. + """ + + name: str + """ + Name of the gateway. + """ + + created_at: Optional[datetime] + """ + Gateway creation date. + """ + + updated_at: Optional[datetime] + """ + Gateway last modification date. + """ + + tags: List[str] + """ + Tags associated with the gateway. + """ + + gateway_networks: List[GatewayNetwork] + """ + GatewayNetwork objects attached to the gateway (each one represents a connection to a Private Network). + """ + + bastion_enabled: bool + """ + Defines whether SSH bastion is enabled on the gateway. + """ + + ipv4: Optional[IP] + """ + Public IPv4 address of the gateway. + """ + + version: Optional[str] + """ + Version of the running gateway software. + """ + + can_upgrade_to: Optional[str] + """ + Newly available gateway software version that can be updated to. + """ + + bastion_port: int + """ + Port of the SSH bastion. + """ + + smtp_enabled: bool + """ + Defines whether SMTP traffic is allowed to pass through the gateway. + """ + + is_legacy: bool + """ + Defines whether the gateway uses non-IPAM IP configurations. + """ + + bastion_allowed_ips: List[str] + """ + Ranges of IP addresses allowed to connect to the gateway's SSH bastion. + """ + + zone: ScwZone + """ + Zone of the gateway. + """ + + +@dataclass +class PatRule: + id: str + """ + PAT rule ID. + """ + + gateway_id: str + """ + Gateway the PAT rule applies to. + """ + + public_port: int + """ + Public port to listen on. + """ + + private_ip: str + """ + Private IP address to forward data to. + """ + + private_port: int + """ + Private port to translate to. + """ + + protocol: PatRuleProtocol + """ + Protocol the rule applies to. + """ + + zone: ScwZone + """ + Zone of the PAT rule. + """ + + created_at: Optional[datetime] + """ + PAT rule creation date. + """ + + updated_at: Optional[datetime] + """ + PAT rule last modification date. + """ + + +@dataclass +class SetPatRulesRequestRule: + public_port: int + """ + Public port to listen on. Uniquely identifies the rule, and a matching rule will be updated with the new parameters. + """ + + private_ip: str + """ + Private IP to forward data to. + """ + + private_port: int + """ + Private port to translate to. + """ + + protocol: PatRuleProtocol + """ + Protocol the rule should apply to. + """ + + +@dataclass +class AddBastionAllowedIPsRequest: + gateway_id: str + """ + ID of the gateway to add the allowed IP range to. + """ + + ip_range: str + """ + IP range allowed to connect to the SSH bastion. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class AddBastionAllowedIPsResponse: + ip_ranges: List[str] + """ + Ranges of IP addresses allowed to connect to the gateway's SSH bastion. + """ + + +@dataclass +class CreateGatewayNetworkRequest: + gateway_id: str + """ + Public Gateway to connect. + """ + + private_network_id: str + """ + Private Network to connect. + """ + + enable_masquerade: bool + """ + Defines whether to enable masquerade (dynamic NAT) on the GatewayNetwork. + """ + + push_default_route: bool + """ + Enabling the default route also enables masquerading. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + ipam_ip_id: Optional[str] + """ + Use this IPAM-booked IP ID as the Gateway's IP in this Private Network. + """ + + +@dataclass +class CreateGatewayRequest: + type_: str + """ + Gateway type (commercial offer type). + """ + + enable_smtp: bool + """ + Defines whether SMTP traffic should be allowed pass through the gateway. + """ + + enable_bastion: bool + """ + Defines whether SSH bastion should be enabled the gateway. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Scaleway Project to create the gateway in. + """ + + name: Optional[str] + """ + Name for the gateway. + """ + + tags: Optional[List[str]] + """ + Tags for the gateway. + """ + + ip_id: Optional[str] + """ + Existing IP address to attach to the gateway. + """ + + bastion_port: Optional[int] + """ + Port of the SSH bastion. + """ + + +@dataclass +class CreateIPRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project to create the IP address in. + """ + + tags: Optional[List[str]] + """ + Tags to give to the IP address. + """ + + +@dataclass +class CreatePatRuleRequest: + gateway_id: str + """ + ID of the Gateway on which to create the rule. + """ + + public_port: int + """ + Public port to listen on. + """ + + private_ip: str + """ + Private IP to forward data to. + """ + + private_port: int + """ + Private port to translate to. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + protocol: Optional[PatRuleProtocol] + """ + Protocol the rule should apply to. + """ + + +@dataclass +class DeleteBastionAllowedIPsRequest: + gateway_id: str + """ + ID of the gateway on which to delete the allowed IP range. + """ + + ip_range: str + """ + IP range to delete from SSH bastion's list of allowed IPs. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteGatewayNetworkRequest: + gateway_network_id: str + """ + ID of the GatewayNetwork to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteGatewayRequest: + gateway_id: str + """ + ID of the gateway to delete. + """ + + delete_ip: bool + """ + Defines whether the PGW's IP should be deleted. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteIPRequest: + ip_id: str + """ + ID of the IP address to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeletePatRuleRequest: + pat_rule_id: str + """ + ID of the PAT rule to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetGatewayNetworkRequest: + gateway_network_id: str + """ + ID of the GatewayNetwork to fetch. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetGatewayRequest: + gateway_id: str + """ + ID of the gateway to fetch. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetIPRequest: + ip_id: str + """ + ID of the IP address to get. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetPatRuleRequest: + pat_rule_id: str + """ + ID of the PAT rule to get. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ListGatewayNetworksRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListGatewayNetworksRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + GatewayNetworks per page. + """ + + status: Optional[List[GatewayNetworkStatus]] + """ + Filter for GatewayNetworks with these status. Use `unknown` to include all statuses. + """ + + gateway_ids: Optional[List[str]] + """ + Filter for GatewayNetworks connected to these gateways. + """ + + private_network_ids: Optional[List[str]] + """ + Filter for GatewayNetworks connected to these Private Networks. + """ + + masquerade_enabled: Optional[bool] + """ + Filter for GatewayNetworks with this `enable_masquerade` setting. + """ + + +@dataclass +class ListGatewayNetworksResponse: + gateway_networks: List[GatewayNetwork] + """ + GatewayNetworks on this page. + """ + + total_count: int + """ + Total GatewayNetworks count matching the filter. + """ + + +@dataclass +class ListGatewayTypesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ListGatewayTypesResponse: + types: List[GatewayType] + """ + Available types of Public Gateway. + """ + + +@dataclass +class ListGatewaysRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListGatewaysRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Gateways per page. + """ + + organization_id: Optional[str] + """ + Include only gateways in this Organization. + """ + + project_id: Optional[str] + """ + Include only gateways in this Project. + """ + + name: Optional[str] + """ + Filter for gateways which have this search term in their name. + """ + + tags: Optional[List[str]] + """ + Filter for gateways with these tags. + """ + + types: Optional[List[str]] + """ + Filter for gateways of these types. + """ + + status: Optional[List[GatewayStatus]] + """ + Filter for gateways with these status. Use `unknown` to include all statuses. + """ + + private_network_ids: Optional[List[str]] + """ + Filter for gateways attached to these Private Networks. + """ + + include_legacy: Optional[bool] + """ + Include also legacy gateways. + """ + + +@dataclass +class ListGatewaysResponse: + gateways: List[Gateway] + """ + Gateways on this page. + """ + + total_count: int + """ + Total count of gateways matching the filter. + """ + + +@dataclass +class ListIPsRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListIPsRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + IP addresses per page. + """ + + organization_id: Optional[str] + """ + Include only gateways in this Organization. + """ + + project_id: Optional[str] + """ + Filter for IP addresses in this Project. + """ + + tags: Optional[List[str]] + """ + Filter for IP addresses with these tags. + """ + + reverse: Optional[str] + """ + Filter for IP addresses that have a reverse containing this string. + """ + + is_free: Optional[bool] + """ + Filter based on whether the IP is attached to a gateway or not. + """ + + +@dataclass +class ListIPsResponse: + ips: List[IP] + """ + IP addresses on this page. + """ + + total_count: int + """ + Total count of IP addresses matching the filter. + """ + + +@dataclass +class ListPatRulesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListPatRulesRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + PAT rules per page. + """ + + gateway_ids: Optional[List[str]] + """ + Filter for PAT rules on these gateways. + """ + + private_ips: Optional[List[str]] + """ + Filter for PAT rules targeting these private ips. + """ + + protocol: Optional[PatRuleProtocol] + """ + Filter for PAT rules with this protocol. + """ + + +@dataclass +class ListPatRulesResponse: + pat_rules: List[PatRule] + """ + Array of PAT rules matching the filter. + """ + + total_count: int + """ + Total count of PAT rules matching the filter. + """ + + +@dataclass +class RefreshSSHKeysRequest: + gateway_id: str + """ + ID of the gateway to refresh SSH keys on. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SetBastionAllowedIPsRequest: + gateway_id: str + """ + ID of the gateway on which to set the allowed IP range. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + ip_ranges: Optional[List[str]] + """ + New list of IP ranges (each range in CIDR notation) allowed to connect to the SSH bastion. + """ + + +@dataclass +class SetBastionAllowedIPsResponse: + ip_ranges: List[str] + """ + Ranges of IP addresses allowed to connect to the gateway's SSH bastion. + """ + + +@dataclass +class SetPatRulesRequest: + gateway_id: str + """ + ID of the gateway on which to set the PAT rules. + """ + + pat_rules: List[SetPatRulesRequestRule] + """ + New list of PAT rules. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SetPatRulesResponse: + pat_rules: List[PatRule] + """ + List of PAT rules. + """ + + +@dataclass +class UpdateGatewayNetworkRequest: + gateway_network_id: str + """ + ID of the GatewayNetwork to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + enable_masquerade: Optional[bool] + """ + Defines whether to enable masquerade (dynamic NAT) on the GatewayNetwork. + """ + + push_default_route: Optional[bool] + """ + Enabling the default route also enables masquerading. + """ + + ipam_ip_id: Optional[str] + """ + Use this IPAM-booked IP ID as the Gateway's IP in this Private Network. + """ + + +@dataclass +class UpdateGatewayRequest: + gateway_id: str + """ + ID of the gateway to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name for the gateway. + """ + + tags: Optional[List[str]] + """ + Tags for the gateway. + """ + + enable_bastion: Optional[bool] + """ + Defines whether SSH bastion should be enabled the gateway. + """ + + bastion_port: Optional[int] + """ + Port of the SSH bastion. + """ + + enable_smtp: Optional[bool] + """ + Defines whether SMTP traffic should be allowed to pass through the gateway. + """ + + +@dataclass +class UpdateIPRequest: + ip_id: str + """ + ID of the IP address to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + tags: Optional[List[str]] + """ + Tags to give to the IP address. + """ + + reverse: Optional[str] + """ + Reverse to set on the address. Empty string to unset. + """ + + gateway_id: Optional[str] + """ + Gateway to attach the IP address to. Empty string to detach. + """ + + +@dataclass +class UpdatePatRuleRequest: + pat_rule_id: str + """ + ID of the PAT rule to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + public_port: Optional[int] + """ + Public port to listen on. + """ + + private_ip: Optional[str] + """ + Private IP to forward data to. + """ + + private_port: Optional[int] + """ + Private port to translate to. + """ + + protocol: Optional[PatRuleProtocol] + """ + Protocol the rule should apply to. + """ + + +@dataclass +class UpgradeGatewayRequest: + gateway_id: str + """ + ID of the gateway to upgrade. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + type_: Optional[str] + """ + Gateway type (commercial offer). + """ diff --git a/scaleway-async/scaleway_async/webhosting/v1/__init__.py b/scaleway-async/scaleway_async/webhosting/v1/__init__.py new file mode 100644 index 00000000..43df2e81 --- /dev/null +++ b/scaleway-async/scaleway_async/webhosting/v1/__init__.py @@ -0,0 +1,213 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DnsRecordStatus +from .types import DnsRecordType +from .types import DnsRecordsStatus +from .types import DomainAction +from .types import DomainAvailabilityAction +from .types import DomainAvailabilityStatus +from .content import DOMAIN_AVAILABILITY_TRANSIENT_STATUSES +from .types import DomainDnsAction +from .types import DomainStatus +from .content import DOMAIN_TRANSIENT_STATUSES +from .types import DomainZoneOwner +from .types import HostingStatus +from .content import HOSTING_TRANSIENT_STATUSES +from .types import ListDatabaseUsersRequestOrderBy +from .types import ListDatabasesRequestOrderBy +from .types import ListFtpAccountsRequestOrderBy +from .types import ListHostingsRequestOrderBy +from .types import ListMailAccountsRequestOrderBy +from .types import ListOffersRequestOrderBy +from .types import ListWebsitesRequestOrderBy +from .types import NameserverStatus +from .types import OfferOptionName +from .types import OfferOptionWarning +from .types import PlatformPlatformGroup +from .types import PlatformControlPanelUrls +from .types import OfferOption +from .types import PlatformControlPanel +from .types import CreateDatabaseRequestUser +from .types import AutoConfigDomainDns +from .types import CreateHostingRequestDomainConfiguration +from .types import OfferOptionRequest +from .types import SyncDomainDnsRecordsRequestRecord +from .types import DnsRecord +from .types import Nameserver +from .types import HostingUser +from .types import Offer +from .types import Platform +from .types import ControlPanel +from .types import DatabaseUser +from .types import Database +from .types import FtpAccount +from .types import HostingSummary +from .types import MailAccount +from .types import Website +from .types import DomainAvailability +from .types import CheckUserOwnsDomainResponse +from .types import ControlPanelApiListControlPanelsRequest +from .types import DatabaseApiAssignDatabaseUserRequest +from .types import DatabaseApiChangeDatabaseUserPasswordRequest +from .types import DatabaseApiCreateDatabaseRequest +from .types import DatabaseApiCreateDatabaseUserRequest +from .types import DatabaseApiDeleteDatabaseRequest +from .types import DatabaseApiDeleteDatabaseUserRequest +from .types import DatabaseApiGetDatabaseRequest +from .types import DatabaseApiGetDatabaseUserRequest +from .types import DatabaseApiListDatabaseUsersRequest +from .types import DatabaseApiListDatabasesRequest +from .types import DatabaseApiUnassignDatabaseUserRequest +from .types import DnsApiCheckUserOwnsDomainRequest +from .types import DnsApiGetDomainDnsRecordsRequest +from .types import DnsApiGetDomainRequest +from .types import DnsApiSearchDomainsRequest +from .types import DnsApiSyncDomainDnsRecordsRequest +from .types import DnsRecords +from .types import Domain +from .types import FtpAccountApiChangeFtpAccountPasswordRequest +from .types import FtpAccountApiCreateFtpAccountRequest +from .types import FtpAccountApiListFtpAccountsRequest +from .types import FtpAccountApiRemoveFtpAccountRequest +from .types import Hosting +from .types import HostingApiCreateHostingRequest +from .types import HostingApiCreateSessionRequest +from .types import HostingApiDeleteHostingRequest +from .types import HostingApiGetHostingRequest +from .types import HostingApiGetResourceSummaryRequest +from .types import HostingApiListHostingsRequest +from .types import HostingApiResetHostingPasswordRequest +from .types import HostingApiUpdateHostingRequest +from .types import ListControlPanelsResponse +from .types import ListDatabaseUsersResponse +from .types import ListDatabasesResponse +from .types import ListFtpAccountsResponse +from .types import ListHostingsResponse +from .types import ListMailAccountsResponse +from .types import ListOffersResponse +from .types import ListWebsitesResponse +from .types import MailAccountApiChangeMailAccountPasswordRequest +from .types import MailAccountApiCreateMailAccountRequest +from .types import MailAccountApiListMailAccountsRequest +from .types import MailAccountApiRemoveMailAccountRequest +from .types import OfferApiListOffersRequest +from .types import ResetHostingPasswordResponse +from .types import ResourceSummary +from .types import SearchDomainsResponse +from .types import Session +from .types import WebsiteApiListWebsitesRequest +from .api import WebhostingV1ControlPanelAPI +from .api import WebhostingV1DatabaseAPI +from .api import WebhostingV1DnsAPI +from .api import WebhostingV1OfferAPI +from .api import WebhostingV1HostingAPI +from .api import WebhostingV1FtpAccountAPI +from .api import WebhostingV1MailAccountAPI +from .api import WebhostingV1WebsiteAPI + +__all__ = [ + "DnsRecordStatus", + "DnsRecordType", + "DnsRecordsStatus", + "DomainAction", + "DomainAvailabilityAction", + "DomainAvailabilityStatus", + "DOMAIN_AVAILABILITY_TRANSIENT_STATUSES", + "DomainDnsAction", + "DomainStatus", + "DOMAIN_TRANSIENT_STATUSES", + "DomainZoneOwner", + "HostingStatus", + "HOSTING_TRANSIENT_STATUSES", + "ListDatabaseUsersRequestOrderBy", + "ListDatabasesRequestOrderBy", + "ListFtpAccountsRequestOrderBy", + "ListHostingsRequestOrderBy", + "ListMailAccountsRequestOrderBy", + "ListOffersRequestOrderBy", + "ListWebsitesRequestOrderBy", + "NameserverStatus", + "OfferOptionName", + "OfferOptionWarning", + "PlatformPlatformGroup", + "PlatformControlPanelUrls", + "OfferOption", + "PlatformControlPanel", + "CreateDatabaseRequestUser", + "AutoConfigDomainDns", + "CreateHostingRequestDomainConfiguration", + "OfferOptionRequest", + "SyncDomainDnsRecordsRequestRecord", + "DnsRecord", + "Nameserver", + "HostingUser", + "Offer", + "Platform", + "ControlPanel", + "DatabaseUser", + "Database", + "FtpAccount", + "HostingSummary", + "MailAccount", + "Website", + "DomainAvailability", + "CheckUserOwnsDomainResponse", + "ControlPanelApiListControlPanelsRequest", + "DatabaseApiAssignDatabaseUserRequest", + "DatabaseApiChangeDatabaseUserPasswordRequest", + "DatabaseApiCreateDatabaseRequest", + "DatabaseApiCreateDatabaseUserRequest", + "DatabaseApiDeleteDatabaseRequest", + "DatabaseApiDeleteDatabaseUserRequest", + "DatabaseApiGetDatabaseRequest", + "DatabaseApiGetDatabaseUserRequest", + "DatabaseApiListDatabaseUsersRequest", + "DatabaseApiListDatabasesRequest", + "DatabaseApiUnassignDatabaseUserRequest", + "DnsApiCheckUserOwnsDomainRequest", + "DnsApiGetDomainDnsRecordsRequest", + "DnsApiGetDomainRequest", + "DnsApiSearchDomainsRequest", + "DnsApiSyncDomainDnsRecordsRequest", + "DnsRecords", + "Domain", + "FtpAccountApiChangeFtpAccountPasswordRequest", + "FtpAccountApiCreateFtpAccountRequest", + "FtpAccountApiListFtpAccountsRequest", + "FtpAccountApiRemoveFtpAccountRequest", + "Hosting", + "HostingApiCreateHostingRequest", + "HostingApiCreateSessionRequest", + "HostingApiDeleteHostingRequest", + "HostingApiGetHostingRequest", + "HostingApiGetResourceSummaryRequest", + "HostingApiListHostingsRequest", + "HostingApiResetHostingPasswordRequest", + "HostingApiUpdateHostingRequest", + "ListControlPanelsResponse", + "ListDatabaseUsersResponse", + "ListDatabasesResponse", + "ListFtpAccountsResponse", + "ListHostingsResponse", + "ListMailAccountsResponse", + "ListOffersResponse", + "ListWebsitesResponse", + "MailAccountApiChangeMailAccountPasswordRequest", + "MailAccountApiCreateMailAccountRequest", + "MailAccountApiListMailAccountsRequest", + "MailAccountApiRemoveMailAccountRequest", + "OfferApiListOffersRequest", + "ResetHostingPasswordResponse", + "ResourceSummary", + "SearchDomainsResponse", + "Session", + "WebsiteApiListWebsitesRequest", + "WebhostingV1ControlPanelAPI", + "WebhostingV1DatabaseAPI", + "WebhostingV1DnsAPI", + "WebhostingV1OfferAPI", + "WebhostingV1HostingAPI", + "WebhostingV1FtpAccountAPI", + "WebhostingV1MailAccountAPI", + "WebhostingV1WebsiteAPI", +] diff --git a/scaleway-async/scaleway_async/webhosting/v1/api.py b/scaleway-async/scaleway_async/webhosting/v1/api.py new file mode 100644 index 00000000..0988b737 --- /dev/null +++ b/scaleway-async/scaleway_async/webhosting/v1/api.py @@ -0,0 +1,2115 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Awaitable, List, Optional, Union + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages_async, + wait_for_resource_async, +) +from .types import ( + HostingStatus, + ListDatabaseUsersRequestOrderBy, + ListDatabasesRequestOrderBy, + ListFtpAccountsRequestOrderBy, + ListHostingsRequestOrderBy, + ListMailAccountsRequestOrderBy, + ListOffersRequestOrderBy, + ListWebsitesRequestOrderBy, + AutoConfigDomainDns, + CheckUserOwnsDomainResponse, + ControlPanel, + CreateDatabaseRequestUser, + CreateHostingRequestDomainConfiguration, + Database, + DatabaseApiAssignDatabaseUserRequest, + DatabaseApiChangeDatabaseUserPasswordRequest, + DatabaseApiCreateDatabaseRequest, + DatabaseApiCreateDatabaseUserRequest, + DatabaseApiUnassignDatabaseUserRequest, + DatabaseUser, + DnsApiCheckUserOwnsDomainRequest, + DnsApiSyncDomainDnsRecordsRequest, + DnsRecords, + Domain, + FtpAccount, + FtpAccountApiChangeFtpAccountPasswordRequest, + FtpAccountApiCreateFtpAccountRequest, + Hosting, + HostingApiCreateHostingRequest, + HostingApiUpdateHostingRequest, + HostingSummary, + ListControlPanelsResponse, + ListDatabaseUsersResponse, + ListDatabasesResponse, + ListFtpAccountsResponse, + ListHostingsResponse, + ListMailAccountsResponse, + ListOffersResponse, + ListWebsitesResponse, + MailAccount, + MailAccountApiChangeMailAccountPasswordRequest, + MailAccountApiCreateMailAccountRequest, + MailAccountApiRemoveMailAccountRequest, + Offer, + OfferOptionRequest, + ResetHostingPasswordResponse, + ResourceSummary, + SearchDomainsResponse, + Session, + SyncDomainDnsRecordsRequestRecord, + Website, +) +from .content import ( + DOMAIN_TRANSIENT_STATUSES, + HOSTING_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_DatabaseUser, + unmarshal_Database, + unmarshal_FtpAccount, + unmarshal_MailAccount, + unmarshal_CheckUserOwnsDomainResponse, + unmarshal_DnsRecords, + unmarshal_Domain, + unmarshal_Hosting, + unmarshal_ListControlPanelsResponse, + unmarshal_ListDatabaseUsersResponse, + unmarshal_ListDatabasesResponse, + unmarshal_ListFtpAccountsResponse, + unmarshal_ListHostingsResponse, + unmarshal_ListMailAccountsResponse, + unmarshal_ListOffersResponse, + unmarshal_ListWebsitesResponse, + unmarshal_ResetHostingPasswordResponse, + unmarshal_ResourceSummary, + unmarshal_SearchDomainsResponse, + unmarshal_Session, + marshal_DatabaseApiAssignDatabaseUserRequest, + marshal_DatabaseApiChangeDatabaseUserPasswordRequest, + marshal_DatabaseApiCreateDatabaseRequest, + marshal_DatabaseApiCreateDatabaseUserRequest, + marshal_DatabaseApiUnassignDatabaseUserRequest, + marshal_DnsApiCheckUserOwnsDomainRequest, + marshal_DnsApiSyncDomainDnsRecordsRequest, + marshal_FtpAccountApiChangeFtpAccountPasswordRequest, + marshal_FtpAccountApiCreateFtpAccountRequest, + marshal_HostingApiCreateHostingRequest, + marshal_HostingApiUpdateHostingRequest, + marshal_MailAccountApiChangeMailAccountPasswordRequest, + marshal_MailAccountApiCreateMailAccountRequest, + marshal_MailAccountApiRemoveMailAccountRequest, +) +from ...std.types import ( + LanguageCode as StdLanguageCode, +) + + +class WebhostingV1ControlPanelAPI(API): + """ + This API allows you to manage your Web Hosting services. + """ + + async def list_control_panels( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListControlPanelsResponse: + """ + "List the control panels type: cpanel or plesk.". + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of control panels to return (must be a positive integer lower or equal to 100). + :return: :class:`ListControlPanelsResponse ` + + Usage: + :: + + result = await api.list_control_panels() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/control-panels", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListControlPanelsResponse(res.json()) + + async def list_control_panels_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[ControlPanel]: + """ + "List the control panels type: cpanel or plesk.". + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of control panels to return (must be a positive integer lower or equal to 100). + :return: :class:`List[ControlPanel] ` + + Usage: + :: + + result = await api.list_control_panels_all() + """ + + return await fetch_all_pages_async( + type=ListControlPanelsResponse, + key="control_panels", + fetcher=self.list_control_panels, + args={ + "region": region, + "page": page, + "page_size": page_size, + }, + ) + + +class WebhostingV1DatabaseAPI(API): + """ + This API allows you to manage your databases and database users for your Web Hosting services. + """ + + async def create_database( + self, + *, + hosting_id: str, + database_name: str, + region: Optional[ScwRegion] = None, + new_user: Optional[CreateDatabaseRequestUser] = None, + existing_username: Optional[str] = None, + ) -> Database: + """ + "Create a new database within your hosting plan". + :param hosting_id: UUID of the hosting plan where the database will be created. + :param database_name: Name of the database to be created. + :param region: Region to target. If none is passed will use default region from the config. + :param new_user: (Optional) Username and password to create a user and link to the database. + One-Of ('user'): at most one of 'new_user', 'existing_username' could be set. + :param existing_username: (Optional) Username to link an existing user to the database. + One-Of ('user'): at most one of 'new_user', 'existing_username' could be set. + :return: :class:`Database ` + + Usage: + :: + + result = await api.create_database( + hosting_id="example", + database_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases", + body=marshal_DatabaseApiCreateDatabaseRequest( + DatabaseApiCreateDatabaseRequest( + hosting_id=hosting_id, + database_name=database_name, + region=region, + new_user=new_user, + existing_username=existing_username, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Database(res.json()) + + async def list_databases( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDatabasesRequestOrderBy] = None, + ) -> ListDatabasesResponse: + """ + "List all databases within your hosting plan". + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of databases to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of databases in the response. + :return: :class:`ListDatabasesResponse ` + + Usage: + :: + + result = await api.list_databases( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDatabasesResponse(res.json()) + + async def list_databases_all( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDatabasesRequestOrderBy] = None, + ) -> List[Database]: + """ + "List all databases within your hosting plan". + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of databases to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of databases in the response. + :return: :class:`List[Database] ` + + Usage: + :: + + result = await api.list_databases_all( + hosting_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListDatabasesResponse, + key="databases", + fetcher=self.list_databases, + args={ + "hosting_id": hosting_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + async def get_database( + self, + *, + hosting_id: str, + database_name: str, + region: Optional[ScwRegion] = None, + ) -> Database: + """ + "Get details of a database within your hosting plan". + :param hosting_id: UUID of the hosting plan. + :param database_name: Name of the database. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Database ` + + Usage: + :: + + result = await api.get_database( + hosting_id="example", + database_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_database_name = validate_path_param("database_name", database_name) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases/{param_database_name}", + ) + + self._throw_on_error(res) + return unmarshal_Database(res.json()) + + async def delete_database( + self, + *, + hosting_id: str, + database_name: str, + region: Optional[ScwRegion] = None, + ) -> Database: + """ + "Delete a database within your hosting plan". + :param hosting_id: UUID of the hosting plan. + :param database_name: Name of the database to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Database ` + + Usage: + :: + + result = await api.delete_database( + hosting_id="example", + database_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_database_name = validate_path_param("database_name", database_name) + + res = self._request( + "DELETE", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases/{param_database_name}", + ) + + self._throw_on_error(res) + return unmarshal_Database(res.json()) + + async def create_database_user( + self, + *, + hosting_id: str, + username: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Create a new database user". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the user to create. + :param password: Password of the user to create. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = await api.create_database_user( + hosting_id="example", + username="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases-users", + body=marshal_DatabaseApiCreateDatabaseUserRequest( + DatabaseApiCreateDatabaseUserRequest( + hosting_id=hosting_id, + username=username, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + async def list_database_users( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDatabaseUsersRequestOrderBy] = None, + ) -> ListDatabaseUsersResponse: + """ + "List all database users". + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of database users to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of database users in the response. + :return: :class:`ListDatabaseUsersResponse ` + + Usage: + :: + + result = await api.list_database_users( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/database-users", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDatabaseUsersResponse(res.json()) + + async def list_database_users_all( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDatabaseUsersRequestOrderBy] = None, + ) -> List[DatabaseUser]: + """ + "List all database users". + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of database users to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of database users in the response. + :return: :class:`List[DatabaseUser] ` + + Usage: + :: + + result = await api.list_database_users_all( + hosting_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListDatabaseUsersResponse, + key="users", + fetcher=self.list_database_users, + args={ + "hosting_id": hosting_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + async def get_database_user( + self, + *, + hosting_id: str, + username: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Get details of a database user". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the database user to retrieve details. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = await api.get_database_user( + hosting_id="example", + username="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_username = validate_path_param("username", username) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases-users/{param_username}", + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + async def delete_database_user( + self, + *, + hosting_id: str, + username: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Delete a database user". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the database user to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = await api.delete_database_user( + hosting_id="example", + username="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_username = validate_path_param("username", username) + + res = self._request( + "DELETE", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/database-users/{param_username}", + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + async def change_database_user_password( + self, + *, + hosting_id: str, + username: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Change the password of a database user". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the user to update. + :param password: New password. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = await api.change_database_user_password( + hosting_id="example", + username="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_username = validate_path_param("username", username) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases-users/{param_username}/change-password", + body=marshal_DatabaseApiChangeDatabaseUserPasswordRequest( + DatabaseApiChangeDatabaseUserPasswordRequest( + hosting_id=hosting_id, + username=username, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + async def assign_database_user( + self, + *, + hosting_id: str, + username: str, + database_name: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Assign a database user to a database". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the user to assign. + :param database_name: Name of the database to be assigned. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = await api.assign_database_user( + hosting_id="example", + username="example", + database_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_database_name = validate_path_param("database_name", database_name) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases/{param_database_name}/assign-user", + body=marshal_DatabaseApiAssignDatabaseUserRequest( + DatabaseApiAssignDatabaseUserRequest( + hosting_id=hosting_id, + username=username, + database_name=database_name, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + async def unassign_database_user( + self, + *, + hosting_id: str, + username: str, + database_name: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Unassign a database user from a database". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the user to unassign. + :param database_name: Name of the database to be unassigned. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = await api.unassign_database_user( + hosting_id="example", + username="example", + database_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_database_name = validate_path_param("database_name", database_name) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases/{param_database_name}/unassign-user", + body=marshal_DatabaseApiUnassignDatabaseUserRequest( + DatabaseApiUnassignDatabaseUserRequest( + hosting_id=hosting_id, + username=username, + database_name=database_name, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + +class WebhostingV1DnsAPI(API): + """ + This API allows you to manage your Web Hosting services. + """ + + async def get_domain_dns_records( + self, + *, + domain: str, + region: Optional[ScwRegion] = None, + ) -> DnsRecords: + """ + Get DNS records. + Get the set of DNS records of a specified domain associated with a Web Hosting plan's domain. + :param domain: Domain associated with the DNS records. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DnsRecords ` + + Usage: + :: + + result = await api.get_domain_dns_records( + domain="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain = validate_path_param("domain", domain) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/domains/{param_domain}/dns-records", + ) + + self._throw_on_error(res) + return unmarshal_DnsRecords(res.json()) + + async def check_user_owns_domain( + self, + *, + domain: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> CheckUserOwnsDomainResponse: + """ + Check whether you own this domain or not. + :param domain: Domain for which ownership is to be verified. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project currently in use. + :return: :class:`CheckUserOwnsDomainResponse ` + + Usage: + :: + + result = await api.check_user_owns_domain( + domain="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain = validate_path_param("domain", domain) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/domains/{param_domain}/check-ownership", + body=marshal_DnsApiCheckUserOwnsDomainRequest( + DnsApiCheckUserOwnsDomainRequest( + domain=domain, + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckUserOwnsDomainResponse(res.json()) + + async def sync_domain_dns_records( + self, + *, + domain: str, + region: Optional[ScwRegion] = None, + update_web_records: Optional[bool] = None, + update_mail_records: Optional[bool] = None, + update_all_records: Optional[bool] = None, + update_nameservers: Optional[bool] = None, + custom_records: Optional[List[SyncDomainDnsRecordsRequestRecord]] = None, + auto_config_domain_dns: Optional[AutoConfigDomainDns] = None, + ) -> DnsRecords: + """ + Synchronize your DNS records on the Elements Console and on cPanel. + :param domain: Domain for which the DNS records will be synchronized. + :param region: Region to target. If none is passed will use default region from the config. + :param update_web_records: Whether or not to synchronize the web records (deprecated, use auto_config_domain_dns). + :param update_mail_records: Whether or not to synchronize the mail records (deprecated, use auto_config_domain_dns). + :param update_all_records: Whether or not to synchronize all types of records. This one has priority (deprecated, use auto_config_domain_dns). + :param update_nameservers: Whether or not to synchronize domain nameservers (deprecated, use auto_config_domain_dns). + :param custom_records: Custom records to synchronize. + :param auto_config_domain_dns: Whether or not to synchronize each types of records. + :return: :class:`DnsRecords ` + + Usage: + :: + + result = await api.sync_domain_dns_records( + domain="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain = validate_path_param("domain", domain) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/domains/{param_domain}/sync-domain-dns-records", + body=marshal_DnsApiSyncDomainDnsRecordsRequest( + DnsApiSyncDomainDnsRecordsRequest( + domain=domain, + region=region, + update_web_records=update_web_records, + update_mail_records=update_mail_records, + update_all_records=update_all_records, + update_nameservers=update_nameservers, + custom_records=custom_records, + auto_config_domain_dns=auto_config_domain_dns, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DnsRecords(res.json()) + + async def search_domains( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> SearchDomainsResponse: + """ + Search for available domains based on domain name. + :param domain_name: Domain name to search. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to search the domain to create the Web Hosting plan. + :return: :class:`SearchDomainsResponse ` + + Usage: + :: + + result = await api.search_domains( + domain_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/search-domains", + params={ + "domain_name": domain_name, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_SearchDomainsResponse(res.json()) + + async def get_domain( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> Domain: + """ + Retrieve detailed information about a specific domain, including its status, DNS configuration, and ownership. + :param domain_name: Domain name to get. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + :return: :class:`Domain ` + + Usage: + :: + + result = await api.get_domain( + domain_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain_name = validate_path_param("domain_name", domain_name) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/domains/{param_domain_name}", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Domain(res.json()) + + async def wait_for_domain( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + options: Optional[WaitForOptions[Domain, Union[bool, Awaitable[bool]]]] = None, + ) -> Domain: + """ + Retrieve detailed information about a specific domain, including its status, DNS configuration, and ownership. + :param domain_name: Domain name to get. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + :return: :class:`Domain ` + + Usage: + :: + + result = await api.get_domain( + domain_name="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in DOMAIN_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_domain, + options=options, + args={ + "domain_name": domain_name, + "region": region, + "project_id": project_id, + }, + ) + + +class WebhostingV1OfferAPI(API): + """ + This API allows you to manage your offer for your Web Hosting services. + """ + + async def list_offers( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOffersRequestOrderBy] = None, + hosting_id: Optional[str] = None, + control_panels: Optional[List[str]] = None, + ) -> ListOffersResponse: + """ + List all available hosting offers along with their specific options. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of websites to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting offers in the response. + :param hosting_id: UUID of the hosting plan. + :param control_panels: Name of the control panel(s) to filter for. + :return: :class:`ListOffersResponse ` + + Usage: + :: + + result = await api.list_offers() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/offers", + params={ + "control_panels": control_panels, + "hosting_id": hosting_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListOffersResponse(res.json()) + + async def list_offers_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOffersRequestOrderBy] = None, + hosting_id: Optional[str] = None, + control_panels: Optional[List[str]] = None, + ) -> List[Offer]: + """ + List all available hosting offers along with their specific options. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of websites to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting offers in the response. + :param hosting_id: UUID of the hosting plan. + :param control_panels: Name of the control panel(s) to filter for. + :return: :class:`List[Offer] ` + + Usage: + :: + + result = await api.list_offers_all() + """ + + return await fetch_all_pages_async( + type=ListOffersResponse, + key="offers", + fetcher=self.list_offers, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "hosting_id": hosting_id, + "control_panels": control_panels, + }, + ) + + +class WebhostingV1HostingAPI(API): + """ + This API allows you to manage your Web Hosting services. + """ + + async def create_hosting( + self, + *, + offer_id: str, + email: str, + domain: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + offer_options: Optional[List[OfferOptionRequest]] = None, + language: Optional[StdLanguageCode] = None, + domain_configuration: Optional[CreateHostingRequestDomainConfiguration] = None, + skip_welcome_email: Optional[bool] = None, + auto_config_domain_dns: Optional[AutoConfigDomainDns] = None, + ) -> Hosting: + """ + Order a Web Hosting plan. + Order a Web Hosting plan, specifying the offer type required via the `offer_id` parameter. + :param offer_id: ID of the selected offer for the Web Hosting plan. + :param email: Contact email for the Web Hosting client. + :param domain: Domain name to link to the Web Hosting plan. You must already own this domain name, and have completed the DNS validation process beforehand. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to create the Web Hosting plan. + :param tags: List of tags for the Web Hosting plan. + :param offer_options: List of the Web Hosting plan options IDs with their quantities. + :param language: Default language for the control panel interface. + :param domain_configuration: Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_config_domain_dns instead). + :param skip_welcome_email: Indicates whether to skip a welcome email to the contact email containing hosting info. + :param auto_config_domain_dns: Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_update_* fields instead). + :return: :class:`Hosting ` + + Usage: + :: + + result = await api.create_hosting( + offer_id="example", + email="example", + domain="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings", + body=marshal_HostingApiCreateHostingRequest( + HostingApiCreateHostingRequest( + offer_id=offer_id, + email=email, + domain=domain, + region=region, + project_id=project_id, + tags=tags, + offer_options=offer_options, + language=language, + domain_configuration=domain_configuration, + skip_welcome_email=skip_welcome_email, + auto_config_domain_dns=auto_config_domain_dns, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Hosting(res.json()) + + async def list_hostings( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListHostingsRequestOrderBy] = None, + tags: Optional[List[str]] = None, + statuses: Optional[List[HostingStatus]] = None, + domain: Optional[str] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + control_panels: Optional[List[str]] = None, + ) -> ListHostingsResponse: + """ + List all Web Hosting plans. + List all of your existing Web Hosting plans. Various filters are available to limit the results, including filtering by domain, status, tag and Project ID. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results (must be a positive integer). + :param page_size: Number of Web Hosting plans to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting plans in the response. + :param tags: Tags to filter for, only Web Hosting plans with matching tags will be returned. + :param statuses: Statuses to filter for, only Web Hosting plans with matching statuses will be returned. + :param domain: Domain to filter for, only Web Hosting plans associated with this domain will be returned. + :param project_id: Project ID to filter for, only Web Hosting plans from this Project will be returned. + :param organization_id: Organization ID to filter for, only Web Hosting plans from this Organization will be returned. + :param control_panels: Name of the control panel to filter for, only Web Hosting plans from this control panel will be returned. + :return: :class:`ListHostingsResponse ` + + Usage: + :: + + result = await api.list_hostings() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings", + params={ + "control_panels": control_panels, + "domain": domain, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "statuses": statuses, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListHostingsResponse(res.json()) + + async def list_hostings_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListHostingsRequestOrderBy] = None, + tags: Optional[List[str]] = None, + statuses: Optional[List[HostingStatus]] = None, + domain: Optional[str] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + control_panels: Optional[List[str]] = None, + ) -> List[HostingSummary]: + """ + List all Web Hosting plans. + List all of your existing Web Hosting plans. Various filters are available to limit the results, including filtering by domain, status, tag and Project ID. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results (must be a positive integer). + :param page_size: Number of Web Hosting plans to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting plans in the response. + :param tags: Tags to filter for, only Web Hosting plans with matching tags will be returned. + :param statuses: Statuses to filter for, only Web Hosting plans with matching statuses will be returned. + :param domain: Domain to filter for, only Web Hosting plans associated with this domain will be returned. + :param project_id: Project ID to filter for, only Web Hosting plans from this Project will be returned. + :param organization_id: Organization ID to filter for, only Web Hosting plans from this Organization will be returned. + :param control_panels: Name of the control panel to filter for, only Web Hosting plans from this control panel will be returned. + :return: :class:`List[HostingSummary] ` + + Usage: + :: + + result = await api.list_hostings_all() + """ + + return await fetch_all_pages_async( + type=ListHostingsResponse, + key="hostings", + fetcher=self.list_hostings, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "tags": tags, + "statuses": statuses, + "domain": domain, + "project_id": project_id, + "organization_id": organization_id, + "control_panels": control_panels, + }, + ) + + async def get_hosting( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> Hosting: + """ + Get a Web Hosting plan. + Get the details of one of your existing Web Hosting plans, specified by its `hosting_id`. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Hosting ` + + Usage: + :: + + result = await api.get_hosting( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}", + ) + + self._throw_on_error(res) + return unmarshal_Hosting(res.json()) + + async def wait_for_hosting( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Hosting, Union[bool, Awaitable[bool]]]] = None, + ) -> Hosting: + """ + Get a Web Hosting plan. + Get the details of one of your existing Web Hosting plans, specified by its `hosting_id`. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Hosting ` + + Usage: + :: + + result = await api.get_hosting( + hosting_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in HOSTING_TRANSIENT_STATUSES + + return await wait_for_resource_async( + fetcher=self.get_hosting, + options=options, + args={ + "hosting_id": hosting_id, + "region": region, + }, + ) + + async def update_hosting( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + email: Optional[str] = None, + tags: Optional[List[str]] = None, + offer_options: Optional[List[OfferOptionRequest]] = None, + offer_id: Optional[str] = None, + protected: Optional[bool] = None, + ) -> Hosting: + """ + Update a Web Hosting plan. + Update the details of one of your existing Web Hosting plans, specified by its `hosting_id`. You can update parameters including the contact email address, tags, options and offer. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :param email: New contact email for the Web Hosting plan. + :param tags: New tags for the Web Hosting plan. + :param offer_options: List of the Web Hosting plan options IDs with their quantities. + :param offer_id: ID of the new offer for the Web Hosting plan. + :param protected: Whether the hosting is protected or not. + :return: :class:`Hosting ` + + Usage: + :: + + result = await api.update_hosting( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "PATCH", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}", + body=marshal_HostingApiUpdateHostingRequest( + HostingApiUpdateHostingRequest( + hosting_id=hosting_id, + region=region, + email=email, + tags=tags, + offer_options=offer_options, + offer_id=offer_id, + protected=protected, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Hosting(res.json()) + + async def delete_hosting( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> Hosting: + """ + Delete a Web Hosting plan. + Delete a Web Hosting plan, specified by its `hosting_id`. Note that deletion is not immediate: it will take place at the end of the calendar month, after which time your Web Hosting plan and all its data (files and emails) will be irreversibly lost. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Hosting ` + + Usage: + :: + + result = await api.delete_hosting( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "DELETE", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}", + ) + + self._throw_on_error(res) + return unmarshal_Hosting(res.json()) + + async def create_session( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> Session: + """ + Create a user session. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Session ` + + Usage: + :: + + result = await api.create_session( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/sessions", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Session(res.json()) + + async def reset_hosting_password( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> ResetHostingPasswordResponse: + """ + Reset a Web Hosting plan password. + :param hosting_id: UUID of the hosting. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ResetHostingPasswordResponse ` + + Usage: + :: + + result = await api.reset_hosting_password( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/reset-password", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_ResetHostingPasswordResponse(res.json()) + + async def get_resource_summary( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> ResourceSummary: + """ + Get the total counts of websites, databases, email accounts, and FTP accounts of a Web Hosting plan. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ResourceSummary ` + + Usage: + :: + + result = await api.get_resource_summary( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/resource-summary", + ) + + self._throw_on_error(res) + return unmarshal_ResourceSummary(res.json()) + + +class WebhostingV1FtpAccountAPI(API): + """ + This API allows you to manage your FTP accounts for your Web Hosting services. + """ + + async def create_ftp_account( + self, + *, + hosting_id: str, + username: str, + path: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> FtpAccount: + """ + Create a new FTP account within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param username: Username for the new FTP account. + :param path: Path for the new FTP account. + :param password: Password for the new FTP account. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`FtpAccount ` + + Usage: + :: + + result = await api.create_ftp_account( + hosting_id="example", + username="example", + path="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/ftp-accounts", + body=marshal_FtpAccountApiCreateFtpAccountRequest( + FtpAccountApiCreateFtpAccountRequest( + hosting_id=hosting_id, + username=username, + path=path, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_FtpAccount(res.json()) + + async def list_ftp_accounts( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListFtpAccountsRequestOrderBy] = None, + domain: Optional[str] = None, + ) -> ListFtpAccountsResponse: + """ + List all FTP accounts within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of FTP accounts to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of FTP accounts in the response. + :param domain: Domain to filter the FTP accounts. + :return: :class:`ListFtpAccountsResponse ` + + Usage: + :: + + result = await api.list_ftp_accounts( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/ftp-accounts", + params={ + "domain": domain, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListFtpAccountsResponse(res.json()) + + async def list_ftp_accounts_all( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListFtpAccountsRequestOrderBy] = None, + domain: Optional[str] = None, + ) -> List[FtpAccount]: + """ + List all FTP accounts within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of FTP accounts to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of FTP accounts in the response. + :param domain: Domain to filter the FTP accounts. + :return: :class:`List[FtpAccount] ` + + Usage: + :: + + result = await api.list_ftp_accounts_all( + hosting_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListFtpAccountsResponse, + key="ftp_accounts", + fetcher=self.list_ftp_accounts, + args={ + "hosting_id": hosting_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "domain": domain, + }, + ) + + async def remove_ftp_account( + self, + *, + hosting_id: str, + username: str, + region: Optional[ScwRegion] = None, + ) -> FtpAccount: + """ + Delete a specific FTP account within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param username: Username of the FTP account to be deleted. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`FtpAccount ` + + Usage: + :: + + result = await api.remove_ftp_account( + hosting_id="example", + username="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_username = validate_path_param("username", username) + + res = self._request( + "DELETE", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/ftp-accounts/{param_username}", + ) + + self._throw_on_error(res) + return unmarshal_FtpAccount(res.json()) + + async def change_ftp_account_password( + self, + *, + hosting_id: str, + username: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> FtpAccount: + """ + :param hosting_id: UUID of the hosting plan. + :param username: Username of the FTP account. + :param password: New password for the FTP account. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`FtpAccount ` + + Usage: + :: + + result = await api.change_ftp_account_password( + hosting_id="example", + username="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_username = validate_path_param("username", username) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/ftp-accounts/{param_username}/change-password", + body=marshal_FtpAccountApiChangeFtpAccountPasswordRequest( + FtpAccountApiChangeFtpAccountPasswordRequest( + hosting_id=hosting_id, + username=username, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_FtpAccount(res.json()) + + +class WebhostingV1MailAccountAPI(API): + """ + This API allows you to manage your mail accounts for your Web Hosting services. + """ + + async def create_mail_account( + self, + *, + hosting_id: str, + domain: str, + username: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> MailAccount: + """ + Create a new mail account within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param domain: Domain part of the mail account address. + :param username: Username part address of the mail account address. + :param password: Password for the new mail account. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`MailAccount ` + + Usage: + :: + + result = await api.create_mail_account( + hosting_id="example", + domain="example", + username="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/mail-accounts", + body=marshal_MailAccountApiCreateMailAccountRequest( + MailAccountApiCreateMailAccountRequest( + hosting_id=hosting_id, + domain=domain, + username=username, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_MailAccount(res.json()) + + async def list_mail_accounts( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListMailAccountsRequestOrderBy] = None, + domain: Optional[str] = None, + ) -> ListMailAccountsResponse: + """ + List all mail accounts within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of mail accounts to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of mail accounts in the response. + :param domain: Domain to filter the mail accounts. + :return: :class:`ListMailAccountsResponse ` + + Usage: + :: + + result = await api.list_mail_accounts( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/mail-accounts", + params={ + "domain": domain, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListMailAccountsResponse(res.json()) + + async def list_mail_accounts_all( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListMailAccountsRequestOrderBy] = None, + domain: Optional[str] = None, + ) -> List[MailAccount]: + """ + List all mail accounts within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of mail accounts to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of mail accounts in the response. + :param domain: Domain to filter the mail accounts. + :return: :class:`List[MailAccount] ` + + Usage: + :: + + result = await api.list_mail_accounts_all( + hosting_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListMailAccountsResponse, + key="mail_accounts", + fetcher=self.list_mail_accounts, + args={ + "hosting_id": hosting_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "domain": domain, + }, + ) + + async def remove_mail_account( + self, + *, + hosting_id: str, + domain: str, + username: str, + region: Optional[ScwRegion] = None, + ) -> MailAccount: + """ + Delete a mail account within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param domain: Domain part of the mail account address. + :param username: Username part of the mail account address. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`MailAccount ` + + Usage: + :: + + result = await api.remove_mail_account( + hosting_id="example", + domain="example", + username="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/remove-mail-account", + body=marshal_MailAccountApiRemoveMailAccountRequest( + MailAccountApiRemoveMailAccountRequest( + hosting_id=hosting_id, + domain=domain, + username=username, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_MailAccount(res.json()) + + async def change_mail_account_password( + self, + *, + hosting_id: str, + domain: str, + username: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> MailAccount: + """ + Update the password of a mail account within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param domain: Domain part of the mail account address. + :param username: Username part of the mail account address. + :param password: New password for the mail account. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`MailAccount ` + + Usage: + :: + + result = await api.change_mail_account_password( + hosting_id="example", + domain="example", + username="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/change-mail-password", + body=marshal_MailAccountApiChangeMailAccountPasswordRequest( + MailAccountApiChangeMailAccountPasswordRequest( + hosting_id=hosting_id, + domain=domain, + username=username, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_MailAccount(res.json()) + + +class WebhostingV1WebsiteAPI(API): + """ + This API allows you to manage your websites for your Web Hosting services. + """ + + async def list_websites( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListWebsitesRequestOrderBy] = None, + ) -> ListWebsitesResponse: + """ + List all websites for a specific hosting. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of websites to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting websites in the response. + :return: :class:`ListWebsitesResponse ` + + Usage: + :: + + result = await api.list_websites( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/websites", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWebsitesResponse(res.json()) + + async def list_websites_all( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListWebsitesRequestOrderBy] = None, + ) -> List[Website]: + """ + List all websites for a specific hosting. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of websites to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting websites in the response. + :return: :class:`List[Website] ` + + Usage: + :: + + result = await api.list_websites_all( + hosting_id="example", + ) + """ + + return await fetch_all_pages_async( + type=ListWebsitesResponse, + key="websites", + fetcher=self.list_websites, + args={ + "hosting_id": hosting_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) diff --git a/scaleway-async/scaleway_async/webhosting/v1/content.py b/scaleway-async/scaleway_async/webhosting/v1/content.py new file mode 100644 index 00000000..9c1b79cf --- /dev/null +++ b/scaleway-async/scaleway_async/webhosting/v1/content.py @@ -0,0 +1,30 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + DomainAvailabilityStatus, + DomainStatus, + HostingStatus, +) + +DOMAIN_AVAILABILITY_TRANSIENT_STATUSES: List[DomainAvailabilityStatus] = [ + DomainAvailabilityStatus.VALIDATING, +] +""" +Lists transient statutes of the enum :class:`DomainAvailabilityStatus `. +""" +DOMAIN_TRANSIENT_STATUSES: List[DomainStatus] = [ + DomainStatus.VALIDATING, +] +""" +Lists transient statutes of the enum :class:`DomainStatus `. +""" +HOSTING_TRANSIENT_STATUSES: List[HostingStatus] = [ + HostingStatus.DELIVERING, + HostingStatus.DELETING, + HostingStatus.MIGRATING, +] +""" +Lists transient statutes of the enum :class:`HostingStatus `. +""" diff --git a/scaleway-async/scaleway_async/webhosting/v1/marshalling.py b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py new file mode 100644 index 00000000..20e51fb2 --- /dev/null +++ b/scaleway-async/scaleway_async/webhosting/v1/marshalling.py @@ -0,0 +1,1391 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + DomainAction, + DomainAvailabilityAction, + DomainDnsAction, + DatabaseUser, + Database, + FtpAccount, + MailAccount, + CheckUserOwnsDomainResponse, + AutoConfigDomainDns, + DnsRecord, + Nameserver, + DnsRecords, + Domain, + PlatformControlPanelUrls, + OfferOption, + PlatformControlPanel, + HostingUser, + Offer, + Platform, + Hosting, + ControlPanel, + ListControlPanelsResponse, + ListDatabaseUsersResponse, + ListDatabasesResponse, + ListFtpAccountsResponse, + HostingSummary, + ListHostingsResponse, + ListMailAccountsResponse, + ListOffersResponse, + Website, + ListWebsitesResponse, + ResetHostingPasswordResponse, + ResourceSummary, + DomainAvailability, + SearchDomainsResponse, + Session, + DatabaseApiAssignDatabaseUserRequest, + DatabaseApiChangeDatabaseUserPasswordRequest, + CreateDatabaseRequestUser, + DatabaseApiCreateDatabaseRequest, + DatabaseApiCreateDatabaseUserRequest, + DatabaseApiUnassignDatabaseUserRequest, + DnsApiCheckUserOwnsDomainRequest, + SyncDomainDnsRecordsRequestRecord, + DnsApiSyncDomainDnsRecordsRequest, + FtpAccountApiChangeFtpAccountPasswordRequest, + FtpAccountApiCreateFtpAccountRequest, + CreateHostingRequestDomainConfiguration, + OfferOptionRequest, + HostingApiCreateHostingRequest, + HostingApiUpdateHostingRequest, + MailAccountApiChangeMailAccountPasswordRequest, + MailAccountApiCreateMailAccountRequest, + MailAccountApiRemoveMailAccountRequest, +) +from ...std.types import ( + LanguageCode as StdLanguageCode, +) + + +def unmarshal_DatabaseUser(data: Any) -> DatabaseUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DatabaseUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("databases", None) + if field is not None: + args["databases"] = field + + return DatabaseUser(**args) + + +def unmarshal_Database(data: Any) -> Database: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Database' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("database_name", None) + if field is not None: + args["database_name"] = field + + field = data.get("users", None) + if field is not None: + args["users"] = field + + return Database(**args) + + +def unmarshal_FtpAccount(data: Any) -> FtpAccount: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'FtpAccount' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("path", None) + if field is not None: + args["path"] = field + + return FtpAccount(**args) + + +def unmarshal_MailAccount(data: Any) -> MailAccount: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'MailAccount' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("username", None) + if field is not None: + args["username"] = field + + return MailAccount(**args) + + +def unmarshal_CheckUserOwnsDomainResponse(data: Any) -> CheckUserOwnsDomainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckUserOwnsDomainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("owns_domain", None) + if field is not None: + args["owns_domain"] = field + + return CheckUserOwnsDomainResponse(**args) + + +def unmarshal_AutoConfigDomainDns(data: Any) -> AutoConfigDomainDns: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AutoConfigDomainDns' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("nameservers", None) + if field is not None: + args["nameservers"] = field + + field = data.get("web_records", None) + if field is not None: + args["web_records"] = field + + field = data.get("mail_records", None) + if field is not None: + args["mail_records"] = field + + field = data.get("all_records", None) + if field is not None: + args["all_records"] = field + + field = data.get("none", None) + if field is not None: + args["none"] = field + + return AutoConfigDomainDns(**args) + + +def unmarshal_DnsRecord(data: Any) -> DnsRecord: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DnsRecord' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("ttl", None) + if field is not None: + args["ttl"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("raw_data", None) + if field is not None: + args["raw_data"] = field + + field = data.get("priority", None) + if field is not None: + args["priority"] = field + else: + args["priority"] = None + + return DnsRecord(**args) + + +def unmarshal_Nameserver(data: Any) -> Nameserver: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Nameserver' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("is_default", None) + if field is not None: + args["is_default"] = field + + return Nameserver(**args) + + +def unmarshal_DnsRecords(data: Any) -> DnsRecords: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DnsRecords' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("records", None) + if field is not None: + args["records"] = ( + [unmarshal_DnsRecord(v) for v in field] if field is not None else None + ) + + field = data.get("name_servers", None) + if field is not None: + args["name_servers"] = ( + [unmarshal_Nameserver(v) for v in field] if field is not None else None + ) + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("dns_config", None) + if field is not None: + args["dns_config"] = ( + [DomainDnsAction(v) for v in field] if field is not None else None + ) + else: + args["dns_config"] = None + + field = data.get("auto_config_domain_dns", None) + if field is not None: + args["auto_config_domain_dns"] = unmarshal_AutoConfigDomainDns(field) + else: + args["auto_config_domain_dns"] = None + + return DnsRecords(**args) + + +def unmarshal_Domain(data: Any) -> Domain: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Domain' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("owner", None) + if field is not None: + args["owner"] = field + + field = data.get("available_actions", None) + if field is not None: + args["available_actions"] = ( + [DomainAction(v) for v in field] if field is not None else None + ) + + field = data.get("available_dns_actions", None) + if field is not None: + args["available_dns_actions"] = ( + [DomainDnsAction(v) for v in field] if field is not None else None + ) + else: + args["available_dns_actions"] = None + + field = data.get("auto_config_domain_dns", None) + if field is not None: + args["auto_config_domain_dns"] = unmarshal_AutoConfigDomainDns(field) + else: + args["auto_config_domain_dns"] = None + + return Domain(**args) + + +def unmarshal_PlatformControlPanelUrls(data: Any) -> PlatformControlPanelUrls: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlatformControlPanelUrls' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dashboard", None) + if field is not None: + args["dashboard"] = field + + field = data.get("webmail", None) + if field is not None: + args["webmail"] = field + + return PlatformControlPanelUrls(**args) + + +def unmarshal_OfferOption(data: Any) -> OfferOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("billing_operation_path", None) + if field is not None: + args["billing_operation_path"] = field + + field = data.get("min_value", None) + if field is not None: + args["min_value"] = field + + field = data.get("current_value", None) + if field is not None: + args["current_value"] = field + + field = data.get("max_value", None) + if field is not None: + args["max_value"] = field + + field = data.get("quota_warning", None) + if field is not None: + args["quota_warning"] = field + + field = data.get("price", None) + if field is not None: + args["price"] = unmarshal_Money(field) + else: + args["price"] = None + + return OfferOption(**args) + + +def unmarshal_PlatformControlPanel(data: Any) -> PlatformControlPanel: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlatformControlPanel' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("urls", None) + if field is not None: + args["urls"] = unmarshal_PlatformControlPanelUrls(field) + else: + args["urls"] = None + + return PlatformControlPanel(**args) + + +def unmarshal_HostingUser(data: Any) -> HostingUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HostingUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("contact_email", None) + if field is not None: + args["contact_email"] = field + + field = data.get("one_time_password", None) + if field is not None: + args["one_time_password"] = field + else: + args["one_time_password"] = None + + field = data.get("one_time_password_b64", None) + if field is not None: + args["one_time_password_b64"] = field + else: + args["one_time_password_b64"] = None + + return HostingUser(**args) + + +def unmarshal_Offer(data: Any) -> Offer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Offer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("billing_operation_path", None) + if field is not None: + args["billing_operation_path"] = field + + field = data.get("options", None) + if field is not None: + args["options"] = ( + [unmarshal_OfferOption(v) for v in field] if field is not None else None + ) + + field = data.get("available", None) + if field is not None: + args["available"] = field + + field = data.get("control_panel_name", None) + if field is not None: + args["control_panel_name"] = field + + field = data.get("end_of_life", None) + if field is not None: + args["end_of_life"] = field + + field = data.get("quota_warning", None) + if field is not None: + args["quota_warning"] = field + + field = data.get("price", None) + if field is not None: + args["price"] = unmarshal_Money(field) + else: + args["price"] = None + + return Offer(**args) + + +def unmarshal_Platform(data: Any) -> Platform: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Platform' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("number", None) + if field is not None: + args["number"] = field + + field = data.get("group_name", None) + if field is not None: + args["group_name"] = field + + field = data.get("ipv4", None) + if field is not None: + args["ipv4"] = field + + field = data.get("ipv6", None) + if field is not None: + args["ipv6"] = field + + field = data.get("control_panel", None) + if field is not None: + args["control_panel"] = unmarshal_PlatformControlPanel(field) + else: + args["control_panel"] = None + + return Platform(**args) + + +def unmarshal_Hosting(data: Any) -> Hosting: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Hosting' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("ipv4", None) + if field is not None: + args["ipv4"] = field + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("protected", None) + if field is not None: + args["protected"] = field + + field = data.get("domain_status", None) + if field is not None: + args["domain_status"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("offer", None) + if field is not None: + args["offer"] = unmarshal_Offer(field) + else: + args["offer"] = None + + field = data.get("platform", None) + if field is not None: + args["platform"] = unmarshal_Platform(field) + else: + args["platform"] = None + + field = data.get("dns_status", None) + if field is not None: + args["dns_status"] = field + else: + args["dns_status"] = None + + field = data.get("user", None) + if field is not None: + args["user"] = unmarshal_HostingUser(field) + else: + args["user"] = None + + return Hosting(**args) + + +def unmarshal_ControlPanel(data: Any) -> ControlPanel: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ControlPanel' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("available", None) + if field is not None: + args["available"] = field + + field = data.get("logo_url", None) + if field is not None: + args["logo_url"] = field + + field = data.get("available_languages", None) + if field is not None: + args["available_languages"] = ( + [StdLanguageCode(v) for v in field] if field is not None else None + ) + + return ControlPanel(**args) + + +def unmarshal_ListControlPanelsResponse(data: Any) -> ListControlPanelsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListControlPanelsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("control_panels", None) + if field is not None: + args["control_panels"] = ( + [unmarshal_ControlPanel(v) for v in field] if field is not None else None + ) + + return ListControlPanelsResponse(**args) + + +def unmarshal_ListDatabaseUsersResponse(data: Any) -> ListDatabaseUsersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDatabaseUsersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("users", None) + if field is not None: + args["users"] = ( + [unmarshal_DatabaseUser(v) for v in field] if field is not None else None + ) + + return ListDatabaseUsersResponse(**args) + + +def unmarshal_ListDatabasesResponse(data: Any) -> ListDatabasesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDatabasesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("databases", None) + if field is not None: + args["databases"] = ( + [unmarshal_Database(v) for v in field] if field is not None else None + ) + + return ListDatabasesResponse(**args) + + +def unmarshal_ListFtpAccountsResponse(data: Any) -> ListFtpAccountsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListFtpAccountsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("ftp_accounts", None) + if field is not None: + args["ftp_accounts"] = ( + [unmarshal_FtpAccount(v) for v in field] if field is not None else None + ) + + return ListFtpAccountsResponse(**args) + + +def unmarshal_HostingSummary(data: Any) -> HostingSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HostingSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("protected", None) + if field is not None: + args["protected"] = field + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("domain_status", None) + if field is not None: + args["domain_status"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("dns_status", None) + if field is not None: + args["dns_status"] = field + else: + args["dns_status"] = None + + return HostingSummary(**args) + + +def unmarshal_ListHostingsResponse(data: Any) -> ListHostingsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListHostingsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("hostings", None) + if field is not None: + args["hostings"] = ( + [unmarshal_HostingSummary(v) for v in field] if field is not None else None + ) + + return ListHostingsResponse(**args) + + +def unmarshal_ListMailAccountsResponse(data: Any) -> ListMailAccountsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListMailAccountsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("mail_accounts", None) + if field is not None: + args["mail_accounts"] = ( + [unmarshal_MailAccount(v) for v in field] if field is not None else None + ) + + return ListMailAccountsResponse(**args) + + +def unmarshal_ListOffersResponse(data: Any) -> ListOffersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOffersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offers", None) + if field is not None: + args["offers"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return ListOffersResponse(**args) + + +def unmarshal_Website(data: Any) -> Website: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Website' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("path", None) + if field is not None: + args["path"] = field + + field = data.get("ssl_status", None) + if field is not None: + args["ssl_status"] = field + + return Website(**args) + + +def unmarshal_ListWebsitesResponse(data: Any) -> ListWebsitesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListWebsitesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("websites", None) + if field is not None: + args["websites"] = ( + [unmarshal_Website(v) for v in field] if field is not None else None + ) + + return ListWebsitesResponse(**args) + + +def unmarshal_ResetHostingPasswordResponse(data: Any) -> ResetHostingPasswordResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ResetHostingPasswordResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("one_time_password_b64", None) + if field is not None: + args["one_time_password_b64"] = field + + field = data.get("one_time_password", None) + if field is not None: + args["one_time_password"] = field + else: + args["one_time_password"] = None + + return ResetHostingPasswordResponse(**args) + + +def unmarshal_ResourceSummary(data: Any) -> ResourceSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ResourceSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("databases_count", None) + if field is not None: + args["databases_count"] = field + + field = data.get("mail_accounts_count", None) + if field is not None: + args["mail_accounts_count"] = field + + field = data.get("ftp_accounts_count", None) + if field is not None: + args["ftp_accounts_count"] = field + + field = data.get("websites_count", None) + if field is not None: + args["websites_count"] = field + + return ResourceSummary(**args) + + +def unmarshal_DomainAvailability(data: Any) -> DomainAvailability: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DomainAvailability' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("zone_name", None) + if field is not None: + args["zone_name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("available_actions", None) + if field is not None: + args["available_actions"] = ( + [DomainAvailabilityAction(v) for v in field] if field is not None else None + ) + + field = data.get("can_create_hosting", None) + if field is not None: + args["can_create_hosting"] = field + + field = data.get("price", None) + if field is not None: + args["price"] = unmarshal_Money(field) + else: + args["price"] = None + + return DomainAvailability(**args) + + +def unmarshal_SearchDomainsResponse(data: Any) -> SearchDomainsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SearchDomainsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("domains_available", None) + if field is not None: + args["domains_available"] = ( + [unmarshal_DomainAvailability(v) for v in field] + if field is not None + else None + ) + + return SearchDomainsResponse(**args) + + +def unmarshal_Session(data: Any) -> Session: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Session' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("url", None) + if field is not None: + args["url"] = field + + return Session(**args) + + +def marshal_DatabaseApiAssignDatabaseUserRequest( + request: DatabaseApiAssignDatabaseUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + return output + + +def marshal_DatabaseApiChangeDatabaseUserPasswordRequest( + request: DatabaseApiChangeDatabaseUserPasswordRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_CreateDatabaseRequestUser( + request: CreateDatabaseRequestUser, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_DatabaseApiCreateDatabaseRequest( + request: DatabaseApiCreateDatabaseRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("new_user", request.new_user), + OneOfPossibility("existing_username", request.existing_username), + ] + ), + ) + + if request.database_name is not None: + output["database_name"] = request.database_name + + return output + + +def marshal_DatabaseApiCreateDatabaseUserRequest( + request: DatabaseApiCreateDatabaseUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_DatabaseApiUnassignDatabaseUserRequest( + request: DatabaseApiUnassignDatabaseUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + return output + + +def marshal_DnsApiCheckUserOwnsDomainRequest( + request: DnsApiCheckUserOwnsDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_AutoConfigDomainDns( + request: AutoConfigDomainDns, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.nameservers is not None: + output["nameservers"] = request.nameservers + + if request.web_records is not None: + output["web_records"] = request.web_records + + if request.mail_records is not None: + output["mail_records"] = request.mail_records + + if request.all_records is not None: + output["all_records"] = request.all_records + + if request.none is not None: + output["none"] = request.none + + return output + + +def marshal_SyncDomainDnsRecordsRequestRecord( + request: SyncDomainDnsRecordsRequestRecord, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.type_ is not None: + output["type"] = str(request.type_) + + return output + + +def marshal_DnsApiSyncDomainDnsRecordsRequest( + request: DnsApiSyncDomainDnsRecordsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.update_web_records is not None: + output["update_web_records"] = request.update_web_records + + if request.update_mail_records is not None: + output["update_mail_records"] = request.update_mail_records + + if request.update_all_records is not None: + output["update_all_records"] = request.update_all_records + + if request.update_nameservers is not None: + output["update_nameservers"] = request.update_nameservers + + if request.custom_records is not None: + output["custom_records"] = [ + marshal_SyncDomainDnsRecordsRequestRecord(item, defaults) + for item in request.custom_records + ] + + if request.auto_config_domain_dns is not None: + output["auto_config_domain_dns"] = marshal_AutoConfigDomainDns( + request.auto_config_domain_dns, defaults + ) + + return output + + +def marshal_FtpAccountApiChangeFtpAccountPasswordRequest( + request: FtpAccountApiChangeFtpAccountPasswordRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_FtpAccountApiCreateFtpAccountRequest( + request: FtpAccountApiCreateFtpAccountRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + if request.path is not None: + output["path"] = request.path + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_CreateHostingRequestDomainConfiguration( + request: CreateHostingRequestDomainConfiguration, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.update_nameservers is not None: + output["update_nameservers"] = request.update_nameservers + + if request.update_web_record is not None: + output["update_web_record"] = request.update_web_record + + if request.update_mail_record is not None: + output["update_mail_record"] = request.update_mail_record + + if request.update_all_records is not None: + output["update_all_records"] = request.update_all_records + + return output + + +def marshal_OfferOptionRequest( + request: OfferOptionRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.id is not None: + output["id"] = request.id + + if request.quantity is not None: + output["quantity"] = request.quantity + + return output + + +def marshal_HostingApiCreateHostingRequest( + request: HostingApiCreateHostingRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.email is not None: + output["email"] = request.email + + if request.domain is not None: + output["domain"] = request.domain + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.offer_options is not None: + output["offer_options"] = [ + marshal_OfferOptionRequest(item, defaults) for item in request.offer_options + ] + + if request.language is not None: + output["language"] = str(request.language) + + if request.domain_configuration is not None: + output["domain_configuration"] = ( + marshal_CreateHostingRequestDomainConfiguration( + request.domain_configuration, defaults + ) + ) + + if request.skip_welcome_email is not None: + output["skip_welcome_email"] = request.skip_welcome_email + + if request.auto_config_domain_dns is not None: + output["auto_config_domain_dns"] = marshal_AutoConfigDomainDns( + request.auto_config_domain_dns, defaults + ) + + return output + + +def marshal_HostingApiUpdateHostingRequest( + request: HostingApiUpdateHostingRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.email is not None: + output["email"] = request.email + + if request.tags is not None: + output["tags"] = request.tags + + if request.offer_options is not None: + output["offer_options"] = [ + marshal_OfferOptionRequest(item, defaults) for item in request.offer_options + ] + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.protected is not None: + output["protected"] = request.protected + + return output + + +def marshal_MailAccountApiChangeMailAccountPasswordRequest( + request: MailAccountApiChangeMailAccountPasswordRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain is not None: + output["domain"] = request.domain + + if request.username is not None: + output["username"] = request.username + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_MailAccountApiCreateMailAccountRequest( + request: MailAccountApiCreateMailAccountRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain is not None: + output["domain"] = request.domain + + if request.username is not None: + output["username"] = request.username + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_MailAccountApiRemoveMailAccountRequest( + request: MailAccountApiRemoveMailAccountRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain is not None: + output["domain"] = request.domain + + if request.username is not None: + output["username"] = request.username + + return output diff --git a/scaleway-async/scaleway_async/webhosting/v1/types.py b/scaleway-async/scaleway_async/webhosting/v1/types.py new file mode 100644 index 00000000..8abd971c --- /dev/null +++ b/scaleway-async/scaleway_async/webhosting/v1/types.py @@ -0,0 +1,1872 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Money, + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + +from ...std.types import ( + LanguageCode as StdLanguageCode, +) + + +class DnsRecordStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + VALID = "valid" + INVALID = "invalid" + + def __str__(self) -> str: + return str(self.value) + + +class DnsRecordType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + A = "a" + CNAME = "cname" + MX = "mx" + TXT = "txt" + NS = "ns" + AAAA = "aaaa" + + def __str__(self) -> str: + return str(self.value) + + +class DnsRecordsStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + VALID = "valid" + INVALID = "invalid" + + def __str__(self) -> str: + return str(self.value) + + +class DomainAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + TRANSFER = "transfer" + MANAGE_EXTERNAL = "manage_external" + RENEW = "renew" + + def __str__(self) -> str: + return str(self.value) + + +class DomainAvailabilityAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + REGISTER = "register" + TRANSFER = "transfer" + MANAGE_EXTERNAL = "manage_external" + + def __str__(self) -> str: + return str(self.value) + + +class DomainAvailabilityStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + AVAILABLE = "available" + NOT_AVAILABLE = "not_available" + OWNED = "owned" + VALIDATING = "validating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class DomainDnsAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_DNS_ACTION = "unknown_dns_action" + AUTO_CONFIG_ALL_RECORDS = "auto_config_all_records" + AUTO_CONFIG_WEB_RECORDS = "auto_config_web_records" + AUTO_CONFIG_MAIL_RECORDS = "auto_config_mail_records" + AUTO_CONFIG_NAMESERVERS = "auto_config_nameservers" + AUTO_CONFIG_NONE = "auto_config_none" + + def __str__(self) -> str: + return str(self.value) + + +class DomainStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + VALID = "valid" + INVALID = "invalid" + VALIDATING = "validating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class DomainZoneOwner(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ZONE_OWNER = "unknown_zone_owner" + EXTERNAL = "external" + SCALEWAY = "scaleway" + ONLINE = "online" + WEBHOSTING = "webhosting" + + def __str__(self) -> str: + return str(self.value) + + +class HostingStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DELIVERING = "delivering" + READY = "ready" + DELETING = "deleting" + ERROR = "error" + LOCKED = "locked" + MIGRATING = "migrating" + + def __str__(self) -> str: + return str(self.value) + + +class ListDatabaseUsersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + USERNAME_ASC = "username_asc" + USERNAME_DESC = "username_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListDatabasesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + DATABASE_NAME_ASC = "database_name_asc" + DATABASE_NAME_DESC = "database_name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListFtpAccountsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + USERNAME_ASC = "username_asc" + USERNAME_DESC = "username_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListHostingsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListMailAccountsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + USERNAME_ASC = "username_asc" + USERNAME_DESC = "username_desc" + DOMAIN_ASC = "domain_asc" + DOMAIN_DESC = "domain_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListOffersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + PRICE_ASC = "price_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ListWebsitesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + DOMAIN_ASC = "domain_asc" + DOMAIN_DESC = "domain_desc" + + def __str__(self) -> str: + return str(self.value) + + +class NameserverStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + VALID = "valid" + INVALID = "invalid" + + def __str__(self) -> str: + return str(self.value) + + +class OfferOptionName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + DOMAIN_COUNT = "domain_count" + EMAIL_COUNT = "email_count" + STORAGE_GB = "storage_gb" + VCPU_COUNT = "vcpu_count" + RAM_GB = "ram_gb" + BACKUP = "backup" + DEDICATED_IP = "dedicated_ip" + EMAIL_STORAGE_GB = "email_storage_gb" + DATABASE_COUNT = "database_count" + SUPPORT = "support" + + def __str__(self) -> str: + return str(self.value) + + +class OfferOptionWarning(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_WARNING = "unknown_warning" + QUOTA_EXCEEDED_WARNING = "quota_exceeded_warning" + USAGE_LOW_WARNING = "usage_low_warning" + + def __str__(self) -> str: + return str(self.value) + + +class PlatformPlatformGroup(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_GROUP = "unknown_group" + DEFAULT = "default" + PREMIUM = "premium" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class PlatformControlPanelUrls: + dashboard: str + """ + URL to connect to the hosting control panel dashboard. + """ + + webmail: str + """ + URL to connect to the hosting Webmail interface. + """ + + +@dataclass +class OfferOption: + id: str + """ + Option ID. + """ + + name: OfferOptionName + """ + Name of the option. + """ + + billing_operation_path: str + """ + Unique identifier used for billing. + """ + + min_value: int + """ + Minimum value for the option in the offer. + """ + + current_value: int + """ + If a hosting_id was specified in the call, defines the current value of the option in the hosting. + """ + + max_value: int + """ + Maximum value for the option in the offer. + """ + + quota_warning: OfferOptionWarning + """ + Defines a warning if the maximum value for the option has been reached. + """ + + price: Optional[Money] + """ + Price of the option for 1 value. + """ + + +@dataclass +class PlatformControlPanel: + name: str + """ + Name of the control panel. + """ + + urls: Optional[PlatformControlPanelUrls] + """ + URL to connect to control panel dashboard and to Webmail interface. + """ + + +@dataclass +class CreateDatabaseRequestUser: + username: str + + password: str + + +@dataclass +class AutoConfigDomainDns: + nameservers: bool + """ + Whether or not to synchronize domain nameservers. + """ + + web_records: bool + """ + Whether or not to synchronize web records. + """ + + mail_records: bool + """ + Whether or not to synchronize mail records. + """ + + all_records: bool + """ + Whether or not to synchronize all types of records. Takes priority over the other fields. + """ + + none: bool + """ + No automatic domain configuration. Users must configure their domain for the Web Hosting to work. + """ + + +@dataclass +class CreateHostingRequestDomainConfiguration: + update_nameservers: bool + + update_web_record: bool + + update_mail_record: bool + + update_all_records: bool + + +@dataclass +class OfferOptionRequest: + id: str + """ + Offer option ID. + """ + + quantity: int + """ + The option requested quantity to set for the Web Hosting plan. + """ + + +@dataclass +class SyncDomainDnsRecordsRequestRecord: + name: str + + type_: DnsRecordType + + +@dataclass +class DnsRecord: + name: str + """ + Record name. + """ + + type_: DnsRecordType + """ + Record type. + """ + + ttl: int + """ + Record time-to-live. + """ + + value: str + """ + Record value. + """ + + status: DnsRecordStatus + """ + Record status. + """ + + raw_data: str + """ + Record representation as it appears in the zone file or DNS management system. + """ + + priority: Optional[int] + """ + Record priority level. + """ + + +@dataclass +class Nameserver: + hostname: str + """ + Hostname of the nameserver. + """ + + status: NameserverStatus + """ + Status of the nameserver. + """ + + is_default: bool + """ + Defines whether the nameserver is the default one. + """ + + +@dataclass +class HostingUser: + username: str + """ + Main Web Hosting control panel username. + """ + + contact_email: str + """ + Contact email used for the hosting. + """ + + one_time_password: Optional[str] + """ + One-time-password used for the first login to the control panel, cleared after first use (deprecated, use password_b64 instead). + """ + + one_time_password_b64: Optional[str] + """ + One-time-password used for the first login to the control panel, cleared after first use, encoded in base64. + """ + + +@dataclass +class Offer: + id: str + """ + Offer ID. + """ + + name: str + """ + Offer name. + """ + + billing_operation_path: str + """ + Unique identifier used for billing. + """ + + options: List[OfferOption] + """ + Options available for the offer. + """ + + available: bool + """ + If a hosting_id was specified in the call, defines whether the offer is available for a specified hosting plan to migrate (update) to. + """ + + control_panel_name: str + """ + Name of the control panel. + """ + + end_of_life: bool + """ + Indicates if the offer has reached its end of life. + """ + + quota_warning: OfferOptionWarning + """ + Defines a warning if the maximum value for an option in the offer is exceeded. + """ + + price: Optional[Money] + """ + Price of the offer. + """ + + +@dataclass +class Platform: + hostname: str + """ + Hostname of the host platform. + """ + + number: int + """ + Number of the host platform. + """ + + group_name: PlatformPlatformGroup + """ + Group name of the hosting's host platform. + """ + + ipv4: str + """ + IPv4 address of the hosting's host platform. + """ + + ipv6: str + """ + IPv6 address of the hosting's host platform. + """ + + control_panel: Optional[PlatformControlPanel] + """ + Details of the platform control panel. + """ + + +@dataclass +class ControlPanel: + name: str + """ + Control panel name. + """ + + available: bool + """ + Define if the control panel type is available to order. + """ + + logo_url: str + """ + URL of the control panel's logo. + """ + + available_languages: List[StdLanguageCode] + """ + List of available languages for the control panel. + """ + + +@dataclass +class DatabaseUser: + username: str + """ + Name of the database user. + """ + + databases: List[str] + """ + List of databases accessible by the user. + """ + + +@dataclass +class Database: + database_name: str + """ + Name of the database. + """ + + users: List[str] + """ + List of users who have access to the database. + """ + + +@dataclass +class FtpAccount: + username: str + """ + The username of the FTP account. + """ + + path: str + """ + The path associated with the FTP account. + """ + + +@dataclass +class HostingSummary: + id: str + """ + ID of the Web Hosting plan. + """ + + project_id: str + """ + ID of the Scaleway Project the Web Hosting plan belongs to. + """ + + status: HostingStatus + """ + Status of the Web Hosting plan. + """ + + domain: str + """ + Main domain associated with the Web Hosting plan. + """ + + protected: bool + """ + Whether the hosting is protected or not. + """ + + offer_name: str + """ + Name of the active offer for the Web Hosting plan. + """ + + domain_status: DomainStatus + """ + Main domain status of the Web Hosting plan. + """ + + region: ScwRegion + """ + Region where the Web Hosting plan is hosted. + """ + + created_at: Optional[datetime] + """ + Date on which the Web Hosting plan was created. + """ + + updated_at: Optional[datetime] + """ + Date on which the Web Hosting plan was last updated. + """ + + dns_status: Optional[DnsRecordsStatus] + """ + DNS status of the Web Hosting plan. + """ + + +@dataclass +class MailAccount: + domain: str + """ + Domain part of the mail account address. + """ + + username: str + """ + Username part address of the mail account address. + """ + + +@dataclass +class Website: + domain: str + """ + The domain of the website. + """ + + path: str + """ + The directory path of the website. + """ + + ssl_status: bool + """ + The SSL status of the website. + """ + + +@dataclass +class DomainAvailability: + name: str + """ + Fully qualified domain name (FQDN). + """ + + zone_name: str + """ + DNS zone associated with the domain. + """ + + status: DomainAvailabilityStatus + """ + Availability status of the domain. + """ + + available_actions: List[DomainAvailabilityAction] + """ + A list of actions that can be performed on the domain. + """ + + can_create_hosting: bool + """ + Whether a hosting can be created for this domain. + """ + + price: Optional[Money] + """ + Price for registering the domain. + """ + + +@dataclass +class CheckUserOwnsDomainResponse: + owns_domain: bool + """ + Indicates whether the specified project owns the domain. + """ + + +@dataclass +class ControlPanelApiListControlPanelsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of control panels to return (must be a positive integer lower or equal to 100). + """ + + +@dataclass +class DatabaseApiAssignDatabaseUserRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the user to assign. + """ + + database_name: str + """ + Name of the database to be assigned. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiChangeDatabaseUserPasswordRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the user to update. + """ + + password: str + """ + New password. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiCreateDatabaseRequest: + hosting_id: str + """ + UUID of the hosting plan where the database will be created. + """ + + database_name: str + """ + Name of the database to be created. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + new_user: Optional[CreateDatabaseRequestUser] + + existing_username: Optional[str] + + +@dataclass +class DatabaseApiCreateDatabaseUserRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the user to create. + """ + + password: str + """ + Password of the user to create. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiDeleteDatabaseRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + database_name: str + """ + Name of the database to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiDeleteDatabaseUserRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the database user to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiGetDatabaseRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + database_name: str + """ + Name of the database. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiGetDatabaseUserRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the database user to retrieve details. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiListDatabaseUsersRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of database users to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListDatabaseUsersRequestOrderBy] + """ + Sort order of database users in the response. + """ + + +@dataclass +class DatabaseApiListDatabasesRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of databases to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListDatabasesRequestOrderBy] + """ + Sort order of databases in the response. + """ + + +@dataclass +class DatabaseApiUnassignDatabaseUserRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the user to unassign. + """ + + database_name: str + """ + Name of the database to be unassigned. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DnsApiCheckUserOwnsDomainRequest: + domain: str + """ + Domain for which ownership is to be verified. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project currently in use. + """ + + +@dataclass +class DnsApiGetDomainDnsRecordsRequest: + domain: str + """ + Domain associated with the DNS records. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DnsApiGetDomainRequest: + domain_name: str + """ + Domain name to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + """ + + +@dataclass +class DnsApiSearchDomainsRequest: + domain_name: str + """ + Domain name to search. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Scaleway Project in which to search the domain to create the Web Hosting plan. + """ + + +@dataclass +class DnsApiSyncDomainDnsRecordsRequest: + domain: str + """ + Domain for which the DNS records will be synchronized. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + update_web_records: Optional[bool] + """ + Whether or not to synchronize the web records (deprecated, use auto_config_domain_dns). + """ + + update_mail_records: Optional[bool] + """ + Whether or not to synchronize the mail records (deprecated, use auto_config_domain_dns). + """ + + update_all_records: Optional[bool] + """ + Whether or not to synchronize all types of records. This one has priority (deprecated, use auto_config_domain_dns). + """ + + update_nameservers: Optional[bool] + """ + Whether or not to synchronize domain nameservers (deprecated, use auto_config_domain_dns). + """ + + custom_records: Optional[List[SyncDomainDnsRecordsRequestRecord]] + """ + Custom records to synchronize. + """ + + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Whether or not to synchronize each types of records. + """ + + +@dataclass +class DnsRecords: + records: List[DnsRecord] + """ + List of DNS records. + """ + + name_servers: List[Nameserver] + """ + List of nameservers. + """ + + status: DnsRecordsStatus + """ + Status of the records. + """ + + dns_config: Optional[List[DomainDnsAction]] + """ + Records dns auto configuration settings (deprecated, use auto_config_domain_dns). + """ + + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Whether or not to synchronize each types of records. + """ + + +@dataclass +class Domain: + name: str + """ + Name of the domain. + """ + + status: DomainStatus + """ + Current status of the domain. + """ + + owner: DomainZoneOwner + """ + Zone owner of the domain. + """ + + available_actions: List[DomainAction] + """ + A list of actions that can be performed on the domain. + """ + + available_dns_actions: Optional[List[DomainDnsAction]] + """ + A list of DNS-related actions that can be auto configured for the domain (deprecated, use auto_config_domain_dns instead). + """ + + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Whether or not to synchronize each type of record. + """ + + +@dataclass +class FtpAccountApiChangeFtpAccountPasswordRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Username of the FTP account. + """ + + password: str + """ + New password for the FTP account. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class FtpAccountApiCreateFtpAccountRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Username for the new FTP account. + """ + + path: str + """ + Path for the new FTP account. + """ + + password: str + """ + Password for the new FTP account. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class FtpAccountApiListFtpAccountsRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of FTP accounts to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListFtpAccountsRequestOrderBy] + """ + Sort order of FTP accounts in the response. + """ + + domain: Optional[str] + """ + Domain to filter the FTP accounts. + """ + + +@dataclass +class FtpAccountApiRemoveFtpAccountRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Username of the FTP account to be deleted. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class Hosting: + id: str + """ + ID of the Web Hosting plan. + """ + + project_id: str + """ + ID of the Scaleway Project the Web Hosting plan belongs to. + """ + + status: HostingStatus + """ + Status of the Web Hosting plan. + """ + + domain: str + """ + Main domain associated with the Web Hosting plan. + """ + + tags: List[str] + """ + List of tags associated with the Web Hosting plan. + """ + + ipv4: str + """ + Current IPv4 address of the hosting. + """ + + updated_at: Optional[datetime] + """ + Date on which the Web Hosting plan was last updated. + """ + + created_at: Optional[datetime] + """ + Date on which the Web Hosting plan was created. + """ + + protected: bool + """ + Whether the hosting is protected or not. + """ + + domain_status: DomainStatus + """ + Main domain status of the Web Hosting plan. + """ + + region: ScwRegion + """ + Region where the Web Hosting plan is hosted. + """ + + offer: Optional[Offer] + """ + Details of the Web Hosting plan offer and options. + """ + + platform: Optional[Platform] + """ + Details of the hosting platform. + """ + + dns_status: Optional[DnsRecordsStatus] + """ + DNS status of the Web Hosting plan. + """ + + user: Optional[HostingUser] + """ + Details of the hosting user. + """ + + +@dataclass +class HostingApiCreateHostingRequest: + offer_id: str + """ + ID of the selected offer for the Web Hosting plan. + """ + + email: str + """ + Contact email for the Web Hosting client. + """ + + domain: str + """ + Domain name to link to the Web Hosting plan. You must already own this domain name, and have completed the DNS validation process beforehand. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Scaleway Project in which to create the Web Hosting plan. + """ + + tags: Optional[List[str]] + """ + List of tags for the Web Hosting plan. + """ + + offer_options: Optional[List[OfferOptionRequest]] + """ + List of the Web Hosting plan options IDs with their quantities. + """ + + language: Optional[StdLanguageCode] + """ + Default language for the control panel interface. + """ + + domain_configuration: Optional[CreateHostingRequestDomainConfiguration] + """ + Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_config_domain_dns instead). + """ + + skip_welcome_email: Optional[bool] + """ + Indicates whether to skip a welcome email to the contact email containing hosting info. + """ + + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_update_* fields instead). + """ + + +@dataclass +class HostingApiCreateSessionRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class HostingApiDeleteHostingRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class HostingApiGetHostingRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class HostingApiGetResourceSummaryRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class HostingApiListHostingsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of Web Hosting plans to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListHostingsRequestOrderBy] + """ + Sort order for Web Hosting plans in the response. + """ + + tags: Optional[List[str]] + """ + Tags to filter for, only Web Hosting plans with matching tags will be returned. + """ + + statuses: Optional[List[HostingStatus]] + """ + Statuses to filter for, only Web Hosting plans with matching statuses will be returned. + """ + + domain: Optional[str] + """ + Domain to filter for, only Web Hosting plans associated with this domain will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only Web Hosting plans from this Project will be returned. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for, only Web Hosting plans from this Organization will be returned. + """ + + control_panels: Optional[List[str]] + """ + Name of the control panel to filter for, only Web Hosting plans from this control panel will be returned. + """ + + +@dataclass +class HostingApiResetHostingPasswordRequest: + hosting_id: str + """ + UUID of the hosting. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class HostingApiUpdateHostingRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + email: Optional[str] + """ + New contact email for the Web Hosting plan. + """ + + tags: Optional[List[str]] + """ + New tags for the Web Hosting plan. + """ + + offer_options: Optional[List[OfferOptionRequest]] + """ + List of the Web Hosting plan options IDs with their quantities. + """ + + offer_id: Optional[str] + """ + ID of the new offer for the Web Hosting plan. + """ + + protected: Optional[bool] + """ + Whether the hosting is protected or not. + """ + + +@dataclass +class ListControlPanelsResponse: + total_count: int + """ + Number of control panels returned. + """ + + control_panels: List[ControlPanel] + """ + List of control panels. + """ + + +@dataclass +class ListDatabaseUsersResponse: + total_count: int + """ + Total number of database users. + """ + + users: List[DatabaseUser] + """ + List of database users. + """ + + +@dataclass +class ListDatabasesResponse: + total_count: int + """ + Total number of databases. + """ + + databases: List[Database] + """ + List of databases. + """ + + +@dataclass +class ListFtpAccountsResponse: + total_count: int + """ + Total number of FTP accounts. + """ + + ftp_accounts: List[FtpAccount] + """ + List of FTP accounts. + """ + + +@dataclass +class ListHostingsResponse: + total_count: int + """ + Number of Web Hosting plans returned. + """ + + hostings: List[HostingSummary] + """ + List of Web Hosting plans. + """ + + +@dataclass +class ListMailAccountsResponse: + total_count: int + """ + Total number of mail accounts. + """ + + mail_accounts: List[MailAccount] + """ + List of mail accounts. + """ + + +@dataclass +class ListOffersResponse: + total_count: int + """ + Total number of offers. + """ + + offers: List[Offer] + """ + List of offers. + """ + + +@dataclass +class ListWebsitesResponse: + total_count: int + """ + Total number of websites. + """ + + websites: List[Website] + """ + List of websites. + """ + + +@dataclass +class MailAccountApiChangeMailAccountPasswordRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + domain: str + """ + Domain part of the mail account address. + """ + + username: str + """ + Username part of the mail account address. + """ + + password: str + """ + New password for the mail account. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class MailAccountApiCreateMailAccountRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + domain: str + """ + Domain part of the mail account address. + """ + + username: str + """ + Username part address of the mail account address. + """ + + password: str + """ + Password for the new mail account. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class MailAccountApiListMailAccountsRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of mail accounts to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListMailAccountsRequestOrderBy] + """ + Sort order of mail accounts in the response. + """ + + domain: Optional[str] + """ + Domain to filter the mail accounts. + """ + + +@dataclass +class MailAccountApiRemoveMailAccountRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + domain: str + """ + Domain part of the mail account address. + """ + + username: str + """ + Username part of the mail account address. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class OfferApiListOffersRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of websites to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListOffersRequestOrderBy] + """ + Sort order for Web Hosting offers in the response. + """ + + hosting_id: Optional[str] + """ + UUID of the hosting plan. + """ + + control_panels: Optional[List[str]] + """ + Name of the control panel(s) to filter for. + """ + + +@dataclass +class ResetHostingPasswordResponse: + one_time_password_b64: str + """ + New temporary password, encoded in base64. + """ + + one_time_password: Optional[str] + """ + New temporary password (deprecated, use password_b64 instead). + """ + + +@dataclass +class ResourceSummary: + databases_count: int + """ + Total number of active databases in the Web Hosting plan. + """ + + mail_accounts_count: int + """ + Total number of active email accounts in the Web Hosting plan. + """ + + ftp_accounts_count: int + """ + Total number of active FTP accounts in the Web Hosting plan. + """ + + websites_count: int + """ + Total number of active domains in the Web Hosting plan. + """ + + +@dataclass +class SearchDomainsResponse: + domains_available: List[DomainAvailability] + """ + List of domains availability. + """ + + +@dataclass +class Session: + url: str + """ + Logged user's session URL. + """ + + +@dataclass +class WebsiteApiListWebsitesRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of websites to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListWebsitesRequestOrderBy] + """ + Sort order for Web Hosting websites in the response. + """ diff --git a/scaleway-async/scaleway_async/webhosting/v1alpha1/__init__.py b/scaleway-async/scaleway_async/webhosting/v1alpha1/__init__.py index 09a3260e..2384d374 100644 --- a/scaleway-async/scaleway_async/webhosting/v1alpha1/__init__.py +++ b/scaleway-async/scaleway_async/webhosting/v1alpha1/__init__.py @@ -12,14 +12,24 @@ from .types import OfferQuotaWarning from .types import HostingCpanelUrls from .types import HostingOption +from .types import EmailAddress from .types import OfferProduct from .types import CreateHostingRequestDomainConfiguration from .types import DnsRecord from .types import Nameserver from .types import ControlPanel from .types import Hosting +from .types import Mailbox from .types import Offer +from .types import CheckUserOwnsDomainRequest +from .types import CheckUserOwnsDomainResponse +from .types import ClassicMailApiCreateMailboxRequest +from .types import ClassicMailApiDeleteMailboxRequest +from .types import ClassicMailApiGetMailboxRequest +from .types import ClassicMailApiListMailboxesRequest +from .types import ClassicMailApiUpdateMailboxRequest from .types import CreateHostingRequest +from .types import CreateSessionRequest from .types import DeleteHostingRequest from .types import DnsRecords from .types import GetDomainDnsRecordsRequest @@ -28,11 +38,16 @@ from .types import ListControlPanelsResponse from .types import ListHostingsRequest from .types import ListHostingsResponse +from .types import ListMailboxesResponse from .types import ListOffersRequest from .types import ListOffersResponse +from .types import ResetHostingPasswordRequest +from .types import ResetHostingPasswordResponse from .types import RestoreHostingRequest +from .types import Session from .types import UpdateHostingRequest from .api import WebhostingV1Alpha1API +from .api import WebhostingV1Alpha1ClassicMailAPI __all__ = [ "DnsRecordStatus", @@ -47,14 +62,24 @@ "OfferQuotaWarning", "HostingCpanelUrls", "HostingOption", + "EmailAddress", "OfferProduct", "CreateHostingRequestDomainConfiguration", "DnsRecord", "Nameserver", "ControlPanel", "Hosting", + "Mailbox", "Offer", + "CheckUserOwnsDomainRequest", + "CheckUserOwnsDomainResponse", + "ClassicMailApiCreateMailboxRequest", + "ClassicMailApiDeleteMailboxRequest", + "ClassicMailApiGetMailboxRequest", + "ClassicMailApiListMailboxesRequest", + "ClassicMailApiUpdateMailboxRequest", "CreateHostingRequest", + "CreateSessionRequest", "DeleteHostingRequest", "DnsRecords", "GetDomainDnsRecordsRequest", @@ -63,9 +88,14 @@ "ListControlPanelsResponse", "ListHostingsRequest", "ListHostingsResponse", + "ListMailboxesResponse", "ListOffersRequest", "ListOffersResponse", + "ResetHostingPasswordRequest", + "ResetHostingPasswordResponse", "RestoreHostingRequest", + "Session", "UpdateHostingRequest", "WebhostingV1Alpha1API", + "WebhostingV1Alpha1ClassicMailAPI", ] diff --git a/scaleway-async/scaleway_async/webhosting/v1alpha1/api.py b/scaleway-async/scaleway_async/webhosting/v1alpha1/api.py index 0874850b..c9d4de46 100644 --- a/scaleway-async/scaleway_async/webhosting/v1alpha1/api.py +++ b/scaleway-async/scaleway_async/webhosting/v1alpha1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( WaitForOptions, @@ -17,14 +17,23 @@ HostingStatus, ListHostingsRequestOrderBy, ListOffersRequestOrderBy, + CheckUserOwnsDomainRequest, + CheckUserOwnsDomainResponse, + ClassicMailApiCreateMailboxRequest, + ClassicMailApiUpdateMailboxRequest, ControlPanel, CreateHostingRequest, CreateHostingRequestDomainConfiguration, DnsRecords, + EmailAddress, Hosting, ListControlPanelsResponse, ListHostingsResponse, + ListMailboxesResponse, ListOffersResponse, + Mailbox, + ResetHostingPasswordResponse, + Session, UpdateHostingRequest, ) from .content import ( @@ -32,10 +41,18 @@ ) from .marshalling import ( unmarshal_Hosting, + unmarshal_Mailbox, + unmarshal_CheckUserOwnsDomainResponse, unmarshal_DnsRecords, unmarshal_ListControlPanelsResponse, unmarshal_ListHostingsResponse, + unmarshal_ListMailboxesResponse, unmarshal_ListOffersResponse, + unmarshal_ResetHostingPasswordResponse, + unmarshal_Session, + marshal_CheckUserOwnsDomainRequest, + marshal_ClassicMailApiCreateMailboxRequest, + marshal_ClassicMailApiUpdateMailboxRequest, marshal_CreateHostingRequest, marshal_UpdateHostingRequest, ) @@ -46,7 +63,7 @@ class WebhostingV1Alpha1API(API): """ - Web Hosting API. + This API allows you to manage your Web Hosting services. """ async def create_hosting( @@ -54,7 +71,7 @@ async def create_hosting( *, offer_id: str, domain: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, email: Optional[str] = None, tags: Optional[List[str]] = None, @@ -114,7 +131,7 @@ async def create_hosting( async def list_hostings( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListHostingsRequestOrderBy] = None, @@ -173,7 +190,7 @@ async def list_hostings( async def list_hostings_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListHostingsRequestOrderBy] = None, @@ -227,7 +244,7 @@ async def get_hosting( self, *, hosting_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hosting: """ Get a Web Hosting plan. @@ -261,7 +278,7 @@ async def wait_for_hosting( self, *, hosting_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Hosting, Union[bool, Awaitable[bool]]]] = None, ) -> Hosting: """ @@ -298,7 +315,7 @@ async def update_hosting( self, *, hosting_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, email: Optional[str] = None, tags: Optional[List[str]] = None, option_ids: Optional[List[str]] = None, @@ -354,7 +371,7 @@ async def delete_hosting( self, *, hosting_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hosting: """ Delete a Web Hosting plan. @@ -388,7 +405,7 @@ async def restore_hosting( self, *, hosting_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hosting: """ Restore a Web Hosting plan. @@ -423,7 +440,7 @@ async def get_domain_dns_records( self, *, domain: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DnsRecords: """ Get DNS records. @@ -453,12 +470,55 @@ async def get_domain_dns_records( self._throw_on_error(res) return unmarshal_DnsRecords(res.json()) + async def check_user_owns_domain( + self, + *, + domain: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> CheckUserOwnsDomainResponse: + """ + "Check whether you own this domain or not.". + :param domain: Domain for which ownership is to be verified. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project currently in use. + :return: :class:`CheckUserOwnsDomainResponse ` + + Usage: + :: + + result = await api.check_user_owns_domain( + domain="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain = validate_path_param("domain", domain) + + res = self._request( + "POST", + f"/webhosting/v1alpha1/regions/{param_region}/domains/{param_domain}/check-ownership", + body=marshal_CheckUserOwnsDomainRequest( + CheckUserOwnsDomainRequest( + domain=domain, + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckUserOwnsDomainResponse(res.json()) + async def list_offers( self, *, without_options: bool, only_options: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListOffersRequestOrderBy] = None, hosting_id: Optional[str] = None, control_panels: Optional[List[str]] = None, @@ -505,13 +565,12 @@ async def list_offers( async def list_control_panels( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListControlPanelsResponse: """ - List all control panels type. - List the control panels type: cpanel or plesk. + "List the control panels type: cpanel or plesk.". :param region: Region to target. If none is passed will use default region from the config. :param page: Page number to return, from the paginated results (must be a positive integer). :param page_size: Number of control panels to return (must be a positive integer lower or equal to 100). @@ -542,13 +601,12 @@ async def list_control_panels( async def list_control_panels_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[ControlPanel]: """ - List all control panels type. - List the control panels type: cpanel or plesk. + "List the control panels type: cpanel or plesk.". :param region: Region to target. If none is passed will use default region from the config. :param page: Page number to return, from the paginated results (must be a positive integer). :param page_size: Number of control panels to return (must be a positive integer lower or equal to 100). @@ -570,3 +628,327 @@ async def list_control_panels_all( "page_size": page_size, }, ) + + async def create_session( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> Session: + """ + Create a user session. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Session ` + + Usage: + :: + + result = await api.create_session( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1alpha1/regions/{param_region}/hostings/{param_hosting_id}/sessions", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Session(res.json()) + + async def reset_hosting_password( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> ResetHostingPasswordResponse: + """ + :param hosting_id: UUID of the hosting. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ResetHostingPasswordResponse ` + + Usage: + :: + + result = await api.reset_hosting_password( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1alpha1/regions/{param_region}/hostings/{param_hosting_id}/reset-password", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_ResetHostingPasswordResponse(res.json()) + + +class WebhostingV1Alpha1ClassicMailAPI(API): + """ + This API allows you to manage your mailboxes for your Web Hosting services. + """ + + async def create_mailbox( + self, + *, + online_id: int, + password: str, + region: Optional[ScwRegion] = None, + email: Optional[EmailAddress] = None, + ) -> Mailbox: + """ + Create a new mailbox within your hosting plan. + :param online_id: The Online hosting ID. + :param password: Password for the new mailbox. + :param region: Region to target. If none is passed will use default region from the config. + :param email: The email address of the mailbox. + :return: :class:`Mailbox ` + + Usage: + :: + + result = await api.create_mailbox( + online_id=1, + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_online_id = validate_path_param("online_id", online_id) + + res = self._request( + "POST", + f"/webhosting/v1alpha1/regions/{param_region}/classic-hostings/{param_online_id}/mailboxes", + body=marshal_ClassicMailApiCreateMailboxRequest( + ClassicMailApiCreateMailboxRequest( + online_id=online_id, + password=password, + region=region, + email=email, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Mailbox(res.json()) + + async def get_mailbox( + self, + *, + online_id: int, + mailbox_id: int, + region: Optional[ScwRegion] = None, + ) -> Mailbox: + """ + Get a mailbox by id within your hosting plan. + :param online_id: The Online hosting ID. + :param mailbox_id: The ID of the mailbox to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Mailbox ` + + Usage: + :: + + result = await api.get_mailbox( + online_id=1, + mailbox_id=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_online_id = validate_path_param("online_id", online_id) + param_mailbox_id = validate_path_param("mailbox_id", mailbox_id) + + res = self._request( + "GET", + f"/webhosting/v1alpha1/regions/{param_region}/classic-hostings/{param_online_id}/mailboxes/{param_mailbox_id}", + ) + + self._throw_on_error(res) + return unmarshal_Mailbox(res.json()) + + async def list_mailboxes( + self, + *, + online_id: int, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + domain: Optional[str] = None, + ) -> ListMailboxesResponse: + """ + List all mailboxes within your hosting plan. + :param online_id: The Online hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of mailboxes to return (must be a positive integer lower or equal to 100). + :param domain: Domain to filter the mailboxes. + :return: :class:`ListMailboxesResponse ` + + Usage: + :: + + result = await api.list_mailboxes( + online_id=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_online_id = validate_path_param("online_id", online_id) + + res = self._request( + "GET", + f"/webhosting/v1alpha1/regions/{param_region}/classic-hostings/{param_online_id}/mailboxes", + params={ + "domain": domain, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListMailboxesResponse(res.json()) + + async def list_mailboxes_all( + self, + *, + online_id: int, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + domain: Optional[str] = None, + ) -> List[Mailbox]: + """ + List all mailboxes within your hosting plan. + :param online_id: The Online hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of mailboxes to return (must be a positive integer lower or equal to 100). + :param domain: Domain to filter the mailboxes. + :return: :class:`List[Mailbox] ` + + Usage: + :: + + result = await api.list_mailboxes_all( + online_id=1, + ) + """ + + return await fetch_all_pages_async( + type=ListMailboxesResponse, + key="mailboxes", + fetcher=self.list_mailboxes, + args={ + "online_id": online_id, + "region": region, + "page": page, + "page_size": page_size, + "domain": domain, + }, + ) + + async def delete_mailbox( + self, + *, + online_id: int, + mailbox_id: int, + region: Optional[ScwRegion] = None, + ) -> Mailbox: + """ + :param online_id: The Online hosting ID. + :param mailbox_id: The ID of the mailbox to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Mailbox ` + + Usage: + :: + + result = await api.delete_mailbox( + online_id=1, + mailbox_id=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_online_id = validate_path_param("online_id", online_id) + param_mailbox_id = validate_path_param("mailbox_id", mailbox_id) + + res = self._request( + "DELETE", + f"/webhosting/v1alpha1/regions/{param_region}/classic-hostings/{param_online_id}/mailboxes/{param_mailbox_id}", + ) + + self._throw_on_error(res) + return unmarshal_Mailbox(res.json()) + + async def update_mailbox( + self, + *, + online_id: int, + mailbox_id: int, + region: Optional[ScwRegion] = None, + password: Optional[str] = None, + ) -> Mailbox: + """ + Update the mailbox within your hosting plan. + :param online_id: The Online hosting ID. + :param mailbox_id: The ID of the mailbox to update. + :param region: Region to target. If none is passed will use default region from the config. + :param password: New password for the mailbox. + :return: :class:`Mailbox ` + + Usage: + :: + + result = await api.update_mailbox( + online_id=1, + mailbox_id=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_online_id = validate_path_param("online_id", online_id) + param_mailbox_id = validate_path_param("mailbox_id", mailbox_id) + + res = self._request( + "PATCH", + f"/webhosting/v1alpha1/regions/{param_region}/classic-hostings/{param_online_id}/mailboxes/{param_mailbox_id}", + body=marshal_ClassicMailApiUpdateMailboxRequest( + ClassicMailApiUpdateMailboxRequest( + online_id=online_id, + mailbox_id=mailbox_id, + region=region, + password=password, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Mailbox(res.json()) diff --git a/scaleway-async/scaleway_async/webhosting/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/webhosting/v1alpha1/marshalling.py index 108fd7db..2b574c20 100644 --- a/scaleway-async/scaleway_async/webhosting/v1alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/webhosting/v1alpha1/marshalling.py @@ -13,19 +13,31 @@ HostingCpanelUrls, HostingOption, Hosting, + EmailAddress, + Mailbox, + CheckUserOwnsDomainResponse, DnsRecord, Nameserver, DnsRecords, ControlPanel, ListControlPanelsResponse, ListHostingsResponse, + ListMailboxesResponse, OfferProduct, Offer, ListOffersResponse, + ResetHostingPasswordResponse, + Session, + CheckUserOwnsDomainRequest, + ClassicMailApiCreateMailboxRequest, + ClassicMailApiUpdateMailboxRequest, CreateHostingRequestDomainConfiguration, CreateHostingRequest, UpdateHostingRequest, ) +from ...std.types import ( + LanguageCode as StdLanguageCode, +) def unmarshal_HostingCpanelUrls(data: Any) -> HostingCpanelUrls: @@ -102,25 +114,31 @@ def unmarshal_Hosting(data: Any) -> Hosting: if field is not None: args["offer_name"] = field + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("platform_number", None) if field is not None: args["platform_number"] = field - - field = data.get("domain", None) - if field is not None: - args["domain"] = field - - field = data.get("tags", None) - if field is not None: - args["tags"] = field + else: + args["platform_number"] = None field = data.get("options", None) if field is not None: @@ -160,6 +178,10 @@ def unmarshal_Hosting(data: Any) -> Hosting: if field is not None: args["protected"] = field + field = data.get("one_time_password", None) + if field is not None: + args["one_time_password"] = field + field = data.get("region", None) if field is not None: args["region"] = field @@ -167,10 +189,67 @@ def unmarshal_Hosting(data: Any) -> Hosting: field = data.get("cpanel_urls", None) if field is not None: args["cpanel_urls"] = unmarshal_HostingCpanelUrls(field) + else: + args["cpanel_urls"] = None return Hosting(**args) +def unmarshal_EmailAddress(data: Any) -> EmailAddress: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EmailAddress' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("login", None) + if field is not None: + args["login"] = field + + return EmailAddress(**args) + + +def unmarshal_Mailbox(data: Any) -> Mailbox: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Mailbox' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("mailbox_id", None) + if field is not None: + args["mailbox_id"] = field + + field = data.get("email", None) + if field is not None: + args["email"] = unmarshal_EmailAddress(field) + else: + args["email"] = None + + return Mailbox(**args) + + +def unmarshal_CheckUserOwnsDomainResponse(data: Any) -> CheckUserOwnsDomainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckUserOwnsDomainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("owns_domain", None) + if field is not None: + args["owns_domain"] = field + + return CheckUserOwnsDomainResponse(**args) + + def unmarshal_DnsRecord(data: Any) -> DnsRecord: if not isinstance(data, dict): raise TypeError( @@ -183,7 +262,7 @@ def unmarshal_DnsRecord(data: Any) -> DnsRecord: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -202,6 +281,8 @@ def unmarshal_DnsRecord(data: Any) -> DnsRecord: field = data.get("priority", None) if field is not None: args["priority"] = field + else: + args["priority"] = None return DnsRecord(**args) @@ -276,6 +357,12 @@ def unmarshal_ControlPanel(data: Any) -> ControlPanel: if field is not None: args["logo_url"] = field + field = data.get("available_languages", None) + if field is not None: + args["available_languages"] = ( + [StdLanguageCode(v) for v in field] if field is not None else None + ) + return ControlPanel(**args) @@ -321,6 +408,27 @@ def unmarshal_ListHostingsResponse(data: Any) -> ListHostingsResponse: return ListHostingsResponse(**args) +def unmarshal_ListMailboxesResponse(data: Any) -> ListMailboxesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListMailboxesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("mailboxes", None) + if field is not None: + args["mailboxes"] = ( + [unmarshal_Mailbox(v) for v in field] if field is not None else None + ) + + return ListMailboxesResponse(**args) + + def unmarshal_OfferProduct(data: Any) -> OfferProduct: if not isinstance(data, dict): raise TypeError( @@ -409,10 +517,14 @@ def unmarshal_Offer(data: Any) -> Offer: field = data.get("product", None) if field is not None: args["product"] = unmarshal_OfferProduct(field) + else: + args["product"] = None field = data.get("price", None) if field is not None: args["price"] = unmarshal_Money(field) + else: + args["price"] = None return Offer(**args) @@ -434,6 +546,90 @@ def unmarshal_ListOffersResponse(data: Any) -> ListOffersResponse: return ListOffersResponse(**args) +def unmarshal_ResetHostingPasswordResponse(data: Any) -> ResetHostingPasswordResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ResetHostingPasswordResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("password", None) + if field is not None: + args["password"] = field + + return ResetHostingPasswordResponse(**args) + + +def unmarshal_Session(data: Any) -> Session: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Session' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("url", None) + if field is not None: + args["url"] = field + + return Session(**args) + + +def marshal_CheckUserOwnsDomainRequest( + request: CheckUserOwnsDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_EmailAddress( + request: EmailAddress, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain is not None: + output["domain"] = request.domain + + if request.login is not None: + output["login"] = request.login + + return output + + +def marshal_ClassicMailApiCreateMailboxRequest( + request: ClassicMailApiCreateMailboxRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + if request.email is not None: + output["email"] = marshal_EmailAddress(request.email, defaults) + + return output + + +def marshal_ClassicMailApiUpdateMailboxRequest( + request: ClassicMailApiUpdateMailboxRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + return output + + def marshal_CreateHostingRequestDomainConfiguration( request: CreateHostingRequestDomainConfiguration, defaults: ProfileDefaults, @@ -486,7 +682,7 @@ def marshal_CreateHostingRequest( output["domain_configuration"] = ( marshal_CreateHostingRequestDomainConfiguration( request.domain_configuration, defaults - ), + ) ) return output diff --git a/scaleway-async/scaleway_async/webhosting/v1alpha1/types.py b/scaleway-async/scaleway_async/webhosting/v1alpha1/types.py index b9650921..ef600c2f 100644 --- a/scaleway-async/scaleway_async/webhosting/v1alpha1/types.py +++ b/scaleway-async/scaleway_async/webhosting/v1alpha1/types.py @@ -9,7 +9,7 @@ from scaleway_core.bridge import ( Money, - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -102,6 +102,7 @@ class OfferQuotaWarning(str, Enum, metaclass=StrEnumMeta): EMAIL_COUNT_EXCEEDED = "email_count_exceeded" DATABASE_COUNT_EXCEEDED = "database_count_exceeded" DISK_USAGE_EXCEEDED = "disk_usage_exceeded" + ADDON_DOMAIN_COUNT_EXCEEDED = "addon_domain_count_exceeded" def __str__(self) -> str: return str(self.value) @@ -127,6 +128,19 @@ class HostingOption: """ +@dataclass +class EmailAddress: + domain: str + """ + Domain part of the mailbox address. + """ + + login: str + """ + Username part address of the mailbox address. + """ + + @dataclass class OfferProduct: name: str @@ -259,6 +273,11 @@ class ControlPanel: URL of this control panel's logo. """ + available_languages: List[StdLanguageCode] + """ + List of available languages for the control panel. + """ + @dataclass class Hosting: @@ -297,29 +316,29 @@ class Hosting: Name of the active offer for the Web Hosting plan. """ - updated_at: Optional[datetime] + domain: str """ - Date on which the Web Hosting plan was last updated. + Main domain associated with the Web Hosting plan. """ - created_at: Optional[datetime] + tags: List[str] """ - Date on which the Web Hosting plan was created. + List of tags associated with the Web Hosting plan. """ - platform_number: Optional[int] + updated_at: Optional[datetime] """ - Number of the host platform. + Date on which the Web Hosting plan was last updated. """ - domain: str + created_at: Optional[datetime] """ - Main domain associated with the Web Hosting plan. + Date on which the Web Hosting plan was created. """ - tags: List[str] + platform_number: Optional[int] """ - List of tags associated with the Web Hosting plan. + Number of the host platform. """ options: List[HostingOption] @@ -367,7 +386,12 @@ class Hosting: Whether the hosting is protected or not. """ - region: Region + one_time_password: str + """ + One-time-password used for the first login or reset password, empty after first use. + """ + + region: ScwRegion """ Region where the Web Hosting plan is hosted. """ @@ -378,6 +402,19 @@ class Hosting: """ +@dataclass +class Mailbox: + mailbox_id: int + """ + The ID of the mailbox. + """ + + email: Optional[EmailAddress] + """ + The email address of the mailbox. + """ + + @dataclass class Offer: id: str @@ -421,6 +458,142 @@ class Offer: """ +@dataclass +class CheckUserOwnsDomainRequest: + domain: str + """ + Domain for which ownership is to be verified. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project currently in use. + """ + + +@dataclass +class CheckUserOwnsDomainResponse: + owns_domain: bool + """ + Indicates whether the specified project owns the domain. + """ + + +@dataclass +class ClassicMailApiCreateMailboxRequest: + online_id: int + """ + The Online hosting ID. + """ + + password: str + """ + Password for the new mailbox. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + email: Optional[EmailAddress] + """ + The email address of the mailbox. + """ + + +@dataclass +class ClassicMailApiDeleteMailboxRequest: + online_id: int + """ + The Online hosting ID. + """ + + mailbox_id: int + """ + The ID of the mailbox to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ClassicMailApiGetMailboxRequest: + online_id: int + """ + The Online hosting ID. + """ + + mailbox_id: int + """ + The ID of the mailbox to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ClassicMailApiListMailboxesRequest: + online_id: int + """ + The Online hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of mailboxes to return (must be a positive integer lower or equal to 100). + """ + + domain: Optional[str] + """ + Domain to filter the mailboxes. + """ + + +@dataclass +class ClassicMailApiUpdateMailboxRequest: + online_id: int + """ + The Online hosting ID. + """ + + mailbox_id: int + """ + The ID of the mailbox to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + password: Optional[str] + """ + New password for the mailbox. + """ + + @dataclass class CreateHostingRequest: offer_id: str @@ -433,7 +606,7 @@ class CreateHostingRequest: Domain name to link to the Web Hosting plan. You must already own this domain name, and have completed the DNS validation process beforehand. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -469,6 +642,19 @@ class CreateHostingRequest: """ +@dataclass +class CreateSessionRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class DeleteHostingRequest: hosting_id: str @@ -476,7 +662,7 @@ class DeleteHostingRequest: Hosting ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -507,7 +693,7 @@ class GetDomainDnsRecordsRequest: Domain associated with the DNS records. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -520,7 +706,7 @@ class GetHostingRequest: Hosting ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -528,7 +714,7 @@ class GetHostingRequest: @dataclass class ListControlPanelsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -559,7 +745,7 @@ class ListControlPanelsResponse: @dataclass class ListHostingsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -623,6 +809,19 @@ class ListHostingsResponse: """ +@dataclass +class ListMailboxesResponse: + total_count: int + """ + Total number of mailboxes. + """ + + mailboxes: List[Mailbox] + """ + List of mailboxes. + """ + + @dataclass class ListOffersRequest: without_options: bool @@ -635,7 +834,7 @@ class ListOffersRequest: Defines whether the response should consist of options only, without offers. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -664,6 +863,27 @@ class ListOffersResponse: """ +@dataclass +class ResetHostingPasswordRequest: + hosting_id: str + """ + UUID of the hosting. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ResetHostingPasswordResponse: + password: str + """ + New password. + """ + + @dataclass class RestoreHostingRequest: hosting_id: str @@ -671,12 +891,20 @@ class RestoreHostingRequest: Hosting ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class Session: + url: str + """ + Logged user's session URL. + """ + + @dataclass class UpdateHostingRequest: hosting_id: str @@ -684,7 +912,7 @@ class UpdateHostingRequest: Hosting ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway-core/poetry.lock b/scaleway-core/poetry.lock index a8d4b38c..c786e530 100644 --- a/scaleway-core/poetry.lock +++ b/scaleway-core/poetry.lock @@ -1,173 +1,184 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, + {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] [[package]] name = "charset-normalizer" -version = "3.3.2" +version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.7" +groups = ["main"] files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, + {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, + {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, ] [[package]] name = "idna" -version = "3.6" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" +groups = ["main"] files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "mypy" -version = "1.9.0" +version = "1.15.0" description = "Optional static typing for Python" -category = "dev" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"}, - {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"}, - {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"}, - {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"}, - {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"}, - {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"}, - {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"}, - {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"}, - {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"}, - {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"}, - {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"}, - {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"}, - {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"}, - {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"}, - {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"}, - {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"}, - {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"}, - {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"}, - {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, + {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, + {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, + {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, + {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, + {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, + {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, + {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, + {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, + {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, + {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, + {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, + {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, ] [package.dependencies] -mypy-extensions = ">=1.0.0" +mypy_extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.1.0" +typing_extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] +faster-cache = ["orjson"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] reports = ["lxml"] @@ -176,9 +187,9 @@ reports = ["lxml"] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, @@ -188,9 +199,9 @@ files = [ name = "python-dateutil" version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -201,75 +212,77 @@ six = ">=1.5" [[package]] name = "pyyaml" -version = "6.0.1" +version = "6.0.2" description = "YAML parser and emitter for Python" -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -284,98 +297,130 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.0.286" -description = "An extremely fast Python linter, written in Rust." -category = "dev" +version = "0.11.7" +description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "ruff-0.0.286-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:8e22cb557e7395893490e7f9cfea1073d19a5b1dd337f44fd81359b2767da4e9"}, - {file = "ruff-0.0.286-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:68ed8c99c883ae79a9133cb1a86d7130feee0397fdf5ba385abf2d53e178d3fa"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8301f0bb4ec1a5b29cfaf15b83565136c47abefb771603241af9d6038f8981e8"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:acc4598f810bbc465ce0ed84417ac687e392c993a84c7eaf3abf97638701c1ec"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88c8e358b445eb66d47164fa38541cfcc267847d1e7a92dd186dddb1a0a9a17f"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0433683d0c5dbcf6162a4beb2356e820a593243f1fa714072fec15e2e4f4c939"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddb61a0c4454cbe4623f4a07fef03c5ae921fe04fede8d15c6e36703c0a73b07"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:47549c7c0be24c8ae9f2bce6f1c49fbafea83bca80142d118306f08ec7414041"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:559aa793149ac23dc4310f94f2c83209eedb16908a0343663be19bec42233d25"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d73cfb1c3352e7aa0ce6fb2321f36fa1d4a2c48d2ceac694cb03611ddf0e4db6"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:3dad93b1f973c6d1db4b6a5da8690c5625a3fa32bdf38e543a6936e634b83dc3"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26afc0851f4fc3738afcf30f5f8b8612a31ac3455cb76e611deea80f5c0bf3ce"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9b6b116d1c4000de1b9bf027131dbc3b8a70507788f794c6b09509d28952c512"}, - {file = "ruff-0.0.286-py3-none-win32.whl", hash = "sha256:556e965ac07c1e8c1c2d759ac512e526ecff62c00fde1a046acb088d3cbc1a6c"}, - {file = "ruff-0.0.286-py3-none-win_amd64.whl", hash = "sha256:5d295c758961376c84aaa92d16e643d110be32add7465e197bfdaec5a431a107"}, - {file = "ruff-0.0.286-py3-none-win_arm64.whl", hash = "sha256:1d6142d53ab7f164204b3133d053c4958d4d11ec3a39abf23a40b13b0784e3f0"}, - {file = "ruff-0.0.286.tar.gz", hash = "sha256:f1e9d169cce81a384a26ee5bb8c919fe9ae88255f39a1a69fd1ebab233a85ed2"}, + {file = "ruff-0.11.7-py3-none-linux_armv6l.whl", hash = "sha256:d29e909d9a8d02f928d72ab7837b5cbc450a5bdf578ab9ebee3263d0a525091c"}, + {file = "ruff-0.11.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dd1fb86b168ae349fb01dd497d83537b2c5541fe0626e70c786427dd8363aaee"}, + {file = "ruff-0.11.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3d7d2e140a6fbbc09033bce65bd7ea29d6a0adeb90b8430262fbacd58c38ada"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4809df77de390a1c2077d9b7945d82f44b95d19ceccf0c287c56e4dc9b91ca64"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3a0c2e169e6b545f8e2dba185eabbd9db4f08880032e75aa0e285a6d3f48201"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49b888200a320dd96a68e86736cf531d6afba03e4f6cf098401406a257fcf3d6"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2b19cdb9cf7dae00d5ee2e7c013540cdc3b31c4f281f1dacb5a799d610e90db4"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64e0ee994c9e326b43539d133a36a455dbaab477bc84fe7bfbd528abe2f05c1e"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bad82052311479a5865f52c76ecee5d468a58ba44fb23ee15079f17dd4c8fd63"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7940665e74e7b65d427b82bffc1e46710ec7f30d58b4b2d5016e3f0321436502"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:169027e31c52c0e36c44ae9a9c7db35e505fee0b39f8d9fca7274a6305295a92"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:305b93f9798aee582e91e34437810439acb28b5fc1fee6b8205c78c806845a94"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a681db041ef55550c371f9cd52a3cf17a0da4c75d6bd691092dfc38170ebc4b6"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:07f1496ad00a4a139f4de220b0c97da6d4c85e0e4aa9b2624167b7d4d44fd6b6"}, + {file = "ruff-0.11.7-py3-none-win32.whl", hash = "sha256:f25dfb853ad217e6e5f1924ae8a5b3f6709051a13e9dad18690de6c8ff299e26"}, + {file = "ruff-0.11.7-py3-none-win_amd64.whl", hash = "sha256:0a931d85959ceb77e92aea4bbedfded0a31534ce191252721128f77e5ae1f98a"}, + {file = "ruff-0.11.7-py3-none-win_arm64.whl", hash = "sha256:778c1e5d6f9e91034142dfd06110534ca13220bfaad5c3735f6cb844654f6177"}, + {file = "ruff-0.11.7.tar.gz", hash = "sha256:655089ad3224070736dc32844fde783454f8558e71f501cb207485fe4eee23d4"}, ] [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] name = "tomli" -version = "2.0.1" +version = "2.2.1" description = "A lil' TOML parser" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version < \"3.11\"" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] name = "types-python-dateutil" -version = "2.9.0.20240316" +version = "2.9.0.20241206" description = "Typing stubs for python-dateutil" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "types-python-dateutil-2.9.0.20240316.tar.gz", hash = "sha256:5d2f2e240b86905e40944dd787db6da9263f0deabef1076ddaed797351ec0202"}, - {file = "types_python_dateutil-2.9.0.20240316-py3-none-any.whl", hash = "sha256:6b8cb66d960771ce5ff974e9dd45e38facb81718cc1e208b10b1baccbfdbee3b"}, + {file = "types_python_dateutil-2.9.0.20241206-py3-none-any.whl", hash = "sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53"}, + {file = "types_python_dateutil-2.9.0.20241206.tar.gz", hash = "sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb"}, ] [[package]] name = "typing-extensions" -version = "4.10.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, - {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] name = "urllib3" -version = "2.2.1" +version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, + {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [metadata] -lock-version = "2.0" -python-versions = "^3.8" -content-hash = "4af429f24e9bad42a4106375d71a3c54958185e5ef53421c960029977d5fef51" +lock-version = "2.1" +python-versions = ">=3.10" +content-hash = "312658cee34f6bafcff1391b6306c8357c17aac9cfa86bb897ee9967cbe2dca3" diff --git a/scaleway-core/pyproject.toml b/scaleway-core/pyproject.toml index 2464c35c..98e53e2a 100644 --- a/scaleway-core/pyproject.toml +++ b/scaleway-core/pyproject.toml @@ -23,19 +23,19 @@ classifiers = [ ] [tool.poetry.dependencies] -python = "^3.8" +python = ">=3.10" requests = "^2.28.1" PyYAML = "^6.0" python-dateutil = "^2.8.2" [tool.poetry.group.dev.dependencies] types-python-dateutil = "^2.8.19" -ruff = "^0.0.286" +ruff = ">=0.5.0,<0.11.8" mypy = "^1.5.1" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" -[tool.ruff] +[tool.ruff.lint] ignore = ["E501"] diff --git a/scaleway-core/scaleway_core/__init__.py b/scaleway-core/scaleway_core/__init__.py index 4cc8657c..8b341577 100644 --- a/scaleway-core/scaleway_core/__init__.py +++ b/scaleway-core/scaleway_core/__init__.py @@ -1,5 +1,5 @@ """Scaleway SDK for Python - Core""" -import pkg_resources +import importlib.metadata -__version__: str = pkg_resources.get_distribution(__name__).version +__version__: str = importlib.metadata.version(__name__) diff --git a/scaleway-core/scaleway_core/api.py b/scaleway-core/scaleway_core/api.py index fc24d958..6dd292ec 100644 --- a/scaleway-core/scaleway_core/api.py +++ b/scaleway-core/scaleway_core/api.py @@ -118,15 +118,18 @@ def _request( body: Optional[Body] = None, ) -> requests.Response: additional_headers: Dict[str, str] = {} - method = method.upper() if method == "POST" or method == "PUT" or method == "PATCH": additional_headers["Content-Type"] = "application/json; charset=utf-8" - if body is None: - body = {} + if body is None: + body = {} - raw_body = json.dumps(body) if body is not None else None + raw_body: Union[bytes, str] + if isinstance(body, bytes): + raw_body = body + else: + raw_body = json.dumps(body) if body is not None else None request_params: List[Tuple[str, Any]] = [] for k, v in params.items(): @@ -141,12 +144,12 @@ def _request( headers = { "accept": "application/json", - "x-auth-token": self.client.secret_key or "", "user-agent": self.client.user_agent, **additional_headers, **headers, } - + if self.client.secret_key is not None: + headers["x-auth-token"] = self.client.secret_key url = f"{self.client.api_url}{path}" logger = APILogger(self._log, self.client._increment_request_count()) @@ -156,9 +159,10 @@ def _request( url=url, params=request_params, headers=headers, - body=raw_body, + body=raw_body.decode("utf-8", errors="replace") + if isinstance(raw_body, bytes) + else raw_body, ) - response = requests.request( method=method, url=url, @@ -168,6 +172,12 @@ def _request( verify=not self.client.api_allow_insecure, ) + if response.headers.get("x-total-count"): + b = response.json() + b["total_count"] = response.headers.get("x-total-count") + b = json.dumps(b) + response._content = bytes(b, "utf-8") + logger.log_response( response=response, ) diff --git a/scaleway-core/scaleway_core/bridge/__init__.py b/scaleway-core/scaleway_core/bridge/__init__.py index 1e6d6087..e0570253 100644 --- a/scaleway-core/scaleway_core/bridge/__init__.py +++ b/scaleway-core/scaleway_core/bridge/__init__.py @@ -22,6 +22,9 @@ from .timeseries import unmarshal_TimeSeriesPoint from .timeseries import marshal_TimeSeriesPoint +from .decimal import unmarshal_Decimal +from .decimal import marshal_Decimal + __all__ = [ "Money", "unmarshal_Money", @@ -42,4 +45,6 @@ "marshal_TimeSeries", "unmarshal_TimeSeriesPoint", "marshal_TimeSeriesPoint", + "unmarshal_Decimal", + "marshal_Decimal", ] diff --git a/scaleway-core/scaleway_core/bridge/decimal.py b/scaleway-core/scaleway_core/bridge/decimal.py new file mode 100644 index 00000000..49f4aec1 --- /dev/null +++ b/scaleway-core/scaleway_core/bridge/decimal.py @@ -0,0 +1,28 @@ +from decimal import Decimal +from typing import Any, Dict + + +def unmarshal_Decimal(data: Any) -> Decimal: + """ + Unmarshal an instance of Decimal from the given data. + """ + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Decimal' failed as data isn't a dictionary." + ) + + if "value" not in data: + raise TypeError( + "Unmarshalling the type 'Decimal' failed as data does not contain a 'value' key." + ) + + return Decimal(data["value"]) + + +def marshal_Decimal(data: Decimal) -> Dict[str, Any]: + """ + Marshal an instance of Decimal into google.protobuf.Decimal JSON representation. + """ + return { + "value": str(data), + } diff --git a/scaleway-core/tests/test_bridge_marshal.py b/scaleway-core/tests/test_bridge_marshal.py new file mode 100644 index 00000000..328a8d16 --- /dev/null +++ b/scaleway-core/tests/test_bridge_marshal.py @@ -0,0 +1,14 @@ +import unittest +from decimal import Decimal + +from scaleway_core.bridge import unmarshal_Decimal, marshal_Decimal + + +class TestBridgeMarshal(unittest.TestCase): + def test_decimal_marshal(self): + decimal = Decimal("1.2") + self.assertEqual(marshal_Decimal(decimal), {"value": "1.2"}) + + def test_decimal_unmarshal(self): + decimal = Decimal("1.2") + self.assertEqual(unmarshal_Decimal({"value": "1.2"}), decimal) diff --git a/scaleway/poetry.lock b/scaleway/poetry.lock index ac19aa15..b2fa0006 100644 --- a/scaleway/poetry.lock +++ b/scaleway/poetry.lock @@ -1,173 +1,184 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, + {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] [[package]] name = "charset-normalizer" -version = "3.3.2" +version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.7" +groups = ["main", "dev"] files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, + {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, + {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, ] [[package]] name = "idna" -version = "3.6" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" +groups = ["main", "dev"] files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "mypy" -version = "1.9.0" +version = "1.15.0" description = "Optional static typing for Python" -category = "dev" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"}, - {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"}, - {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"}, - {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"}, - {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"}, - {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"}, - {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"}, - {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"}, - {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"}, - {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"}, - {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"}, - {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"}, - {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"}, - {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"}, - {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"}, - {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"}, - {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"}, - {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"}, - {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, + {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, + {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, + {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, + {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, + {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, + {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, + {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, + {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, + {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, + {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, + {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, + {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, ] [package.dependencies] -mypy-extensions = ">=1.0.0" +mypy_extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.1.0" +typing_extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] +faster-cache = ["orjson"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] reports = ["lxml"] @@ -176,9 +187,9 @@ reports = ["lxml"] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, @@ -188,9 +199,9 @@ files = [ name = "python-dateutil" version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -201,75 +212,77 @@ six = ">=1.5" [[package]] name = "pyyaml" -version = "6.0.1" +version = "6.0.2" description = "YAML parser and emitter for Python" -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -284,38 +297,39 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.0.286" -description = "An extremely fast Python linter, written in Rust." -category = "dev" +version = "0.11.7" +description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "ruff-0.0.286-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:8e22cb557e7395893490e7f9cfea1073d19a5b1dd337f44fd81359b2767da4e9"}, - {file = "ruff-0.0.286-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:68ed8c99c883ae79a9133cb1a86d7130feee0397fdf5ba385abf2d53e178d3fa"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8301f0bb4ec1a5b29cfaf15b83565136c47abefb771603241af9d6038f8981e8"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:acc4598f810bbc465ce0ed84417ac687e392c993a84c7eaf3abf97638701c1ec"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88c8e358b445eb66d47164fa38541cfcc267847d1e7a92dd186dddb1a0a9a17f"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0433683d0c5dbcf6162a4beb2356e820a593243f1fa714072fec15e2e4f4c939"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddb61a0c4454cbe4623f4a07fef03c5ae921fe04fede8d15c6e36703c0a73b07"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:47549c7c0be24c8ae9f2bce6f1c49fbafea83bca80142d118306f08ec7414041"}, - {file = "ruff-0.0.286-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:559aa793149ac23dc4310f94f2c83209eedb16908a0343663be19bec42233d25"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d73cfb1c3352e7aa0ce6fb2321f36fa1d4a2c48d2ceac694cb03611ddf0e4db6"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:3dad93b1f973c6d1db4b6a5da8690c5625a3fa32bdf38e543a6936e634b83dc3"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26afc0851f4fc3738afcf30f5f8b8612a31ac3455cb76e611deea80f5c0bf3ce"}, - {file = "ruff-0.0.286-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9b6b116d1c4000de1b9bf027131dbc3b8a70507788f794c6b09509d28952c512"}, - {file = "ruff-0.0.286-py3-none-win32.whl", hash = "sha256:556e965ac07c1e8c1c2d759ac512e526ecff62c00fde1a046acb088d3cbc1a6c"}, - {file = "ruff-0.0.286-py3-none-win_amd64.whl", hash = "sha256:5d295c758961376c84aaa92d16e643d110be32add7465e197bfdaec5a431a107"}, - {file = "ruff-0.0.286-py3-none-win_arm64.whl", hash = "sha256:1d6142d53ab7f164204b3133d053c4958d4d11ec3a39abf23a40b13b0784e3f0"}, - {file = "ruff-0.0.286.tar.gz", hash = "sha256:f1e9d169cce81a384a26ee5bb8c919fe9ae88255f39a1a69fd1ebab233a85ed2"}, + {file = "ruff-0.11.7-py3-none-linux_armv6l.whl", hash = "sha256:d29e909d9a8d02f928d72ab7837b5cbc450a5bdf578ab9ebee3263d0a525091c"}, + {file = "ruff-0.11.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dd1fb86b168ae349fb01dd497d83537b2c5541fe0626e70c786427dd8363aaee"}, + {file = "ruff-0.11.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3d7d2e140a6fbbc09033bce65bd7ea29d6a0adeb90b8430262fbacd58c38ada"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4809df77de390a1c2077d9b7945d82f44b95d19ceccf0c287c56e4dc9b91ca64"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3a0c2e169e6b545f8e2dba185eabbd9db4f08880032e75aa0e285a6d3f48201"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49b888200a320dd96a68e86736cf531d6afba03e4f6cf098401406a257fcf3d6"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2b19cdb9cf7dae00d5ee2e7c013540cdc3b31c4f281f1dacb5a799d610e90db4"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64e0ee994c9e326b43539d133a36a455dbaab477bc84fe7bfbd528abe2f05c1e"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bad82052311479a5865f52c76ecee5d468a58ba44fb23ee15079f17dd4c8fd63"}, + {file = "ruff-0.11.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7940665e74e7b65d427b82bffc1e46710ec7f30d58b4b2d5016e3f0321436502"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:169027e31c52c0e36c44ae9a9c7db35e505fee0b39f8d9fca7274a6305295a92"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:305b93f9798aee582e91e34437810439acb28b5fc1fee6b8205c78c806845a94"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a681db041ef55550c371f9cd52a3cf17a0da4c75d6bd691092dfc38170ebc4b6"}, + {file = "ruff-0.11.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:07f1496ad00a4a139f4de220b0c97da6d4c85e0e4aa9b2624167b7d4d44fd6b6"}, + {file = "ruff-0.11.7-py3-none-win32.whl", hash = "sha256:f25dfb853ad217e6e5f1924ae8a5b3f6709051a13e9dad18690de6c8ff299e26"}, + {file = "ruff-0.11.7-py3-none-win_amd64.whl", hash = "sha256:0a931d85959ceb77e92aea4bbedfded0a31534ce191252721128f77e5ae1f98a"}, + {file = "ruff-0.11.7-py3-none-win_arm64.whl", hash = "sha256:778c1e5d6f9e91034142dfd06110534ca13220bfaad5c3735f6cb844654f6177"}, + {file = "ruff-0.11.7.tar.gz", hash = "sha256:655089ad3224070736dc32844fde783454f8558e71f501cb207485fe4eee23d4"}, ] [[package]] name = "scaleway-core" version = "2.0.0" description = "Scaleway SDK for Python" -category = "main" optional = false -python-versions = "^3.8" +python-versions = ">=3.10" +groups = ["main", "dev"] files = [] develop = true @@ -330,59 +344,90 @@ url = "../scaleway-core" [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] name = "tomli" -version = "2.0.1" +version = "2.2.1" description = "A lil' TOML parser" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version < \"3.11\"" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] name = "typing-extensions" -version = "4.10.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" -category = "dev" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, - {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] name = "urllib3" -version = "2.2.1" +version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main", "dev"] files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, + {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [metadata] -lock-version = "2.0" -python-versions = "^3.8" -content-hash = "441285c99087ba7e2715e85918cefdd80615528d46711cb9c85dc8d28e1f308c" +lock-version = "2.1" +python-versions = ">=3.10" +content-hash = "68ef82872418760889cf9cc20b83ca32fe57cd6a0fe8df937f4907f5f0809b98" diff --git a/scaleway/pyproject.toml b/scaleway/pyproject.toml index 825cc4ae..cdba14e5 100644 --- a/scaleway/pyproject.toml +++ b/scaleway/pyproject.toml @@ -23,17 +23,17 @@ classifiers = [ ] [tool.poetry.dependencies] -python = "^3.8" +python = ">=3.10" scaleway-core = "*" [tool.poetry.group.dev.dependencies] scaleway-core = { path = "../scaleway-core", develop = true } -ruff = "^0.0.286" +ruff = ">=0.5.0,<0.11.8" mypy = "^1.5.1" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" -[tool.ruff] +[tool.ruff.lint] ignore = ["E501"] diff --git a/scaleway/scaleway/__init__.py b/scaleway/scaleway/__init__.py index 51c3304e..04021154 100644 --- a/scaleway/scaleway/__init__.py +++ b/scaleway/scaleway/__init__.py @@ -1,8 +1,8 @@ """Scaleway SDK for Python""" -import pkg_resources +import importlib.metadata -__version__: str = pkg_resources.get_distribution(__name__).version +__version__: str = importlib.metadata.version(__name__) from scaleway_core.api import ( API, diff --git a/scaleway/scaleway/account/v2/api.py b/scaleway/scaleway/account/v2/api.py index f8311c2b..120ffe2a 100644 --- a/scaleway/scaleway/account/v2/api.py +++ b/scaleway/scaleway/account/v2/api.py @@ -26,7 +26,7 @@ class AccountV2API(API): """ - This API allows you to manage projects. + This API allows you to manage your Scaleway Projects. """ def create_project( diff --git a/scaleway/scaleway/account/v2/marshalling.py b/scaleway/scaleway/account/v2/marshalling.py index 869668e9..c577c2d2 100644 --- a/scaleway/scaleway/account/v2/marshalling.py +++ b/scaleway/scaleway/account/v2/marshalling.py @@ -40,10 +40,14 @@ def unmarshal_Project(data: Any) -> Project: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Project(**args) diff --git a/scaleway/scaleway/account/v3/__init__.py b/scaleway/scaleway/account/v3/__init__.py index 262de9a5..db42391c 100644 --- a/scaleway/scaleway/account/v3/__init__.py +++ b/scaleway/scaleway/account/v3/__init__.py @@ -1,23 +1,91 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import ContractType +from .types import ListContractSignaturesRequestOrderBy from .types import ListProjectsRequestOrderBy +from .types import QualificationAiMachineSubUseCase +from .types import QualificationArchitectureType +from .types import QualificationArchiveDataSubUseCase +from .types import QualificationContainerSubUseCase +from .types import QualificationDeploySoftwareSubUseCase +from .types import QualificationHostApplicationSubUseCase +from .types import QualificationHostWebsiteSubUseCase +from .types import QualificationOtherUseCaseSubUseCase +from .types import QualificationSetScalewayEnvironmentSubUseCase +from .types import QualificationShareDataSubUseCase +from .types import QualificationAiMachine +from .types import QualificationArchiveData +from .types import QualificationContainer +from .types import QualificationDeploySoftware +from .types import QualificationHostApplication +from .types import QualificationHostWebsite +from .types import QualificationOtherUseCase +from .types import QualificationSetScalewayEnvironment +from .types import QualificationShareData +from .types import Contract +from .types import Qualification +from .types import ContractSignature from .types import Project +from .types import CheckContractSignatureResponse +from .types import ContractApiCheckContractSignatureRequest +from .types import ContractApiCreateContractSignatureRequest +from .types import ContractApiDownloadContractSignatureRequest +from .types import ContractApiListContractSignaturesRequest +from .types import ContractApiValidateContractSignatureRequest +from .types import ListContractSignaturesResponse from .types import ListProjectsResponse from .types import ProjectApiCreateProjectRequest from .types import ProjectApiDeleteProjectRequest from .types import ProjectApiGetProjectRequest from .types import ProjectApiListProjectsRequest +from .types import ProjectApiSetProjectQualificationRequest from .types import ProjectApiUpdateProjectRequest +from .types import ProjectQualification +from .api import AccountV3ContractAPI from .api import AccountV3ProjectAPI __all__ = [ + "ContractType", + "ListContractSignaturesRequestOrderBy", "ListProjectsRequestOrderBy", + "QualificationAiMachineSubUseCase", + "QualificationArchitectureType", + "QualificationArchiveDataSubUseCase", + "QualificationContainerSubUseCase", + "QualificationDeploySoftwareSubUseCase", + "QualificationHostApplicationSubUseCase", + "QualificationHostWebsiteSubUseCase", + "QualificationOtherUseCaseSubUseCase", + "QualificationSetScalewayEnvironmentSubUseCase", + "QualificationShareDataSubUseCase", + "QualificationAiMachine", + "QualificationArchiveData", + "QualificationContainer", + "QualificationDeploySoftware", + "QualificationHostApplication", + "QualificationHostWebsite", + "QualificationOtherUseCase", + "QualificationSetScalewayEnvironment", + "QualificationShareData", + "Contract", + "Qualification", + "ContractSignature", "Project", + "CheckContractSignatureResponse", + "ContractApiCheckContractSignatureRequest", + "ContractApiCreateContractSignatureRequest", + "ContractApiDownloadContractSignatureRequest", + "ContractApiListContractSignaturesRequest", + "ContractApiValidateContractSignatureRequest", + "ListContractSignaturesResponse", "ListProjectsResponse", "ProjectApiCreateProjectRequest", "ProjectApiDeleteProjectRequest", "ProjectApiGetProjectRequest", "ProjectApiListProjectsRequest", + "ProjectApiSetProjectQualificationRequest", "ProjectApiUpdateProjectRequest", + "ProjectQualification", + "AccountV3ContractAPI", "AccountV3ProjectAPI", ] diff --git a/scaleway/scaleway/account/v3/api.py b/scaleway/scaleway/account/v3/api.py index fb0155c3..0631e537 100644 --- a/scaleway/scaleway/account/v3/api.py +++ b/scaleway/scaleway/account/v3/api.py @@ -4,29 +4,276 @@ from typing import List, Optional from scaleway_core.api import API +from scaleway_core.bridge import ( + ScwFile, + unmarshal_ScwFile, +) from scaleway_core.utils import ( random_name, validate_path_param, fetch_all_pages, ) from .types import ( + ContractType, + ListContractSignaturesRequestOrderBy, ListProjectsRequestOrderBy, + CheckContractSignatureResponse, + ContractApiCheckContractSignatureRequest, + ContractApiCreateContractSignatureRequest, + ContractSignature, + ListContractSignaturesResponse, ListProjectsResponse, Project, ProjectApiCreateProjectRequest, + ProjectApiSetProjectQualificationRequest, ProjectApiUpdateProjectRequest, + ProjectQualification, + Qualification, ) from .marshalling import ( + unmarshal_ContractSignature, unmarshal_Project, + unmarshal_CheckContractSignatureResponse, + unmarshal_ListContractSignaturesResponse, unmarshal_ListProjectsResponse, + unmarshal_ProjectQualification, + marshal_ContractApiCheckContractSignatureRequest, + marshal_ContractApiCreateContractSignatureRequest, marshal_ProjectApiCreateProjectRequest, + marshal_ProjectApiSetProjectQualificationRequest, marshal_ProjectApiUpdateProjectRequest, ) +from ...std.types import ( + LanguageCode as StdLanguageCode, +) + + +class AccountV3ContractAPI(API): + """ + The Contract API allows you to manage contracts. + """ + + def download_contract_signature( + self, + *, + contract_signature_id: str, + locale: Optional[StdLanguageCode] = None, + ) -> ScwFile: + """ + Download a contract content. + :param contract_signature_id: The contract signature ID. + :param locale: The locale requested for the content of the contract. + :return: :class:`ScwFile ` + + Usage: + :: + + result = api.download_contract_signature( + contract_signature_id="example", + ) + """ + + param_contract_signature_id = validate_path_param( + "contract_signature_id", contract_signature_id + ) + + res = self._request( + "GET", + f"/account/v3/contract-signatures/{param_contract_signature_id}/download", + params={ + "locale": locale, + }, + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + def create_contract_signature( + self, + *, + contract_name: str, + validated: bool, + contract_type: Optional[ContractType] = None, + organization_id: Optional[str] = None, + ) -> ContractSignature: + """ + Create a signature for your Organization for the latest version of the requested contract. + :param contract_name: The name of the contract. + :param validated: Whether the contract is validated at creation. + :param contract_type: The type of the contract. + :param organization_id: ID of the Organization. + :return: :class:`ContractSignature ` + + Usage: + :: + + result = api.create_contract_signature( + contract_name="example", + validated=False, + ) + """ + + res = self._request( + "POST", + "/account/v3/contract-signatures", + body=marshal_ContractApiCreateContractSignatureRequest( + ContractApiCreateContractSignatureRequest( + contract_name=contract_name, + validated=validated, + contract_type=contract_type, + organization_id=organization_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ContractSignature(res.json()) + + def validate_contract_signature( + self, + *, + contract_signature_id: str, + ) -> ContractSignature: + """ + Sign a contract for your Organization. + :param contract_signature_id: The contract linked to your Organization you want to sign. + :return: :class:`ContractSignature ` + + Usage: + :: + + result = api.validate_contract_signature( + contract_signature_id="example", + ) + """ + + param_contract_signature_id = validate_path_param( + "contract_signature_id", contract_signature_id + ) + + res = self._request( + "POST", + f"/account/v3/contract-signatures/{param_contract_signature_id}/validate", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_ContractSignature(res.json()) + + def check_contract_signature( + self, + *, + contract_name: str, + organization_id: Optional[str] = None, + contract_type: Optional[ContractType] = None, + ) -> CheckContractSignatureResponse: + """ + Check if a contract is signed for your Organization. + :param contract_name: Filter on contract name. + :param organization_id: ID of the Organization to check the contract signature for. + :param contract_type: Filter on contract type. + :return: :class:`CheckContractSignatureResponse ` + + Usage: + :: + + result = api.check_contract_signature( + contract_name="example", + ) + """ + + res = self._request( + "POST", + "/account/v3/contract-signatures/check", + body=marshal_ContractApiCheckContractSignatureRequest( + ContractApiCheckContractSignatureRequest( + contract_name=contract_name, + organization_id=organization_id, + contract_type=contract_type, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckContractSignatureResponse(res.json()) + + def list_contract_signatures( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListContractSignaturesRequestOrderBy] = None, + organization_id: Optional[str] = None, + ) -> ListContractSignaturesResponse: + """ + List contract signatures for an Organization. + :param page: The page number for the returned contracts. + :param page_size: The maximum number of contracts per page. + :param order_by: How the contracts are ordered in the response. + :param organization_id: Filter on Organization ID. + :return: :class:`ListContractSignaturesResponse ` + + Usage: + :: + + result = api.list_contract_signatures() + """ + + res = self._request( + "GET", + "/account/v3/contract-signatures", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListContractSignaturesResponse(res.json()) + + def list_contract_signatures_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListContractSignaturesRequestOrderBy] = None, + organization_id: Optional[str] = None, + ) -> List[ContractSignature]: + """ + List contract signatures for an Organization. + :param page: The page number for the returned contracts. + :param page_size: The maximum number of contracts per page. + :param order_by: How the contracts are ordered in the response. + :param organization_id: Filter on Organization ID. + :return: :class:`List[ContractSignature] ` + + Usage: + :: + + result = api.list_contract_signatures_all() + """ + + return fetch_all_pages( + type=ListContractSignaturesResponse, + key="contract_signatures", + fetcher=self.list_contract_signatures, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "organization_id": organization_id, + }, + ) class AccountV3ProjectAPI(API): """ - This API allows you to manage projects. + This API allows you to manage your Scaleway Projects. """ def create_project( @@ -249,3 +496,41 @@ def update_project( self._throw_on_error(res) return unmarshal_Project(res.json()) + + def set_project_qualification( + self, + *, + project_id: Optional[str] = None, + qualification: Optional[Qualification] = None, + ) -> ProjectQualification: + """ + Set project use case. + Set the project use case for a new or existing Project, specified by its Project ID. You can customize the use case, sub use case, and architecture type you want to use in the Project. + :param project_id: Project ID. + :param qualification: Use case chosen for the Project. + :return: :class:`ProjectQualification ` + + Usage: + :: + + result = api.set_project_qualification() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "POST", + f"/account/v3/projects/{param_project_id}/project-qualification", + body=marshal_ProjectApiSetProjectQualificationRequest( + ProjectApiSetProjectQualificationRequest( + project_id=project_id, + qualification=qualification, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ProjectQualification(res.json()) diff --git a/scaleway/scaleway/account/v3/marshalling.py b/scaleway/scaleway/account/v3/marshalling.py index 2725094d..2875dfa3 100644 --- a/scaleway/scaleway/account/v3/marshalling.py +++ b/scaleway/scaleway/account/v3/marshalling.py @@ -5,14 +5,326 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) from .types import ( + Contract, + ContractSignature, + QualificationAiMachine, + QualificationArchiveData, + QualificationContainer, + QualificationDeploySoftware, + QualificationHostApplication, + QualificationHostWebsite, + QualificationOtherUseCase, + QualificationSetScalewayEnvironment, + QualificationShareData, + Qualification, Project, + CheckContractSignatureResponse, + ListContractSignaturesResponse, ListProjectsResponse, + ProjectQualification, + ContractApiCheckContractSignatureRequest, + ContractApiCreateContractSignatureRequest, ProjectApiCreateProjectRequest, + ProjectApiSetProjectQualificationRequest, ProjectApiUpdateProjectRequest, ) +def unmarshal_Contract(data: Any) -> Contract: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Contract' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Contract(**args) + + +def unmarshal_ContractSignature(data: Any) -> ContractSignature: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContractSignature' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("signed_at", None) + if field is not None: + args["signed_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["signed_at"] = None + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + field = data.get("contract", None) + if field is not None: + args["contract"] = unmarshal_Contract(field) + else: + args["contract"] = None + + return ContractSignature(**args) + + +def unmarshal_QualificationAiMachine(data: Any) -> QualificationAiMachine: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationAiMachine' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationAiMachine(**args) + + +def unmarshal_QualificationArchiveData(data: Any) -> QualificationArchiveData: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationArchiveData' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationArchiveData(**args) + + +def unmarshal_QualificationContainer(data: Any) -> QualificationContainer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationContainer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationContainer(**args) + + +def unmarshal_QualificationDeploySoftware(data: Any) -> QualificationDeploySoftware: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationDeploySoftware' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationDeploySoftware(**args) + + +def unmarshal_QualificationHostApplication(data: Any) -> QualificationHostApplication: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationHostApplication' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationHostApplication(**args) + + +def unmarshal_QualificationHostWebsite(data: Any) -> QualificationHostWebsite: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationHostWebsite' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationHostWebsite(**args) + + +def unmarshal_QualificationOtherUseCase(data: Any) -> QualificationOtherUseCase: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationOtherUseCase' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationOtherUseCase(**args) + + +def unmarshal_QualificationSetScalewayEnvironment( + data: Any, +) -> QualificationSetScalewayEnvironment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationSetScalewayEnvironment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationSetScalewayEnvironment(**args) + + +def unmarshal_QualificationShareData(data: Any) -> QualificationShareData: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QualificationShareData' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sub_use_case", None) + if field is not None: + args["sub_use_case"] = field + + return QualificationShareData(**args) + + +def unmarshal_Qualification(data: Any) -> Qualification: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Qualification' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("architecture_type", None) + if field is not None: + args["architecture_type"] = field + + field = data.get("host_website", None) + if field is not None: + args["host_website"] = unmarshal_QualificationHostWebsite(field) + else: + args["host_website"] = None + + field = data.get("host_application", None) + if field is not None: + args["host_application"] = unmarshal_QualificationHostApplication(field) + else: + args["host_application"] = None + + field = data.get("deploy_software", None) + if field is not None: + args["deploy_software"] = unmarshal_QualificationDeploySoftware(field) + else: + args["deploy_software"] = None + + field = data.get("set_scaleway_environment", None) + if field is not None: + args["set_scaleway_environment"] = ( + unmarshal_QualificationSetScalewayEnvironment(field) + ) + else: + args["set_scaleway_environment"] = None + + field = data.get("ai_machine", None) + if field is not None: + args["ai_machine"] = unmarshal_QualificationAiMachine(field) + else: + args["ai_machine"] = None + + field = data.get("container", None) + if field is not None: + args["container"] = unmarshal_QualificationContainer(field) + else: + args["container"] = None + + field = data.get("archive_data", None) + if field is not None: + args["archive_data"] = unmarshal_QualificationArchiveData(field) + else: + args["archive_data"] = None + + field = data.get("share_data", None) + if field is not None: + args["share_data"] = unmarshal_QualificationShareData(field) + else: + args["share_data"] = None + + field = data.get("other_use_case", None) + if field is not None: + args["other_use_case"] = unmarshal_QualificationOtherUseCase(field) + else: + args["other_use_case"] = None + + return Qualification(**args) + + def unmarshal_Project(data: Any) -> Project: if not isinstance(data, dict): raise TypeError( @@ -40,14 +352,70 @@ def unmarshal_Project(data: Any) -> Project: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("qualification", None) + if field is not None: + args["qualification"] = unmarshal_Qualification(field) + else: + args["qualification"] = None return Project(**args) +def unmarshal_CheckContractSignatureResponse( + data: Any, +) -> CheckContractSignatureResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckContractSignatureResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("created", None) + if field is not None: + args["created"] = field + + field = data.get("validated", None) + if field is not None: + args["validated"] = field + + return CheckContractSignatureResponse(**args) + + +def unmarshal_ListContractSignaturesResponse( + data: Any, +) -> ListContractSignaturesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListContractSignaturesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("contract_signatures", None) + if field is not None: + args["contract_signatures"] = ( + [unmarshal_ContractSignature(v) for v in field] + if field is not None + else None + ) + + return ListContractSignaturesResponse(**args) + + def unmarshal_ListProjectsResponse(data: Any) -> ListProjectsResponse: if not isinstance(data, dict): raise TypeError( @@ -69,6 +437,70 @@ def unmarshal_ListProjectsResponse(data: Any) -> ListProjectsResponse: return ListProjectsResponse(**args) +def unmarshal_ProjectQualification(data: Any) -> ProjectQualification: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectQualification' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("qualification", None) + if field is not None: + args["qualification"] = unmarshal_Qualification(field) + else: + args["qualification"] = None + + return ProjectQualification(**args) + + +def marshal_ContractApiCheckContractSignatureRequest( + request: ContractApiCheckContractSignatureRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.contract_name is not None: + output["contract_name"] = request.contract_name + + if request.organization_id is not None: + output["organization_id"] = ( + request.organization_id or defaults.default_organization_id + ) + + if request.contract_type is not None: + output["contract_type"] = str(request.contract_type) + + return output + + +def marshal_ContractApiCreateContractSignatureRequest( + request: ContractApiCreateContractSignatureRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.contract_name is not None: + output["contract_name"] = request.contract_name + + if request.validated is not None: + output["validated"] = request.validated + + if request.contract_type is not None: + output["contract_type"] = str(request.contract_type) + + if request.organization_id is not None: + output["organization_id"] = ( + request.organization_id or defaults.default_organization_id + ) + + return output + + def marshal_ProjectApiCreateProjectRequest( request: ProjectApiCreateProjectRequest, defaults: ProfileDefaults, @@ -89,6 +521,155 @@ def marshal_ProjectApiCreateProjectRequest( return output +def marshal_QualificationAiMachine( + request: QualificationAiMachine, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationArchiveData( + request: QualificationArchiveData, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationContainer( + request: QualificationContainer, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationDeploySoftware( + request: QualificationDeploySoftware, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationHostApplication( + request: QualificationHostApplication, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationHostWebsite( + request: QualificationHostWebsite, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationOtherUseCase( + request: QualificationOtherUseCase, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationSetScalewayEnvironment( + request: QualificationSetScalewayEnvironment, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_QualificationShareData( + request: QualificationShareData, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.sub_use_case is not None: + output["sub_use_case"] = str(request.sub_use_case) + + return output + + +def marshal_Qualification( + request: Qualification, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("host_website", request.host_website), + OneOfPossibility("host_application", request.host_application), + OneOfPossibility("deploy_software", request.deploy_software), + OneOfPossibility( + "set_scaleway_environment", request.set_scaleway_environment + ), + OneOfPossibility("ai_machine", request.ai_machine), + OneOfPossibility("container", request.container), + OneOfPossibility("archive_data", request.archive_data), + OneOfPossibility("share_data", request.share_data), + OneOfPossibility("other_use_case", request.other_use_case), + ] + ), + ) + + if request.architecture_type is not None: + output["architecture_type"] = str(request.architecture_type) + + return output + + +def marshal_ProjectApiSetProjectQualificationRequest( + request: ProjectApiSetProjectQualificationRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.qualification is not None: + output["qualification"] = marshal_Qualification(request.qualification, defaults) + + return output + + def marshal_ProjectApiUpdateProjectRequest( request: ProjectApiUpdateProjectRequest, defaults: ProfileDefaults, diff --git a/scaleway/scaleway/account/v3/types.py b/scaleway/scaleway/account/v3/types.py index 915bdd22..d8c33ddd 100644 --- a/scaleway/scaleway/account/v3/types.py +++ b/scaleway/scaleway/account/v3/types.py @@ -11,6 +11,34 @@ StrEnumMeta, ) +from ...std.types import ( + LanguageCode as StdLanguageCode, +) + + +class ContractType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + GLOBAL = "global" + K8S = "k8s" + INSTANCE = "instance" + CONTAINER = "container" + BAREMETAL = "baremetal" + + def __str__(self) -> str: + return str(self.value) + + +class ListContractSignaturesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + SIGNED_AT_ASC = "signed_at_asc" + SIGNED_AT_DESC = "signed_at_desc" + EXPIRES_AT_ASC = "expires_at_asc" + EXPIRES_AT_DESC = "expires_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + class ListProjectsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" @@ -22,6 +50,227 @@ def __str__(self) -> str: return str(self.value) +class QualificationAiMachineSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationArchitectureType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ARCHITECTURE_TYPE = "unknown_architecture_type" + OBJECT_STORAGE = "object_storage" + WEB_HOSTING = "web_hosting" + INSTANCE = "instance" + ELASTIC = "elastic" + KUBERNETES = "kubernetes" + SERVERLESS = "serverless" + DEDICATED_SERVER = "dedicated_server" + OTHER_ARCHITECTURE_TYPE = "other_architecture_type" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationArchiveDataSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationContainerSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationDeploySoftwareSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationHostApplicationSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + SAAS_APP = "saas_app" + GOVERNMENT_APP = "government_app" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationHostWebsiteSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + INFORMATION_WEBSITE = "information_website" + ECOMMERCE_WEBSITE = "ecommerce_website" + HIGH_WEBSITE = "high_website" + OTHER_SUB_USE_CASE = "other_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationOtherUseCaseSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationSetScalewayEnvironmentSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +class QualificationShareDataSubUseCase(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SUB_USE_CASE = "unknown_sub_use_case" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class QualificationAiMachine: + sub_use_case: QualificationAiMachineSubUseCase + + +@dataclass +class QualificationArchiveData: + sub_use_case: QualificationArchiveDataSubUseCase + + +@dataclass +class QualificationContainer: + sub_use_case: QualificationContainerSubUseCase + + +@dataclass +class QualificationDeploySoftware: + sub_use_case: QualificationDeploySoftwareSubUseCase + + +@dataclass +class QualificationHostApplication: + sub_use_case: QualificationHostApplicationSubUseCase + + +@dataclass +class QualificationHostWebsite: + sub_use_case: QualificationHostWebsiteSubUseCase + + +@dataclass +class QualificationOtherUseCase: + sub_use_case: QualificationOtherUseCaseSubUseCase + + +@dataclass +class QualificationSetScalewayEnvironment: + sub_use_case: QualificationSetScalewayEnvironmentSubUseCase + + +@dataclass +class QualificationShareData: + sub_use_case: QualificationShareDataSubUseCase + + +@dataclass +class Contract: + id: str + """ + ID of the contract. + """ + + type_: ContractType + """ + The type of the contract. + """ + + name: str + """ + The name of the contract. + """ + + version: int + """ + The version of the contract. + """ + + created_at: Optional[datetime] + """ + The creation date of the contract. + """ + + updated_at: Optional[datetime] + """ + The last modification date of the contract. + """ + + +@dataclass +class Qualification: + architecture_type: QualificationArchitectureType + """ + Architecture type of the qualification. + """ + + host_website: Optional[QualificationHostWebsite] + + host_application: Optional[QualificationHostApplication] + + deploy_software: Optional[QualificationDeploySoftware] + + set_scaleway_environment: Optional[QualificationSetScalewayEnvironment] + + ai_machine: Optional[QualificationAiMachine] + + container: Optional[QualificationContainer] + + archive_data: Optional[QualificationArchiveData] + + share_data: Optional[QualificationShareData] + + other_use_case: Optional[QualificationOtherUseCase] + + +@dataclass +class ContractSignature: + id: str + """ + ID of the contract signature. + """ + + organization_id: str + """ + The Organization ID which signed the contract. + """ + + created_at: Optional[datetime] + """ + The creation date of the contract signature. + """ + + signed_at: Optional[datetime] + """ + The signing date of the contract signature. + """ + + expires_at: Optional[datetime] + """ + The expiration date of the contract signature. + """ + + contract: Optional[Contract] + """ + The contract signed. + """ + + @dataclass class Project: id: str @@ -54,6 +303,122 @@ class Project: Update date of the Project. """ + qualification: Optional[Qualification] + """ + Qualification of the Project. + """ + + +@dataclass +class CheckContractSignatureResponse: + created: bool + """ + Whether a signature has been requested for this contract. + """ + + validated: bool + """ + Whether the signature for this contract has been validated. + """ + + +@dataclass +class ContractApiCheckContractSignatureRequest: + contract_name: str + """ + Filter on contract name. + """ + + organization_id: Optional[str] + """ + ID of the Organization to check the contract signature for. + """ + + contract_type: Optional[ContractType] + """ + Filter on contract type. + """ + + +@dataclass +class ContractApiCreateContractSignatureRequest: + contract_name: str + """ + The name of the contract. + """ + + validated: bool + """ + Whether the contract is validated at creation. + """ + + contract_type: Optional[ContractType] + """ + The type of the contract. + """ + + organization_id: Optional[str] + """ + ID of the Organization. + """ + + +@dataclass +class ContractApiDownloadContractSignatureRequest: + contract_signature_id: str + """ + The contract signature ID. + """ + + locale: Optional[StdLanguageCode] + """ + The locale requested for the content of the contract. + """ + + +@dataclass +class ContractApiListContractSignaturesRequest: + page: Optional[int] + """ + The page number for the returned contracts. + """ + + page_size: Optional[int] + """ + The maximum number of contracts per page. + """ + + order_by: Optional[ListContractSignaturesRequestOrderBy] + """ + How the contracts are ordered in the response. + """ + + organization_id: Optional[str] + """ + Filter on Organization ID. + """ + + +@dataclass +class ContractApiValidateContractSignatureRequest: + contract_signature_id: str + """ + The contract linked to your Organization you want to sign. + """ + + +@dataclass +class ListContractSignaturesResponse: + total_count: int + """ + The total number of contract signatures. + """ + + contract_signatures: List[ContractSignature] + """ + The paginated returned contract signatures. + """ + @dataclass class ListProjectsResponse: @@ -135,6 +500,19 @@ class ProjectApiListProjectsRequest: """ +@dataclass +class ProjectApiSetProjectQualificationRequest: + project_id: Optional[str] + """ + Project ID. + """ + + qualification: Optional[Qualification] + """ + Use case chosen for the Project. + """ + + @dataclass class ProjectApiUpdateProjectRequest: project_id: Optional[str] @@ -151,3 +529,16 @@ class ProjectApiUpdateProjectRequest: """ Description of the Project. """ + + +@dataclass +class ProjectQualification: + project_id: str + """ + Project ID. + """ + + qualification: Optional[Qualification] + """ + Qualification of the Project. + """ diff --git a/scaleway/scaleway/applesilicon/v1alpha1/__init__.py b/scaleway/scaleway/applesilicon/v1alpha1/__init__.py index fed91efc..e50c753f 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/__init__.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/__init__.py @@ -1,55 +1,107 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import CommitmentType +from .types import ConnectivityDiagnosticActionType +from .types import ConnectivityDiagnosticDiagnosticStatus +from .types import ListServerPrivateNetworksRequestOrderBy from .types import ListServersRequestOrderBy +from .types import ServerPrivateNetworkServerStatus +from .content import SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES +from .types import ServerPrivateNetworkStatus +from .content import SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES from .types import ServerStatus from .content import SERVER_TRANSIENT_STATUSES from .types import ServerTypeStock +from .types import OS from .types import ServerTypeCPU from .types import ServerTypeDisk +from .types import ServerTypeGPU from .types import ServerTypeMemory -from .types import OS +from .types import ServerTypeNetwork +from .types import Commitment +from .types import ConnectivityDiagnosticServerHealth +from .types import ServerPrivateNetwork from .types import ServerType from .types import Server +from .types import CommitmentTypeValue +from .types import ConnectivityDiagnostic from .types import CreateServerRequest from .types import DeleteServerRequest +from .types import GetConnectivityDiagnosticRequest from .types import GetOSRequest from .types import GetServerRequest from .types import GetServerTypeRequest from .types import ListOSRequest from .types import ListOSResponse +from .types import ListServerPrivateNetworksResponse from .types import ListServerTypesRequest from .types import ListServerTypesResponse from .types import ListServersRequest from .types import ListServersResponse +from .types import PrivateNetworkApiAddServerPrivateNetworkRequest +from .types import PrivateNetworkApiDeleteServerPrivateNetworkRequest +from .types import PrivateNetworkApiGetServerPrivateNetworkRequest +from .types import PrivateNetworkApiListServerPrivateNetworksRequest +from .types import PrivateNetworkApiSetServerPrivateNetworksRequest from .types import RebootServerRequest from .types import ReinstallServerRequest +from .types import SetServerPrivateNetworksResponse +from .types import StartConnectivityDiagnosticRequest +from .types import StartConnectivityDiagnosticResponse from .types import UpdateServerRequest from .api import ApplesiliconV1Alpha1API +from .api import ApplesiliconV1Alpha1PrivateNetworkAPI __all__ = [ + "CommitmentType", + "ConnectivityDiagnosticActionType", + "ConnectivityDiagnosticDiagnosticStatus", + "ListServerPrivateNetworksRequestOrderBy", "ListServersRequestOrderBy", + "ServerPrivateNetworkServerStatus", + "SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES", + "ServerPrivateNetworkStatus", + "SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES", "ServerStatus", "SERVER_TRANSIENT_STATUSES", "ServerTypeStock", + "OS", "ServerTypeCPU", "ServerTypeDisk", + "ServerTypeGPU", "ServerTypeMemory", - "OS", + "ServerTypeNetwork", + "Commitment", + "ConnectivityDiagnosticServerHealth", + "ServerPrivateNetwork", "ServerType", "Server", + "CommitmentTypeValue", + "ConnectivityDiagnostic", "CreateServerRequest", "DeleteServerRequest", + "GetConnectivityDiagnosticRequest", "GetOSRequest", "GetServerRequest", "GetServerTypeRequest", "ListOSRequest", "ListOSResponse", + "ListServerPrivateNetworksResponse", "ListServerTypesRequest", "ListServerTypesResponse", "ListServersRequest", "ListServersResponse", + "PrivateNetworkApiAddServerPrivateNetworkRequest", + "PrivateNetworkApiDeleteServerPrivateNetworkRequest", + "PrivateNetworkApiGetServerPrivateNetworkRequest", + "PrivateNetworkApiListServerPrivateNetworksRequest", + "PrivateNetworkApiSetServerPrivateNetworksRequest", "RebootServerRequest", "ReinstallServerRequest", + "SetServerPrivateNetworksResponse", + "StartConnectivityDiagnosticRequest", + "StartConnectivityDiagnosticResponse", "UpdateServerRequest", "ApplesiliconV1Alpha1API", + "ApplesiliconV1Alpha1PrivateNetworkAPI", ] diff --git a/scaleway/scaleway/applesilicon/v1alpha1/api.py b/scaleway/scaleway/applesilicon/v1alpha1/api.py index 350cefe5..8a0fc312 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/api.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/api.py @@ -1,11 +1,11 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. -from typing import List, Optional +from typing import Dict, List, Optional from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, @@ -15,38 +15,62 @@ wait_for_resource, ) from .types import ( + CommitmentType, + ListServerPrivateNetworksRequestOrderBy, ListServersRequestOrderBy, + CommitmentTypeValue, + ConnectivityDiagnostic, CreateServerRequest, ListOSResponse, + ListServerPrivateNetworksResponse, ListServerTypesResponse, ListServersResponse, OS, + PrivateNetworkApiAddServerPrivateNetworkRequest, + PrivateNetworkApiSetServerPrivateNetworksRequest, + ReinstallServerRequest, Server, + ServerPrivateNetwork, ServerType, + SetServerPrivateNetworksResponse, + StartConnectivityDiagnosticRequest, + StartConnectivityDiagnosticResponse, UpdateServerRequest, ) from .content import ( + SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES, SERVER_TRANSIENT_STATUSES, ) from .marshalling import ( unmarshal_OS, + unmarshal_ServerPrivateNetwork, unmarshal_ServerType, unmarshal_Server, + unmarshal_ConnectivityDiagnostic, unmarshal_ListOSResponse, + unmarshal_ListServerPrivateNetworksResponse, unmarshal_ListServerTypesResponse, unmarshal_ListServersResponse, + unmarshal_SetServerPrivateNetworksResponse, + unmarshal_StartConnectivityDiagnosticResponse, marshal_CreateServerRequest, + marshal_PrivateNetworkApiAddServerPrivateNetworkRequest, + marshal_PrivateNetworkApiSetServerPrivateNetworksRequest, + marshal_ReinstallServerRequest, + marshal_StartConnectivityDiagnosticRequest, marshal_UpdateServerRequest, ) class ApplesiliconV1Alpha1API(API): - """ """ + """ + This API allows you to manage your Apple silicon machines. + """ def list_server_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ListServerTypesResponse: """ List server types. @@ -74,7 +98,7 @@ def get_server_type( self, *, server_type: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ServerType: """ Get a server type. @@ -106,17 +130,23 @@ def create_server( self, *, type_: str, - zone: Optional[Zone] = None, + enable_vpc: bool, + zone: Optional[ScwZone] = None, name: Optional[str] = None, project_id: Optional[str] = None, + os_id: Optional[str] = None, + commitment_type: Optional[CommitmentType] = None, ) -> Server: """ Create a server. Create a new server in the targeted zone, specifying its configuration including name and type. :param type_: Create a server of the given type. + :param enable_vpc: Activate the Private Network feature for this server. This feature is configured through the Apple Silicon - Private Networks API. :param zone: Zone to target. If none is passed will use default zone from the config. :param name: Create a server with this given name. :param project_id: Create a server in the given project ID. + :param os_id: Create a server & install the given os_id, when no os_id provided the default OS for this server type is chosen. Requesting a non-default OS will induce an extended delivery time. + :param commitment_type: Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing (commitment_type `duration_24h`). It can be updated with the Update Server request. Available commitment depends on server type. :return: :class:`Server ` Usage: @@ -124,6 +154,7 @@ def create_server( result = api.create_server( type="example", + enable_vpc=False, ) """ @@ -135,9 +166,12 @@ def create_server( body=marshal_CreateServerRequest( CreateServerRequest( type_=type_, + enable_vpc=enable_vpc, zone=zone, name=name or random_name(prefix="as"), project_id=project_id, + os_id=os_id, + commitment_type=commitment_type, ), self.client, ), @@ -149,7 +183,7 @@ def create_server( def list_servers( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListServersRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -194,7 +228,7 @@ def list_servers( def list_servers_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListServersRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -235,7 +269,7 @@ def list_servers_all( def list_os( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, server_type: Optional[str] = None, @@ -276,7 +310,7 @@ def list_os( def list_os_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, server_type: Optional[str] = None, @@ -315,7 +349,7 @@ def get_os( self, *, os_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> OS: """ Get an Operating System (OS). @@ -347,7 +381,7 @@ def get_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Get a server. @@ -379,7 +413,7 @@ def wait_for_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Server, bool]] = None, ) -> Server: """ @@ -416,8 +450,11 @@ def update_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, + schedule_deletion: Optional[bool] = None, + enable_vpc: Optional[bool] = None, + commitment_type: Optional[CommitmentTypeValue] = None, ) -> Server: """ Update a server. @@ -425,6 +462,9 @@ def update_server( :param server_id: UUID of the server you want to update. :param zone: Zone to target. If none is passed will use default zone from the config. :param name: Updated name for your server. + :param schedule_deletion: Specify whether the server should be flagged for automatic deletion. + :param enable_vpc: Activate or deactivate Private Network support for this server. + :param commitment_type: Change commitment. Use 'none' to automatically cancel a renewing commitment. :return: :class:`Server ` Usage: @@ -446,6 +486,9 @@ def update_server( server_id=server_id, zone=zone, name=name, + schedule_deletion=schedule_deletion, + enable_vpc=enable_vpc, + commitment_type=commitment_type, ), self.client, ), @@ -458,7 +501,7 @@ def delete_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a server. @@ -488,7 +531,7 @@ def reboot_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Reboot a server. @@ -521,13 +564,15 @@ def reinstall_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, + os_id: Optional[str] = None, ) -> Server: """ Reinstall a server. Reinstall an existing Apple silicon server (specified by its server ID) from a new image (OS). All the data on the disk is deleted and all configuration is reset to the defailt configuration values of the image (OS). :param server_id: UUID of the server you want to reinstall. :param zone: Zone to target. If none is passed will use default zone from the config. + :param os_id: Reinstall the server with the target OS, when no os_id provided the default OS for the server type is used. :return: :class:`Server ` Usage: @@ -544,8 +589,393 @@ def reinstall_server( res = self._request( "POST", f"/apple-silicon/v1alpha1/zones/{param_zone}/servers/{param_server_id}/reinstall", - body={}, + body=marshal_ReinstallServerRequest( + ReinstallServerRequest( + server_id=server_id, + zone=zone, + os_id=os_id, + ), + self.client, + ), ) self._throw_on_error(res) return unmarshal_Server(res.json()) + + def start_connectivity_diagnostic( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> StartConnectivityDiagnosticResponse: + """ + :param server_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`StartConnectivityDiagnosticResponse ` + + Usage: + :: + + result = api.start_connectivity_diagnostic( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/apple-silicon/v1alpha1/zones/{param_zone}/connectivity-diagnostics", + body=marshal_StartConnectivityDiagnosticRequest( + StartConnectivityDiagnosticRequest( + server_id=server_id, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_StartConnectivityDiagnosticResponse(res.json()) + + def get_connectivity_diagnostic( + self, + *, + diagnostic_id: str, + zone: Optional[ScwZone] = None, + ) -> ConnectivityDiagnostic: + """ + :param diagnostic_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ConnectivityDiagnostic ` + + Usage: + :: + + result = api.get_connectivity_diagnostic( + diagnostic_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_diagnostic_id = validate_path_param("diagnostic_id", diagnostic_id) + + res = self._request( + "GET", + f"/apple-silicon/v1alpha1/zones/{param_zone}/connectivity-diagnostics/{param_diagnostic_id}", + ) + + self._throw_on_error(res) + return unmarshal_ConnectivityDiagnostic(res.json()) + + +class ApplesiliconV1Alpha1PrivateNetworkAPI(API): + """ + Apple silicon - Private Networks API. + """ + + def get_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + ) -> ServerPrivateNetwork: + """ + :param server_id: + :param private_network_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerPrivateNetwork ` + + Usage: + :: + + result = api.get_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + param_private_network_id = validate_path_param( + "private_network_id", private_network_id + ) + + res = self._request( + "GET", + f"/apple-silicon/v1alpha1/zones/{param_zone}/servers/{param_server_id}/private-networks/{param_private_network_id}", + ) + + self._throw_on_error(res) + return unmarshal_ServerPrivateNetwork(res.json()) + + def wait_for_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[ServerPrivateNetwork, bool]] = None, + ) -> ServerPrivateNetwork: + """ + :param server_id: + :param private_network_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerPrivateNetwork ` + + Usage: + :: + + result = api.get_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status + not in SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES + ) + + return wait_for_resource( + fetcher=self.get_server_private_network, + options=options, + args={ + "server_id": server_id, + "private_network_id": private_network_id, + "zone": zone, + }, + ) + + def add_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> ServerPrivateNetwork: + """ + Add a server to a Private Network. + Add an Apple silicon server to a Private Network. + :param server_id: ID of the server. + :param private_network_id: ID of the Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param ipam_ip_ids: IPAM IDs of IPs to attach to the server. + :return: :class:`ServerPrivateNetwork ` + + Usage: + :: + + result = api.add_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/apple-silicon/v1alpha1/zones/{param_zone}/servers/{param_server_id}/private-networks", + body=marshal_PrivateNetworkApiAddServerPrivateNetworkRequest( + PrivateNetworkApiAddServerPrivateNetworkRequest( + server_id=server_id, + private_network_id=private_network_id, + zone=zone, + ipam_ip_ids=ipam_ip_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ServerPrivateNetwork(res.json()) + + def set_server_private_networks( + self, + *, + server_id: str, + per_private_network_ipam_ip_ids: Dict[str, List[str]], + zone: Optional[ScwZone] = None, + ) -> SetServerPrivateNetworksResponse: + """ + Set multiple Private Networks on a server. + Configure multiple Private Networks on an Apple silicon server. + :param server_id: ID of the server. + :param per_private_network_ipam_ip_ids: Object where the keys are the IDs of Private Networks and the values are arrays of IPAM IDs representing the IPs to assign to this Apple silicon server on the Private Network. If the array supplied for a Private Network is empty, the next available IP from the Private Network's CIDR block will automatically be used for attachment. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`SetServerPrivateNetworksResponse ` + + Usage: + :: + + result = api.set_server_private_networks( + server_id="example", + per_private_network_ipam_ip_ids={}, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "PUT", + f"/apple-silicon/v1alpha1/zones/{param_zone}/servers/{param_server_id}/private-networks", + body=marshal_PrivateNetworkApiSetServerPrivateNetworksRequest( + PrivateNetworkApiSetServerPrivateNetworksRequest( + server_id=server_id, + per_private_network_ipam_ip_ids=per_private_network_ipam_ip_ids, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetServerPrivateNetworksResponse(res.json()) + + def list_server_private_networks( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + server_id: Optional[str] = None, + private_network_id: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> ListServerPrivateNetworksResponse: + """ + List the Private Networks of a server. + List the Private Networks of an Apple silicon server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order for the returned Private Networks. + :param page: Page number for the returned Private Networks. + :param page_size: Maximum number of Private Networks per page. + :param server_id: Filter Private Networks by server ID. + :param private_network_id: Filter Private Networks by Private Network ID. + :param organization_id: Filter Private Networks by Organization ID. + :param project_id: Filter Private Networks by Project ID. + :param ipam_ip_ids: Filter Private Networks by IPAM IP IDs. + :return: :class:`ListServerPrivateNetworksResponse ` + + Usage: + :: + + result = api.list_server_private_networks() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/apple-silicon/v1alpha1/zones/{param_zone}/server-private-networks", + params={ + "ipam_ip_ids": ipam_ip_ids, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "private_network_id": private_network_id, + "project_id": project_id or self.client.default_project_id, + "server_id": server_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServerPrivateNetworksResponse(res.json()) + + def list_server_private_networks_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + server_id: Optional[str] = None, + private_network_id: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> List[ServerPrivateNetwork]: + """ + List the Private Networks of a server. + List the Private Networks of an Apple silicon server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order for the returned Private Networks. + :param page: Page number for the returned Private Networks. + :param page_size: Maximum number of Private Networks per page. + :param server_id: Filter Private Networks by server ID. + :param private_network_id: Filter Private Networks by Private Network ID. + :param organization_id: Filter Private Networks by Organization ID. + :param project_id: Filter Private Networks by Project ID. + :param ipam_ip_ids: Filter Private Networks by IPAM IP IDs. + :return: :class:`List[ServerPrivateNetwork] ` + + Usage: + :: + + result = api.list_server_private_networks_all() + """ + + return fetch_all_pages( + type=ListServerPrivateNetworksResponse, + key="server_private_networks", + fetcher=self.list_server_private_networks, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "server_id": server_id, + "private_network_id": private_network_id, + "organization_id": organization_id, + "project_id": project_id, + "ipam_ip_ids": ipam_ip_ids, + }, + ) + + def delete_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a Private Network. + :param server_id: ID of the server. + :param private_network_id: ID of the Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + param_private_network_id = validate_path_param( + "private_network_id", private_network_id + ) + + res = self._request( + "DELETE", + f"/apple-silicon/v1alpha1/zones/{param_zone}/servers/{param_server_id}/private-networks/{param_private_network_id}", + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/applesilicon/v1alpha1/content.py b/scaleway/scaleway/applesilicon/v1alpha1/content.py index bac38d1e..d8118f9f 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/content.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/content.py @@ -3,9 +3,26 @@ from typing import List from .types import ( + ServerPrivateNetworkServerStatus, + ServerPrivateNetworkStatus, ServerStatus, ) +SERVER_PRIVATE_NETWORK_SERVER_TRANSIENT_STATUSES: List[ + ServerPrivateNetworkServerStatus +] = [ + ServerPrivateNetworkServerStatus.ATTACHING, + ServerPrivateNetworkServerStatus.DETACHING, +] +""" +Lists transient statutes of the enum :class:`ServerPrivateNetworkServerStatus `. +""" +SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES: List[ServerPrivateNetworkStatus] = [ + ServerPrivateNetworkStatus.VPC_UPDATING, +] +""" +Lists transient statutes of the enum :class:`ServerPrivateNetworkStatus `. +""" SERVER_TRANSIENT_STATUSES: List[ServerStatus] = [ ServerStatus.STARTING, ServerStatus.REBOOTING, @@ -13,6 +30,7 @@ ServerStatus.LOCKING, ServerStatus.UNLOCKING, ServerStatus.REINSTALLING, + ServerStatus.BUSY, ] """ Lists transient statutes of the enum :class:`ServerStatus `. diff --git a/scaleway/scaleway/applesilicon/v1alpha1/marshalling.py b/scaleway/scaleway/applesilicon/v1alpha1/marshalling.py index 4524d1c5..be75811b 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/marshalling.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/marshalling.py @@ -6,16 +6,31 @@ from scaleway_core.profile import ProfileDefaults from .types import ( + ConnectivityDiagnosticActionType, OS, + ServerPrivateNetwork, ServerTypeCPU, ServerTypeDisk, + ServerTypeGPU, ServerTypeMemory, + ServerTypeNetwork, ServerType, + Commitment, Server, + ConnectivityDiagnosticServerHealth, + ConnectivityDiagnostic, ListOSResponse, + ListServerPrivateNetworksResponse, ListServerTypesResponse, ListServersResponse, + SetServerPrivateNetworksResponse, + StartConnectivityDiagnosticResponse, CreateServerRequest, + PrivateNetworkApiAddServerPrivateNetworkRequest, + PrivateNetworkApiSetServerPrivateNetworksRequest, + ReinstallServerRequest, + StartConnectivityDiagnosticRequest, + CommitmentTypeValue, UpdateServerRequest, ) @@ -44,6 +59,22 @@ def unmarshal_OS(data: Any) -> OS: if field is not None: args["image_url"] = field + field = data.get("family", None) + if field is not None: + args["family"] = field + + field = data.get("is_beta", None) + if field is not None: + args["is_beta"] = field + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("xcode_version", None) + if field is not None: + args["xcode_version"] = field + field = data.get("compatible_server_types", None) if field is not None: args["compatible_server_types"] = field @@ -51,6 +82,59 @@ def unmarshal_OS(data: Any) -> OS: return OS(**args) +def unmarshal_ServerPrivateNetwork(data: Any) -> ServerPrivateNetwork: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerPrivateNetwork' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("server_id", None) + if field is not None: + args["server_id"] = field + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("ipam_ip_ids", None) + if field is not None: + args["ipam_ip_ids"] = field + + field = data.get("vlan", None) + if field is not None: + args["vlan"] = field + else: + args["vlan"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return ServerPrivateNetwork(**args) + + def unmarshal_ServerTypeCPU(data: Any) -> ServerTypeCPU: if not isinstance(data, dict): raise TypeError( @@ -67,6 +151,10 @@ def unmarshal_ServerTypeCPU(data: Any) -> ServerTypeCPU: if field is not None: args["core_count"] = field + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + return ServerTypeCPU(**args) @@ -82,13 +170,28 @@ def unmarshal_ServerTypeDisk(data: Any) -> ServerTypeDisk: if field is not None: args["capacity"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field return ServerTypeDisk(**args) +def unmarshal_ServerTypeGPU(data: Any) -> ServerTypeGPU: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerTypeGPU' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("count", None) + if field is not None: + args["count"] = field + + return ServerTypeGPU(**args) + + def unmarshal_ServerTypeMemory(data: Any) -> ServerTypeMemory: if not isinstance(data, dict): raise TypeError( @@ -101,13 +204,28 @@ def unmarshal_ServerTypeMemory(data: Any) -> ServerTypeMemory: if field is not None: args["capacity"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field return ServerTypeMemory(**args) +def unmarshal_ServerTypeNetwork(data: Any) -> ServerTypeNetwork: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerTypeNetwork' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("public_bandwidth_bps", None) + if field is not None: + args["public_bandwidth_bps"] = field + + return ServerTypeNetwork(**args) + + def unmarshal_ServerType(data: Any) -> ServerType: if not isinstance(data, dict): raise TypeError( @@ -127,22 +245,67 @@ def unmarshal_ServerType(data: Any) -> ServerType: field = data.get("cpu", None) if field is not None: args["cpu"] = unmarshal_ServerTypeCPU(field) + else: + args["cpu"] = None field = data.get("disk", None) if field is not None: args["disk"] = unmarshal_ServerTypeDisk(field) + else: + args["disk"] = None field = data.get("memory", None) if field is not None: args["memory"] = unmarshal_ServerTypeMemory(field) + else: + args["memory"] = None field = data.get("minimum_lease_duration", None) if field is not None: args["minimum_lease_duration"] = field + else: + args["minimum_lease_duration"] = None + + field = data.get("gpu", None) + if field is not None: + args["gpu"] = unmarshal_ServerTypeGPU(field) + else: + args["gpu"] = None + + field = data.get("network", None) + if field is not None: + args["network"] = unmarshal_ServerTypeNetwork(field) + else: + args["network"] = None + + field = data.get("default_os", None) + if field is not None: + args["default_os"] = unmarshal_OS(field) + else: + args["default_os"] = None return ServerType(**args) +def unmarshal_Commitment(data: Any) -> Commitment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Commitment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("cancelled", None) + if field is not None: + args["cancelled"] = field + + return Commitment(**args) + + def unmarshal_Server(data: Any) -> Server: if not isinstance(data, dict): raise TypeError( @@ -155,7 +318,7 @@ def unmarshal_Server(data: Any) -> Server: if field is not None: args["id"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -179,31 +342,155 @@ def unmarshal_Server(data: Any) -> Server: if field is not None: args["vnc_url"] = field + field = data.get("ssh_username", None) + if field is not None: + args["ssh_username"] = field + + field = data.get("sudo_password", None) + if field is not None: + args["sudo_password"] = field + + field = data.get("vnc_port", None) + if field is not None: + args["vnc_port"] = field + field = data.get("status", None) if field is not None: args["status"] = field - field = data.get("zone", None) + field = data.get("os", None) if field is not None: - args["zone"] = field + args["os"] = unmarshal_OS(field) + else: + args["os"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("deletable_at", None) if field is not None: args["deletable_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["deletable_at"] = None + + field = data.get("deletion_scheduled", None) + if field is not None: + args["deletion_scheduled"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("delivered", None) + if field is not None: + args["delivered"] = field + + field = data.get("vpc_status", None) + if field is not None: + args["vpc_status"] = field + + field = data.get("commitment", None) + if field is not None: + args["commitment"] = unmarshal_Commitment(field) + else: + args["commitment"] = None return Server(**args) +def unmarshal_ConnectivityDiagnosticServerHealth( + data: Any, +) -> ConnectivityDiagnosticServerHealth: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ConnectivityDiagnosticServerHealth' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_server_alive", None) + if field is not None: + args["is_server_alive"] = field + + field = data.get("is_agent_alive", None) + if field is not None: + args["is_agent_alive"] = field + + field = data.get("is_mdm_alive", None) + if field is not None: + args["is_mdm_alive"] = field + + field = data.get("is_ssh_port_up", None) + if field is not None: + args["is_ssh_port_up"] = field + + field = data.get("is_vnc_port_up", None) + if field is not None: + args["is_vnc_port_up"] = field + + field = data.get("last_checkin_date", None) + if field is not None: + args["last_checkin_date"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["last_checkin_date"] = None + + return ConnectivityDiagnosticServerHealth(**args) + + +def unmarshal_ConnectivityDiagnostic(data: Any) -> ConnectivityDiagnostic: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ConnectivityDiagnostic' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("is_healthy", None) + if field is not None: + args["is_healthy"] = field + + field = data.get("supported_actions", None) + if field is not None: + args["supported_actions"] = ( + [ConnectivityDiagnosticActionType(v) for v in field] + if field is not None + else None + ) + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + + field = data.get("health_details", None) + if field is not None: + args["health_details"] = unmarshal_ConnectivityDiagnosticServerHealth(field) + else: + args["health_details"] = None + + return ConnectivityDiagnostic(**args) + + def unmarshal_ListOSResponse(data: Any) -> ListOSResponse: if not isinstance(data, dict): raise TypeError( @@ -223,6 +510,31 @@ def unmarshal_ListOSResponse(data: Any) -> ListOSResponse: return ListOSResponse(**args) +def unmarshal_ListServerPrivateNetworksResponse( + data: Any, +) -> ListServerPrivateNetworksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServerPrivateNetworksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("server_private_networks", None) + if field is not None: + args["server_private_networks"] = ( + [unmarshal_ServerPrivateNetwork(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListServerPrivateNetworksResponse(**args) + + def unmarshal_ListServerTypesResponse(data: Any) -> ListServerTypesResponse: if not isinstance(data, dict): raise TypeError( @@ -261,6 +573,44 @@ def unmarshal_ListServersResponse(data: Any) -> ListServersResponse: return ListServersResponse(**args) +def unmarshal_SetServerPrivateNetworksResponse( + data: Any, +) -> SetServerPrivateNetworksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetServerPrivateNetworksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("server_private_networks", None) + if field is not None: + args["server_private_networks"] = ( + [unmarshal_ServerPrivateNetwork(v) for v in field] + if field is not None + else None + ) + + return SetServerPrivateNetworksResponse(**args) + + +def unmarshal_StartConnectivityDiagnosticResponse( + data: Any, +) -> StartConnectivityDiagnosticResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'StartConnectivityDiagnosticResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("diagnostic_id", None) + if field is not None: + args["diagnostic_id"] = field + + return StartConnectivityDiagnosticResponse(**args) + + def marshal_CreateServerRequest( request: CreateServerRequest, defaults: ProfileDefaults, @@ -270,12 +620,86 @@ def marshal_CreateServerRequest( if request.type_ is not None: output["type"] = request.type_ + if request.enable_vpc is not None: + output["enable_vpc"] = request.enable_vpc + if request.name is not None: output["name"] = request.name if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id + if request.os_id is not None: + output["os_id"] = request.os_id + + if request.commitment_type is not None: + output["commitment_type"] = str(request.commitment_type) + + return output + + +def marshal_PrivateNetworkApiAddServerPrivateNetworkRequest( + request: PrivateNetworkApiAddServerPrivateNetworkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + if request.ipam_ip_ids is not None: + output["ipam_ip_ids"] = request.ipam_ip_ids + + return output + + +def marshal_PrivateNetworkApiSetServerPrivateNetworksRequest( + request: PrivateNetworkApiSetServerPrivateNetworksRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.per_private_network_ipam_ip_ids is not None: + output["per_private_network_ipam_ip_ids"] = { + key: value for key, value in request.per_private_network_ipam_ip_ids.items() + } + + return output + + +def marshal_ReinstallServerRequest( + request: ReinstallServerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.os_id is not None: + output["os_id"] = request.os_id + + return output + + +def marshal_StartConnectivityDiagnosticRequest( + request: StartConnectivityDiagnosticRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.server_id is not None: + output["server_id"] = request.server_id + + return output + + +def marshal_CommitmentTypeValue( + request: CommitmentTypeValue, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.commitment_type is not None: + output["commitment_type"] = str(request.commitment_type) + return output @@ -288,4 +712,15 @@ def marshal_UpdateServerRequest( if request.name is not None: output["name"] = request.name + if request.schedule_deletion is not None: + output["schedule_deletion"] = request.schedule_deletion + + if request.enable_vpc is not None: + output["enable_vpc"] = request.enable_vpc + + if request.commitment_type is not None: + output["commitment_type"] = marshal_CommitmentTypeValue( + request.commitment_type, defaults + ) + return output diff --git a/scaleway/scaleway/applesilicon/v1alpha1/types.py b/scaleway/scaleway/applesilicon/v1alpha1/types.py index 79291bad..692f3e59 100644 --- a/scaleway/scaleway/applesilicon/v1alpha1/types.py +++ b/scaleway/scaleway/applesilicon/v1alpha1/types.py @@ -5,16 +5,53 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import List, Optional +from typing import Dict, List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, ) +class CommitmentType(str, Enum, metaclass=StrEnumMeta): + DURATION_24H = "duration_24h" + RENEWED_MONTHLY = "renewed_monthly" + NONE = "none" + + def __str__(self) -> str: + return str(self.value) + + +class ConnectivityDiagnosticActionType(str, Enum, metaclass=StrEnumMeta): + REBOOT_SERVER = "reboot_server" + REINSTALL_SERVER = "reinstall_server" + + def __str__(self) -> str: + return str(self.value) + + +class ConnectivityDiagnosticDiagnosticStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + PROCESSING = "processing" + ERROR = "error" + COMPLETED = "completed" + + def __str__(self) -> str: + return str(self.value) + + +class ListServerPrivateNetworksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + UPDATED_AT_ASC = "updated_at_asc" + UPDATED_AT_DESC = "updated_at_desc" + + def __str__(self) -> str: + return str(self.value) + + class ListServersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -23,6 +60,28 @@ def __str__(self) -> str: return str(self.value) +class ServerPrivateNetworkServerStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + ATTACHING = "attaching" + ATTACHED = "attached" + ERROR = "error" + DETACHING = "detaching" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class ServerPrivateNetworkStatus(str, Enum, metaclass=StrEnumMeta): + VPC_UNKNOWN_STATUS = "vpc_unknown_status" + VPC_ENABLED = "vpc_enabled" + VPC_UPDATING = "vpc_updating" + VPC_DISABLED = "vpc_disabled" + + def __str__(self) -> str: + return str(self.value) + + class ServerStatus(str, Enum, metaclass=StrEnumMeta): UNKNOWN_STATUS = "unknown_status" STARTING = "starting" @@ -34,6 +93,7 @@ class ServerStatus(str, Enum, metaclass=StrEnumMeta): LOCKED = "locked" UNLOCKING = "unlocking" REINSTALLING = "reinstalling" + BUSY = "busy" def __str__(self) -> str: return str(self.value) @@ -49,12 +109,62 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class OS: + id: str + """ + Unique ID of the OS. + """ + + name: str + """ + OS name. + """ + + label: str + """ + OS name as it should be displayed. + """ + + image_url: str + """ + URL of the image. + """ + + family: str + """ + The OS family to which this OS belongs, eg. 13 or 14. + """ + + is_beta: bool + """ + Describes if the OS is in beta. + """ + + version: str + """ + The OS version number, eg. Sonoma has version number 14.3. + """ + + xcode_version: str + """ + The current xcode version for this OS. + """ + + compatible_server_types: List[str] + """ + List of compatible server types. + """ + + @dataclass class ServerTypeCPU: name: str core_count: int + frequency: int + @dataclass class ServerTypeDisk: @@ -63,6 +173,11 @@ class ServerTypeDisk: type_: str +@dataclass +class ServerTypeGPU: + count: int + + @dataclass class ServerTypeMemory: capacity: int @@ -71,30 +186,77 @@ class ServerTypeMemory: @dataclass -class OS: +class ServerTypeNetwork: + public_bandwidth_bps: int + + +@dataclass +class Commitment: + type_: CommitmentType + + cancelled: bool + + +@dataclass +class ConnectivityDiagnosticServerHealth: + is_server_alive: bool + + is_agent_alive: bool + + is_mdm_alive: bool + + is_ssh_port_up: bool + + is_vnc_port_up: bool + + last_checkin_date: Optional[datetime] + + +@dataclass +class ServerPrivateNetwork: id: str """ - Unique ID of the OS. + ID of the Server-to-Private Network mapping. """ - name: str + project_id: str """ - OS name. + Private Network Project ID. """ - label: str + server_id: str """ - OS name as it should be displayed. + Apple silicon server ID. """ - image_url: str + private_network_id: str """ - URL of the image. + Private Network ID. """ - compatible_server_types: List[str] + status: ServerPrivateNetworkServerStatus """ - List of compatible server types. + Configuration status of the Private Network. + """ + + ipam_ip_ids: List[str] + """ + IPAM IP IDs of the server, if it has any. + """ + + vlan: Optional[int] + """ + ID of the VLAN associated with the Private Network. + """ + + created_at: Optional[datetime] + """ + Private Network creation date. + """ + + updated_at: Optional[datetime] + """ + Date the Private Network was last modified. """ @@ -130,6 +292,21 @@ class ServerType: Minimum duration of the lease in seconds (example. 3.4s). """ + gpu: Optional[ServerTypeGPU] + """ + GPU description. + """ + + network: Optional[ServerTypeNetwork] + """ + Network description. + """ + + default_os: Optional[OS] + """ + The default OS for this server type. + """ + @dataclass class Server: @@ -165,7 +342,22 @@ class Server: vnc_url: str """ - URL of the VNC. + Vnc:// URL to access Apple Remote Desktop. + """ + + ssh_username: str + """ + SSH Username for remote shell. + """ + + sudo_password: str + """ + Admin password required to execute commands. + """ + + vnc_port: int + """ + VNC port to use for remote desktop connection. """ status: ServerStatus @@ -173,9 +365,9 @@ class Server: Current status of the server. """ - zone: Zone + os: Optional[OS] """ - Zone of the server. + Initially installed OS, this does not necessarily reflect the current OS version. """ created_at: Optional[datetime] @@ -190,10 +382,55 @@ class Server: deletable_at: Optional[datetime] """ - Date on which the server was last deleted. + Date from which the server can be deleted. + """ + + deletion_scheduled: bool + """ + Set to true to mark the server for automatic deletion depending on `deletable_at` date. Set to false to cancel an existing deletion schedule. Leave unset otherwise. + """ + + zone: ScwZone + """ + Zone of the server. + """ + + delivered: bool + """ + Set to true once the server has completed its provisioning steps and is ready to use. Some OS configurations might require a reinstallation of the server before delivery depending on the available stock. A reinstallation after the initial delivery will not change this flag and can be tracked using the server status. + """ + + vpc_status: ServerPrivateNetworkStatus + """ + Activation status of optional Private Network feature support for this server. + """ + + commitment: Optional[Commitment] + """ + Commitment scheme applied to this server. """ +@dataclass +class CommitmentTypeValue: + commitment_type: CommitmentType + + +@dataclass +class ConnectivityDiagnostic: + id: str + + status: ConnectivityDiagnosticDiagnosticStatus + + is_healthy: bool + + supported_actions: List[ConnectivityDiagnosticActionType] + + error_message: str + + health_details: Optional[ConnectivityDiagnosticServerHealth] + + @dataclass class CreateServerRequest: type_: str @@ -201,7 +438,12 @@ class CreateServerRequest: Create a server of the given type. """ - zone: Optional[Zone] + enable_vpc: bool + """ + Activate the Private Network feature for this server. This feature is configured through the Apple Silicon - Private Networks API. + """ + + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -216,6 +458,16 @@ class CreateServerRequest: Create a server in the given project ID. """ + os_id: Optional[str] + """ + Create a server & install the given os_id, when no os_id provided the default OS for this server type is chosen. Requesting a non-default OS will induce an extended delivery time. + """ + + commitment_type: Optional[CommitmentType] + """ + Activate commitment for this server. If not specified, there is a 24h commitment due to Apple licensing (commitment_type `duration_24h`). It can be updated with the Update Server request. Available commitment depends on server type. + """ + @dataclass class DeleteServerRequest: @@ -224,7 +476,17 @@ class DeleteServerRequest: UUID of the server you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetConnectivityDiagnosticRequest: + diagnostic_id: str + + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -237,7 +499,7 @@ class GetOSRequest: UUID of the OS you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -250,7 +512,7 @@ class GetServerRequest: UUID of the server you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -263,7 +525,7 @@ class GetServerTypeRequest: Server type identifier. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -271,7 +533,7 @@ class GetServerTypeRequest: @dataclass class ListOSRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -310,9 +572,16 @@ class ListOSResponse: """ +@dataclass +class ListServerPrivateNetworksResponse: + server_private_networks: List[ServerPrivateNetwork] + + total_count: int + + @dataclass class ListServerTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -328,7 +597,7 @@ class ListServerTypesResponse: @dataclass class ListServersRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -372,6 +641,125 @@ class ListServersResponse: """ +@dataclass +class PrivateNetworkApiAddServerPrivateNetworkRequest: + server_id: str + """ + ID of the server. + """ + + private_network_id: str + """ + ID of the Private Network. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + ipam_ip_ids: Optional[List[str]] + """ + IPAM IDs of IPs to attach to the server. + """ + + +@dataclass +class PrivateNetworkApiDeleteServerPrivateNetworkRequest: + server_id: str + """ + ID of the server. + """ + + private_network_id: str + """ + ID of the Private Network. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class PrivateNetworkApiGetServerPrivateNetworkRequest: + server_id: str + + private_network_id: str + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class PrivateNetworkApiListServerPrivateNetworksRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] + """ + Sort order for the returned Private Networks. + """ + + page: Optional[int] + """ + Page number for the returned Private Networks. + """ + + page_size: Optional[int] + """ + Maximum number of Private Networks per page. + """ + + server_id: Optional[str] + """ + Filter Private Networks by server ID. + """ + + private_network_id: Optional[str] + """ + Filter Private Networks by Private Network ID. + """ + + organization_id: Optional[str] + """ + Filter Private Networks by Organization ID. + """ + + project_id: Optional[str] + """ + Filter Private Networks by Project ID. + """ + + ipam_ip_ids: Optional[List[str]] + """ + Filter Private Networks by IPAM IP IDs. + """ + + +@dataclass +class PrivateNetworkApiSetServerPrivateNetworksRequest: + server_id: str + """ + ID of the server. + """ + + per_private_network_ipam_ip_ids: Dict[str, List[str]] + """ + Object where the keys are the IDs of Private Networks and the values are arrays of IPAM IDs representing the IPs to assign to this Apple silicon server on the Private Network. If the array supplied for a Private Network is empty, the next available IP from the Private Network's CIDR block will automatically be used for attachment. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class RebootServerRequest: server_id: str @@ -379,7 +767,7 @@ class RebootServerRequest: UUID of the server you want to reboot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -392,11 +780,36 @@ class ReinstallServerRequest: UUID of the server you want to reinstall. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ + os_id: Optional[str] + """ + Reinstall the server with the target OS, when no os_id provided the default OS for the server type is used. + """ + + +@dataclass +class SetServerPrivateNetworksResponse: + server_private_networks: List[ServerPrivateNetwork] + + +@dataclass +class StartConnectivityDiagnosticRequest: + server_id: str + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StartConnectivityDiagnosticResponse: + diagnostic_id: str + @dataclass class UpdateServerRequest: @@ -405,7 +818,7 @@ class UpdateServerRequest: UUID of the server you want to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -414,3 +827,18 @@ class UpdateServerRequest: """ Updated name for your server. """ + + schedule_deletion: Optional[bool] + """ + Specify whether the server should be flagged for automatic deletion. + """ + + enable_vpc: Optional[bool] + """ + Activate or deactivate Private Network support for this server. + """ + + commitment_type: Optional[CommitmentTypeValue] + """ + Change commitment. Use 'none' to automatically cancel a renewing commitment. + """ diff --git a/scaleway/scaleway/audit_trail/__init__.py b/scaleway/scaleway/audit_trail/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway/scaleway/audit_trail/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/audit_trail/v1alpha1/__init__.py b/scaleway/scaleway/audit_trail/v1alpha1/__init__.py new file mode 100644 index 00000000..519c5190 --- /dev/null +++ b/scaleway/scaleway/audit_trail/v1alpha1/__init__.py @@ -0,0 +1,47 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import ListEventsRequestOrderBy +from .types import ResourceType +from .types import AccountOrganizationInfo +from .types import AccountUserInfo +from .types import KeyManagerKeyInfo +from .types import KubernetesACLInfo +from .types import KubernetesClusterInfo +from .types import KubernetesNodeInfo +from .types import KubernetesPoolInfo +from .types import SecretManagerSecretInfo +from .types import SecretManagerSecretVersionInfo +from .types import EventPrincipal +from .types import Resource +from .types import ProductService +from .types import Event +from .types import Product +from .types import ListEventsRequest +from .types import ListEventsResponse +from .types import ListProductsRequest +from .types import ListProductsResponse +from .api import AuditTrailV1Alpha1API + +__all__ = [ + "ListEventsRequestOrderBy", + "ResourceType", + "AccountOrganizationInfo", + "AccountUserInfo", + "KeyManagerKeyInfo", + "KubernetesACLInfo", + "KubernetesClusterInfo", + "KubernetesNodeInfo", + "KubernetesPoolInfo", + "SecretManagerSecretInfo", + "SecretManagerSecretVersionInfo", + "EventPrincipal", + "Resource", + "ProductService", + "Event", + "Product", + "ListEventsRequest", + "ListEventsResponse", + "ListProductsRequest", + "ListProductsResponse", + "AuditTrailV1Alpha1API", +] diff --git a/scaleway/scaleway/audit_trail/v1alpha1/api.py b/scaleway/scaleway/audit_trail/v1alpha1/api.py new file mode 100644 index 00000000..f2e593c9 --- /dev/null +++ b/scaleway/scaleway/audit_trail/v1alpha1/api.py @@ -0,0 +1,131 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from datetime import datetime +from typing import Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + validate_path_param, +) +from .types import ( + ListEventsRequestOrderBy, + ResourceType, + ListEventsResponse, + ListProductsResponse, +) +from .marshalling import ( + unmarshal_ListEventsResponse, + unmarshal_ListProductsResponse, +) + + +class AuditTrailV1Alpha1API(API): + """ + This API allows you to ensure accountability and security by recording events and changes performed within your Scaleway Organization. + """ + + def list_events( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + resource_type: Optional[ResourceType] = None, + method_name: Optional[str] = None, + status: Optional[int] = None, + recorded_after: Optional[datetime] = None, + recorded_before: Optional[datetime] = None, + order_by: Optional[ListEventsRequestOrderBy] = None, + page_size: Optional[int] = None, + page_token: Optional[str] = None, + product_name: Optional[str] = None, + service_name: Optional[str] = None, + ) -> ListEventsResponse: + """ + List events. + Retrieve the list of Audit Trail events for a Scaleway Organization and/or Project. You must specify the `organization_id` and optionally, the `project_id`. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: (Optional) ID of the Project containing the Audit Trail events. + :param organization_id: ID of the Organization containing the Audit Trail events. + :param resource_type: (Optional) Returns a paginated list of Scaleway resources' features. + :param method_name: (Optional) Name of the method of the API call performed. + :param status: (Optional) HTTP status code of the request. Returns either `200` if the request was successful or `403` if the permission was denied. + :param recorded_after: (Optional) The `recorded_after` parameter defines the earliest timestamp from which Audit Trail events are retrieved. Returns `one hour ago` by default. + :param recorded_before: (Optional) The `recorded_before` parameter defines the latest timestamp up to which Audit Trail events are retrieved. Returns `now` by default. + :param order_by: + :param page_size: + :param page_token: + :param product_name: (Optional) Name of the Scaleway resource in a hyphenated format. + :param service_name: (Optional) Name of the service of the API call performed. + :return: :class:`ListEventsResponse ` + + Usage: + :: + + result = api.list_events() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/audit-trail/v1alpha1/regions/{param_region}/events", + params={ + "method_name": method_name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page_size": page_size or self.client.default_page_size, + "page_token": page_token, + "product_name": product_name, + "project_id": project_id or self.client.default_project_id, + "recorded_after": recorded_after, + "recorded_before": recorded_before, + "resource_type": resource_type, + "service_name": service_name, + "status": status, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListEventsResponse(res.json()) + + def list_products( + self, + *, + region: Optional[ScwRegion] = None, + organization_id: Optional[str] = None, + ) -> ListProductsResponse: + """ + Retrieve the list of Scaleway resources for which you have Audit Trail events. + :param region: Region to target. If none is passed will use default region from the config. + :param organization_id: ID of the Organization containing the Audit Trail events. + :return: :class:`ListProductsResponse ` + + Usage: + :: + + result = api.list_products() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/audit-trail/v1alpha1/regions/{param_region}/products", + params={ + "organization_id": organization_id + or self.client.default_organization_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListProductsResponse(res.json()) diff --git a/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py b/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py new file mode 100644 index 00000000..f1d0b7f2 --- /dev/null +++ b/scaleway/scaleway/audit_trail/v1alpha1/marshalling.py @@ -0,0 +1,466 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from .types import ( + AccountOrganizationInfo, + AccountUserInfo, + KeyManagerKeyInfo, + KubernetesACLInfo, + KubernetesClusterInfo, + KubernetesNodeInfo, + KubernetesPoolInfo, + SecretManagerSecretInfo, + SecretManagerSecretVersionInfo, + EventPrincipal, + Resource, + Event, + ListEventsResponse, + ProductService, + Product, + ListProductsResponse, +) + + +def unmarshal_AccountOrganizationInfo(data: Any) -> AccountOrganizationInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AccountOrganizationInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return AccountOrganizationInfo(**args) + + +def unmarshal_AccountUserInfo(data: Any) -> AccountUserInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AccountUserInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("email", None) + if field is not None: + args["email"] = field + + return AccountUserInfo(**args) + + +def unmarshal_KeyManagerKeyInfo(data: Any) -> KeyManagerKeyInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KeyManagerKeyInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return KeyManagerKeyInfo(**args) + + +def unmarshal_KubernetesACLInfo(data: Any) -> KubernetesACLInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KubernetesACLInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return KubernetesACLInfo(**args) + + +def unmarshal_KubernetesClusterInfo(data: Any) -> KubernetesClusterInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KubernetesClusterInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return KubernetesClusterInfo(**args) + + +def unmarshal_KubernetesNodeInfo(data: Any) -> KubernetesNodeInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KubernetesNodeInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + return KubernetesNodeInfo(**args) + + +def unmarshal_KubernetesPoolInfo(data: Any) -> KubernetesPoolInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KubernetesPoolInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + return KubernetesPoolInfo(**args) + + +def unmarshal_SecretManagerSecretInfo(data: Any) -> SecretManagerSecretInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SecretManagerSecretInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("path", None) + if field is not None: + args["path"] = field + + return SecretManagerSecretInfo(**args) + + +def unmarshal_SecretManagerSecretVersionInfo( + data: Any, +) -> SecretManagerSecretVersionInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SecretManagerSecretVersionInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("revision", None) + if field is not None: + args["revision"] = field + + return SecretManagerSecretVersionInfo(**args) + + +def unmarshal_EventPrincipal(data: Any) -> EventPrincipal: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EventPrincipal' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + return EventPrincipal(**args) + + +def unmarshal_Resource(data: Any) -> Resource: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Resource' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("deleted_at", None) + if field is not None: + args["deleted_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["deleted_at"] = None + + field = data.get("name", None) + if field is not None: + args["name"] = field + else: + args["name"] = None + + field = data.get("secm_secret_info", None) + if field is not None: + args["secm_secret_info"] = unmarshal_SecretManagerSecretInfo(field) + else: + args["secm_secret_info"] = None + + field = data.get("secm_secret_version_info", None) + if field is not None: + args["secm_secret_version_info"] = unmarshal_SecretManagerSecretVersionInfo( + field + ) + else: + args["secm_secret_version_info"] = None + + field = data.get("kube_cluster_info", None) + if field is not None: + args["kube_cluster_info"] = unmarshal_KubernetesClusterInfo(field) + else: + args["kube_cluster_info"] = None + + field = data.get("kube_pool_info", None) + if field is not None: + args["kube_pool_info"] = unmarshal_KubernetesPoolInfo(field) + else: + args["kube_pool_info"] = None + + field = data.get("kube_node_info", None) + if field is not None: + args["kube_node_info"] = unmarshal_KubernetesNodeInfo(field) + else: + args["kube_node_info"] = None + + field = data.get("kube_acl_info", None) + if field is not None: + args["kube_acl_info"] = unmarshal_KubernetesACLInfo(field) + else: + args["kube_acl_info"] = None + + field = data.get("keym_key_info", None) + if field is not None: + args["keym_key_info"] = unmarshal_KeyManagerKeyInfo(field) + else: + args["keym_key_info"] = None + + field = data.get("secret_manager_secret_info", None) + if field is not None: + args["secret_manager_secret_info"] = unmarshal_SecretManagerSecretInfo(field) + else: + args["secret_manager_secret_info"] = None + + field = data.get("secret_manager_version_info", None) + if field is not None: + args["secret_manager_version_info"] = unmarshal_SecretManagerSecretVersionInfo( + field + ) + else: + args["secret_manager_version_info"] = None + + field = data.get("key_manager_key_info", None) + if field is not None: + args["key_manager_key_info"] = unmarshal_KeyManagerKeyInfo(field) + else: + args["key_manager_key_info"] = None + + field = data.get("account_user_info", None) + if field is not None: + args["account_user_info"] = unmarshal_AccountUserInfo(field) + else: + args["account_user_info"] = None + + field = data.get("account_organization_info", None) + if field is not None: + args["account_organization_info"] = unmarshal_AccountOrganizationInfo(field) + else: + args["account_organization_info"] = None + + return Resource(**args) + + +def unmarshal_Event(data: Any) -> Event: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Event' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("locality", None) + if field is not None: + args["locality"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("source_ip", None) + if field is not None: + args["source_ip"] = field + + field = data.get("recorded_at", None) + if field is not None: + args["recorded_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["recorded_at"] = None + + field = data.get("principal", None) + if field is not None: + args["principal"] = unmarshal_EventPrincipal(field) + else: + args["principal"] = None + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + else: + args["project_id"] = None + + field = data.get("user_agent", None) + if field is not None: + args["user_agent"] = field + else: + args["user_agent"] = None + + field = data.get("product_name", None) + if field is not None: + args["product_name"] = field + + field = data.get("service_name", None) + if field is not None: + args["service_name"] = field + + field = data.get("method_name", None) + if field is not None: + args["method_name"] = field + + field = data.get("resources", None) + if field is not None: + args["resources"] = ( + [unmarshal_Resource(v) for v in field] if field is not None else None + ) + + field = data.get("request_id", None) + if field is not None: + args["request_id"] = field + + field = data.get("status_code", None) + if field is not None: + args["status_code"] = field + + field = data.get("resource", None) + if field is not None: + args["resource"] = unmarshal_Resource(field) + else: + args["resource"] = None + + field = data.get("request_body", None) + if field is not None: + args["request_body"] = field + else: + args["request_body"] = None + + return Event(**args) + + +def unmarshal_ListEventsResponse(data: Any) -> ListEventsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListEventsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("events", None) + if field is not None: + args["events"] = ( + [unmarshal_Event(v) for v in field] if field is not None else None + ) + + field = data.get("next_page_token", None) + if field is not None: + args["next_page_token"] = field + else: + args["next_page_token"] = None + + return ListEventsResponse(**args) + + +def unmarshal_ProductService(data: Any) -> ProductService: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProductService' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("methods", None) + if field is not None: + args["methods"] = field + + return ProductService(**args) + + +def unmarshal_Product(data: Any) -> Product: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Product' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("title", None) + if field is not None: + args["title"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("services", None) + if field is not None: + args["services"] = ( + [unmarshal_ProductService(v) for v in field] if field is not None else None + ) + + return Product(**args) + + +def unmarshal_ListProductsResponse(data: Any) -> ListProductsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListProductsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("products", None) + if field is not None: + args["products"] = ( + [unmarshal_Product(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListProductsResponse(**args) diff --git a/scaleway/scaleway/audit_trail/v1alpha1/types.py b/scaleway/scaleway/audit_trail/v1alpha1/types.py new file mode 100644 index 00000000..ea9c8cf2 --- /dev/null +++ b/scaleway/scaleway/audit_trail/v1alpha1/types.py @@ -0,0 +1,348 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Any, Dict, List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class ListEventsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + RECORDED_AT_DESC = "recorded_at_desc" + RECORDED_AT_ASC = "recorded_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ResourceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + SECM_SECRET = "secm_secret" + SECM_SECRET_VERSION = "secm_secret_version" + KUBE_CLUSTER = "kube_cluster" + KUBE_POOL = "kube_pool" + KUBE_NODE = "kube_node" + KUBE_ACL = "kube_acl" + KEYM_KEY = "keym_key" + IAM_USER = "iam_user" + IAM_APPLICATION = "iam_application" + IAM_GROUP = "iam_group" + IAM_POLICY = "iam_policy" + IAM_API_KEY = "iam_api_key" + IAM_SSH_KEY = "iam_ssh_key" + IAM_RULE = "iam_rule" + SECRET_MANAGER_SECRET = "secret_manager_secret" + SECRET_MANAGER_VERSION = "secret_manager_version" + KEY_MANAGER_KEY = "key_manager_key" + ACCOUNT_USER = "account_user" + ACCOUNT_ORGANIZATION = "account_organization" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class AccountOrganizationInfo: + pass + + +@dataclass +class AccountUserInfo: + email: str + + +@dataclass +class KeyManagerKeyInfo: + pass + + +@dataclass +class KubernetesACLInfo: + pass + + +@dataclass +class KubernetesClusterInfo: + pass + + +@dataclass +class KubernetesNodeInfo: + id: str + + name: str + + +@dataclass +class KubernetesPoolInfo: + id: str + + name: str + + +@dataclass +class SecretManagerSecretInfo: + path: str + + +@dataclass +class SecretManagerSecretVersionInfo: + revision: int + + +@dataclass +class EventPrincipal: + id: str + + +@dataclass +class Resource: + id: str + + type_: ResourceType + + created_at: Optional[datetime] + + updated_at: Optional[datetime] + + deleted_at: Optional[datetime] + + name: Optional[str] + + secm_secret_info: Optional[SecretManagerSecretInfo] + + secm_secret_version_info: Optional[SecretManagerSecretVersionInfo] + + kube_cluster_info: Optional[KubernetesClusterInfo] + + kube_pool_info: Optional[KubernetesPoolInfo] + + kube_node_info: Optional[KubernetesNodeInfo] + + kube_acl_info: Optional[KubernetesACLInfo] + + keym_key_info: Optional[KeyManagerKeyInfo] + + secret_manager_secret_info: Optional[SecretManagerSecretInfo] + + secret_manager_version_info: Optional[SecretManagerSecretVersionInfo] + + key_manager_key_info: Optional[KeyManagerKeyInfo] + + account_user_info: Optional[AccountUserInfo] + + account_organization_info: Optional[AccountOrganizationInfo] + + +@dataclass +class ProductService: + name: str + + methods: List[str] + + +@dataclass +class Event: + id: str + """ + ID of the event. + """ + + locality: str + """ + Locality of the resource attached to the event. + """ + + organization_id: str + """ + Organization ID containing the event. + """ + + source_ip: str + """ + IP address at the origin of the event. + """ + + recorded_at: Optional[datetime] + """ + Timestamp of the event. + """ + + principal: Optional[EventPrincipal] + """ + User or IAM application at the origin of the event. + """ + + project_id: Optional[str] + """ + (Optional) Project of the resource attached to the event. + """ + + user_agent: Optional[str] + """ + User Agent at the origin of the event. + """ + + product_name: str + """ + Product name of the resource attached to the event. + """ + + service_name: str + """ + API name called to trigger the event. + """ + + method_name: str + """ + API method called to trigger the event. + """ + + resources: List[Resource] + """ + Resources attached to the event. + """ + + request_id: str + """ + Unique identifier of the request at the origin of the event. + """ + + status_code: int + """ + HTTP status code resulting of the API call. + """ + + resource: Optional[Resource] + """ + Resource attached to the event. + """ + + request_body: Optional[Dict[str, Any]] + """ + Request at the origin of the event. + """ + + +@dataclass +class Product: + title: str + """ + Product title. + """ + + name: str + """ + Product name. + """ + + services: List[ProductService] + """ + Specifies the API versions of the products integrated with Audit Trail. Each version defines the methods logged by Audit Trail. + """ + + +@dataclass +class ListEventsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + (Optional) ID of the Project containing the Audit Trail events. + """ + + organization_id: Optional[str] + """ + ID of the Organization containing the Audit Trail events. + """ + + resource_type: Optional[ResourceType] + """ + (Optional) Returns a paginated list of Scaleway resources' features. + """ + + method_name: Optional[str] + """ + (Optional) Name of the method of the API call performed. + """ + + status: Optional[int] + """ + (Optional) HTTP status code of the request. Returns either `200` if the request was successful or `403` if the permission was denied. + """ + + recorded_after: Optional[datetime] + """ + (Optional) The `recorded_after` parameter defines the earliest timestamp from which Audit Trail events are retrieved. Returns `one hour ago` by default. + """ + + recorded_before: Optional[datetime] + """ + (Optional) The `recorded_before` parameter defines the latest timestamp up to which Audit Trail events are retrieved. Returns `now` by default. + """ + + order_by: Optional[ListEventsRequestOrderBy] + + page_size: Optional[int] + + page_token: Optional[str] + + product_name: Optional[str] + """ + (Optional) Name of the Scaleway resource in a hyphenated format. + """ + + service_name: Optional[str] + """ + (Optional) Name of the service of the API call performed. + """ + + +@dataclass +class ListEventsResponse: + events: List[Event] + """ + Single page of events matching the requested criteria. + """ + + next_page_token: Optional[str] + """ + Page token to use in following calls to keep listing. + """ + + +@dataclass +class ListProductsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + organization_id: Optional[str] + """ + ID of the Organization containing the Audit Trail events. + """ + + +@dataclass +class ListProductsResponse: + products: List[Product] + """ + List of all products integrated with Audit Trail. + """ + + total_count: int + """ + Number of integrated products. + """ diff --git a/scaleway/scaleway/autoscaling/__init__.py b/scaleway/scaleway/autoscaling/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway/scaleway/autoscaling/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/autoscaling/v1alpha1/__init__.py b/scaleway/scaleway/autoscaling/v1alpha1/__init__.py new file mode 100644 index 00000000..67bcfcbe --- /dev/null +++ b/scaleway/scaleway/autoscaling/v1alpha1/__init__.py @@ -0,0 +1,105 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import InstanceGroupEventLevel +from .types import InstanceGroupEventSource +from .types import InstancePolicyAction +from .types import InstancePolicyType +from .types import InstanceTemplateStatus +from .types import ListInstanceGroupEventsRequestOrderBy +from .types import ListInstanceGroupsRequestOrderBy +from .types import ListInstancePoliciesRequestOrderBy +from .types import ListInstanceTemplatesRequestOrderBy +from .types import MetricAggregate +from .types import MetricManagedMetric +from .types import MetricOperator +from .types import UpdateInstancePolicyRequestMetricAggregate +from .types import UpdateInstancePolicyRequestMetricManagedMetric +from .types import UpdateInstancePolicyRequestMetricOperator +from .types import VolumeInstanceTemplateVolumeType +from .types import VolumeInstanceTemplateFromEmpty +from .types import VolumeInstanceTemplateFromSnapshot +from .types import Capacity +from .types import Loadbalancer +from .types import Metric +from .types import VolumeInstanceTemplate +from .types import InstanceGroupEvent +from .types import InstanceGroup +from .types import InstancePolicy +from .types import InstanceTemplate +from .types import UpdateInstanceGroupRequestCapacity +from .types import UpdateInstanceGroupRequestLoadbalancer +from .types import UpdateInstancePolicyRequestMetric +from .types import CreateInstanceGroupRequest +from .types import CreateInstancePolicyRequest +from .types import CreateInstanceTemplateRequest +from .types import DeleteInstanceGroupRequest +from .types import DeleteInstancePolicyRequest +from .types import DeleteInstanceTemplateRequest +from .types import GetInstanceGroupRequest +from .types import GetInstancePolicyRequest +from .types import GetInstanceTemplateRequest +from .types import ListInstanceGroupEventsRequest +from .types import ListInstanceGroupEventsResponse +from .types import ListInstanceGroupsRequest +from .types import ListInstanceGroupsResponse +from .types import ListInstancePoliciesRequest +from .types import ListInstancePoliciesResponse +from .types import ListInstanceTemplatesRequest +from .types import ListInstanceTemplatesResponse +from .types import UpdateInstanceGroupRequest +from .types import UpdateInstancePolicyRequest +from .types import UpdateInstanceTemplateRequest +from .api import AutoscalingV1Alpha1API + +__all__ = [ + "InstanceGroupEventLevel", + "InstanceGroupEventSource", + "InstancePolicyAction", + "InstancePolicyType", + "InstanceTemplateStatus", + "ListInstanceGroupEventsRequestOrderBy", + "ListInstanceGroupsRequestOrderBy", + "ListInstancePoliciesRequestOrderBy", + "ListInstanceTemplatesRequestOrderBy", + "MetricAggregate", + "MetricManagedMetric", + "MetricOperator", + "UpdateInstancePolicyRequestMetricAggregate", + "UpdateInstancePolicyRequestMetricManagedMetric", + "UpdateInstancePolicyRequestMetricOperator", + "VolumeInstanceTemplateVolumeType", + "VolumeInstanceTemplateFromEmpty", + "VolumeInstanceTemplateFromSnapshot", + "Capacity", + "Loadbalancer", + "Metric", + "VolumeInstanceTemplate", + "InstanceGroupEvent", + "InstanceGroup", + "InstancePolicy", + "InstanceTemplate", + "UpdateInstanceGroupRequestCapacity", + "UpdateInstanceGroupRequestLoadbalancer", + "UpdateInstancePolicyRequestMetric", + "CreateInstanceGroupRequest", + "CreateInstancePolicyRequest", + "CreateInstanceTemplateRequest", + "DeleteInstanceGroupRequest", + "DeleteInstancePolicyRequest", + "DeleteInstanceTemplateRequest", + "GetInstanceGroupRequest", + "GetInstancePolicyRequest", + "GetInstanceTemplateRequest", + "ListInstanceGroupEventsRequest", + "ListInstanceGroupEventsResponse", + "ListInstanceGroupsRequest", + "ListInstanceGroupsResponse", + "ListInstancePoliciesRequest", + "ListInstancePoliciesResponse", + "ListInstanceTemplatesRequest", + "ListInstanceTemplatesResponse", + "UpdateInstanceGroupRequest", + "UpdateInstancePolicyRequest", + "UpdateInstanceTemplateRequest", + "AutoscalingV1Alpha1API", +] diff --git a/scaleway/scaleway/autoscaling/v1alpha1/api.py b/scaleway/scaleway/autoscaling/v1alpha1/api.py new file mode 100644 index 00000000..cbcf0251 --- /dev/null +++ b/scaleway/scaleway/autoscaling/v1alpha1/api.py @@ -0,0 +1,939 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Dict, List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + validate_path_param, + fetch_all_pages, +) +from .types import ( + InstancePolicyAction, + InstancePolicyType, + ListInstanceGroupEventsRequestOrderBy, + ListInstanceGroupsRequestOrderBy, + ListInstancePoliciesRequestOrderBy, + ListInstanceTemplatesRequestOrderBy, + Capacity, + CreateInstanceGroupRequest, + CreateInstancePolicyRequest, + CreateInstanceTemplateRequest, + InstanceGroup, + InstanceGroupEvent, + InstancePolicy, + InstanceTemplate, + ListInstanceGroupEventsResponse, + ListInstanceGroupsResponse, + ListInstancePoliciesResponse, + ListInstanceTemplatesResponse, + Loadbalancer, + Metric, + UpdateInstanceGroupRequest, + UpdateInstanceGroupRequestCapacity, + UpdateInstanceGroupRequestLoadbalancer, + UpdateInstancePolicyRequest, + UpdateInstancePolicyRequestMetric, + UpdateInstanceTemplateRequest, + VolumeInstanceTemplate, +) +from .marshalling import ( + unmarshal_InstanceGroup, + unmarshal_InstancePolicy, + unmarshal_InstanceTemplate, + unmarshal_ListInstanceGroupEventsResponse, + unmarshal_ListInstanceGroupsResponse, + unmarshal_ListInstancePoliciesResponse, + unmarshal_ListInstanceTemplatesResponse, + marshal_CreateInstanceGroupRequest, + marshal_CreateInstancePolicyRequest, + marshal_CreateInstanceTemplateRequest, + marshal_UpdateInstanceGroupRequest, + marshal_UpdateInstancePolicyRequest, + marshal_UpdateInstanceTemplateRequest, +) + + +class AutoscalingV1Alpha1API(API): + """ """ + + def get_instance_group( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + ) -> InstanceGroup: + """ + Get Instance group. + Retrieve information about an existing Instance group, specified by its `instance_group_id`. Its full details, including errors, are returned in the response object. + :param instance_group_id: ID of the requested Instance group. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`InstanceGroup ` + + Usage: + :: + + result = api.get_instance_group( + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_instance_group_id = validate_path_param( + "instance_group_id", instance_group_id + ) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups/{param_instance_group_id}", + ) + + self._throw_on_error(res) + return unmarshal_InstanceGroup(res.json()) + + def create_instance_group( + self, + *, + name: str, + template_id: str, + capacity: Capacity, + loadbalancer: Loadbalancer, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> InstanceGroup: + """ + Create Instance group. + Create a new Instance group. You must specify a `template_id`, capacity and Load Balancer object. + :param name: Name of Instance group. + :param template_id: Template ID (ID of the Instance template to attach to the Instance group). + :param capacity: Specification of the minimum and maximum replicas for the Instance group, and the cooldown interval between two scaling events. + :param loadbalancer: Specification of the Load Balancer to link to the Instance group. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID to filter for, only Instance groups from this Project will be returned. + :param tags: List of tags for the Instance group. + :return: :class:`InstanceGroup ` + + Usage: + :: + + result = api.create_instance_group( + name="example", + template_id="example", + capacity=Capacity(), + loadbalancer=Loadbalancer(), + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups", + body=marshal_CreateInstanceGroupRequest( + CreateInstanceGroupRequest( + name=name, + template_id=template_id, + capacity=capacity, + loadbalancer=loadbalancer, + zone=zone, + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstanceGroup(res.json()) + + def list_instance_groups( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceGroupsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListInstanceGroupsResponse: + """ + List Instance groups. + List all Instance groups, for a Scaleway Organization or Scaleway Project. By default, the Instance groups returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`ListInstanceGroupsResponse ` + + Usage: + :: + + result = api.list_instance_groups() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInstanceGroupsResponse(res.json()) + + def list_instance_groups_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceGroupsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[InstanceGroup]: + """ + List Instance groups. + List all Instance groups, for a Scaleway Organization or Scaleway Project. By default, the Instance groups returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`List[InstanceGroup] ` + + Usage: + :: + + result = api.list_instance_groups_all() + """ + + return fetch_all_pages( + type=ListInstanceGroupsResponse, + key="instance_groups", + fetcher=self.list_instance_groups, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + }, + ) + + def update_instance_group( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + capacity: Optional[UpdateInstanceGroupRequestCapacity] = None, + loadbalancer: Optional[UpdateInstanceGroupRequestLoadbalancer] = None, + ) -> InstanceGroup: + """ + Update Instance group. + Update the parameters of an existing Instance group, specified by its `instance_group_id`. + :param instance_group_id: Instance group ID to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of Instance group. + :param tags: List of tags for the Load Balancer. + :param capacity: Specification of the minimum and maximum replicas for the Instance group, and the cooldown interval between two scaling events. + :param loadbalancer: Specification of the Load Balancer to link to the Instance group. + :return: :class:`InstanceGroup ` + + Usage: + :: + + result = api.update_instance_group( + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_instance_group_id = validate_path_param( + "instance_group_id", instance_group_id + ) + + res = self._request( + "PATCH", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups/{param_instance_group_id}", + body=marshal_UpdateInstanceGroupRequest( + UpdateInstanceGroupRequest( + instance_group_id=instance_group_id, + zone=zone, + name=name, + tags=tags, + capacity=capacity, + loadbalancer=loadbalancer, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstanceGroup(res.json()) + + def delete_instance_group( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete Instance group. + Delete an existing Instance group, specified by its `instance_group_id`. Deleting an Instance group is permanent, and cannot be undone. + :param instance_group_id: ID of the Instance group to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_instance_group( + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_instance_group_id = validate_path_param( + "instance_group_id", instance_group_id + ) + + res = self._request( + "DELETE", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups/{param_instance_group_id}", + ) + + self._throw_on_error(res) + + def create_instance_template( + self, + *, + zone: Optional[ScwZone] = None, + commercial_type: str, + volumes: Dict[str, VolumeInstanceTemplate], + image_id: Optional[str] = None, + tags: Optional[List[str]] = None, + security_group_id: Optional[str] = None, + name: str, + placement_group_id: Optional[str] = None, + public_ips_v4_count: Optional[int] = None, + public_ips_v6_count: Optional[int] = None, + project_id: Optional[str] = None, + private_network_ids: Optional[List[str]] = None, + cloud_init: Optional[str] = None, + ) -> InstanceTemplate: + """ + Create Instance template. + Create a new Instance template. This specifies the details of the Instance (commercial type, zone, image, volumes etc.) that will be in the Instance group. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param commercial_type: Name of Instance commercial type. + :param volumes: Template of Instance volume. + :param image_id: Instance image ID. Can be an ID of a marketplace or personal image. This image must be compatible with `volume` and `commercial_type` template. + :param tags: List of tags for the Instance template. + :param security_group_id: Instance security group ID (optional). + :param name: Name of Instance template. + :param placement_group_id: Instance placement group ID. This is optional, but it is highly recommended to set a preference for Instance location within Availability Zone. + :param public_ips_v4_count: Number of flexible IPv4 addresses to attach to the new Instance. + :param public_ips_v6_count: Number of flexible IPv6 addresses to attach to the new Instance. + :param project_id: ID of the Project containing the Instance template resource. + :param private_network_ids: Private Network IDs to attach to the new Instance. + :param cloud_init: Cloud-config file must be passed in Base64 format. Cloud-config files are special scripts designed to be run by the cloud-init process. These are generally used for initial configuration on the very first boot of a server. + :return: :class:`InstanceTemplate ` + + Usage: + :: + + result = api.create_instance_template( + commercial_type="example", + volumes={}, + name="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-templates", + body=marshal_CreateInstanceTemplateRequest( + CreateInstanceTemplateRequest( + zone=zone, + commercial_type=commercial_type, + volumes=volumes, + image_id=image_id, + tags=tags, + security_group_id=security_group_id, + name=name, + placement_group_id=placement_group_id, + public_ips_v4_count=public_ips_v4_count, + public_ips_v6_count=public_ips_v6_count, + project_id=project_id, + private_network_ids=private_network_ids, + cloud_init=cloud_init, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstanceTemplate(res.json()) + + def update_instance_template( + self, + *, + template_id: str, + zone: Optional[ScwZone] = None, + commercial_type: Optional[str] = None, + image_id: Optional[str] = None, + volumes: Optional[Dict[str, VolumeInstanceTemplate]] = None, + tags: Optional[List[str]] = None, + security_group_id: Optional[str] = None, + placement_group_id: Optional[str] = None, + public_ips_v4_count: Optional[int] = None, + public_ips_v6_count: Optional[int] = None, + name: Optional[str] = None, + private_network_ids: Optional[List[str]] = None, + cloud_init: Optional[str] = None, + ) -> InstanceTemplate: + """ + Update Instance template. + Update an Instance template, such as its commercial offer type, image or volume template. + :param template_id: Template ID of the resource. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param commercial_type: Name of Instance commercial type. + :param image_id: Instance image ID. Can be an ID of a marketplace or personal image. This image must be compatible with `volume` and `commercial_type` template. + :param volumes: Template of Instance volume. + :param tags: List of tags for the Instance template. + :param security_group_id: Instance security group ID (optional). + :param placement_group_id: Instance placement group ID. This is optional, but it is highly recommended to set a preference for Instance location within Availability Zone. + :param public_ips_v4_count: Number of flexible IPv4 addresses to attach to the new Instance. + :param public_ips_v6_count: Number of flexible IPv6 addresses to attach to the new Instance. + :param name: Name of Instance template. + :param private_network_ids: Private Network IDs to attach to the new Instance. + :param cloud_init: Cloud-config file must be passed in Base64 format. Cloud-config files are special scripts designed to be run by the cloud-init process. These are generally used for initial configuration on the very first boot of a server. + :return: :class:`InstanceTemplate ` + + Usage: + :: + + result = api.update_instance_template( + template_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_template_id = validate_path_param("template_id", template_id) + + res = self._request( + "PATCH", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-templates/{param_template_id}", + body=marshal_UpdateInstanceTemplateRequest( + UpdateInstanceTemplateRequest( + template_id=template_id, + zone=zone, + commercial_type=commercial_type, + image_id=image_id, + volumes=volumes, + tags=tags, + security_group_id=security_group_id, + placement_group_id=placement_group_id, + public_ips_v4_count=public_ips_v4_count, + public_ips_v6_count=public_ips_v6_count, + name=name, + private_network_ids=private_network_ids, + cloud_init=cloud_init, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstanceTemplate(res.json()) + + def get_instance_template( + self, + *, + template_id: str, + zone: Optional[ScwZone] = None, + ) -> InstanceTemplate: + """ + Get Instance template. + Get an existing Instance template from its `template_id`. + :param template_id: Template ID of the resource. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`InstanceTemplate ` + + Usage: + :: + + result = api.get_instance_template( + template_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_template_id = validate_path_param("template_id", template_id) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-templates/{param_template_id}", + ) + + self._throw_on_error(res) + return unmarshal_InstanceTemplate(res.json()) + + def delete_instance_template( + self, + *, + template_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete Instance template. + Delete an existing Instance template. This action is permanent and cannot be undone. + :param template_id: ID of the template to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_instance_template( + template_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_template_id = validate_path_param("template_id", template_id) + + res = self._request( + "DELETE", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-templates/{param_template_id}", + ) + + self._throw_on_error(res) + + def list_instance_templates( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceTemplatesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListInstanceTemplatesResponse: + """ + List Instance templates. + List all Instance templates, for a Scaleway Organization or Scaleway Project. By default, the Instance templates returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`ListInstanceTemplatesResponse ` + + Usage: + :: + + result = api.list_instance_templates() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-templates", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInstanceTemplatesResponse(res.json()) + + def list_instance_templates_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceTemplatesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[InstanceTemplate]: + """ + List Instance templates. + List all Instance templates, for a Scaleway Organization or Scaleway Project. By default, the Instance templates returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`List[InstanceTemplate] ` + + Usage: + :: + + result = api.list_instance_templates_all() + """ + + return fetch_all_pages( + type=ListInstanceTemplatesResponse, + key="instance_templates", + fetcher=self.list_instance_templates, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + }, + ) + + def create_instance_policy( + self, + *, + name: str, + action: InstancePolicyAction, + type_: InstancePolicyType, + value: int, + priority: int, + instance_group_id: str, + zone: Optional[ScwZone] = None, + metric: Optional[Metric] = None, + ) -> InstancePolicy: + """ + Create scaling policy. + Create a new scaling policy. You must specify a `policy_id`, capacity and Load Balancer object. + :param name: Name of the policy. + :param action: Action to execute when the metric-based condition is met. + :param type_: How to use the number defined in `value` when determining by how many Instances to scale up/down. + :param value: Value representing the magnitude of the scaling action to take for the Instance group. Depending on the `type` parameter, this number could represent a total number of Instances in the group, a number of Instances to add, or a percentage to scale the group by. + :param priority: Priority of this policy compared to all other scaling policies. This determines the processing order. The lower the number, the higher the priority. + :param instance_group_id: Instance group ID related to this policy. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param metric: Cockpit metric to use when determining whether to trigger a scale up/down action. + One-Of ('trigger'): at most one of 'metric' could be set. + :return: :class:`InstancePolicy ` + + Usage: + :: + + result = api.create_instance_policy( + name="example", + action=InstancePolicyAction.unknown_action, + type=InstancePolicyType.unknown_type, + value=1, + priority=1, + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-policies", + body=marshal_CreateInstancePolicyRequest( + CreateInstancePolicyRequest( + name=name, + action=action, + type_=type_, + value=value, + priority=priority, + instance_group_id=instance_group_id, + zone=zone, + metric=metric, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstancePolicy(res.json()) + + def update_instance_policy( + self, + *, + policy_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + metric: Optional[UpdateInstancePolicyRequestMetric] = None, + action: Optional[InstancePolicyAction] = None, + type_: Optional[InstancePolicyType] = None, + value: Optional[int] = None, + priority: Optional[int] = None, + ) -> InstancePolicy: + """ + Update scaling policy. + Update the parameters of an existing scaling policy, specified by its `policy_id`. + :param policy_id: Policy ID to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Policy name to update. + :param metric: Metric specification to update (Cockpit metric to use when determining whether to trigger a scale up/down action). + One-Of ('trigger'): at most one of 'metric' could be set. + :param action: Action to update (action to execute when the metric-based condition is met). + :param type_: Type to update (how to use the number defined in `value` when determining by how many Instances to scale up/down). + :param value: Value to update (number representing the magnitude of the scaling action to take for the Instance group). + :param priority: Priority to update (priority of this policy compared to all other scaling policies. The lower the number, the higher the priority). + :return: :class:`InstancePolicy ` + + Usage: + :: + + result = api.update_instance_policy( + policy_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_policy_id = validate_path_param("policy_id", policy_id) + + res = self._request( + "PATCH", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-policies/{param_policy_id}", + body=marshal_UpdateInstancePolicyRequest( + UpdateInstancePolicyRequest( + policy_id=policy_id, + zone=zone, + name=name, + action=action, + type_=type_, + value=value, + priority=priority, + metric=metric, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_InstancePolicy(res.json()) + + def list_instance_policies( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstancePoliciesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListInstancePoliciesResponse: + """ + List scaling policies. + List all scaling policies, for a Scaleway Organization or Scaleway Project. By default, the policies returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param instance_group_id: Instance group ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of scaling policies to return per page. + :return: :class:`ListInstancePoliciesResponse ` + + Usage: + :: + + result = api.list_instance_policies( + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-policies", + params={ + "instance_group_id": instance_group_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInstancePoliciesResponse(res.json()) + + def list_instance_policies_all( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstancePoliciesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[InstancePolicy]: + """ + List scaling policies. + List all scaling policies, for a Scaleway Organization or Scaleway Project. By default, the policies returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param instance_group_id: Instance group ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of scaling policies to return per page. + :return: :class:`List[InstancePolicy] ` + + Usage: + :: + + result = api.list_instance_policies_all( + instance_group_id="example", + ) + """ + + return fetch_all_pages( + type=ListInstancePoliciesResponse, + key="policies", + fetcher=self.list_instance_policies, + args={ + "instance_group_id": instance_group_id, + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + }, + ) + + def get_instance_policy( + self, + *, + policy_id: str, + zone: Optional[ScwZone] = None, + ) -> InstancePolicy: + """ + Get scaling policy. + Retrieve information about an existing scaling policy, specified by its `policy_id`. Its full details are returned in the response object. + :param policy_id: Policy ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`InstancePolicy ` + + Usage: + :: + + result = api.get_instance_policy( + policy_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_policy_id = validate_path_param("policy_id", policy_id) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-policies/{param_policy_id}", + ) + + self._throw_on_error(res) + return unmarshal_InstancePolicy(res.json()) + + def delete_instance_policy( + self, + *, + policy_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete scaling policy. + Delete an existing scaling policy, specified by its `policy_id`. Deleting a scaling policy is permanent, and cannot be undone. + :param policy_id: ID of the policy to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_instance_policy( + policy_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_policy_id = validate_path_param("policy_id", policy_id) + + res = self._request( + "DELETE", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-policies/{param_policy_id}", + ) + + self._throw_on_error(res) + + def list_instance_group_events( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceGroupEventsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListInstanceGroupEventsResponse: + """ + List events. + List all events for a given Instance group. By default, the events are ordered by creation date in descending order, though this can be modified via the `order_by` field. + :param instance_group_id: List all event logs for the Instance group ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`ListInstanceGroupEventsResponse ` + + Usage: + :: + + result = api.list_instance_group_events( + instance_group_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_instance_group_id = validate_path_param( + "instance_group_id", instance_group_id + ) + + res = self._request( + "GET", + f"/autoscaling/v1alpha1/zones/{param_zone}/instance-groups/{param_instance_group_id}/events", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInstanceGroupEventsResponse(res.json()) + + def list_instance_group_events_all( + self, + *, + instance_group_id: str, + zone: Optional[ScwZone] = None, + order_by: Optional[ListInstanceGroupEventsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[InstanceGroupEvent]: + """ + List events. + List all events for a given Instance group. By default, the events are ordered by creation date in descending order, though this can be modified via the `order_by` field. + :param instance_group_id: List all event logs for the Instance group ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order of Instance groups in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Instance groups to return per page. + :return: :class:`List[InstanceGroupEvent] ` + + Usage: + :: + + result = api.list_instance_group_events_all( + instance_group_id="example", + ) + """ + + return fetch_all_pages( + type=ListInstanceGroupEventsResponse, + key="instance_events", + fetcher=self.list_instance_group_events, + args={ + "instance_group_id": instance_group_id, + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + }, + ) diff --git a/scaleway/scaleway/autoscaling/v1alpha1/marshalling.py b/scaleway/scaleway/autoscaling/v1alpha1/marshalling.py new file mode 100644 index 00000000..0558608f --- /dev/null +++ b/scaleway/scaleway/autoscaling/v1alpha1/marshalling.py @@ -0,0 +1,942 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + Capacity, + Loadbalancer, + InstanceGroup, + Metric, + InstancePolicy, + VolumeInstanceTemplateFromEmpty, + VolumeInstanceTemplateFromSnapshot, + VolumeInstanceTemplate, + InstanceTemplate, + InstanceGroupEvent, + ListInstanceGroupEventsResponse, + ListInstanceGroupsResponse, + ListInstancePoliciesResponse, + ListInstanceTemplatesResponse, + CreateInstanceGroupRequest, + CreateInstancePolicyRequest, + CreateInstanceTemplateRequest, + UpdateInstanceGroupRequestCapacity, + UpdateInstanceGroupRequestLoadbalancer, + UpdateInstanceGroupRequest, + UpdateInstancePolicyRequestMetric, + UpdateInstancePolicyRequest, + UpdateInstanceTemplateRequest, +) + + +def unmarshal_Capacity(data: Any) -> Capacity: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Capacity' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("max_replicas", None) + if field is not None: + args["max_replicas"] = field + + field = data.get("min_replicas", None) + if field is not None: + args["min_replicas"] = field + + field = data.get("cooldown_delay", None) + if field is not None: + args["cooldown_delay"] = field + else: + args["cooldown_delay"] = None + + return Capacity(**args) + + +def unmarshal_Loadbalancer(data: Any) -> Loadbalancer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Loadbalancer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("backend_ids", None) + if field is not None: + args["backend_ids"] = field + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + return Loadbalancer(**args) + + +def unmarshal_InstanceGroup(data: Any) -> InstanceGroup: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InstanceGroup' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("instance_template_id", None) + if field is not None: + args["instance_template_id"] = field + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = unmarshal_Capacity(field) + + field = data.get("loadbalancer", None) + if field is not None: + args["loadbalancer"] = unmarshal_Loadbalancer(field) + + field = data.get("error_messages", None) + if field is not None: + args["error_messages"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return InstanceGroup(**args) + + +def unmarshal_Metric(data: Any) -> Metric: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Metric' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("operator", None) + if field is not None: + args["operator"] = field + + field = data.get("aggregate", None) + if field is not None: + args["aggregate"] = field + + field = data.get("sampling_range_min", None) + if field is not None: + args["sampling_range_min"] = field + + field = data.get("threshold", None) + if field is not None: + args["threshold"] = field + + field = data.get("managed_metric", None) + if field is not None: + args["managed_metric"] = field + else: + args["managed_metric"] = None + + field = data.get("cockpit_metric_name", None) + if field is not None: + args["cockpit_metric_name"] = field + else: + args["cockpit_metric_name"] = None + + return Metric(**args) + + +def unmarshal_InstancePolicy(data: Any) -> InstancePolicy: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InstancePolicy' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("action", None) + if field is not None: + args["action"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + field = data.get("priority", None) + if field is not None: + args["priority"] = field + + field = data.get("instance_group_id", None) + if field is not None: + args["instance_group_id"] = field + + field = data.get("metric", None) + if field is not None: + args["metric"] = unmarshal_Metric(field) + else: + args["metric"] = None + + return InstancePolicy(**args) + + +def unmarshal_VolumeInstanceTemplateFromEmpty( + data: Any, +) -> VolumeInstanceTemplateFromEmpty: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeInstanceTemplateFromEmpty' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("size", None) + if field is not None: + args["size"] = field + + return VolumeInstanceTemplateFromEmpty(**args) + + +def unmarshal_VolumeInstanceTemplateFromSnapshot( + data: Any, +) -> VolumeInstanceTemplateFromSnapshot: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeInstanceTemplateFromSnapshot' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("snapshot_id", None) + if field is not None: + args["snapshot_id"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + else: + args["size"] = None + + return VolumeInstanceTemplateFromSnapshot(**args) + + +def unmarshal_VolumeInstanceTemplate(data: Any) -> VolumeInstanceTemplate: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeInstanceTemplate' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("boot", None) + if field is not None: + args["boot"] = field + + field = data.get("volume_type", None) + if field is not None: + args["volume_type"] = field + + field = data.get("perf_iops", None) + if field is not None: + args["perf_iops"] = field + else: + args["perf_iops"] = None + + field = data.get("from_empty", None) + if field is not None: + args["from_empty"] = unmarshal_VolumeInstanceTemplateFromEmpty(field) + else: + args["from_empty"] = None + + field = data.get("from_snapshot", None) + if field is not None: + args["from_snapshot"] = unmarshal_VolumeInstanceTemplateFromSnapshot(field) + else: + args["from_snapshot"] = None + + return VolumeInstanceTemplate(**args) + + +def unmarshal_InstanceTemplate(data: Any) -> InstanceTemplate: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InstanceTemplate' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("commercial_type", None) + if field is not None: + args["commercial_type"] = field + + field = data.get("volumes", None) + if field is not None: + args["volumes"] = ( + { + key: unmarshal_VolumeInstanceTemplate(value) + for key, value in field.items() + } + if field is not None + else None + ) + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("private_network_ids", None) + if field is not None: + args["private_network_ids"] = field + + field = data.get("image_id", None) + if field is not None: + args["image_id"] = field + else: + args["image_id"] = None + + field = data.get("security_group_id", None) + if field is not None: + args["security_group_id"] = field + else: + args["security_group_id"] = None + + field = data.get("placement_group_id", None) + if field is not None: + args["placement_group_id"] = field + else: + args["placement_group_id"] = None + + field = data.get("public_ips_v4_count", None) + if field is not None: + args["public_ips_v4_count"] = field + else: + args["public_ips_v4_count"] = None + + field = data.get("public_ips_v6_count", None) + if field is not None: + args["public_ips_v6_count"] = field + else: + args["public_ips_v6_count"] = None + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("cloud_init", None) + if field is not None: + args["cloud_init"] = field + else: + args["cloud_init"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return InstanceTemplate(**args) + + +def unmarshal_InstanceGroupEvent(data: Any) -> InstanceGroupEvent: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InstanceGroupEvent' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("source", None) + if field is not None: + args["source"] = field + + field = data.get("level", None) + if field is not None: + args["level"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("details", None) + if field is not None: + args["details"] = field + else: + args["details"] = None + + return InstanceGroupEvent(**args) + + +def unmarshal_ListInstanceGroupEventsResponse( + data: Any, +) -> ListInstanceGroupEventsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInstanceGroupEventsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("instance_events", None) + if field is not None: + args["instance_events"] = ( + [unmarshal_InstanceGroupEvent(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListInstanceGroupEventsResponse(**args) + + +def unmarshal_ListInstanceGroupsResponse(data: Any) -> ListInstanceGroupsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInstanceGroupsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("instance_groups", None) + if field is not None: + args["instance_groups"] = ( + [unmarshal_InstanceGroup(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListInstanceGroupsResponse(**args) + + +def unmarshal_ListInstancePoliciesResponse(data: Any) -> ListInstancePoliciesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInstancePoliciesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("policies", None) + if field is not None: + args["policies"] = ( + [unmarshal_InstancePolicy(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListInstancePoliciesResponse(**args) + + +def unmarshal_ListInstanceTemplatesResponse(data: Any) -> ListInstanceTemplatesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInstanceTemplatesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("instance_templates", None) + if field is not None: + args["instance_templates"] = ( + [unmarshal_InstanceTemplate(v) for v in field] + if field is not None + else None + ) + + return ListInstanceTemplatesResponse(**args) + + +def marshal_Capacity( + request: Capacity, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.max_replicas is not None: + output["max_replicas"] = request.max_replicas + + if request.min_replicas is not None: + output["min_replicas"] = request.min_replicas + + if request.cooldown_delay is not None: + output["cooldown_delay"] = request.cooldown_delay + + return output + + +def marshal_Loadbalancer( + request: Loadbalancer, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.id is not None: + output["id"] = request.id + + if request.backend_ids is not None: + output["backend_ids"] = request.backend_ids + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + return output + + +def marshal_CreateInstanceGroupRequest( + request: CreateInstanceGroupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.template_id is not None: + output["template_id"] = request.template_id + + if request.capacity is not None: + output["capacity"] = marshal_Capacity(request.capacity, defaults) + + if request.loadbalancer is not None: + output["loadbalancer"] = marshal_Loadbalancer(request.loadbalancer, defaults) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_Metric( + request: Metric, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("managed_metric", request.managed_metric), + OneOfPossibility("cockpit_metric_name", request.cockpit_metric_name), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.operator is not None: + output["operator"] = str(request.operator) + + if request.aggregate is not None: + output["aggregate"] = str(request.aggregate) + + if request.sampling_range_min is not None: + output["sampling_range_min"] = request.sampling_range_min + + if request.threshold is not None: + output["threshold"] = request.threshold + + return output + + +def marshal_CreateInstancePolicyRequest( + request: CreateInstancePolicyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("metric", request.metric), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.action is not None: + output["action"] = str(request.action) + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.value is not None: + output["value"] = request.value + + if request.priority is not None: + output["priority"] = request.priority + + if request.instance_group_id is not None: + output["instance_group_id"] = request.instance_group_id + + return output + + +def marshal_VolumeInstanceTemplateFromEmpty( + request: VolumeInstanceTemplateFromEmpty, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_VolumeInstanceTemplateFromSnapshot( + request: VolumeInstanceTemplateFromSnapshot, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.snapshot_id is not None: + output["snapshot_id"] = request.snapshot_id + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_VolumeInstanceTemplate( + request: VolumeInstanceTemplate, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("from_empty", request.from_empty), + OneOfPossibility("from_snapshot", request.from_snapshot), + ] + ), + ) + output.update( + resolve_one_of( + [ + OneOfPossibility("perf_iops", request.perf_iops), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.boot is not None: + output["boot"] = request.boot + + if request.volume_type is not None: + output["volume_type"] = str(request.volume_type) + + return output + + +def marshal_CreateInstanceTemplateRequest( + request: CreateInstanceTemplateRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.commercial_type is not None: + output["commercial_type"] = request.commercial_type + + if request.volumes is not None: + output["volumes"] = { + key: marshal_VolumeInstanceTemplate(value, defaults) + for key, value in request.volumes.items() + } + + if request.image_id is not None: + output["image_id"] = request.image_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.security_group_id is not None: + output["security_group_id"] = request.security_group_id + + if request.name is not None: + output["name"] = request.name + + if request.placement_group_id is not None: + output["placement_group_id"] = request.placement_group_id + + if request.public_ips_v4_count is not None: + output["public_ips_v4_count"] = request.public_ips_v4_count + + if request.public_ips_v6_count is not None: + output["public_ips_v6_count"] = request.public_ips_v6_count + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.private_network_ids is not None: + output["private_network_ids"] = request.private_network_ids + + if request.cloud_init is not None: + output["cloud_init"] = request.cloud_init + + return output + + +def marshal_UpdateInstanceGroupRequestCapacity( + request: UpdateInstanceGroupRequestCapacity, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.max_replicas is not None: + output["max_replicas"] = request.max_replicas + + if request.min_replicas is not None: + output["min_replicas"] = request.min_replicas + + if request.cooldown_delay is not None: + output["cooldown_delay"] = request.cooldown_delay + + return output + + +def marshal_UpdateInstanceGroupRequestLoadbalancer( + request: UpdateInstanceGroupRequestLoadbalancer, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.backend_ids is not None: + output["backend_ids"] = request.backend_ids + + return output + + +def marshal_UpdateInstanceGroupRequest( + request: UpdateInstanceGroupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.capacity is not None: + output["capacity"] = marshal_UpdateInstanceGroupRequestCapacity( + request.capacity, defaults + ) + + if request.loadbalancer is not None: + output["loadbalancer"] = marshal_UpdateInstanceGroupRequestLoadbalancer( + request.loadbalancer, defaults + ) + + return output + + +def marshal_UpdateInstancePolicyRequestMetric( + request: UpdateInstancePolicyRequestMetric, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("managed_metric", request.managed_metric), + OneOfPossibility("cockpit_metric_name", request.cockpit_metric_name), + ] + ), + ) + + if request.operator is not None: + output["operator"] = str(request.operator) + + if request.aggregate is not None: + output["aggregate"] = str(request.aggregate) + + if request.name is not None: + output["name"] = request.name + + if request.sampling_range_min is not None: + output["sampling_range_min"] = request.sampling_range_min + + if request.threshold is not None: + output["threshold"] = request.threshold + + return output + + +def marshal_UpdateInstancePolicyRequest( + request: UpdateInstancePolicyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("metric", request.metric), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.action is not None: + output["action"] = str(request.action) + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.value is not None: + output["value"] = request.value + + if request.priority is not None: + output["priority"] = request.priority + + return output + + +def marshal_UpdateInstanceTemplateRequest( + request: UpdateInstanceTemplateRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.commercial_type is not None: + output["commercial_type"] = request.commercial_type + + if request.image_id is not None: + output["image_id"] = request.image_id + + if request.volumes is not None: + output["volumes"] = { + key: marshal_VolumeInstanceTemplate(value, defaults) + for key, value in request.volumes.items() + } + + if request.tags is not None: + output["tags"] = request.tags + + if request.security_group_id is not None: + output["security_group_id"] = request.security_group_id + + if request.placement_group_id is not None: + output["placement_group_id"] = request.placement_group_id + + if request.public_ips_v4_count is not None: + output["public_ips_v4_count"] = request.public_ips_v4_count + + if request.public_ips_v6_count is not None: + output["public_ips_v6_count"] = request.public_ips_v6_count + + if request.name is not None: + output["name"] = request.name + + if request.private_network_ids is not None: + output["private_network_ids"] = request.private_network_ids + + if request.cloud_init is not None: + output["cloud_init"] = request.cloud_init + + return output diff --git a/scaleway/scaleway/autoscaling/v1alpha1/types.py b/scaleway/scaleway/autoscaling/v1alpha1/types.py new file mode 100644 index 00000000..f1ecfd81 --- /dev/null +++ b/scaleway/scaleway/autoscaling/v1alpha1/types.py @@ -0,0 +1,1067 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class InstanceGroupEventLevel(str, Enum, metaclass=StrEnumMeta): + INFO = "info" + SUCCESS = "success" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class InstanceGroupEventSource(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SOURCE = "unknown_source" + WATCHER = "watcher" + SCALER = "scaler" + INSTANCE_MANAGER = "instance_manager" + SUPERVISOR = "supervisor" + + def __str__(self) -> str: + return str(self.value) + + +class InstancePolicyAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + SCALE_UP = "scale_up" + SCALE_DOWN = "scale_down" + + def __str__(self) -> str: + return str(self.value) + + +class InstancePolicyType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + FLAT_COUNT = "flat_count" + PERCENT_OF_TOTAL_GROUP = "percent_of_total_group" + SET_TOTAL_GROUP = "set_total_group" + + def __str__(self) -> str: + return str(self.value) + + +class InstanceTemplateStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class ListInstanceGroupEventsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ListInstanceGroupsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ListInstancePoliciesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ListInstanceTemplatesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class MetricAggregate(str, Enum, metaclass=StrEnumMeta): + AGGREGATE_UNKNOWN = "aggregate_unknown" + AGGREGATE_AVERAGE = "aggregate_average" + AGGREGATE_MAX = "aggregate_max" + AGGREGATE_MIN = "aggregate_min" + AGGREGATE_SUM = "aggregate_sum" + + def __str__(self) -> str: + return str(self.value) + + +class MetricManagedMetric(str, Enum, metaclass=StrEnumMeta): + MANAGED_METRIC_UNKNOWN = "managed_metric_unknown" + MANAGED_METRIC_INSTANCE_CPU = "managed_metric_instance_cpu" + MANAGED_METRIC_INSTANCE_NETWORK_IN = "managed_metric_instance_network_in" + MANAGED_METRIC_INSTANCE_NETWORK_OUT = "managed_metric_instance_network_out" + MANAGED_LOADBALANCER_BACKEND_CONNECTIONS_RATE = ( + "managed_loadbalancer_backend_connections_rate" + ) + MANAGED_LOADBALANCER_BACKEND_THROUGHPUT = "managed_loadbalancer_backend_throughput" + + def __str__(self) -> str: + return str(self.value) + + +class MetricOperator(str, Enum, metaclass=StrEnumMeta): + OPERATOR_UNKNOWN = "operator_unknown" + OPERATOR_GREATER_THAN = "operator_greater_than" + OPERATOR_LESS_THAN = "operator_less_than" + + def __str__(self) -> str: + return str(self.value) + + +class UpdateInstancePolicyRequestMetricAggregate(str, Enum, metaclass=StrEnumMeta): + AGGREGATE_UNKNOWN = "aggregate_unknown" + AGGREGATE_AVERAGE = "aggregate_average" + AGGREGATE_MAX = "aggregate_max" + AGGREGATE_MIN = "aggregate_min" + AGGREGATE_SUM = "aggregate_sum" + + def __str__(self) -> str: + return str(self.value) + + +class UpdateInstancePolicyRequestMetricManagedMetric(str, Enum, metaclass=StrEnumMeta): + MANAGED_METRIC_UNKNOWN = "managed_metric_unknown" + MANAGED_METRIC_INSTANCE_CPU = "managed_metric_instance_cpu" + MANAGED_METRIC_INSTANCE_NETWORK_IN = "managed_metric_instance_network_in" + MANAGED_METRIC_INSTANCE_NETWORK_OUT = "managed_metric_instance_network_out" + MANAGED_LOADBALANCER_BACKEND_CONNECTIONS_RATE = ( + "managed_loadbalancer_backend_connections_rate" + ) + MANAGED_LOADBALANCER_BACKEND_THROUGHPUT = "managed_loadbalancer_backend_throughput" + + def __str__(self) -> str: + return str(self.value) + + +class UpdateInstancePolicyRequestMetricOperator(str, Enum, metaclass=StrEnumMeta): + OPERATOR_UNKNOWN = "operator_unknown" + OPERATOR_GREATER_THAN = "operator_greater_than" + OPERATOR_LESS_THAN = "operator_less_than" + + def __str__(self) -> str: + return str(self.value) + + +class VolumeInstanceTemplateVolumeType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_VOLUME_TYPE = "unknown_volume_type" + L_SSD = "l_ssd" + SBS = "sbs" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class VolumeInstanceTemplateFromEmpty: + size: int + + +@dataclass +class VolumeInstanceTemplateFromSnapshot: + snapshot_id: str + + size: Optional[int] + + +@dataclass +class Capacity: + max_replicas: int + """ + Maximum count of Instances for the Instance group. + """ + + min_replicas: int + """ + Minimum count of Instances for the Instance group. + """ + + cooldown_delay: Optional[str] + """ + Time (in seconds) after a scaling action during which requests to carry out a new scaling action will be denied. + """ + + +@dataclass +class Loadbalancer: + id: str + """ + Load Balancer ID. + """ + + backend_ids: List[str] + """ + Load Balancer backend IDs. + """ + + private_network_id: str + """ + ID of the Private Network attached to the Load Balancer. + """ + + +@dataclass +class Metric: + name: str + """ + Name or description of the metric policy. + """ + + operator: MetricOperator + """ + Operator used when comparing the threshold value of the chosen `metric` to the actual sampled and aggregated value. + """ + + aggregate: MetricAggregate + """ + How the values sampled for the `metric` should be aggregated. + """ + + sampling_range_min: int + """ + Interval of time, in minutes, during which metric is sampled. + """ + + threshold: float + """ + Threshold value to measure the aggregated sampled `metric` value against. Combined with the `operator` field, determines whether a scaling action should be triggered. + """ + + managed_metric: Optional[MetricManagedMetric] + + cockpit_metric_name: Optional[str] + + +@dataclass +class VolumeInstanceTemplate: + name: str + """ + Name of the volume. + """ + + tags: List[str] + """ + List of tags assigned to the volume. + """ + + boot: bool + """ + Force the Instance to boot on this volume. + """ + + volume_type: VolumeInstanceTemplateVolumeType + """ + Type of the volume. + """ + + from_empty: Optional[VolumeInstanceTemplateFromEmpty] + + from_snapshot: Optional[VolumeInstanceTemplateFromSnapshot] + + perf_iops: Optional[int] + + +@dataclass +class InstanceGroupEvent: + id: str + """ + Instance group event ID. + """ + + source: InstanceGroupEventSource + """ + Log source. + """ + + level: InstanceGroupEventLevel + """ + The severity of the log. + """ + + name: str + """ + Log title. + """ + + created_at: Optional[datetime] + """ + Date and time of the log. + """ + + details: Optional[str] + """ + Full text of the log. + """ + + +@dataclass +class InstanceGroup: + id: str + """ + Instance group ID. + """ + + project_id: str + """ + Project ID of the Instance group. + """ + + name: str + """ + Name of the Instance group. + """ + + tags: List[str] + """ + Instance group tags. + """ + + instance_template_id: str + """ + Template ID (ID of the Instance template to attach to the Instance group). + """ + + capacity: Capacity + """ + Specification of the minimum and maximum replicas for the Instance group, and the cooldown interval between two scaling events. + """ + + loadbalancer: Loadbalancer + """ + Specification of the Load Balancer linked to the Instance group. + """ + + error_messages: List[str] + """ + Any configuration errors for dependencies (Load Balancer, Private Network, Instance template etc.). + """ + + created_at: Optional[datetime] + """ + Date on which the Instance group was created. + """ + + updated_at: Optional[datetime] + """ + Date on which the Instance group was last updated. + """ + + +@dataclass +class InstancePolicy: + id: str + """ + Scaling policy ID. + """ + + name: str + """ + Name of scaling policy. + """ + + action: InstancePolicyAction + """ + Action to execute when the metric-based condition is met. + """ + + type_: InstancePolicyType + """ + How to use the number defined in `value` when determining by how many Instances to scale up/down. + """ + + value: int + """ + Number representing the magnitude of the scaling action to take for the Instance group. + """ + + priority: int + """ + Priority of this policy compared to all other scaling policies. The lower the number, the higher the priority (higher priority will be processed sooner in the order). + """ + + instance_group_id: str + """ + Instance group ID related to this policy. + """ + + metric: Optional[Metric] + + +@dataclass +class InstanceTemplate: + id: str + """ + ID of Instance template resource. + """ + + commercial_type: str + """ + Name of Instance commercial type. + """ + + volumes: Dict[str, VolumeInstanceTemplate] + """ + Template of Instance volume. + """ + + tags: List[str] + """ + List of tags for the Instance template. + """ + + project_id: str + """ + ID of the Project containing the Instance template resource. + """ + + name: str + """ + Name of Instance template. + """ + + private_network_ids: List[str] + """ + Private Network IDs to attach to the new Instance. + """ + + image_id: Optional[str] + """ + Instance image ID. Can be an ID of a marketplace or personal image. This image must be compatible with `volume` and `commercial_type` template. + """ + + security_group_id: Optional[str] + """ + Instance security group ID (optional). + """ + + placement_group_id: Optional[str] + """ + Instance placement group ID. This is optional, but it is highly recommended to set a preference for Instance location within Availability Zone. + """ + + public_ips_v4_count: Optional[int] + """ + Number of flexible IPv4 addresses to attach to the new Instance. + """ + + public_ips_v6_count: Optional[int] + """ + Number of flexible IPv6 addresses to attach to the new Instance. + """ + + status: InstanceTemplateStatus + """ + Status of Instance template. + """ + + cloud_init: Optional[str] + """ + Cloud-config file must be passed in Base64 format. Cloud-config files are special scripts designed to be run by the cloud-init process. These are generally used for initial configuration on the very first boot of a server. + """ + + created_at: Optional[datetime] + """ + Date on which the Instance template was created. + """ + + updated_at: Optional[datetime] + """ + Date on which the Instance template was last updated. + """ + + +@dataclass +class UpdateInstanceGroupRequestCapacity: + max_replicas: Optional[int] + """ + Maximum count of Instances for the Instance group. + """ + + min_replicas: Optional[int] + """ + Minimum count of Instances for the Instance group. + """ + + cooldown_delay: Optional[str] + """ + Time (in seconds) after a scaling action during which requests to carry out a new scaling action will be denied. + """ + + +@dataclass +class UpdateInstanceGroupRequestLoadbalancer: + backend_ids: Optional[List[str]] + """ + Load Balancer backend IDs. + """ + + +@dataclass +class UpdateInstancePolicyRequestMetric: + operator: UpdateInstancePolicyRequestMetricOperator + """ + Operator used when comparing the threshold value of the chosen `metric` to the actual sampled and aggregated value. + """ + + aggregate: UpdateInstancePolicyRequestMetricAggregate + """ + How the values sampled for the `metric` should be aggregated. + """ + + name: Optional[str] + """ + Name or description of your metric policy. + """ + + sampling_range_min: Optional[int] + """ + Interval of time, in minutes, during which metric is sampled. + """ + + threshold: Optional[float] + """ + Threshold value to measure the aggregated sampled `metric` value against. Combined with the `operator` field, determines whether a scaling action should be triggered. + """ + + managed_metric: Optional[UpdateInstancePolicyRequestMetricManagedMetric] + + cockpit_metric_name: Optional[str] + + +@dataclass +class CreateInstanceGroupRequest: + name: str + """ + Name of Instance group. + """ + + template_id: str + """ + Template ID (ID of the Instance template to attach to the Instance group). + """ + + capacity: Capacity + """ + Specification of the minimum and maximum replicas for the Instance group, and the cooldown interval between two scaling events. + """ + + loadbalancer: Loadbalancer + """ + Specification of the Load Balancer to link to the Instance group. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only Instance groups from this Project will be returned. + """ + + tags: Optional[List[str]] + """ + List of tags for the Instance group. + """ + + +@dataclass +class CreateInstancePolicyRequest: + name: str + """ + Name of the policy. + """ + + action: InstancePolicyAction + """ + Action to execute when the metric-based condition is met. + """ + + type_: InstancePolicyType + """ + How to use the number defined in `value` when determining by how many Instances to scale up/down. + """ + + value: int + """ + Value representing the magnitude of the scaling action to take for the Instance group. Depending on the `type` parameter, this number could represent a total number of Instances in the group, a number of Instances to add, or a percentage to scale the group by. + """ + + priority: int + """ + Priority of this policy compared to all other scaling policies. This determines the processing order. The lower the number, the higher the priority. + """ + + instance_group_id: str + """ + Instance group ID related to this policy. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + metric: Optional[Metric] + + +@dataclass +class CreateInstanceTemplateRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + commercial_type: str + """ + Name of Instance commercial type. + """ + + volumes: Dict[str, VolumeInstanceTemplate] + """ + Template of Instance volume. + """ + + image_id: Optional[str] + """ + Instance image ID. Can be an ID of a marketplace or personal image. This image must be compatible with `volume` and `commercial_type` template. + """ + + tags: Optional[List[str]] + """ + List of tags for the Instance template. + """ + + security_group_id: Optional[str] + """ + Instance security group ID (optional). + """ + + name: str + """ + Name of Instance template. + """ + + placement_group_id: Optional[str] + """ + Instance placement group ID. This is optional, but it is highly recommended to set a preference for Instance location within Availability Zone. + """ + + public_ips_v4_count: Optional[int] + """ + Number of flexible IPv4 addresses to attach to the new Instance. + """ + + public_ips_v6_count: Optional[int] + """ + Number of flexible IPv6 addresses to attach to the new Instance. + """ + + project_id: Optional[str] + """ + ID of the Project containing the Instance template resource. + """ + + private_network_ids: Optional[List[str]] + """ + Private Network IDs to attach to the new Instance. + """ + + cloud_init: Optional[str] + """ + Cloud-config file must be passed in Base64 format. Cloud-config files are special scripts designed to be run by the cloud-init process. These are generally used for initial configuration on the very first boot of a server. + """ + + +@dataclass +class DeleteInstanceGroupRequest: + instance_group_id: str + """ + ID of the Instance group to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteInstancePolicyRequest: + policy_id: str + """ + ID of the policy to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteInstanceTemplateRequest: + template_id: str + """ + ID of the template to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetInstanceGroupRequest: + instance_group_id: str + """ + ID of the requested Instance group. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetInstancePolicyRequest: + policy_id: str + """ + Policy ID. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetInstanceTemplateRequest: + template_id: str + """ + Template ID of the resource. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ListInstanceGroupEventsRequest: + instance_group_id: str + """ + List all event logs for the Instance group ID. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListInstanceGroupEventsRequestOrderBy] + """ + Sort order of Instance groups in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of Instance groups to return per page. + """ + + +@dataclass +class ListInstanceGroupEventsResponse: + instance_events: List[InstanceGroupEvent] + """ + Paginated list of Instance groups. + """ + + total_count: int + """ + Count of all Instance groups matching the requested criteria. + """ + + +@dataclass +class ListInstanceGroupsRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListInstanceGroupsRequestOrderBy] + """ + Sort order of Instance groups in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of Instance groups to return per page. + """ + + +@dataclass +class ListInstanceGroupsResponse: + instance_groups: List[InstanceGroup] + """ + Paginated list of Instance groups. + """ + + total_count: int + """ + Count of all Instance groups matching the requested criteria. + """ + + +@dataclass +class ListInstancePoliciesRequest: + instance_group_id: str + """ + Instance group ID. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListInstancePoliciesRequestOrderBy] + """ + Sort order of Instance groups in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of scaling policies to return per page. + """ + + +@dataclass +class ListInstancePoliciesResponse: + policies: List[InstancePolicy] + """ + Paginated list of policies. + """ + + total_count: int + """ + Count of all policies matching the requested criteria. + """ + + +@dataclass +class ListInstanceTemplatesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListInstanceTemplatesRequestOrderBy] + """ + Sort order of Instance groups in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of Instance groups to return per page. + """ + + +@dataclass +class ListInstanceTemplatesResponse: + total_count: int + """ + Count of all templates matching the requested criteria. + """ + + instance_templates: List[InstanceTemplate] + """ + Paginated list of Instance templates. + """ + + +@dataclass +class UpdateInstanceGroupRequest: + instance_group_id: str + """ + Instance group ID to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name of Instance group. + """ + + tags: Optional[List[str]] + """ + List of tags for the Load Balancer. + """ + + capacity: Optional[UpdateInstanceGroupRequestCapacity] + """ + Specification of the minimum and maximum replicas for the Instance group, and the cooldown interval between two scaling events. + """ + + loadbalancer: Optional[UpdateInstanceGroupRequestLoadbalancer] + """ + Specification of the Load Balancer to link to the Instance group. + """ + + +@dataclass +class UpdateInstancePolicyRequest: + policy_id: str + """ + Policy ID to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Policy name to update. + """ + + action: Optional[InstancePolicyAction] + """ + Action to update (action to execute when the metric-based condition is met). + """ + + type_: Optional[InstancePolicyType] + """ + Type to update (how to use the number defined in `value` when determining by how many Instances to scale up/down). + """ + + value: Optional[int] + """ + Value to update (number representing the magnitude of the scaling action to take for the Instance group). + """ + + priority: Optional[int] + """ + Priority to update (priority of this policy compared to all other scaling policies. The lower the number, the higher the priority). + """ + + metric: Optional[UpdateInstancePolicyRequestMetric] + + +@dataclass +class UpdateInstanceTemplateRequest: + template_id: str + """ + Template ID of the resource. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + commercial_type: Optional[str] + """ + Name of Instance commercial type. + """ + + image_id: Optional[str] + """ + Instance image ID. Can be an ID of a marketplace or personal image. This image must be compatible with `volume` and `commercial_type` template. + """ + + volumes: Optional[Dict[str, VolumeInstanceTemplate]] + """ + Template of Instance volume. + """ + + tags: Optional[List[str]] + """ + List of tags for the Instance template. + """ + + security_group_id: Optional[str] + """ + Instance security group ID (optional). + """ + + placement_group_id: Optional[str] + """ + Instance placement group ID. This is optional, but it is highly recommended to set a preference for Instance location within Availability Zone. + """ + + public_ips_v4_count: Optional[int] + """ + Number of flexible IPv4 addresses to attach to the new Instance. + """ + + public_ips_v6_count: Optional[int] + """ + Number of flexible IPv6 addresses to attach to the new Instance. + """ + + name: Optional[str] + """ + Name of Instance template. + """ + + private_network_ids: Optional[List[str]] + """ + Private Network IDs to attach to the new Instance. + """ + + cloud_init: Optional[str] + """ + Cloud-config file must be passed in Base64 format. Cloud-config files are special scripts designed to be run by the cloud-init process. These are generally used for initial configuration on the very first boot of a server. + """ diff --git a/scaleway/scaleway/baremetal/v1/__init__.py b/scaleway/scaleway/baremetal/v1/__init__.py index 6381cd5e..f1ec9f1e 100644 --- a/scaleway/scaleway/baremetal/v1/__init__.py +++ b/scaleway/scaleway/baremetal/v1/__init__.py @@ -8,6 +8,10 @@ from .types import ListSettingsRequestOrderBy from .types import OfferStock from .types import OfferSubscriptionPeriod +from .types import SchemaFilesystemFormat +from .types import SchemaPartitionLabel +from .types import SchemaPoolType +from .types import SchemaRAIDLevel from .types import ServerBootType from .types import ServerInstallStatus from .content import SERVER_INSTALL_TRANSIENT_STATUSES @@ -18,9 +22,22 @@ from .types import ServerStatus from .content import SERVER_TRANSIENT_STATUSES from .types import SettingType +from .types import SchemaPartition +from .types import SchemaPool +from .types import SchemaDisk +from .types import SchemaFilesystem +from .types import SchemaRAID +from .types import SchemaZFS +from .types import CertificationOption +from .types import LicenseOption +from .types import PrivateNetworkOption +from .types import PublicBandwidthOption +from .types import RemoteAccessOption +from .types import Schema from .types import OSOSField from .types import CPU from .types import Disk +from .types import GPU from .types import Memory from .types import OfferOptionOffer from .types import PersistentMemory @@ -43,6 +60,7 @@ from .types import DeleteOptionServerRequest from .types import DeleteServerRequest from .types import GetBMCAccessRequest +from .types import GetDefaultPartitioningSchemaRequest from .types import GetOSRequest from .types import GetOfferRequest from .types import GetOptionRequest @@ -63,6 +81,7 @@ from .types import ListServersResponse from .types import ListSettingsRequest from .types import ListSettingsResponse +from .types import MigrateServerToMonthlyOfferRequest from .types import PrivateNetworkApiAddServerPrivateNetworkRequest from .types import PrivateNetworkApiDeleteServerPrivateNetworkRequest from .types import PrivateNetworkApiListServerPrivateNetworksRequest @@ -76,6 +95,7 @@ from .types import UpdateIPRequest from .types import UpdateServerRequest from .types import UpdateSettingRequest +from .types import ValidatePartitioningSchemaRequest from .api import BaremetalV1API from .api import BaremetalV1PrivateNetworkAPI @@ -88,6 +108,10 @@ "ListSettingsRequestOrderBy", "OfferStock", "OfferSubscriptionPeriod", + "SchemaFilesystemFormat", + "SchemaPartitionLabel", + "SchemaPoolType", + "SchemaRAIDLevel", "ServerBootType", "ServerInstallStatus", "SERVER_INSTALL_TRANSIENT_STATUSES", @@ -98,9 +122,22 @@ "ServerStatus", "SERVER_TRANSIENT_STATUSES", "SettingType", + "SchemaPartition", + "SchemaPool", + "SchemaDisk", + "SchemaFilesystem", + "SchemaRAID", + "SchemaZFS", + "CertificationOption", + "LicenseOption", + "PrivateNetworkOption", + "PublicBandwidthOption", + "RemoteAccessOption", + "Schema", "OSOSField", "CPU", "Disk", + "GPU", "Memory", "OfferOptionOffer", "PersistentMemory", @@ -123,6 +160,7 @@ "DeleteOptionServerRequest", "DeleteServerRequest", "GetBMCAccessRequest", + "GetDefaultPartitioningSchemaRequest", "GetOSRequest", "GetOfferRequest", "GetOptionRequest", @@ -143,6 +181,7 @@ "ListServersResponse", "ListSettingsRequest", "ListSettingsResponse", + "MigrateServerToMonthlyOfferRequest", "PrivateNetworkApiAddServerPrivateNetworkRequest", "PrivateNetworkApiDeleteServerPrivateNetworkRequest", "PrivateNetworkApiListServerPrivateNetworksRequest", @@ -156,6 +195,7 @@ "UpdateIPRequest", "UpdateServerRequest", "UpdateSettingRequest", + "ValidatePartitioningSchemaRequest", "BaremetalV1API", "BaremetalV1PrivateNetworkAPI", ] diff --git a/scaleway/scaleway/baremetal/v1/api.py b/scaleway/scaleway/baremetal/v1/api.py index 6674eaca..d9b73a50 100644 --- a/scaleway/scaleway/baremetal/v1/api.py +++ b/scaleway/scaleway/baremetal/v1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, @@ -41,6 +41,7 @@ PrivateNetworkApiAddServerPrivateNetworkRequest, PrivateNetworkApiSetServerPrivateNetworksRequest, RebootServerRequest, + Schema, Server, ServerEvent, ServerPrivateNetwork, @@ -51,11 +52,13 @@ UpdateIPRequest, UpdateServerRequest, UpdateSettingRequest, + ValidatePartitioningSchemaRequest, ) from .content import ( SERVER_TRANSIENT_STATUSES, ) from .marshalling import ( + unmarshal_Schema, unmarshal_IP, unmarshal_OS, unmarshal_Offer, @@ -84,18 +87,19 @@ marshal_UpdateIPRequest, marshal_UpdateServerRequest, marshal_UpdateSettingRequest, + marshal_ValidatePartitioningSchemaRequest, ) class BaremetalV1API(API): """ - This API allows to manage your Elastic Metal server. + This API allows you to manage your Elastic Metal servers. """ def list_servers( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListServersRequestOrderBy] = None, @@ -152,7 +156,7 @@ def list_servers( def list_servers_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListServersRequestOrderBy] = None, @@ -206,7 +210,7 @@ def get_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Get a specific Elastic Metal server. @@ -238,7 +242,7 @@ def wait_for_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Server, bool]] = None, ) -> Server: """ @@ -277,7 +281,7 @@ def create_server( offer_id: str, name: str, description: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, @@ -338,7 +342,7 @@ def update_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, @@ -389,11 +393,12 @@ def install_server( os_id: str, hostname: str, ssh_key_ids: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, user: Optional[str] = None, password: Optional[str] = None, service_user: Optional[str] = None, service_password: Optional[str] = None, + partitioning_schema: Optional[Schema] = None, ) -> Server: """ Install an Elastic Metal server. @@ -407,6 +412,7 @@ def install_server( :param password: Password used for the installation. :param service_user: User used for the service to install. :param service_password: Password used for the service to install. + :param partitioning_schema: Partitioning schema. :return: :class:`Server ` Usage: @@ -437,6 +443,7 @@ def install_server( password=password, service_user=service_user, service_password=service_password, + partitioning_schema=partitioning_schema, ), self.client, ), @@ -449,7 +456,7 @@ def get_server_metrics( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetServerMetricsResponse: """ Return server metrics. @@ -481,7 +488,7 @@ def delete_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Delete an Elastic Metal server. @@ -513,7 +520,7 @@ def reboot_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, boot_type: Optional[ServerBootType] = None, ) -> Server: """ @@ -555,7 +562,7 @@ def start_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, boot_type: Optional[ServerBootType] = None, ) -> Server: """ @@ -597,7 +604,7 @@ def stop_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Stop an Elastic Metal server. @@ -630,7 +637,7 @@ def list_server_events( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListServerEventsRequestOrderBy] = None, @@ -673,7 +680,7 @@ def list_server_events_all( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListServerEventsRequestOrderBy] = None, @@ -709,12 +716,93 @@ def list_server_events_all( }, ) + def get_default_partitioning_schema( + self, + *, + offer_id: str, + os_id: str, + zone: Optional[ScwZone] = None, + ) -> Schema: + """ + Get default partitioning schema. + Get the default partitioning schema for the given offer ID and OS ID. + :param offer_id: ID of the offer. + :param os_id: ID of the OS. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Schema ` + + Usage: + :: + + result = api.get_default_partitioning_schema( + offer_id="example", + os_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/baremetal/v1/zones/{param_zone}/partitioning-schemas/default", + params={ + "offer_id": offer_id, + "os_id": os_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Schema(res.json()) + + def validate_partitioning_schema( + self, + *, + offer_id: str, + os_id: str, + zone: Optional[ScwZone] = None, + partitioning_schema: Optional[Schema] = None, + ) -> None: + """ + Validate client partitioning schema. + Validate the incoming partitioning schema from a user before installing the server. Return default ErrorCode if invalid. + :param offer_id: Offer ID of the server. + :param os_id: OS ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param partitioning_schema: Partitioning schema. + + Usage: + :: + + result = api.validate_partitioning_schema( + offer_id="example", + os_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/baremetal/v1/zones/{param_zone}/partitioning-schemas/validate", + body=marshal_ValidatePartitioningSchemaRequest( + ValidatePartitioningSchemaRequest( + offer_id=offer_id, + os_id=os_id, + zone=zone, + partitioning_schema=partitioning_schema, + ), + self.client, + ), + ) + + self._throw_on_error(res) + def start_bmc_access( self, *, server_id: str, ip: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> BMCAccess: """ Start BMC access. @@ -759,7 +847,7 @@ def get_bmc_access( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> BMCAccess: """ Get BMC access. @@ -791,7 +879,7 @@ def stop_bmc_access( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Stop BMC access. @@ -822,7 +910,7 @@ def update_ip( *, server_id: str, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, reverse: Optional[str] = None, ) -> IP: """ @@ -869,7 +957,7 @@ def add_option_server( *, server_id: str, option_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, expires_at: Optional[datetime] = None, ) -> Server: """ @@ -916,7 +1004,7 @@ def delete_option_server( *, server_id: str, option_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Server: """ Delete server option. @@ -947,13 +1035,46 @@ def delete_option_server( self._throw_on_error(res) return unmarshal_Server(res.json()) + def migrate_server_to_monthly_offer( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> Server: + """ + Migrate server offer. + Migrate server with hourly offer to monthly offer. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Server ` + + Usage: + :: + + result = api.migrate_server_to_monthly_offer( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/baremetal/v1/zones/{param_zone}/servers/{param_server_id}/migrate-offer-monthly", + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + def list_offers( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, subscription_period: Optional[OfferSubscriptionPeriod] = None, + name: Optional[str] = None, ) -> ListOffersResponse: """ List offers. @@ -962,6 +1083,7 @@ def list_offers( :param page: Page number. :param page_size: Number of offers per page. :param subscription_period: Subscription period type to filter offers by. + :param name: Offer name to filter offers by. :return: :class:`ListOffersResponse ` Usage: @@ -976,6 +1098,7 @@ def list_offers( "GET", f"/baremetal/v1/zones/{param_zone}/offers", params={ + "name": name, "page": page, "page_size": page_size or self.client.default_page_size, "subscription_period": subscription_period, @@ -988,10 +1111,11 @@ def list_offers( def list_offers_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, subscription_period: Optional[OfferSubscriptionPeriod] = None, + name: Optional[str] = None, ) -> List[Offer]: """ List offers. @@ -1000,6 +1124,7 @@ def list_offers_all( :param page: Page number. :param page_size: Number of offers per page. :param subscription_period: Subscription period type to filter offers by. + :param name: Offer name to filter offers by. :return: :class:`List[Offer] ` Usage: @@ -1017,6 +1142,7 @@ def list_offers_all( "page": page, "page_size": page_size, "subscription_period": subscription_period, + "name": name, }, ) @@ -1024,7 +1150,7 @@ def get_offer( self, *, offer_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Offer: """ Get offer. @@ -1056,7 +1182,7 @@ def get_option( self, *, option_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Option: """ Get option. @@ -1087,7 +1213,7 @@ def get_option( def list_options( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, offer_id: Optional[str] = None, @@ -1128,7 +1254,7 @@ def list_options( def list_options_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, offer_id: Optional[str] = None, @@ -1166,7 +1292,7 @@ def list_options_all( def list_settings( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSettingsRequestOrderBy] = None, @@ -1207,7 +1333,7 @@ def list_settings( def list_settings_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSettingsRequestOrderBy] = None, @@ -1246,7 +1372,7 @@ def update_setting( self, *, setting_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, enabled: Optional[bool] = None, ) -> Setting: """ @@ -1287,7 +1413,7 @@ def update_setting( def list_os( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, offer_id: Optional[str] = None, @@ -1325,7 +1451,7 @@ def list_os( def list_os_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, offer_id: Optional[str] = None, @@ -1361,7 +1487,7 @@ def get_os( self, *, os_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> OS: """ Get OS with an ID. @@ -1392,7 +1518,7 @@ def get_os( class BaremetalV1PrivateNetworkAPI(API): """ - Elastic Metal Private Network API. + Elastic Metal - Private Network API. """ def add_server_private_network( @@ -1400,7 +1526,7 @@ def add_server_private_network( *, server_id: str, private_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ServerPrivateNetwork: """ Add a server to a Private Network. @@ -1442,7 +1568,7 @@ def set_server_private_networks( *, server_id: str, private_network_ids: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetServerPrivateNetworksResponse: """ Set multiple Private Networks on a server. @@ -1482,7 +1608,7 @@ def set_server_private_networks( def list_server_private_networks( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1532,7 +1658,7 @@ def list_server_private_networks( def list_server_private_networks_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1580,7 +1706,7 @@ def delete_server_private_network( *, server_id: str, private_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a Private Network. diff --git a/scaleway/scaleway/baremetal/v1/content.py b/scaleway/scaleway/baremetal/v1/content.py index e0817ef4..cc244bae 100644 --- a/scaleway/scaleway/baremetal/v1/content.py +++ b/scaleway/scaleway/baremetal/v1/content.py @@ -29,6 +29,7 @@ ServerStatus.DELETING, ServerStatus.ORDERED, ServerStatus.RESETTING, + ServerStatus.MIGRATING, ] """ Lists transient statutes of the enum :class:`ServerStatus `. diff --git a/scaleway/scaleway/baremetal/v1/marshalling.py b/scaleway/scaleway/baremetal/v1/marshalling.py index 60471d4d..594312c7 100644 --- a/scaleway/scaleway/baremetal/v1/marshalling.py +++ b/scaleway/scaleway/baremetal/v1/marshalling.py @@ -14,11 +14,24 @@ resolve_one_of, ) from .types import ( + SchemaPartition, + SchemaPool, + SchemaDisk, + SchemaFilesystem, + SchemaRAID, + SchemaZFS, + Schema, IP, OSOSField, OS, + CertificationOption, + LicenseOption, + PrivateNetworkOption, + PublicBandwidthOption, + RemoteAccessOption, CPU, Disk, + GPU, Memory, OfferOptionOffer, PersistentMemory, @@ -54,9 +67,189 @@ UpdateIPRequest, UpdateServerRequest, UpdateSettingRequest, + ValidatePartitioningSchemaRequest, ) +def unmarshal_SchemaPartition(data: Any) -> SchemaPartition: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaPartition' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("label", None) + if field is not None: + args["label"] = field + + field = data.get("number", None) + if field is not None: + args["number"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("use_all_available_space", None) + if field is not None: + args["use_all_available_space"] = field + + return SchemaPartition(**args) + + +def unmarshal_SchemaPool(data: Any) -> SchemaPool: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaPool' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("devices", None) + if field is not None: + args["devices"] = field + + field = data.get("options", None) + if field is not None: + args["options"] = field + + field = data.get("filesystem_options", None) + if field is not None: + args["filesystem_options"] = field + + return SchemaPool(**args) + + +def unmarshal_SchemaDisk(data: Any) -> SchemaDisk: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaDisk' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("device", None) + if field is not None: + args["device"] = field + + field = data.get("partitions", None) + if field is not None: + args["partitions"] = ( + [unmarshal_SchemaPartition(v) for v in field] if field is not None else None + ) + + return SchemaDisk(**args) + + +def unmarshal_SchemaFilesystem(data: Any) -> SchemaFilesystem: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaFilesystem' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("device", None) + if field is not None: + args["device"] = field + + field = data.get("format", None) + if field is not None: + args["format"] = field + + field = data.get("mountpoint", None) + if field is not None: + args["mountpoint"] = field + + return SchemaFilesystem(**args) + + +def unmarshal_SchemaRAID(data: Any) -> SchemaRAID: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaRAID' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("level", None) + if field is not None: + args["level"] = field + + field = data.get("devices", None) + if field is not None: + args["devices"] = field + + return SchemaRAID(**args) + + +def unmarshal_SchemaZFS(data: Any) -> SchemaZFS: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SchemaZFS' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pools", None) + if field is not None: + args["pools"] = ( + [unmarshal_SchemaPool(v) for v in field] if field is not None else None + ) + + return SchemaZFS(**args) + + +def unmarshal_Schema(data: Any) -> Schema: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Schema' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("disks", None) + if field is not None: + args["disks"] = ( + [unmarshal_SchemaDisk(v) for v in field] if field is not None else None + ) + + field = data.get("raids", None) + if field is not None: + args["raids"] = ( + [unmarshal_SchemaRAID(v) for v in field] if field is not None else None + ) + + field = data.get("filesystems", None) + if field is not None: + args["filesystems"] = ( + [unmarshal_SchemaFilesystem(v) for v in field] + if field is not None + else None + ) + + field = data.get("zfs", None) + if field is not None: + args["zfs"] = unmarshal_SchemaZFS(field) + else: + args["zfs"] = None + + return Schema(**args) + + def unmarshal_IP(data: Any) -> IP: if not isinstance(data, dict): raise TypeError( @@ -111,6 +304,8 @@ def unmarshal_OSOSField(data: Any) -> OSOSField: field = data.get("default_value", None) if field is not None: args["default_value"] = field + else: + args["default_value"] = None return OSOSField(**args) @@ -139,41 +334,122 @@ def unmarshal_OS(data: Any) -> OS: if field is not None: args["logo_url"] = field - field = data.get("enabled", None) - if field is not None: - args["enabled"] = field - - field = data.get("license_required", None) - if field is not None: - args["license_required"] = field - - field = data.get("allowed", None) - if field is not None: - args["allowed"] = field - field = data.get("ssh", None) if field is not None: args["ssh"] = unmarshal_OSOSField(field) + else: + args["ssh"] = None field = data.get("user", None) if field is not None: args["user"] = unmarshal_OSOSField(field) + else: + args["user"] = None field = data.get("password", None) if field is not None: args["password"] = unmarshal_OSOSField(field) + else: + args["password"] = None field = data.get("service_user", None) if field is not None: args["service_user"] = unmarshal_OSOSField(field) + else: + args["service_user"] = None field = data.get("service_password", None) if field is not None: args["service_password"] = unmarshal_OSOSField(field) + else: + args["service_password"] = None + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + field = data.get("license_required", None) + if field is not None: + args["license_required"] = field + + field = data.get("allowed", None) + if field is not None: + args["allowed"] = field + + field = data.get("custom_partitioning_supported", None) + if field is not None: + args["custom_partitioning_supported"] = field return OS(**args) +def unmarshal_CertificationOption(data: Any) -> CertificationOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CertificationOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return CertificationOption(**args) + + +def unmarshal_LicenseOption(data: Any) -> LicenseOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'LicenseOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("os_id", None) + if field is not None: + args["os_id"] = field + + return LicenseOption(**args) + + +def unmarshal_PrivateNetworkOption(data: Any) -> PrivateNetworkOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PrivateNetworkOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bandwidth_in_bps", None) + if field is not None: + args["bandwidth_in_bps"] = field + + return PrivateNetworkOption(**args) + + +def unmarshal_PublicBandwidthOption(data: Any) -> PublicBandwidthOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicBandwidthOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bandwidth_in_bps", None) + if field is not None: + args["bandwidth_in_bps"] = field + + return PublicBandwidthOption(**args) + + +def unmarshal_RemoteAccessOption(data: Any) -> RemoteAccessOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RemoteAccessOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return RemoteAccessOption(**args) + + def unmarshal_CPU(data: Any) -> CPU: if not isinstance(data, dict): raise TypeError( @@ -217,13 +493,32 @@ def unmarshal_Disk(data: Any) -> Disk: if field is not None: args["capacity"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field return Disk(**args) +def unmarshal_GPU(data: Any) -> GPU: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GPU' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("vram", None) + if field is not None: + args["vram"] = field + + return GPU(**args) + + def unmarshal_Memory(data: Any) -> Memory: if not isinstance(data, dict): raise TypeError( @@ -236,7 +531,7 @@ def unmarshal_Memory(data: Any) -> Memory: if field is not None: args["capacity"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -282,10 +577,44 @@ def unmarshal_OfferOptionOffer(data: Any) -> OfferOptionOffer: field = data.get("price", None) if field is not None: args["price"] = unmarshal_Money(field) + else: + args["price"] = None field = data.get("os_id", None) if field is not None: args["os_id"] = field + else: + args["os_id"] = None + + field = data.get("license", None) + if field is not None: + args["license"] = unmarshal_LicenseOption(field) + else: + args["license"] = None + + field = data.get("public_bandwidth", None) + if field is not None: + args["public_bandwidth"] = unmarshal_PublicBandwidthOption(field) + else: + args["public_bandwidth"] = None + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_PrivateNetworkOption(field) + else: + args["private_network"] = None + + field = data.get("remote_access", None) + if field is not None: + args["remote_access"] = unmarshal_RemoteAccessOption(field) + else: + args["remote_access"] = None + + field = data.get("certification", None) + if field is not None: + args["certification"] = unmarshal_CertificationOption(field) + else: + args["certification"] = None return OfferOptionOffer(**args) @@ -302,7 +631,7 @@ def unmarshal_PersistentMemory(data: Any) -> PersistentMemory: if field is not None: args["capacity"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -356,6 +685,10 @@ def unmarshal_Offer(data: Any) -> Offer: if field is not None: args["bandwidth"] = field + field = data.get("max_bandwidth", None) + if field is not None: + args["max_bandwidth"] = field + field = data.get("commercial_range", None) if field is not None: args["commercial_range"] = field @@ -370,14 +703,6 @@ def unmarshal_Offer(data: Any) -> Offer: if field is not None: args["enable"] = field - field = data.get("price_per_hour", None) - if field is not None: - args["price_per_hour"] = unmarshal_Money(field) - - field = data.get("price_per_month", None) - if field is not None: - args["price_per_month"] = unmarshal_Money(field) - field = data.get("cpus", None) if field is not None: args["cpus"] = [unmarshal_CPU(v) for v in field] if field is not None else None @@ -388,6 +713,18 @@ def unmarshal_Offer(data: Any) -> Offer: [unmarshal_Memory(v) for v in field] if field is not None else None ) + field = data.get("price_per_hour", None) + if field is not None: + args["price_per_hour"] = unmarshal_Money(field) + else: + args["price_per_hour"] = None + + field = data.get("price_per_month", None) + if field is not None: + args["price_per_month"] = unmarshal_Money(field) + else: + args["price_per_month"] = None + field = data.get("quota_name", None) if field is not None: args["quota_name"] = field @@ -438,9 +775,21 @@ def unmarshal_Offer(data: Any) -> Offer: if field is not None: args["tags"] = field + field = data.get("gpus", None) + if field is not None: + args["gpus"] = [unmarshal_GPU(v) for v in field] if field is not None else None + field = data.get("fee", None) if field is not None: args["fee"] = unmarshal_Money(field) + else: + args["fee"] = None + + field = data.get("monthly_offer_id", None) + if field is not None: + args["monthly_offer_id"] = field + else: + args["monthly_offer_id"] = None return Offer(**args) @@ -465,6 +814,36 @@ def unmarshal_Option(data: Any) -> Option: if field is not None: args["manageable"] = field + field = data.get("license", None) + if field is not None: + args["license"] = unmarshal_LicenseOption(field) + else: + args["license"] = None + + field = data.get("public_bandwidth", None) + if field is not None: + args["public_bandwidth"] = unmarshal_PublicBandwidthOption(field) + else: + args["public_bandwidth"] = None + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_PrivateNetworkOption(field) + else: + args["private_network"] = None + + field = data.get("remote_access", None) + if field is not None: + args["remote_access"] = unmarshal_RemoteAccessOption(field) + else: + args["remote_access"] = None + + field = data.get("certification", None) + if field is not None: + args["certification"] = unmarshal_CertificationOption(field) + else: + args["certification"] = None + return Option(**args) @@ -499,14 +878,20 @@ def unmarshal_ServerPrivateNetwork(data: Any) -> ServerPrivateNetwork: field = data.get("vlan", None) if field is not None: args["vlan"] = field + else: + args["vlan"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return ServerPrivateNetwork(**args) @@ -547,6 +932,12 @@ def unmarshal_ServerInstall(data: Any) -> ServerInstall: if field is not None: args["service_url"] = field + field = data.get("partitioning_schema", None) + if field is not None: + args["partitioning_schema"] = unmarshal_Schema(field) + else: + args["partitioning_schema"] = None + return ServerInstall(**args) @@ -577,6 +968,38 @@ def unmarshal_ServerOption(data: Any) -> ServerOption: field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + field = data.get("license", None) + if field is not None: + args["license"] = unmarshal_LicenseOption(field) + else: + args["license"] = None + + field = data.get("public_bandwidth", None) + if field is not None: + args["public_bandwidth"] = unmarshal_PublicBandwidthOption(field) + else: + args["public_bandwidth"] = None + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_PrivateNetworkOption(field) + else: + args["private_network"] = None + + field = data.get("remote_access", None) + if field is not None: + args["remote_access"] = unmarshal_RemoteAccessOption(field) + else: + args["remote_access"] = None + + field = data.get("certification", None) + if field is not None: + args["certification"] = unmarshal_CertificationOption(field) + else: + args["certification"] = None return ServerOption(**args) @@ -635,10 +1058,14 @@ def unmarshal_Server(data: Any) -> Server: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("offer_id", None) if field is not None: @@ -681,10 +1108,14 @@ def unmarshal_Server(data: Any) -> Server: field = data.get("install", None) if field is not None: args["install"] = unmarshal_ServerInstall(field) + else: + args["install"] = None field = data.get("rescue_server", None) if field is not None: args["rescue_server"] = unmarshal_ServerRescueServer(field) + else: + args["rescue_server"] = None return Server(**args) @@ -701,7 +1132,7 @@ def unmarshal_Setting(data: Any) -> Setting: if field is not None: args["id"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -739,6 +1170,8 @@ def unmarshal_BMCAccess(data: Any) -> BMCAccess: field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None return BMCAccess(**args) @@ -754,6 +1187,8 @@ def unmarshal_GetServerMetricsResponse(data: Any) -> GetServerMetricsResponse: field = data.get("pings", None) if field is not None: args["pings"] = unmarshal_TimeSeries(field) + else: + args["pings"] = None return GetServerMetricsResponse(**args) @@ -838,10 +1273,14 @@ def unmarshal_ServerEvent(data: Any) -> ServerEvent: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return ServerEvent(**args) @@ -962,7 +1401,140 @@ def marshal_AddOptionServerRequest( output: Dict[str, Any] = {} if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() + + return output + + +def marshal_SchemaPartition( + request: SchemaPartition, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.label is not None: + output["label"] = str(request.label) + + if request.number is not None: + output["number"] = request.number + + if request.size is not None: + output["size"] = request.size + + if request.use_all_available_space is not None: + output["use_all_available_space"] = request.use_all_available_space + + return output + + +def marshal_SchemaPool( + request: SchemaPool, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.devices is not None: + output["devices"] = request.devices + + if request.options is not None: + output["options"] = request.options + + if request.filesystem_options is not None: + output["filesystem_options"] = request.filesystem_options + + return output + + +def marshal_SchemaDisk( + request: SchemaDisk, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.device is not None: + output["device"] = request.device + + if request.partitions is not None: + output["partitions"] = [ + marshal_SchemaPartition(item, defaults) for item in request.partitions + ] + + return output + + +def marshal_SchemaFilesystem( + request: SchemaFilesystem, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.device is not None: + output["device"] = request.device + + if request.format is not None: + output["format"] = str(request.format) + + if request.mountpoint is not None: + output["mountpoint"] = request.mountpoint + + return output + + +def marshal_SchemaRAID( + request: SchemaRAID, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.level is not None: + output["level"] = str(request.level) + + if request.devices is not None: + output["devices"] = request.devices + + return output + + +def marshal_SchemaZFS( + request: SchemaZFS, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.pools is not None: + output["pools"] = [marshal_SchemaPool(item, defaults) for item in request.pools] + + return output + + +def marshal_Schema( + request: Schema, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.disks is not None: + output["disks"] = [marshal_SchemaDisk(item, defaults) for item in request.disks] + + if request.raids is not None: + output["raids"] = [marshal_SchemaRAID(item, defaults) for item in request.raids] + + if request.filesystems is not None: + output["filesystems"] = [ + marshal_SchemaFilesystem(item, defaults) for item in request.filesystems + ] + + if request.zfs is not None: + output["zfs"] = marshal_SchemaZFS(request.zfs, defaults) return output @@ -994,6 +1566,11 @@ def marshal_CreateServerRequestInstall( if request.service_password is not None: output["service_password"] = request.service_password + if request.partitioning_schema is not None: + output["partitioning_schema"] = marshal_Schema( + request.partitioning_schema, defaults + ) + return output @@ -1030,8 +1607,8 @@ def marshal_CreateServerRequest( output["tags"] = request.tags if request.install is not None: - output["install"] = ( - marshal_CreateServerRequestInstall(request.install, defaults), + output["install"] = marshal_CreateServerRequestInstall( + request.install, defaults ) if request.option_ids is not None: @@ -1067,6 +1644,11 @@ def marshal_InstallServerRequest( if request.service_password is not None: output["service_password"] = request.service_password + if request.partitioning_schema is not None: + output["partitioning_schema"] = marshal_Schema( + request.partitioning_schema, defaults + ) + return output @@ -1170,3 +1752,23 @@ def marshal_UpdateSettingRequest( output["enabled"] = request.enabled return output + + +def marshal_ValidatePartitioningSchemaRequest( + request: ValidatePartitioningSchemaRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.os_id is not None: + output["os_id"] = request.os_id + + if request.partitioning_schema is not None: + output["partitioning_schema"] = marshal_Schema( + request.partitioning_schema, defaults + ) + + return output diff --git a/scaleway/scaleway/baremetal/v1/types.py b/scaleway/scaleway/baremetal/v1/types.py index 74e29494..fac2f380 100644 --- a/scaleway/scaleway/baremetal/v1/types.py +++ b/scaleway/scaleway/baremetal/v1/types.py @@ -10,7 +10,7 @@ from scaleway_core.bridge import ( Money, TimeSeries, - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -87,6 +87,57 @@ def __str__(self) -> str: return str(self.value) +class SchemaFilesystemFormat(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_FORMAT = "unknown_format" + FAT32 = "fat32" + EXT4 = "ext4" + SWAP = "swap" + ZFS = "zfs" + XFS = "xfs" + + def __str__(self) -> str: + return str(self.value) + + +class SchemaPartitionLabel(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PARTITION_LABEL = "unknown_partition_label" + UEFI = "uefi" + LEGACY = "legacy" + ROOT = "root" + BOOT = "boot" + SWAP = "swap" + DATA = "data" + HOME = "home" + RAID = "raid" + ZFS = "zfs" + + def __str__(self) -> str: + return str(self.value) + + +class SchemaPoolType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + NO_RAID = "no_raid" + MIRROR = "mirror" + RAIDZ1 = "raidz1" + RAIDZ2 = "raidz2" + + def __str__(self) -> str: + return str(self.value) + + +class SchemaRAIDLevel(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_RAID_LEVEL = "unknown_raid_level" + RAID_LEVEL_0 = "raid_level_0" + RAID_LEVEL_1 = "raid_level_1" + RAID_LEVEL_5 = "raid_level_5" + RAID_LEVEL_6 = "raid_level_6" + RAID_LEVEL_10 = "raid_level_10" + + def __str__(self) -> str: + return str(self.value) + + class ServerBootType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_BOOT_TYPE = "unknown_boot_type" NORMAL = "normal" @@ -152,6 +203,7 @@ class ServerStatus(str, Enum, metaclass=StrEnumMeta): OUT_OF_STOCK = "out_of_stock" ORDERED = "ordered" RESETTING = "resetting" + MIGRATING = "migrating" def __str__(self) -> str: return str(self.value) @@ -165,6 +217,96 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class SchemaPartition: + label: SchemaPartitionLabel + + number: int + + size: int + + use_all_available_space: bool + + +@dataclass +class SchemaPool: + name: str + + type_: SchemaPoolType + + devices: List[str] + + options: List[str] + + filesystem_options: List[str] + + +@dataclass +class SchemaDisk: + device: str + + partitions: List[SchemaPartition] + + +@dataclass +class SchemaFilesystem: + device: str + + format: SchemaFilesystemFormat + + mountpoint: str + + +@dataclass +class SchemaRAID: + name: str + + level: SchemaRAIDLevel + + devices: List[str] + + +@dataclass +class SchemaZFS: + pools: List[SchemaPool] + + +@dataclass +class CertificationOption: + pass + + +@dataclass +class LicenseOption: + os_id: str + + +@dataclass +class PrivateNetworkOption: + bandwidth_in_bps: int + + +@dataclass +class PublicBandwidthOption: + bandwidth_in_bps: int + + +@dataclass +class RemoteAccessOption: + pass + + +@dataclass +class Schema: + disks: List[SchemaDisk] + + raids: List[SchemaRAID] + + filesystems: List[SchemaFilesystem] + + zfs: Optional[SchemaZFS] + + @dataclass class OSOSField: editable: bool @@ -215,6 +357,19 @@ class Disk: """ +@dataclass +class GPU: + name: str + """ + Name of the GPU. + """ + + vram: int + """ + Capacity of the vram in bytes. + """ + + @dataclass class Memory: capacity: int @@ -273,9 +428,19 @@ class OfferOptionOffer: os_id: Optional[str] """ - ID of the OS linked to the option. + Deprecated, use LicenseOptionVars.os_id instead. """ + license: Optional[LicenseOption] + + public_bandwidth: Optional[PublicBandwidthOption] + + private_network: Optional[PrivateNetworkOption] + + remote_access: Optional[RemoteAccessOption] + + certification: Optional[CertificationOption] + @dataclass class PersistentMemory: @@ -372,6 +537,11 @@ class ServerInstall: Address of the installed service. """ + partitioning_schema: Optional[Schema] + """ + Partitioning schema. + """ + @dataclass class ServerOption: @@ -400,6 +570,16 @@ class ServerOption: Auto expiration date for compatible options. """ + license: Optional[LicenseOption] + + public_bandwidth: Optional[PublicBandwidthOption] + + private_network: Optional[PrivateNetworkOption] + + remote_access: Optional[RemoteAccessOption] + + certification: Optional[CertificationOption] + @dataclass class ServerRescueServer: @@ -451,6 +631,11 @@ class CreateServerRequestInstall: Password used for the service to install. """ + partitioning_schema: Optional[Schema] + """ + Partitioning schema. + """ + @dataclass class OS: @@ -474,21 +659,6 @@ class OS: URL of this OS's logo. """ - enabled: bool - """ - Defines if the operating system is enabled or not. - """ - - license_required: bool - """ - License required (check server options for pricing details). - """ - - allowed: bool - """ - Defines if a specific Organization is allowed to install this OS type. - """ - ssh: Optional[OSOSField] """ Object defining the SSH requirements to install the OS. @@ -514,6 +684,26 @@ class OS: Object defining the password requirements to install the service. """ + enabled: bool + """ + Defines if the operating system is enabled or not. + """ + + license_required: bool + """ + License required (check server options for pricing details). + """ + + allowed: bool + """ + Defines if a specific Organization is allowed to install this OS type. + """ + + custom_partitioning_supported: bool + """ + Defines if custom partitioning is supported by this OS. + """ + @dataclass class Offer: @@ -537,6 +727,11 @@ class Offer: Public bandwidth available (in bits/s) with the offer. """ + max_bandwidth: int + """ + Maximum public bandwidth available (in bits/s) depending on available options. + """ + commercial_range: str """ Commercial range of the offer. @@ -552,24 +747,24 @@ class Offer: Defines whether the offer is currently available. """ - price_per_hour: Optional[Money] + cpus: List[CPU] """ - Price of the offer for the next 60 minutes (a server order at 11h32 will be payed until 12h32). + CPU specifications of the offer. """ - price_per_month: Optional[Money] + memories: List[Memory] """ - Monthly price of the offer, if subscribing on a monthly basis. + Memory specifications of the offer. """ - cpus: List[CPU] + price_per_hour: Optional[Money] """ - CPU specifications of the offer. + Price of the offer for the next 60 minutes (a server order at 11h32 will be paid until 12h32). """ - memories: List[Memory] + price_per_month: Optional[Money] """ - Memory specifications of the offer. + Monthly price of the offer, if subscribing on a monthly basis. """ quota_name: str @@ -622,11 +817,21 @@ class Offer: Array of tags attached to the offer. """ + gpus: List[GPU] + """ + GPU specifications of the offer. + """ + fee: Optional[Money] """ One time fee invoiced by Scaleway for the setup and activation of the server. """ + monthly_offer_id: Optional[str] + """ + Exist only for hourly offers, to migrate to the monthly offer. + """ + @dataclass class Option: @@ -645,6 +850,16 @@ class Option: Defines whether the option is manageable (could be added or removed). """ + license: Optional[LicenseOption] + + public_bandwidth: Optional[PublicBandwidthOption] + + private_network: Optional[PrivateNetworkOption] + + remote_access: Optional[RemoteAccessOption] + + certification: Optional[CertificationOption] + @dataclass class ServerEvent: @@ -784,7 +999,7 @@ class Server: Boot type of the server. """ - zone: Zone + zone: ScwZone """ Zone in which is the server located. """ @@ -845,7 +1060,7 @@ class AddOptionServerRequest: ID of the option to add. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -896,7 +1111,7 @@ class CreateServerRequest: Description associated with the server, max 255 characters. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -933,7 +1148,7 @@ class DeleteOptionServerRequest: ID of the option to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -946,7 +1161,7 @@ class DeleteServerRequest: ID of the server to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -959,7 +1174,25 @@ class GetBMCAccessRequest: ID of the server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetDefaultPartitioningSchemaRequest: + offer_id: str + """ + ID of the offer. + """ + + os_id: str + """ + ID of the OS. + """ + + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -972,7 +1205,7 @@ class GetOSRequest: ID of the OS. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -985,7 +1218,7 @@ class GetOfferRequest: ID of the researched Offer. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -998,7 +1231,7 @@ class GetOptionRequest: ID of the option. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1011,7 +1244,7 @@ class GetServerMetricsRequest: Server ID to get the metrics. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1032,7 +1265,7 @@ class GetServerRequest: ID of the server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1060,7 +1293,7 @@ class InstallServerRequest: SSH key IDs authorized on the server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1085,10 +1318,15 @@ class InstallServerRequest: Password used for the service to install. """ + partitioning_schema: Optional[Schema] + """ + Partitioning schema. + """ + @dataclass class ListOSRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1124,7 +1362,7 @@ class ListOSResponse: @dataclass class ListOffersRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1144,6 +1382,11 @@ class ListOffersRequest: Subscription period type to filter offers by. """ + name: Optional[str] + """ + Offer name to filter offers by. + """ + @dataclass class ListOffersResponse: @@ -1160,7 +1403,7 @@ class ListOffersResponse: @dataclass class ListOptionsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1206,7 +1449,7 @@ class ListServerEventsRequest: ID of the server events searched. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1249,7 +1492,7 @@ class ListServerPrivateNetworksResponse: @dataclass class ListServersRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1315,7 +1558,7 @@ class ListServersResponse: @dataclass class ListSettingsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1354,6 +1597,19 @@ class ListSettingsResponse: """ +@dataclass +class MigrateServerToMonthlyOfferRequest: + server_id: str + """ + ID of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class PrivateNetworkApiAddServerPrivateNetworkRequest: server_id: str @@ -1366,7 +1622,7 @@ class PrivateNetworkApiAddServerPrivateNetworkRequest: The ID of the Private Network. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1384,7 +1640,7 @@ class PrivateNetworkApiDeleteServerPrivateNetworkRequest: The ID of the Private Network. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1392,7 +1648,7 @@ class PrivateNetworkApiDeleteServerPrivateNetworkRequest: @dataclass class PrivateNetworkApiListServerPrivateNetworksRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1445,7 +1701,7 @@ class PrivateNetworkApiSetServerPrivateNetworksRequest: The IDs of the Private Networks. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1458,7 +1714,7 @@ class RebootServerRequest: ID of the server to reboot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1486,7 +1742,7 @@ class StartBMCAccessRequest: The IP authorized to connect to the server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1499,7 +1755,7 @@ class StartServerRequest: ID of the server to start. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1517,7 +1773,7 @@ class StopBMCAccessRequest: ID of the server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1530,7 +1786,7 @@ class StopServerRequest: ID of the server to stop. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1548,7 +1804,7 @@ class UpdateIPRequest: ID of the IP to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1566,7 +1822,7 @@ class UpdateServerRequest: ID of the server to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1594,7 +1850,7 @@ class UpdateSettingRequest: ID of the setting. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1603,3 +1859,26 @@ class UpdateSettingRequest: """ Defines whether the setting is enabled. """ + + +@dataclass +class ValidatePartitioningSchemaRequest: + offer_id: str + """ + Offer ID of the server. + """ + + os_id: str + """ + OS ID. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + partitioning_schema: Optional[Schema] + """ + Partitioning schema. + """ diff --git a/scaleway/scaleway/baremetal/v3/__init__.py b/scaleway/scaleway/baremetal/v3/__init__.py new file mode 100644 index 00000000..990fa6b2 --- /dev/null +++ b/scaleway/scaleway/baremetal/v3/__init__.py @@ -0,0 +1,27 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import ListServerPrivateNetworksRequestOrderBy +from .types import ServerPrivateNetworkStatus +from .content import SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES +from .types import ServerPrivateNetwork +from .types import ListServerPrivateNetworksResponse +from .types import PrivateNetworkApiAddServerPrivateNetworkRequest +from .types import PrivateNetworkApiDeleteServerPrivateNetworkRequest +from .types import PrivateNetworkApiListServerPrivateNetworksRequest +from .types import PrivateNetworkApiSetServerPrivateNetworksRequest +from .types import SetServerPrivateNetworksResponse +from .api import BaremetalV3PrivateNetworkAPI + +__all__ = [ + "ListServerPrivateNetworksRequestOrderBy", + "ServerPrivateNetworkStatus", + "SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES", + "ServerPrivateNetwork", + "ListServerPrivateNetworksResponse", + "PrivateNetworkApiAddServerPrivateNetworkRequest", + "PrivateNetworkApiDeleteServerPrivateNetworkRequest", + "PrivateNetworkApiListServerPrivateNetworksRequest", + "PrivateNetworkApiSetServerPrivateNetworksRequest", + "SetServerPrivateNetworksResponse", + "BaremetalV3PrivateNetworkAPI", +] diff --git a/scaleway/scaleway/baremetal/v3/api.py b/scaleway/scaleway/baremetal/v3/api.py new file mode 100644 index 00000000..4c136b10 --- /dev/null +++ b/scaleway/scaleway/baremetal/v3/api.py @@ -0,0 +1,262 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Dict, List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + validate_path_param, + fetch_all_pages, +) +from .types import ( + ListServerPrivateNetworksRequestOrderBy, + ListServerPrivateNetworksResponse, + PrivateNetworkApiAddServerPrivateNetworkRequest, + PrivateNetworkApiSetServerPrivateNetworksRequest, + ServerPrivateNetwork, + SetServerPrivateNetworksResponse, +) +from .marshalling import ( + unmarshal_ServerPrivateNetwork, + unmarshal_ListServerPrivateNetworksResponse, + unmarshal_SetServerPrivateNetworksResponse, + marshal_PrivateNetworkApiAddServerPrivateNetworkRequest, + marshal_PrivateNetworkApiSetServerPrivateNetworksRequest, +) + + +class BaremetalV3PrivateNetworkAPI(API): + """ + Elastic Metal - Private Networks API. + """ + + def add_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> ServerPrivateNetwork: + """ + Add a server to a Private Network. + Add an Elastic Metal server to a Private Network. + :param server_id: UUID of the server. + :param private_network_id: UUID of the Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param ipam_ip_ids: IPAM IDs of an IPs to attach to the server. + :return: :class:`ServerPrivateNetwork ` + + Usage: + :: + + result = api.add_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/baremetal/v3/zones/{param_zone}/servers/{param_server_id}/private-networks", + body=marshal_PrivateNetworkApiAddServerPrivateNetworkRequest( + PrivateNetworkApiAddServerPrivateNetworkRequest( + server_id=server_id, + private_network_id=private_network_id, + zone=zone, + ipam_ip_ids=ipam_ip_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ServerPrivateNetwork(res.json()) + + def set_server_private_networks( + self, + *, + server_id: str, + per_private_network_ipam_ip_ids: Dict[str, List[str]], + zone: Optional[ScwZone] = None, + ) -> SetServerPrivateNetworksResponse: + """ + Set multiple Private Networks on a server. + Configure multiple Private Networks on an Elastic Metal server. + :param server_id: UUID of the server. + :param per_private_network_ipam_ip_ids: Object where the keys are the UUIDs of Private Networks and the values are arrays of IPAM IDs representing the IPs to assign to this Elastic Metal server on the Private Network. If the array supplied for a Private Network is empty, the next available IP from the Private Network's CIDR block will automatically be used for attachment. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`SetServerPrivateNetworksResponse ` + + Usage: + :: + + result = api.set_server_private_networks( + server_id="example", + per_private_network_ipam_ip_ids={}, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "PUT", + f"/baremetal/v3/zones/{param_zone}/servers/{param_server_id}/private-networks", + body=marshal_PrivateNetworkApiSetServerPrivateNetworksRequest( + PrivateNetworkApiSetServerPrivateNetworksRequest( + server_id=server_id, + per_private_network_ipam_ip_ids=per_private_network_ipam_ip_ids, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetServerPrivateNetworksResponse(res.json()) + + def list_server_private_networks( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + server_id: Optional[str] = None, + private_network_id: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> ListServerPrivateNetworksResponse: + """ + List the Private Networks of a server. + List the Private Networks of an Elastic Metal server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order for the returned Private Networks. + :param page: Page number for the returned Private Networks. + :param page_size: Maximum number of Private Networks per page. + :param server_id: Filter Private Networks by server UUID. + :param private_network_id: Filter Private Networks by Private Network UUID. + :param organization_id: Filter Private Networks by organization UUID. + :param project_id: Filter Private Networks by project UUID. + :param ipam_ip_ids: Filter Private Networks by IPAM IP UUIDs. + :return: :class:`ListServerPrivateNetworksResponse ` + + Usage: + :: + + result = api.list_server_private_networks() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/baremetal/v3/zones/{param_zone}/server-private-networks", + params={ + "ipam_ip_ids": ipam_ip_ids, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "private_network_id": private_network_id, + "project_id": project_id or self.client.default_project_id, + "server_id": server_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServerPrivateNetworksResponse(res.json()) + + def list_server_private_networks_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + server_id: Optional[str] = None, + private_network_id: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ipam_ip_ids: Optional[List[str]] = None, + ) -> List[ServerPrivateNetwork]: + """ + List the Private Networks of a server. + List the Private Networks of an Elastic Metal server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Sort order for the returned Private Networks. + :param page: Page number for the returned Private Networks. + :param page_size: Maximum number of Private Networks per page. + :param server_id: Filter Private Networks by server UUID. + :param private_network_id: Filter Private Networks by Private Network UUID. + :param organization_id: Filter Private Networks by organization UUID. + :param project_id: Filter Private Networks by project UUID. + :param ipam_ip_ids: Filter Private Networks by IPAM IP UUIDs. + :return: :class:`List[ServerPrivateNetwork] ` + + Usage: + :: + + result = api.list_server_private_networks_all() + """ + + return fetch_all_pages( + type=ListServerPrivateNetworksResponse, + key="server_private_networks", + fetcher=self.list_server_private_networks, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "server_id": server_id, + "private_network_id": private_network_id, + "organization_id": organization_id, + "project_id": project_id, + "ipam_ip_ids": ipam_ip_ids, + }, + ) + + def delete_server_private_network( + self, + *, + server_id: str, + private_network_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a Private Network. + :param server_id: UUID of the server. + :param private_network_id: UUID of the Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_server_private_network( + server_id="example", + private_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + param_private_network_id = validate_path_param( + "private_network_id", private_network_id + ) + + res = self._request( + "DELETE", + f"/baremetal/v3/zones/{param_zone}/servers/{param_server_id}/private-networks/{param_private_network_id}", + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/baremetal/v3/content.py b/scaleway/scaleway/baremetal/v3/content.py new file mode 100644 index 00000000..66774cc7 --- /dev/null +++ b/scaleway/scaleway/baremetal/v3/content.py @@ -0,0 +1,15 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + ServerPrivateNetworkStatus, +) + +SERVER_PRIVATE_NETWORK_TRANSIENT_STATUSES: List[ServerPrivateNetworkStatus] = [ + ServerPrivateNetworkStatus.ATTACHING, + ServerPrivateNetworkStatus.DETACHING, +] +""" +Lists transient statutes of the enum :class:`ServerPrivateNetworkStatus `. +""" diff --git a/scaleway/scaleway/baremetal/v3/marshalling.py b/scaleway/scaleway/baremetal/v3/marshalling.py new file mode 100644 index 00000000..d1c8dee3 --- /dev/null +++ b/scaleway/scaleway/baremetal/v3/marshalling.py @@ -0,0 +1,142 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from .types import ( + ServerPrivateNetwork, + ListServerPrivateNetworksResponse, + SetServerPrivateNetworksResponse, + PrivateNetworkApiAddServerPrivateNetworkRequest, + PrivateNetworkApiSetServerPrivateNetworksRequest, +) + + +def unmarshal_ServerPrivateNetwork(data: Any) -> ServerPrivateNetwork: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerPrivateNetwork' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("server_id", None) + if field is not None: + args["server_id"] = field + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("ipam_ip_ids", None) + if field is not None: + args["ipam_ip_ids"] = field + + field = data.get("vlan", None) + if field is not None: + args["vlan"] = field + else: + args["vlan"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return ServerPrivateNetwork(**args) + + +def unmarshal_ListServerPrivateNetworksResponse( + data: Any, +) -> ListServerPrivateNetworksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServerPrivateNetworksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("server_private_networks", None) + if field is not None: + args["server_private_networks"] = ( + [unmarshal_ServerPrivateNetwork(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListServerPrivateNetworksResponse(**args) + + +def unmarshal_SetServerPrivateNetworksResponse( + data: Any, +) -> SetServerPrivateNetworksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetServerPrivateNetworksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("server_private_networks", None) + if field is not None: + args["server_private_networks"] = ( + [unmarshal_ServerPrivateNetwork(v) for v in field] + if field is not None + else None + ) + + return SetServerPrivateNetworksResponse(**args) + + +def marshal_PrivateNetworkApiAddServerPrivateNetworkRequest( + request: PrivateNetworkApiAddServerPrivateNetworkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + if request.ipam_ip_ids is not None: + output["ipam_ip_ids"] = request.ipam_ip_ids + + return output + + +def marshal_PrivateNetworkApiSetServerPrivateNetworksRequest( + request: PrivateNetworkApiSetServerPrivateNetworksRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.per_private_network_ipam_ip_ids is not None: + output["per_private_network_ipam_ip_ids"] = { + key: value for key, value in request.per_private_network_ipam_ip_ids.items() + } + + return output diff --git a/scaleway/scaleway/baremetal/v3/types.py b/scaleway/scaleway/baremetal/v3/types.py new file mode 100644 index 00000000..e4831889 --- /dev/null +++ b/scaleway/scaleway/baremetal/v3/types.py @@ -0,0 +1,204 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class ListServerPrivateNetworksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + UPDATED_AT_ASC = "updated_at_asc" + UPDATED_AT_DESC = "updated_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ServerPrivateNetworkStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + ATTACHING = "attaching" + ATTACHED = "attached" + ERROR = "error" + DETACHING = "detaching" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ServerPrivateNetwork: + id: str + """ + UUID of the Server-to-Private Network mapping. + """ + + project_id: str + """ + Private Network Project UUID. + """ + + server_id: str + """ + Server UUID. + """ + + private_network_id: str + """ + Private Network UUID. + """ + + status: ServerPrivateNetworkStatus + """ + Configuration status of the Private Network. + """ + + ipam_ip_ids: List[str] + """ + IPAM IP IDs of the server, if it has any. + """ + + vlan: Optional[int] + """ + VLAN UUID associated with the Private Network. + """ + + created_at: Optional[datetime] + """ + Private Network creation date. + """ + + updated_at: Optional[datetime] + """ + Date the Private Network was last modified. + """ + + +@dataclass +class ListServerPrivateNetworksResponse: + server_private_networks: List[ServerPrivateNetwork] + + total_count: int + + +@dataclass +class PrivateNetworkApiAddServerPrivateNetworkRequest: + server_id: str + """ + UUID of the server. + """ + + private_network_id: str + """ + UUID of the Private Network. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + ipam_ip_ids: Optional[List[str]] + """ + IPAM IDs of an IPs to attach to the server. + """ + + +@dataclass +class PrivateNetworkApiDeleteServerPrivateNetworkRequest: + server_id: str + """ + UUID of the server. + """ + + private_network_id: str + """ + UUID of the Private Network. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class PrivateNetworkApiListServerPrivateNetworksRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListServerPrivateNetworksRequestOrderBy] + """ + Sort order for the returned Private Networks. + """ + + page: Optional[int] + """ + Page number for the returned Private Networks. + """ + + page_size: Optional[int] + """ + Maximum number of Private Networks per page. + """ + + server_id: Optional[str] + """ + Filter Private Networks by server UUID. + """ + + private_network_id: Optional[str] + """ + Filter Private Networks by Private Network UUID. + """ + + organization_id: Optional[str] + """ + Filter Private Networks by organization UUID. + """ + + project_id: Optional[str] + """ + Filter Private Networks by project UUID. + """ + + ipam_ip_ids: Optional[List[str]] + """ + Filter Private Networks by IPAM IP UUIDs. + """ + + +@dataclass +class PrivateNetworkApiSetServerPrivateNetworksRequest: + server_id: str + """ + UUID of the server. + """ + + per_private_network_ipam_ip_ids: Dict[str, List[str]] + """ + Object where the keys are the UUIDs of Private Networks and the values are arrays of IPAM IDs representing the IPs to assign to this Elastic Metal server on the Private Network. If the array supplied for a Private Network is empty, the next available IP from the Private Network's CIDR block will automatically be used for attachment. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SetServerPrivateNetworksResponse: + server_private_networks: List[ServerPrivateNetwork] diff --git a/scaleway/scaleway/billing/v2alpha1/api.py b/scaleway/scaleway/billing/v2alpha1/api.py index 2c30d1e8..92a02480 100644 --- a/scaleway/scaleway/billing/v2alpha1/api.py +++ b/scaleway/scaleway/billing/v2alpha1/api.py @@ -33,7 +33,7 @@ class BillingV2Alpha1API(API): """ - This API allows you to query your consumption. + This API allows you to manage and query your Scaleway billing and consumption. """ def get_consumption( diff --git a/scaleway/scaleway/billing/v2alpha1/marshalling.py b/scaleway/scaleway/billing/v2alpha1/marshalling.py index 351e16f2..58682a3f 100644 --- a/scaleway/scaleway/billing/v2alpha1/marshalling.py +++ b/scaleway/scaleway/billing/v2alpha1/marshalling.py @@ -48,6 +48,8 @@ def unmarshal_GetConsumptionResponseConsumption( field = data.get("value", None) if field is not None: args["value"] = unmarshal_Money(field) + else: + args["value"] = None return GetConsumptionResponseConsumption(**args) @@ -71,6 +73,8 @@ def unmarshal_GetConsumptionResponse(data: Any) -> GetConsumptionResponse: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return GetConsumptionResponse(**args) @@ -86,6 +90,8 @@ def unmarshal_DiscountCoupon(data: Any) -> DiscountCoupon: field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None return DiscountCoupon(**args) @@ -98,7 +104,7 @@ def unmarshal_DiscountFilter(data: Any) -> DiscountFilter: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -106,6 +112,10 @@ def unmarshal_DiscountFilter(data: Any) -> DiscountFilter: if field is not None: args["value"] = field + field = data.get("exclude", None) + if field is not None: + args["exclude"] = field + return DiscountFilter(**args) @@ -156,18 +166,26 @@ def unmarshal_Discount(data: Any) -> Discount: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("start_date", None) if field is not None: args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None field = data.get("stop_date", None) if field is not None: args["stop_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stop_date"] = None field = data.get("coupon", None) if field is not None: args["coupon"] = unmarshal_DiscountCoupon(field) + else: + args["coupon"] = None return Discount(**args) @@ -216,24 +234,34 @@ def unmarshal_Invoice(data: Any) -> Invoice: field = data.get("start_date", None) if field is not None: args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None field = data.get("issued_date", None) if field is not None: args["issued_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["issued_date"] = None field = data.get("due_date", None) if field is not None: args["due_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["due_date"] = None field = data.get("total_untaxed", None) if field is not None: args["total_untaxed"] = unmarshal_Money(field) + else: + args["total_untaxed"] = None field = data.get("total_taxed", None) if field is not None: args["total_taxed"] = unmarshal_Money(field) + else: + args["total_taxed"] = None return Invoice(**args) diff --git a/scaleway/scaleway/billing/v2alpha1/types.py b/scaleway/scaleway/billing/v2alpha1/types.py index 34ea0916..e4458efc 100644 --- a/scaleway/scaleway/billing/v2alpha1/types.py +++ b/scaleway/scaleway/billing/v2alpha1/types.py @@ -102,6 +102,11 @@ class DiscountFilter: Value of filter, it can be a product/range/region/zone value. """ + exclude: bool + """ + Boolean to describe if filter is an excluding filter. + """ + @dataclass class GetConsumptionResponseConsumption: diff --git a/scaleway/scaleway/billing/v2beta1/api.py b/scaleway/scaleway/billing/v2beta1/api.py index ef1d388a..268bf032 100644 --- a/scaleway/scaleway/billing/v2beta1/api.py +++ b/scaleway/scaleway/billing/v2beta1/api.py @@ -44,7 +44,7 @@ class BillingV2Beta1API(API): """ - This API allows you to query your consumption. + This API allows you to manage and query your Scaleway billing and consumption. """ def list_consumptions( @@ -438,7 +438,10 @@ def list_discounts( ) -> ListDiscountsResponse: """ List discounts. - List all discounts for your organization and usable categories, products, offers, references, regions and zones where the discount can be applied. + List all discounts for your Organization and usable categories, products, offers, references, regions and zones where the discount can be applied. As a reseller: + - If you do not specify an `organization_id` you will list the discounts applied to your own Organization and your customers + - If you indicate your `organization_id` you will list only the discounts applied to your Organization + - If you indicate `the organization_id` of one of your customers, you will list the discounts applied to their Organization. :param order_by: Order discounts in the response by their description. :param page: Positive integer to choose the page to return. :param page_size: Positive integer lower or equal to 100 to select the number of items to return. @@ -476,7 +479,10 @@ def list_discounts_all( ) -> List[Discount]: """ List discounts. - List all discounts for your organization and usable categories, products, offers, references, regions and zones where the discount can be applied. + List all discounts for your Organization and usable categories, products, offers, references, regions and zones where the discount can be applied. As a reseller: + - If you do not specify an `organization_id` you will list the discounts applied to your own Organization and your customers + - If you indicate your `organization_id` you will list only the discounts applied to your Organization + - If you indicate `the organization_id` of one of your customers, you will list the discounts applied to their Organization. :param order_by: Order discounts in the response by their description. :param page: Positive integer to choose the page to return. :param page_size: Positive integer lower or equal to 100 to select the number of items to return. diff --git a/scaleway/scaleway/billing/v2beta1/marshalling.py b/scaleway/scaleway/billing/v2beta1/marshalling.py index 48328d55..19355940 100644 --- a/scaleway/scaleway/billing/v2beta1/marshalling.py +++ b/scaleway/scaleway/billing/v2beta1/marshalling.py @@ -44,28 +44,38 @@ def unmarshal_Invoice(data: Any) -> Invoice: field = data.get("start_date", None) if field is not None: args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None field = data.get("stop_date", None) if field is not None: args["stop_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stop_date"] = None field = data.get("billing_period", None) if field is not None: args["billing_period"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["billing_period"] = None field = data.get("issued_date", None) if field is not None: args["issued_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["issued_date"] = None field = data.get("due_date", None) if field is not None: args["due_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["due_date"] = None - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -84,22 +94,32 @@ def unmarshal_Invoice(data: Any) -> Invoice: field = data.get("total_untaxed", None) if field is not None: args["total_untaxed"] = unmarshal_Money(field) + else: + args["total_untaxed"] = None field = data.get("total_taxed", None) if field is not None: args["total_taxed"] = unmarshal_Money(field) + else: + args["total_taxed"] = None field = data.get("total_tax", None) if field is not None: args["total_tax"] = unmarshal_Money(field) + else: + args["total_tax"] = None field = data.get("total_discount", None) if field is not None: args["total_discount"] = unmarshal_Money(field) + else: + args["total_discount"] = None field = data.get("total_undiscount", None) if field is not None: args["total_undiscount"] = unmarshal_Money(field) + else: + args["total_undiscount"] = None return Invoice(**args) @@ -145,6 +165,8 @@ def unmarshal_ListConsumptionsResponseConsumption( field = data.get("value", None) if field is not None: args["value"] = unmarshal_Money(field) + else: + args["value"] = None return ListConsumptionsResponseConsumption(**args) @@ -176,6 +198,8 @@ def unmarshal_ListConsumptionsResponse(data: Any) -> ListConsumptionsResponse: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return ListConsumptionsResponse(**args) @@ -191,6 +215,8 @@ def unmarshal_DiscountCoupon(data: Any) -> DiscountCoupon: field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None return DiscountCoupon(**args) @@ -203,7 +229,7 @@ def unmarshal_DiscountFilter(data: Any) -> DiscountFilter: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -211,6 +237,10 @@ def unmarshal_DiscountFilter(data: Any) -> DiscountFilter: if field is not None: args["value"] = field + field = data.get("exclude", None) + if field is not None: + args["exclude"] = field + return DiscountFilter(**args) @@ -261,18 +291,26 @@ def unmarshal_Discount(data: Any) -> Discount: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("start_date", None) if field is not None: args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None field = data.get("stop_date", None) if field is not None: args["stop_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stop_date"] = None field = data.get("coupon", None) if field is not None: args["coupon"] = unmarshal_DiscountCoupon(field) + else: + args["coupon"] = None return Discount(**args) @@ -338,10 +376,14 @@ def unmarshal_ListTaxesResponseTax(data: Any) -> ListTaxesResponseTax: field = data.get("rate", None) if field is not None: args["rate"] = field + else: + args["rate"] = None field = data.get("total_tax_value", None) if field is not None: args["total_tax_value"] = field + else: + args["total_tax_value"] = None return ListTaxesResponseTax(**args) @@ -369,5 +411,7 @@ def unmarshal_ListTaxesResponse(data: Any) -> ListTaxesResponse: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return ListTaxesResponse(**args) diff --git a/scaleway/scaleway/billing/v2beta1/types.py b/scaleway/scaleway/billing/v2beta1/types.py index bf0979ca..3bb5b5d2 100644 --- a/scaleway/scaleway/billing/v2beta1/types.py +++ b/scaleway/scaleway/billing/v2beta1/types.py @@ -94,6 +94,10 @@ def __str__(self) -> str: class ListDiscountsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATION_DATE_DESC = "creation_date_desc" CREATION_DATE_ASC = "creation_date_asc" + START_DATE_DESC = "start_date_desc" + START_DATE_ASC = "start_date_asc" + STOP_DATE_DESC = "stop_date_desc" + STOP_DATE_ASC = "stop_date_asc" def __str__(self) -> str: return str(self.value) @@ -149,6 +153,11 @@ class DiscountFilter: Value of filter. """ + exclude: bool + """ + Boolean to describe if filter is an excluding filter. + """ + @dataclass class ListConsumptionsResponseConsumption: @@ -202,7 +211,7 @@ class Discount: organization_id: str """ - The organization ID of the discount. + The Organization ID of the discount. """ description: str diff --git a/scaleway/scaleway/block/v1/__init__.py b/scaleway/scaleway/block/v1/__init__.py new file mode 100644 index 00000000..1e48ec13 --- /dev/null +++ b/scaleway/scaleway/block/v1/__init__.py @@ -0,0 +1,75 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import ListSnapshotsRequestOrderBy +from .types import ListVolumesRequestOrderBy +from .types import ReferenceStatus +from .content import REFERENCE_TRANSIENT_STATUSES +from .types import ReferenceType +from .types import SnapshotStatus +from .content import SNAPSHOT_TRANSIENT_STATUSES +from .types import StorageClass +from .types import VolumeStatus +from .content import VOLUME_TRANSIENT_STATUSES +from .types import Reference +from .types import SnapshotParentVolume +from .types import VolumeSpecifications +from .types import CreateVolumeRequestFromEmpty +from .types import CreateVolumeRequestFromSnapshot +from .types import Snapshot +from .types import VolumeType +from .types import Volume +from .types import CreateSnapshotRequest +from .types import CreateVolumeRequest +from .types import DeleteSnapshotRequest +from .types import DeleteVolumeRequest +from .types import ExportSnapshotToObjectStorageRequest +from .types import GetSnapshotRequest +from .types import GetVolumeRequest +from .types import ImportSnapshotFromObjectStorageRequest +from .types import ListSnapshotsRequest +from .types import ListSnapshotsResponse +from .types import ListVolumeTypesRequest +from .types import ListVolumeTypesResponse +from .types import ListVolumesRequest +from .types import ListVolumesResponse +from .types import UpdateSnapshotRequest +from .types import UpdateVolumeRequest +from .api import BlockV1API + +__all__ = [ + "ListSnapshotsRequestOrderBy", + "ListVolumesRequestOrderBy", + "ReferenceStatus", + "REFERENCE_TRANSIENT_STATUSES", + "ReferenceType", + "SnapshotStatus", + "SNAPSHOT_TRANSIENT_STATUSES", + "StorageClass", + "VolumeStatus", + "VOLUME_TRANSIENT_STATUSES", + "Reference", + "SnapshotParentVolume", + "VolumeSpecifications", + "CreateVolumeRequestFromEmpty", + "CreateVolumeRequestFromSnapshot", + "Snapshot", + "VolumeType", + "Volume", + "CreateSnapshotRequest", + "CreateVolumeRequest", + "DeleteSnapshotRequest", + "DeleteVolumeRequest", + "ExportSnapshotToObjectStorageRequest", + "GetSnapshotRequest", + "GetVolumeRequest", + "ImportSnapshotFromObjectStorageRequest", + "ListSnapshotsRequest", + "ListSnapshotsResponse", + "ListVolumeTypesRequest", + "ListVolumeTypesResponse", + "ListVolumesRequest", + "ListVolumesResponse", + "UpdateSnapshotRequest", + "UpdateVolumeRequest", + "BlockV1API", +] diff --git a/scaleway/scaleway/block/v1/api.py b/scaleway/scaleway/block/v1/api.py new file mode 100644 index 00000000..508e9d16 --- /dev/null +++ b/scaleway/scaleway/block/v1/api.py @@ -0,0 +1,835 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + ListSnapshotsRequestOrderBy, + ListVolumesRequestOrderBy, + CreateSnapshotRequest, + CreateVolumeRequest, + CreateVolumeRequestFromEmpty, + CreateVolumeRequestFromSnapshot, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + ListSnapshotsResponse, + ListVolumeTypesResponse, + ListVolumesResponse, + Snapshot, + UpdateSnapshotRequest, + UpdateVolumeRequest, + Volume, + VolumeType, +) +from .content import ( + SNAPSHOT_TRANSIENT_STATUSES, + VOLUME_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_Snapshot, + unmarshal_Volume, + unmarshal_ListSnapshotsResponse, + unmarshal_ListVolumeTypesResponse, + unmarshal_ListVolumesResponse, + marshal_CreateSnapshotRequest, + marshal_CreateVolumeRequest, + marshal_ExportSnapshotToObjectStorageRequest, + marshal_ImportSnapshotFromObjectStorageRequest, + marshal_UpdateSnapshotRequest, + marshal_UpdateVolumeRequest, +) + + +class BlockV1API(API): + """ + This API allows you to manage your Block Storage volumes. + """ + + def list_volume_types( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListVolumeTypesResponse: + """ + List volume types. + List all available volume types in a specified zone. The volume types listed are ordered by name in ascending order. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :return: :class:`ListVolumeTypesResponse ` + + Usage: + :: + + result = api.list_volume_types() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volume-types", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListVolumeTypesResponse(res.json()) + + def list_volume_types_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[VolumeType]: + """ + List volume types. + List all available volume types in a specified zone. The volume types listed are ordered by name in ascending order. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :return: :class:`List[VolumeType] ` + + Usage: + :: + + result = api.list_volume_types_all() + """ + + return fetch_all_pages( + type=ListVolumeTypesResponse, + key="volume_types", + fetcher=self.list_volume_types, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + }, + ) + + def list_volumes( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListVolumesRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListVolumesResponse: + """ + List volumes. + List all existing volumes in a specified zone. By default, the volumes listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param name: Filter the return volumes by their names. + :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. + :return: :class:`ListVolumesResponse ` + + Usage: + :: + + result = api.list_volumes() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volumes", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "product_resource_id": product_resource_id, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListVolumesResponse(res.json()) + + def list_volumes_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListVolumesRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Volume]: + """ + List volumes. + List all existing volumes in a specified zone. By default, the volumes listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param name: Filter the return volumes by their names. + :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. + :return: :class:`List[Volume] ` + + Usage: + :: + + result = api.list_volumes_all() + """ + + return fetch_all_pages( + type=ListVolumesResponse, + key="volumes", + fetcher=self.list_volumes, + args={ + "zone": zone, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "page": page, + "page_size": page_size, + "name": name, + "product_resource_id": product_resource_id, + "tags": tags, + }, + ) + + def create_volume( + self, + *, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + perf_iops: Optional[int] = None, + project_id: Optional[str] = None, + from_empty: Optional[CreateVolumeRequestFromEmpty] = None, + from_snapshot: Optional[CreateVolumeRequestFromSnapshot] = None, + tags: Optional[List[str]] = None, + ) -> Volume: + """ + Create a volume. + To create a new volume from scratch, you must specify `from_empty` and the `size`. + To create a volume from an existing snapshot, specify `from_snapshot` and the `snapshot_id` in the request payload instead, size is optional and can be specified if you need to extend the original size. The volume will take on the same volume class and underlying IOPS limitations as the original snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the volume. + :param perf_iops: The maximum IO/s expected, according to the different options available in stock (`5000 | 15000`). + One-Of ('requirements'): at most one of 'perf_iops' could be set. + :param project_id: UUID of the project the volume belongs to. + :param from_empty: Specify the size of the new volume if creating a new one from scratch. + One-Of ('from'): at most one of 'from_empty', 'from_snapshot' could be set. + :param from_snapshot: Specify the snapshot ID of the original snapshot. + One-Of ('from'): at most one of 'from_empty', 'from_snapshot' could be set. + :param tags: List of tags assigned to the volume. + :return: :class:`Volume ` + + Usage: + :: + + result = api.create_volume() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/volumes", + body=marshal_CreateVolumeRequest( + CreateVolumeRequest( + zone=zone, + name=name or random_name(prefix="vol"), + project_id=project_id, + tags=tags, + from_empty=from_empty, + from_snapshot=from_snapshot, + perf_iops=perf_iops, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + def get_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + ) -> Volume: + """ + Get a volume. + Retrieve technical information about a specific volume. Details such as size, type, and status are returned in the response. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Volume ` + + Usage: + :: + + result = api.get_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + def wait_for_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[Volume, bool]] = None, + ) -> Volume: + """ + Get a volume. + Retrieve technical information about a specific volume. Details such as size, type, and status are returned in the response. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Volume ` + + Usage: + :: + + result = api.get_volume( + volume_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in VOLUME_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_volume, + options=options, + args={ + "volume_id": volume_id, + "zone": zone, + }, + ) + + def delete_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a detached volume. + You must specify the `volume_id` of the volume you want to delete. The volume must not be in the `in_use` status. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "DELETE", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + ) + + self._throw_on_error(res) + + def update_volume( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + size: Optional[int] = None, + tags: Optional[List[str]] = None, + perf_iops: Optional[int] = None, + ) -> Volume: + """ + Update a volume. + Update the technical details of a volume, such as its name, tags, or its new size and `volume_type` (within the same Block Storage class). + You can only resize a volume to a larger size. It is currently not possible to change your Block Storage Class. + :param volume_id: UUID of the volume. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: When defined, is the new name of the volume. + :param size: Size in bytes of the volume, with a granularity of 1 GB (10^9 bytes). + Must be compliant with the minimum (1GB) and maximum (10TB) allowed size. + :param tags: List of tags assigned to the volume. + :param perf_iops: The selected value must be available for the volume's current storage class. + :return: :class:`Volume ` + + Usage: + :: + + result = api.update_volume( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_volume_id = validate_path_param("volume_id", volume_id) + + res = self._request( + "PATCH", + f"/block/v1/zones/{param_zone}/volumes/{param_volume_id}", + body=marshal_UpdateVolumeRequest( + UpdateVolumeRequest( + volume_id=volume_id, + zone=zone, + name=name, + size=size, + tags=tags, + perf_iops=perf_iops, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Volume(res.json()) + + def list_snapshots( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + volume_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListSnapshotsResponse: + """ + List all snapshots. + List all available snapshots in a specified zone. By default, the snapshots listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param volume_id: Filter snapshots by the ID of the original volume. + :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. + :return: :class:`ListSnapshotsResponse ` + + Usage: + :: + + result = api.list_snapshots() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/snapshots", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + "volume_id": volume_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListSnapshotsResponse(res.json()) + + def list_snapshots_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + volume_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Snapshot]: + """ + List all snapshots. + List all available snapshots in a specified zone. By default, the snapshots listed are ordered by creation date in ascending order. This can be modified via the `order_by` field. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param page: Page number. + :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. + :param volume_id: Filter snapshots by the ID of the original volume. + :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. + :return: :class:`List[Snapshot] ` + + Usage: + :: + + result = api.list_snapshots_all() + """ + + return fetch_all_pages( + type=ListSnapshotsResponse, + key="snapshots", + fetcher=self.list_snapshots, + args={ + "zone": zone, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "page": page, + "page_size": page_size, + "volume_id": volume_id, + "name": name, + "tags": tags, + }, + ) + + def get_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + ) -> Snapshot: + """ + Get a snapshot. + Retrieve technical information about a specific snapshot. Details such as size, volume type, and status are returned in the response. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.get_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "GET", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def wait_for_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[Snapshot, bool]] = None, + ) -> Snapshot: + """ + Get a snapshot. + Retrieve technical information about a specific snapshot. Details such as size, volume type, and status are returned in the response. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.get_snapshot( + snapshot_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in SNAPSHOT_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_snapshot, + options=options, + args={ + "snapshot_id": snapshot_id, + "zone": zone, + }, + ) + + def create_snapshot( + self, + *, + volume_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> Snapshot: + """ + Create a snapshot of a volume. + To create a snapshot, the volume must be in the `in_use` or the `available` status. + If your volume is in a transient state, you need to wait until the end of the current operation. + :param volume_id: UUID of the volume to snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the snapshot. + :param project_id: UUID of the project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.create_snapshot( + volume_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots", + body=marshal_CreateSnapshotRequest( + CreateSnapshotRequest( + volume_id=volume_id, + zone=zone, + name=name or random_name(prefix="snp"), + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def import_snapshot_from_object_storage( + self, + *, + bucket: str, + key: str, + name: str, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + size: Optional[int] = None, + ) -> Snapshot: + """ + Import a snapshot from a Scaleway Object Storage bucket. + The bucket must contain a QCOW2 image. + The bucket can be imported into any Availability Zone as long as it is in the same region as the bucket. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param name: Name of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: UUID of the Project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :param size: Size of the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.import_snapshot_from_object_storage( + bucket="example", + key="example", + name="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots/import-from-object-storage", + body=marshal_ImportSnapshotFromObjectStorageRequest( + ImportSnapshotFromObjectStorageRequest( + bucket=bucket, + key=key, + name=name, + zone=zone, + project_id=project_id, + tags=tags, + size=size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def export_snapshot_to_object_storage( + self, + *, + snapshot_id: str, + bucket: str, + key: str, + zone: Optional[ScwZone] = None, + ) -> Snapshot: + """ + Export a snapshot to a Scaleway Object Storage bucket. + The snapshot is exported in QCOW2 format. + The snapshot must not be in transient state. + :param snapshot_id: UUID of the snapshot. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.export_snapshot_to_object_storage( + snapshot_id="example", + bucket="example", + key="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "POST", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}/export-to-object-storage", + body=marshal_ExportSnapshotToObjectStorageRequest( + ExportSnapshotToObjectStorageRequest( + snapshot_id=snapshot_id, + bucket=bucket, + key=key, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def delete_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a snapshot. + You must specify the `snapshot_id` of the snapshot you want to delete. The snapshot must not be in use. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "DELETE", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + + def update_snapshot( + self, + *, + snapshot_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> Snapshot: + """ + Update a snapshot. + Update the name or tags of the snapshot. + :param snapshot_id: UUID of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: When defined, is the name of the snapshot. + :param tags: List of tags assigned to the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.update_snapshot( + snapshot_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "PATCH", + f"/block/v1/zones/{param_zone}/snapshots/{param_snapshot_id}", + body=marshal_UpdateSnapshotRequest( + UpdateSnapshotRequest( + snapshot_id=snapshot_id, + zone=zone, + name=name, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) diff --git a/scaleway/scaleway/block/v1/content.py b/scaleway/scaleway/block/v1/content.py new file mode 100644 index 00000000..a6cf1ee6 --- /dev/null +++ b/scaleway/scaleway/block/v1/content.py @@ -0,0 +1,36 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + ReferenceStatus, + SnapshotStatus, + VolumeStatus, +) + +REFERENCE_TRANSIENT_STATUSES: List[ReferenceStatus] = [ + ReferenceStatus.ATTACHING, + ReferenceStatus.DETACHING, + ReferenceStatus.CREATING, +] +""" +Lists transient statutes of the enum :class:`ReferenceStatus `. +""" +SNAPSHOT_TRANSIENT_STATUSES: List[SnapshotStatus] = [ + SnapshotStatus.CREATING, + SnapshotStatus.DELETING, + SnapshotStatus.EXPORTING, +] +""" +Lists transient statutes of the enum :class:`SnapshotStatus `. +""" +VOLUME_TRANSIENT_STATUSES: List[VolumeStatus] = [ + VolumeStatus.CREATING, + VolumeStatus.DELETING, + VolumeStatus.RESIZING, + VolumeStatus.SNAPSHOTTING, + VolumeStatus.UPDATING, +] +""" +Lists transient statutes of the enum :class:`VolumeStatus `. +""" diff --git a/scaleway/scaleway/block/v1/marshalling.py b/scaleway/scaleway/block/v1/marshalling.py new file mode 100644 index 00000000..d1aef668 --- /dev/null +++ b/scaleway/scaleway/block/v1/marshalling.py @@ -0,0 +1,521 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + Reference, + SnapshotParentVolume, + Snapshot, + VolumeSpecifications, + Volume, + ListSnapshotsResponse, + VolumeType, + ListVolumeTypesResponse, + ListVolumesResponse, + CreateSnapshotRequest, + CreateVolumeRequestFromEmpty, + CreateVolumeRequestFromSnapshot, + CreateVolumeRequest, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + UpdateSnapshotRequest, + UpdateVolumeRequest, +) + + +def unmarshal_Reference(data: Any) -> Reference: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Reference' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("product_resource_type", None) + if field is not None: + args["product_resource_type"] = field + + field = data.get("product_resource_id", None) + if field is not None: + args["product_resource_id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + return Reference(**args) + + +def unmarshal_SnapshotParentVolume(data: Any) -> SnapshotParentVolume: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SnapshotParentVolume' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + return SnapshotParentVolume(**args) + + +def unmarshal_Snapshot(data: Any) -> Snapshot: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Snapshot' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("references", None) + if field is not None: + args["references"] = ( + [unmarshal_Reference(v) for v in field] if field is not None else None + ) + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("class", None) + if field is not None: + args["class_"] = field + + field = data.get("parent_volume", None) + if field is not None: + args["parent_volume"] = unmarshal_SnapshotParentVolume(field) + else: + args["parent_volume"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Snapshot(**args) + + +def unmarshal_VolumeSpecifications(data: Any) -> VolumeSpecifications: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeSpecifications' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("class", None) + if field is not None: + args["class_"] = field + + field = data.get("perf_iops", None) + if field is not None: + args["perf_iops"] = field + else: + args["perf_iops"] = None + + return VolumeSpecifications(**args) + + +def unmarshal_Volume(data: Any) -> Volume: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Volume' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("references", None) + if field is not None: + args["references"] = ( + [unmarshal_Reference(v) for v in field] if field is not None else None + ) + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("parent_snapshot_id", None) + if field is not None: + args["parent_snapshot_id"] = field + else: + args["parent_snapshot_id"] = None + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("specs", None) + if field is not None: + args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None + + field = data.get("last_detached_at", None) + if field is not None: + args["last_detached_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["last_detached_at"] = None + + return Volume(**args) + + +def unmarshal_ListSnapshotsResponse(data: Any) -> ListSnapshotsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSnapshotsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("snapshots", None) + if field is not None: + args["snapshots"] = ( + [unmarshal_Snapshot(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListSnapshotsResponse(**args) + + +def unmarshal_VolumeType(data: Any) -> VolumeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VolumeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("pricing", None) + if field is not None: + args["pricing"] = unmarshal_Money(field) + else: + args["pricing"] = None + + field = data.get("snapshot_pricing", None) + if field is not None: + args["snapshot_pricing"] = unmarshal_Money(field) + else: + args["snapshot_pricing"] = None + + field = data.get("specs", None) + if field is not None: + args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None + + return VolumeType(**args) + + +def unmarshal_ListVolumeTypesResponse(data: Any) -> ListVolumeTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListVolumeTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("volume_types", None) + if field is not None: + args["volume_types"] = ( + [unmarshal_VolumeType(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListVolumeTypesResponse(**args) + + +def unmarshal_ListVolumesResponse(data: Any) -> ListVolumesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListVolumesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("volumes", None) + if field is not None: + args["volumes"] = ( + [unmarshal_Volume(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListVolumesResponse(**args) + + +def marshal_CreateSnapshotRequest( + request: CreateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.volume_id is not None: + output["volume_id"] = request.volume_id + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_CreateVolumeRequestFromEmpty( + request: CreateVolumeRequestFromEmpty, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_CreateVolumeRequestFromSnapshot( + request: CreateVolumeRequestFromSnapshot, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.snapshot_id is not None: + output["snapshot_id"] = request.snapshot_id + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_CreateVolumeRequest( + request: CreateVolumeRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("from_empty", request.from_empty), + OneOfPossibility("from_snapshot", request.from_snapshot), + ] + ), + ) + output.update( + resolve_one_of( + [ + OneOfPossibility("perf_iops", request.perf_iops), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_ExportSnapshotToObjectStorageRequest( + request: ExportSnapshotToObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + return output + + +def marshal_ImportSnapshotFromObjectStorageRequest( + request: ImportSnapshotFromObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_UpdateSnapshotRequest( + request: UpdateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_UpdateVolumeRequest( + request: UpdateVolumeRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.size is not None: + output["size"] = request.size + + if request.tags is not None: + output["tags"] = request.tags + + if request.perf_iops is not None: + output["perf_iops"] = request.perf_iops + + return output diff --git a/scaleway/scaleway/block/v1/types.py b/scaleway/scaleway/block/v1/types.py new file mode 100644 index 00000000..d666ce94 --- /dev/null +++ b/scaleway/scaleway/block/v1/types.py @@ -0,0 +1,731 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Money, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class ListSnapshotsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListVolumesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ReferenceStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + ATTACHING = "attaching" + ATTACHED = "attached" + DETACHING = "detaching" + DETACHED = "detached" + CREATING = "creating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class ReferenceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + LINK = "link" + EXCLUSIVE = "exclusive" + READ_ONLY = "read_only" + + def __str__(self) -> str: + return str(self.value) + + +class SnapshotStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + AVAILABLE = "available" + ERROR = "error" + DELETING = "deleting" + DELETED = "deleted" + IN_USE = "in_use" + LOCKED = "locked" + EXPORTING = "exporting" + + def __str__(self) -> str: + return str(self.value) + + +class StorageClass(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STORAGE_CLASS = "unknown_storage_class" + UNSPECIFIED = "unspecified" + BSSD = "bssd" + SBS = "sbs" + + def __str__(self) -> str: + return str(self.value) + + +class VolumeStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + AVAILABLE = "available" + IN_USE = "in_use" + DELETING = "deleting" + DELETED = "deleted" + RESIZING = "resizing" + ERROR = "error" + SNAPSHOTTING = "snapshotting" + LOCKED = "locked" + UPDATING = "updating" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class Reference: + id: str + """ + UUID of the reference. + """ + + product_resource_type: str + """ + Type of resource to which the reference is associated. + """ + + product_resource_id: str + """ + UUID of the product resource it refers to (according to the product_resource_type). + """ + + type_: ReferenceType + """ + Type of reference (link, exclusive, read_only). + """ + + status: ReferenceStatus + """ + Status of the reference. Statuses include `attaching`, `attached`, and `detaching`. + """ + + created_at: Optional[datetime] + """ + Creation date of the reference. + """ + + +@dataclass +class SnapshotParentVolume: + id: str + """ + Parent volume UUID (volume from which the snapshot originates). + """ + + name: str + """ + Name of the parent volume. + """ + + type_: str + """ + Volume type of the parent volume. + """ + + status: VolumeStatus + """ + Current status the parent volume. + """ + + +@dataclass +class VolumeSpecifications: + class_: StorageClass + """ + The storage class of the volume. + """ + + perf_iops: Optional[int] + """ + The maximum IO/s expected, according to the different options available in stock (`5000 | 15000`). + """ + + +@dataclass +class CreateVolumeRequestFromEmpty: + size: int + """ + Must be compliant with the minimum (1 GB) and maximum (10 TB) allowed size. + """ + + +@dataclass +class CreateVolumeRequestFromSnapshot: + snapshot_id: str + """ + Source snapshot from which volume will be created. + """ + + size: Optional[int] + """ + Must be compliant with the minimum (1 GB) and maximum (10 TB) allowed size. +Size is optional and is used only if a resize of the volume is requested, otherwise original snapshot size will be used. + """ + + +@dataclass +class Snapshot: + id: str + """ + UUID of the snapshot. + """ + + name: str + """ + Name of the snapshot. + """ + + size: int + """ + Size in bytes of the snapshot. + """ + + project_id: str + """ + UUID of the project the snapshot belongs to. + """ + + references: List[Reference] + """ + List of the references to the snapshot. + """ + + status: SnapshotStatus + """ + Current status of the snapshot (available, in_use, ...). + """ + + tags: List[str] + """ + List of tags assigned to the volume. + """ + + zone: ScwZone + """ + Snapshot zone. + """ + + class_: StorageClass + """ + Storage class of the snapshot. + """ + + parent_volume: Optional[SnapshotParentVolume] + """ + If the parent volume was deleted, value is null. + """ + + created_at: Optional[datetime] + """ + Creation date of the snapshot. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the properties of a snapshot. + """ + + +@dataclass +class VolumeType: + type_: str + """ + Volume type. + """ + + pricing: Optional[Money] + """ + Price of the volume billed in GB/hour. + """ + + snapshot_pricing: Optional[Money] + """ + Price of the snapshot billed in GB/hour. + """ + + specs: Optional[VolumeSpecifications] + """ + Volume specifications of the volume type. + """ + + +@dataclass +class Volume: + id: str + """ + UUID of the volume. + """ + + name: str + """ + Name of the volume. + """ + + type_: str + """ + Volume type. + """ + + size: int + """ + Volume size in bytes. + """ + + project_id: str + """ + UUID of the project to which the volume belongs. + """ + + references: List[Reference] + """ + List of the references to the volume. + """ + + created_at: Optional[datetime] + """ + Creation date of the volume. + """ + + updated_at: Optional[datetime] + """ + Last update of the properties of a volume. + """ + + parent_snapshot_id: Optional[str] + """ + When a volume is created from a snapshot, is the UUID of the snapshot from which the volume has been created. + """ + + status: VolumeStatus + """ + Current status of the volume (available, in_use, ...). + """ + + tags: List[str] + """ + List of tags assigned to the volume. + """ + + zone: ScwZone + """ + Volume zone. + """ + + specs: Optional[VolumeSpecifications] + """ + Specifications of the volume. + """ + + last_detached_at: Optional[datetime] + """ + Last time the volume was detached. + """ + + +@dataclass +class CreateSnapshotRequest: + volume_id: str + """ + UUID of the volume to snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name of the snapshot. + """ + + project_id: Optional[str] + """ + UUID of the project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + +@dataclass +class CreateVolumeRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name of the volume. + """ + + project_id: Optional[str] + """ + UUID of the project the volume belongs to. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the volume. + """ + + from_empty: Optional[CreateVolumeRequestFromEmpty] + + from_snapshot: Optional[CreateVolumeRequestFromSnapshot] + + perf_iops: Optional[int] + + +@dataclass +class DeleteSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ExportSnapshotToObjectStorageRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ImportSnapshotFromObjectStorageRequest: + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + name: str + """ + Name of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + UUID of the Project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + size: Optional[int] + """ + Size of the snapshot. + """ + + +@dataclass +class ListSnapshotsRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListSnapshotsRequestOrderBy] + """ + Criteria to use when ordering the list. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + volume_id: Optional[str] + """ + Filter snapshots by the ID of the original volume. + """ + + name: Optional[str] + """ + Filter snapshots by their names. + """ + + tags: Optional[List[str]] + """ + Filter by tags. Only snapshots with one or more matching tags will be returned. + """ + + +@dataclass +class ListSnapshotsResponse: + snapshots: List[Snapshot] + """ + Paginated returned list of snapshots. + """ + + total_count: int + """ + Total number of snpashots in the project. + """ + + +@dataclass +class ListVolumeTypesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + +@dataclass +class ListVolumeTypesResponse: + volume_types: List[VolumeType] + """ + Returns paginated list of volume-types. + """ + + total_count: int + """ + Total number of volume-types currently available in stock. + """ + + +@dataclass +class ListVolumesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListVolumesRequestOrderBy] + """ + Criteria to use when ordering the list. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size, defines how many entries are returned in one page, must be lower or equal to 100. + """ + + name: Optional[str] + """ + Filter the return volumes by their names. + """ + + product_resource_id: Optional[str] + """ + Filter by a product resource ID linked to this volume (such as an Instance ID). + """ + + tags: Optional[List[str]] + """ + Filter by tags. Only volumes with one or more matching tags will be returned. + """ + + +@dataclass +class ListVolumesResponse: + volumes: List[Volume] + """ + Paginated returned list of volumes. + """ + + total_count: int + """ + Total number of volumes in the project. + """ + + +@dataclass +class UpdateSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + When defined, is the name of the snapshot. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + +@dataclass +class UpdateVolumeRequest: + volume_id: str + """ + UUID of the volume. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + When defined, is the new name of the volume. + """ + + size: Optional[int] + """ + Size in bytes of the volume, with a granularity of 1 GB (10^9 bytes). +Must be compliant with the minimum (1GB) and maximum (10TB) allowed size. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the volume. + """ + + perf_iops: Optional[int] + """ + The selected value must be available for the volume's current storage class. + """ diff --git a/scaleway/scaleway/block/v1alpha1/__init__.py b/scaleway/scaleway/block/v1alpha1/__init__.py index 67c4ae05..93d2a254 100644 --- a/scaleway/scaleway/block/v1alpha1/__init__.py +++ b/scaleway/scaleway/block/v1alpha1/__init__.py @@ -22,8 +22,11 @@ from .types import CreateVolumeRequest from .types import DeleteSnapshotRequest from .types import DeleteVolumeRequest +from .types import ExportSnapshotToObjectStorageRequest from .types import GetSnapshotRequest from .types import GetVolumeRequest +from .types import ImportSnapshotFromObjectStorageRequest +from .types import ImportSnapshotFromS3Request from .types import ListSnapshotsRequest from .types import ListSnapshotsResponse from .types import ListVolumeTypesRequest @@ -57,8 +60,11 @@ "CreateVolumeRequest", "DeleteSnapshotRequest", "DeleteVolumeRequest", + "ExportSnapshotToObjectStorageRequest", "GetSnapshotRequest", "GetVolumeRequest", + "ImportSnapshotFromObjectStorageRequest", + "ImportSnapshotFromS3Request", "ListSnapshotsRequest", "ListSnapshotsResponse", "ListVolumeTypesRequest", diff --git a/scaleway/scaleway/block/v1alpha1/api.py b/scaleway/scaleway/block/v1alpha1/api.py index f1f509bb..11058a60 100644 --- a/scaleway/scaleway/block/v1alpha1/api.py +++ b/scaleway/scaleway/block/v1alpha1/api.py @@ -5,10 +5,11 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, + random_name, validate_path_param, fetch_all_pages, wait_for_resource, @@ -20,6 +21,9 @@ CreateVolumeRequest, CreateVolumeRequestFromEmpty, CreateVolumeRequestFromSnapshot, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + ImportSnapshotFromS3Request, ListSnapshotsResponse, ListVolumeTypesResponse, ListVolumesResponse, @@ -41,6 +45,9 @@ unmarshal_ListVolumesResponse, marshal_CreateSnapshotRequest, marshal_CreateVolumeRequest, + marshal_ExportSnapshotToObjectStorageRequest, + marshal_ImportSnapshotFromObjectStorageRequest, + marshal_ImportSnapshotFromS3Request, marshal_UpdateSnapshotRequest, marshal_UpdateVolumeRequest, ) @@ -48,13 +55,13 @@ class BlockV1Alpha1API(API): """ - This API allows you to use and manage your Block Storage volumes. + This API allows you to manage your Block Storage volumes. """ def list_volume_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListVolumeTypesResponse: @@ -89,7 +96,7 @@ def list_volume_types( def list_volume_types_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[VolumeType]: @@ -121,7 +128,7 @@ def list_volume_types_all( def list_volumes( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListVolumesRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -129,6 +136,7 @@ def list_volumes( page_size: Optional[int] = None, name: Optional[str] = None, product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> ListVolumesResponse: """ List volumes. @@ -141,6 +149,7 @@ def list_volumes( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param name: Filter the return volumes by their names. :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. :return: :class:`ListVolumesResponse ` Usage: @@ -163,6 +172,7 @@ def list_volumes( "page_size": page_size or self.client.default_page_size, "product_resource_id": product_resource_id, "project_id": project_id or self.client.default_project_id, + "tags": tags, }, ) @@ -172,7 +182,7 @@ def list_volumes( def list_volumes_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListVolumesRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -180,6 +190,7 @@ def list_volumes_all( page_size: Optional[int] = None, name: Optional[str] = None, product_resource_id: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> List[Volume]: """ List volumes. @@ -192,6 +203,7 @@ def list_volumes_all( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param name: Filter the return volumes by their names. :param product_resource_id: Filter by a product resource ID linked to this volume (such as an Instance ID). + :param tags: Filter by tags. Only volumes with one or more matching tags will be returned. :return: :class:`List[Volume] ` Usage: @@ -213,14 +225,15 @@ def list_volumes_all( "page_size": page_size, "name": name, "product_resource_id": product_resource_id, + "tags": tags, }, ) def create_volume( self, *, - name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, perf_iops: Optional[int] = None, project_id: Optional[str] = None, from_empty: Optional[CreateVolumeRequestFromEmpty] = None, @@ -231,8 +244,8 @@ def create_volume( Create a volume. To create a new volume from scratch, you must specify `from_empty` and the `size`. To create a volume from an existing snapshot, specify `from_snapshot` and the `snapshot_id` in the request payload instead, size is optional and can be specified if you need to extend the original size. The volume will take on the same volume class and underlying IOPS limitations as the original snapshot. - :param name: Name of the volume. :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the volume. :param perf_iops: The maximum IO/s expected, according to the different options available in stock (`5000 | 15000`). One-Of ('requirements'): at most one of 'perf_iops' could be set. :param project_id: UUID of the project the volume belongs to. @@ -246,9 +259,7 @@ def create_volume( Usage: :: - result = api.create_volume( - name="example", - ) + result = api.create_volume() """ param_zone = validate_path_param("zone", zone or self.client.default_zone) @@ -258,8 +269,8 @@ def create_volume( f"/block/v1alpha1/zones/{param_zone}/volumes", body=marshal_CreateVolumeRequest( CreateVolumeRequest( - name=name, zone=zone, + name=name or random_name(prefix="vol"), project_id=project_id, tags=tags, from_empty=from_empty, @@ -277,7 +288,7 @@ def get_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Volume: """ Get a volume. @@ -309,7 +320,7 @@ def wait_for_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Volume, bool]] = None, ) -> Volume: """ @@ -346,7 +357,7 @@ def delete_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a detached volume. @@ -376,7 +387,7 @@ def update_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, size: Optional[int] = None, tags: Optional[List[str]] = None, @@ -428,7 +439,7 @@ def update_volume( def list_snapshots( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListSnapshotsRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -436,6 +447,7 @@ def list_snapshots( page_size: Optional[int] = None, volume_id: Optional[str] = None, name: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> ListSnapshotsResponse: """ List all snapshots. @@ -448,6 +460,7 @@ def list_snapshots( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param volume_id: Filter snapshots by the ID of the original volume. :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. :return: :class:`ListSnapshotsResponse ` Usage: @@ -469,6 +482,7 @@ def list_snapshots( "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, + "tags": tags, "volume_id": volume_id, }, ) @@ -479,7 +493,7 @@ def list_snapshots( def list_snapshots_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListSnapshotsRequestOrderBy] = None, project_id: Optional[str] = None, organization_id: Optional[str] = None, @@ -487,6 +501,7 @@ def list_snapshots_all( page_size: Optional[int] = None, volume_id: Optional[str] = None, name: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> List[Snapshot]: """ List all snapshots. @@ -499,6 +514,7 @@ def list_snapshots_all( :param page_size: Page size, defines how many entries are returned in one page, must be lower or equal to 100. :param volume_id: Filter snapshots by the ID of the original volume. :param name: Filter snapshots by their names. + :param tags: Filter by tags. Only snapshots with one or more matching tags will be returned. :return: :class:`List[Snapshot] ` Usage: @@ -520,6 +536,7 @@ def list_snapshots_all( "page_size": page_size, "volume_id": volume_id, "name": name, + "tags": tags, }, ) @@ -527,7 +544,7 @@ def get_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Snapshot: """ Get a snapshot. @@ -559,7 +576,7 @@ def wait_for_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Snapshot, bool]] = None, ) -> Snapshot: """ @@ -596,8 +613,8 @@ def create_snapshot( self, *, volume_id: str, - name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, ) -> Snapshot: @@ -606,8 +623,8 @@ def create_snapshot( To create a snapshot, the volume must be in the `in_use` or the `available` status. If your volume is in a transient state, you need to wait until the end of the current operation. :param volume_id: UUID of the volume to snapshot. - :param name: Name of the snapshot. :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name of the snapshot. :param project_id: UUID of the project to which the volume and the snapshot belong. :param tags: List of tags assigned to the snapshot. :return: :class:`Snapshot ` @@ -617,7 +634,6 @@ def create_snapshot( result = api.create_snapshot( volume_id="example", - name="example", ) """ @@ -629,10 +645,172 @@ def create_snapshot( body=marshal_CreateSnapshotRequest( CreateSnapshotRequest( volume_id=volume_id, + zone=zone, + name=name or random_name(prefix="snp"), + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def import_snapshot_from_s3( + self, + *, + bucket: str, + key: str, + name: str, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + size: Optional[int] = None, + ) -> Snapshot: + """ + (Deprecated in favor of `ImportSnapshotFromObjectStorage`). + Import a snapshot from a Scaleway Object Storage bucket + The bucket must contain a QCOW2 image. + The bucket can be imported into any Availability Zone as long as it is in the same region as the bucket. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param name: Name of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: UUID of the Project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :param size: Size of the snapshot. + :return: :class:`Snapshot ` + :deprecated + + Usage: + :: + + result = api.import_snapshot_from_s3( + bucket="example", + key="example", + name="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1alpha1/zones/{param_zone}/snapshots/import-from-s3", + body=marshal_ImportSnapshotFromS3Request( + ImportSnapshotFromS3Request( + bucket=bucket, + key=key, + name=name, + zone=zone, + project_id=project_id, + tags=tags, + size=size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def import_snapshot_from_object_storage( + self, + *, + bucket: str, + key: str, + name: str, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + size: Optional[int] = None, + ) -> Snapshot: + """ + Import a snapshot from a Scaleway Object Storage bucket. + The bucket must contain a QCOW2 image. + The bucket can be imported into any Availability Zone as long as it is in the same region as the bucket. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param name: Name of the snapshot. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: UUID of the Project to which the volume and the snapshot belong. + :param tags: List of tags assigned to the snapshot. + :param size: Size of the snapshot. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.import_snapshot_from_object_storage( + bucket="example", + key="example", + name="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/block/v1alpha1/zones/{param_zone}/snapshots/import-from-object-storage", + body=marshal_ImportSnapshotFromObjectStorageRequest( + ImportSnapshotFromObjectStorageRequest( + bucket=bucket, + key=key, name=name, zone=zone, project_id=project_id, tags=tags, + size=size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def export_snapshot_to_object_storage( + self, + *, + snapshot_id: str, + bucket: str, + key: str, + zone: Optional[ScwZone] = None, + ) -> Snapshot: + """ + Export a snapshot to a Scaleway Object Storage bucket. + The snapshot is exported in QCOW2 format. + The snapshot must not be in transient state. + :param snapshot_id: UUID of the snapshot. + :param bucket: Scaleway Object Storage bucket where the object is stored. + :param key: The object key inside the given bucket. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.export_snapshot_to_object_storage( + snapshot_id="example", + bucket="example", + key="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "POST", + f"/block/v1alpha1/zones/{param_zone}/snapshots/{param_snapshot_id}/export-to-object-storage", + body=marshal_ExportSnapshotToObjectStorageRequest( + ExportSnapshotToObjectStorageRequest( + snapshot_id=snapshot_id, + bucket=bucket, + key=key, + zone=zone, ), self.client, ), @@ -645,7 +823,7 @@ def delete_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a snapshot. @@ -675,7 +853,7 @@ def update_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, ) -> Snapshot: diff --git a/scaleway/scaleway/block/v1alpha1/content.py b/scaleway/scaleway/block/v1alpha1/content.py index a657c57f..a6cf1ee6 100644 --- a/scaleway/scaleway/block/v1alpha1/content.py +++ b/scaleway/scaleway/block/v1alpha1/content.py @@ -19,6 +19,7 @@ SNAPSHOT_TRANSIENT_STATUSES: List[SnapshotStatus] = [ SnapshotStatus.CREATING, SnapshotStatus.DELETING, + SnapshotStatus.EXPORTING, ] """ Lists transient statutes of the enum :class:`SnapshotStatus `. @@ -28,6 +29,7 @@ VolumeStatus.DELETING, VolumeStatus.RESIZING, VolumeStatus.SNAPSHOTTING, + VolumeStatus.UPDATING, ] """ Lists transient statutes of the enum :class:`VolumeStatus `. diff --git a/scaleway/scaleway/block/v1alpha1/marshalling.py b/scaleway/scaleway/block/v1alpha1/marshalling.py index 4381f821..e7289e49 100644 --- a/scaleway/scaleway/block/v1alpha1/marshalling.py +++ b/scaleway/scaleway/block/v1alpha1/marshalling.py @@ -26,6 +26,9 @@ CreateVolumeRequestFromEmpty, CreateVolumeRequestFromSnapshot, CreateVolumeRequest, + ExportSnapshotToObjectStorageRequest, + ImportSnapshotFromObjectStorageRequest, + ImportSnapshotFromS3Request, UpdateSnapshotRequest, UpdateVolumeRequest, ) @@ -51,7 +54,7 @@ def unmarshal_Reference(data: Any) -> Reference: if field is not None: args["product_resource_id"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -62,6 +65,8 @@ def unmarshal_Reference(data: Any) -> Reference: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return Reference(**args) @@ -82,7 +87,7 @@ def unmarshal_SnapshotParentVolume(data: Any) -> SnapshotParentVolume: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -135,21 +140,27 @@ def unmarshal_Snapshot(data: Any) -> Snapshot: if field is not None: args["zone"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field field = data.get("parent_volume", None) if field is not None: args["parent_volume"] = unmarshal_SnapshotParentVolume(field) + else: + args["parent_volume"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Snapshot(**args) @@ -162,13 +173,15 @@ def unmarshal_VolumeSpecifications(data: Any) -> VolumeSpecifications: args: Dict[str, Any] = {} - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field field = data.get("perf_iops", None) if field is not None: args["perf_iops"] = field + else: + args["perf_iops"] = None return VolumeSpecifications(**args) @@ -189,7 +202,7 @@ def unmarshal_Volume(data: Any) -> Volume: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -210,14 +223,20 @@ def unmarshal_Volume(data: Any) -> Volume: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("parent_snapshot_id", None) if field is not None: args["parent_snapshot_id"] = field + else: + args["parent_snapshot_id"] = None field = data.get("status", None) if field is not None: @@ -234,12 +253,16 @@ def unmarshal_Volume(data: Any) -> Volume: field = data.get("specs", None) if field is not None: args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None field = data.get("last_detached_at", None) if field is not None: args["last_detached_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_detached_at"] = None return Volume(**args) @@ -273,21 +296,27 @@ def unmarshal_VolumeType(data: Any) -> VolumeType: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field field = data.get("pricing", None) if field is not None: args["pricing"] = unmarshal_Money(field) + else: + args["pricing"] = None field = data.get("snapshot_pricing", None) if field is not None: args["snapshot_pricing"] = unmarshal_Money(field) + else: + args["snapshot_pricing"] = None field = data.get("specs", None) if field is not None: args["specs"] = unmarshal_VolumeSpecifications(field) + else: + args["specs"] = None return VolumeType(**args) @@ -415,6 +444,75 @@ def marshal_CreateVolumeRequest( return output +def marshal_ExportSnapshotToObjectStorageRequest( + request: ExportSnapshotToObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + return output + + +def marshal_ImportSnapshotFromObjectStorageRequest( + request: ImportSnapshotFromObjectStorageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.size is not None: + output["size"] = request.size + + return output + + +def marshal_ImportSnapshotFromS3Request( + request: ImportSnapshotFromS3Request, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket is not None: + output["bucket"] = request.bucket + + if request.key is not None: + output["key"] = request.key + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.size is not None: + output["size"] = request.size + + return output + + def marshal_UpdateSnapshotRequest( request: UpdateSnapshotRequest, defaults: ProfileDefaults, diff --git a/scaleway/scaleway/block/v1alpha1/types.py b/scaleway/scaleway/block/v1alpha1/types.py index cc1ceb20..2f15d1ec 100644 --- a/scaleway/scaleway/block/v1alpha1/types.py +++ b/scaleway/scaleway/block/v1alpha1/types.py @@ -9,7 +9,7 @@ from scaleway_core.bridge import ( Money, - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -68,6 +68,7 @@ class SnapshotStatus(str, Enum, metaclass=StrEnumMeta): DELETED = "deleted" IN_USE = "in_use" LOCKED = "locked" + EXPORTING = "exporting" def __str__(self) -> str: return str(self.value) @@ -94,6 +95,7 @@ class VolumeStatus(str, Enum, metaclass=StrEnumMeta): ERROR = "error" SNAPSHOTTING = "snapshotting" LOCKED = "locked" + UPDATING = "updating" def __str__(self) -> str: return str(self.value) @@ -123,7 +125,7 @@ class Reference: status: ReferenceStatus """ - Status of reference (attaching, attached, detaching). + Status of the reference. Statuses include `attaching`, `attached`, and `detaching`. """ created_at: Optional[datetime] @@ -227,7 +229,7 @@ class Snapshot: List of tags assigned to the volume. """ - zone: Zone + zone: ScwZone """ Snapshot zone. """ @@ -333,7 +335,7 @@ class Volume: List of tags assigned to the volume. """ - zone: Zone + zone: ScwZone """ Volume zone. """ @@ -356,14 +358,14 @@ class CreateSnapshotRequest: UUID of the volume to snapshot. """ - name: str + zone: Optional[ScwZone] """ - Name of the snapshot. + Zone to target. If none is passed will use default zone from the config. """ - zone: Optional[Zone] + name: Optional[str] """ - Zone to target. If none is passed will use default zone from the config. + Name of the snapshot. """ project_id: Optional[str] @@ -379,14 +381,14 @@ class CreateSnapshotRequest: @dataclass class CreateVolumeRequest: - name: str + zone: Optional[ScwZone] """ - Name of the volume. + Zone to target. If none is passed will use default zone from the config. """ - zone: Optional[Zone] + name: Optional[str] """ - Zone to target. If none is passed will use default zone from the config. + Name of the volume. """ project_id: Optional[str] @@ -413,7 +415,7 @@ class DeleteSnapshotRequest: UUID of the snapshot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -426,7 +428,30 @@ class DeleteVolumeRequest: UUID of the volume. """ - zone: Optional[Zone] + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ExportSnapshotToObjectStorageRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -439,7 +464,7 @@ class GetSnapshotRequest: UUID of the snapshot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -452,15 +477,91 @@ class GetVolumeRequest: UUID of the volume. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ +@dataclass +class ImportSnapshotFromObjectStorageRequest: + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + name: str + """ + Name of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + UUID of the Project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + size: Optional[int] + """ + Size of the snapshot. + """ + + +@dataclass +class ImportSnapshotFromS3Request: + bucket: str + """ + Scaleway Object Storage bucket where the object is stored. + """ + + key: str + """ + The object key inside the given bucket. + """ + + name: str + """ + Name of the snapshot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + UUID of the Project to which the volume and the snapshot belong. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the snapshot. + """ + + size: Optional[int] + """ + Size of the snapshot. + """ + + @dataclass class ListSnapshotsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -500,6 +601,11 @@ class ListSnapshotsRequest: Filter snapshots by their names. """ + tags: Optional[List[str]] + """ + Filter by tags. Only snapshots with one or more matching tags will be returned. + """ + @dataclass class ListSnapshotsResponse: @@ -516,7 +622,7 @@ class ListSnapshotsResponse: @dataclass class ListVolumeTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -547,7 +653,7 @@ class ListVolumeTypesResponse: @dataclass class ListVolumesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -587,6 +693,11 @@ class ListVolumesRequest: Filter by a product resource ID linked to this volume (such as an Instance ID). """ + tags: Optional[List[str]] + """ + Filter by tags. Only volumes with one or more matching tags will be returned. + """ + @dataclass class ListVolumesResponse: @@ -608,7 +719,7 @@ class UpdateSnapshotRequest: UUID of the snapshot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -631,7 +742,7 @@ class UpdateVolumeRequest: UUID of the volume. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway/scaleway/cockpit/v1/__init__.py b/scaleway/scaleway/cockpit/v1/__init__.py new file mode 100644 index 00000000..44d90e37 --- /dev/null +++ b/scaleway/scaleway/cockpit/v1/__init__.py @@ -0,0 +1,149 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import AlertState +from .types import DataSourceOrigin +from .types import DataSourceType +from .types import GrafanaUserRole +from .types import ListDataSourcesRequestOrderBy +from .types import ListGrafanaUsersRequestOrderBy +from .types import ListPlansRequestOrderBy +from .types import ListTokensRequestOrderBy +from .types import PlanName +from .types import TokenScope +from .types import UsageUnit +from .types import PreconfiguredAlertData +from .types import ContactPointEmail +from .types import GetConfigResponseRetention +from .types import Alert +from .types import ContactPoint +from .types import DataSource +from .types import GrafanaProductDashboard +from .types import GrafanaUser +from .types import Plan +from .types import Token +from .types import Usage +from .types import AlertManager +from .types import DisableAlertRulesResponse +from .types import EnableAlertRulesResponse +from .types import GetConfigResponse +from .types import GlobalApiCreateGrafanaUserRequest +from .types import GlobalApiDeleteGrafanaUserRequest +from .types import GlobalApiGetCurrentPlanRequest +from .types import GlobalApiGetGrafanaProductDashboardRequest +from .types import GlobalApiGetGrafanaRequest +from .types import GlobalApiListGrafanaProductDashboardsRequest +from .types import GlobalApiListGrafanaUsersRequest +from .types import GlobalApiListPlansRequest +from .types import GlobalApiResetGrafanaUserPasswordRequest +from .types import GlobalApiSelectPlanRequest +from .types import GlobalApiSyncGrafanaDataSourcesRequest +from .types import Grafana +from .types import ListAlertsResponse +from .types import ListContactPointsResponse +from .types import ListDataSourcesResponse +from .types import ListGrafanaProductDashboardsResponse +from .types import ListGrafanaUsersResponse +from .types import ListPlansResponse +from .types import ListTokensResponse +from .types import RegionalApiCreateContactPointRequest +from .types import RegionalApiCreateDataSourceRequest +from .types import RegionalApiCreateTokenRequest +from .types import RegionalApiDeleteContactPointRequest +from .types import RegionalApiDeleteDataSourceRequest +from .types import RegionalApiDeleteTokenRequest +from .types import RegionalApiDisableAlertManagerRequest +from .types import RegionalApiDisableAlertRulesRequest +from .types import RegionalApiDisableManagedAlertsRequest +from .types import RegionalApiEnableAlertManagerRequest +from .types import RegionalApiEnableAlertRulesRequest +from .types import RegionalApiEnableManagedAlertsRequest +from .types import RegionalApiGetAlertManagerRequest +from .types import RegionalApiGetConfigRequest +from .types import RegionalApiGetDataSourceRequest +from .types import RegionalApiGetTokenRequest +from .types import RegionalApiGetUsageOverviewRequest +from .types import RegionalApiListAlertsRequest +from .types import RegionalApiListContactPointsRequest +from .types import RegionalApiListDataSourcesRequest +from .types import RegionalApiListTokensRequest +from .types import RegionalApiTriggerTestAlertRequest +from .types import RegionalApiUpdateContactPointRequest +from .types import RegionalApiUpdateDataSourceRequest +from .types import UsageOverview +from .api import CockpitV1GlobalAPI +from .api import CockpitV1RegionalAPI + +__all__ = [ + "AlertState", + "DataSourceOrigin", + "DataSourceType", + "GrafanaUserRole", + "ListDataSourcesRequestOrderBy", + "ListGrafanaUsersRequestOrderBy", + "ListPlansRequestOrderBy", + "ListTokensRequestOrderBy", + "PlanName", + "TokenScope", + "UsageUnit", + "PreconfiguredAlertData", + "ContactPointEmail", + "GetConfigResponseRetention", + "Alert", + "ContactPoint", + "DataSource", + "GrafanaProductDashboard", + "GrafanaUser", + "Plan", + "Token", + "Usage", + "AlertManager", + "DisableAlertRulesResponse", + "EnableAlertRulesResponse", + "GetConfigResponse", + "GlobalApiCreateGrafanaUserRequest", + "GlobalApiDeleteGrafanaUserRequest", + "GlobalApiGetCurrentPlanRequest", + "GlobalApiGetGrafanaProductDashboardRequest", + "GlobalApiGetGrafanaRequest", + "GlobalApiListGrafanaProductDashboardsRequest", + "GlobalApiListGrafanaUsersRequest", + "GlobalApiListPlansRequest", + "GlobalApiResetGrafanaUserPasswordRequest", + "GlobalApiSelectPlanRequest", + "GlobalApiSyncGrafanaDataSourcesRequest", + "Grafana", + "ListAlertsResponse", + "ListContactPointsResponse", + "ListDataSourcesResponse", + "ListGrafanaProductDashboardsResponse", + "ListGrafanaUsersResponse", + "ListPlansResponse", + "ListTokensResponse", + "RegionalApiCreateContactPointRequest", + "RegionalApiCreateDataSourceRequest", + "RegionalApiCreateTokenRequest", + "RegionalApiDeleteContactPointRequest", + "RegionalApiDeleteDataSourceRequest", + "RegionalApiDeleteTokenRequest", + "RegionalApiDisableAlertManagerRequest", + "RegionalApiDisableAlertRulesRequest", + "RegionalApiDisableManagedAlertsRequest", + "RegionalApiEnableAlertManagerRequest", + "RegionalApiEnableAlertRulesRequest", + "RegionalApiEnableManagedAlertsRequest", + "RegionalApiGetAlertManagerRequest", + "RegionalApiGetConfigRequest", + "RegionalApiGetDataSourceRequest", + "RegionalApiGetTokenRequest", + "RegionalApiGetUsageOverviewRequest", + "RegionalApiListAlertsRequest", + "RegionalApiListContactPointsRequest", + "RegionalApiListDataSourcesRequest", + "RegionalApiListTokensRequest", + "RegionalApiTriggerTestAlertRequest", + "RegionalApiUpdateContactPointRequest", + "RegionalApiUpdateDataSourceRequest", + "UsageOverview", + "CockpitV1GlobalAPI", + "CockpitV1RegionalAPI", +] diff --git a/scaleway/scaleway/cockpit/v1/api.py b/scaleway/scaleway/cockpit/v1/api.py new file mode 100644 index 00000000..2f986204 --- /dev/null +++ b/scaleway/scaleway/cockpit/v1/api.py @@ -0,0 +1,1679 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + validate_path_param, + fetch_all_pages, +) +from .types import ( + AlertState, + DataSourceOrigin, + DataSourceType, + GrafanaUserRole, + ListDataSourcesRequestOrderBy, + ListGrafanaUsersRequestOrderBy, + ListPlansRequestOrderBy, + ListTokensRequestOrderBy, + PlanName, + TokenScope, + AlertManager, + ContactPoint, + ContactPointEmail, + DataSource, + DisableAlertRulesResponse, + EnableAlertRulesResponse, + GetConfigResponse, + GlobalApiCreateGrafanaUserRequest, + GlobalApiResetGrafanaUserPasswordRequest, + GlobalApiSelectPlanRequest, + GlobalApiSyncGrafanaDataSourcesRequest, + Grafana, + GrafanaProductDashboard, + GrafanaUser, + ListAlertsResponse, + ListContactPointsResponse, + ListDataSourcesResponse, + ListGrafanaProductDashboardsResponse, + ListGrafanaUsersResponse, + ListPlansResponse, + ListTokensResponse, + Plan, + RegionalApiCreateContactPointRequest, + RegionalApiCreateDataSourceRequest, + RegionalApiCreateTokenRequest, + RegionalApiDeleteContactPointRequest, + RegionalApiDisableAlertManagerRequest, + RegionalApiDisableAlertRulesRequest, + RegionalApiDisableManagedAlertsRequest, + RegionalApiEnableAlertManagerRequest, + RegionalApiEnableAlertRulesRequest, + RegionalApiEnableManagedAlertsRequest, + RegionalApiTriggerTestAlertRequest, + RegionalApiUpdateContactPointRequest, + RegionalApiUpdateDataSourceRequest, + Token, + UsageOverview, +) +from .marshalling import ( + unmarshal_ContactPoint, + unmarshal_DataSource, + unmarshal_GrafanaProductDashboard, + unmarshal_GrafanaUser, + unmarshal_Plan, + unmarshal_Token, + unmarshal_AlertManager, + unmarshal_DisableAlertRulesResponse, + unmarshal_EnableAlertRulesResponse, + unmarshal_GetConfigResponse, + unmarshal_Grafana, + unmarshal_ListAlertsResponse, + unmarshal_ListContactPointsResponse, + unmarshal_ListDataSourcesResponse, + unmarshal_ListGrafanaProductDashboardsResponse, + unmarshal_ListGrafanaUsersResponse, + unmarshal_ListPlansResponse, + unmarshal_ListTokensResponse, + unmarshal_UsageOverview, + marshal_GlobalApiCreateGrafanaUserRequest, + marshal_GlobalApiResetGrafanaUserPasswordRequest, + marshal_GlobalApiSelectPlanRequest, + marshal_GlobalApiSyncGrafanaDataSourcesRequest, + marshal_RegionalApiCreateContactPointRequest, + marshal_RegionalApiCreateDataSourceRequest, + marshal_RegionalApiCreateTokenRequest, + marshal_RegionalApiDeleteContactPointRequest, + marshal_RegionalApiDisableAlertManagerRequest, + marshal_RegionalApiDisableAlertRulesRequest, + marshal_RegionalApiDisableManagedAlertsRequest, + marshal_RegionalApiEnableAlertManagerRequest, + marshal_RegionalApiEnableAlertRulesRequest, + marshal_RegionalApiEnableManagedAlertsRequest, + marshal_RegionalApiTriggerTestAlertRequest, + marshal_RegionalApiUpdateContactPointRequest, + marshal_RegionalApiUpdateDataSourceRequest, +) + + +class CockpitV1GlobalAPI(API): + """ + The Cockpit Global API allows you to manage your Cockpit's Grafana. + """ + + def get_grafana( + self, + *, + project_id: Optional[str] = None, + ) -> Grafana: + """ + Get your Cockpit's Grafana. + Retrieve information on your Cockpit's Grafana, specified by the ID of the Project the Cockpit belongs to. + The output returned displays the URL to access your Cockpit's Grafana. + :param project_id: ID of the Project. + :return: :class:`Grafana ` + + Usage: + :: + + result = api.get_grafana() + """ + + res = self._request( + "GET", + "/cockpit/v1/grafana", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Grafana(res.json()) + + def sync_grafana_data_sources( + self, + *, + project_id: Optional[str] = None, + ) -> None: + """ + Synchronize Grafana data sources. + Trigger the synchronization of all your data sources and the alert manager in the relevant regions. The alert manager will only be synchronized if you have enabled it. + :param project_id: ID of the Project to target. + + Usage: + :: + + result = api.sync_grafana_data_sources() + """ + + res = self._request( + "POST", + "/cockpit/v1/grafana/sync-data-sources", + body=marshal_GlobalApiSyncGrafanaDataSourcesRequest( + GlobalApiSyncGrafanaDataSourcesRequest( + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def create_grafana_user( + self, + *, + login: str, + project_id: Optional[str] = None, + role: Optional[GrafanaUserRole] = None, + ) -> GrafanaUser: + """ + Create a Grafana user. + Create a Grafana user to connect to your Cockpit's Grafana. Upon creation, your user password displays only once, so make sure that you save it. + Each Grafana user is associated with a role: viewer or editor. A viewer can only view dashboards, whereas an editor can create and edit dashboards. Note that the `admin` username is not available for creation. + :param login: Username of the Grafana user. Note that the `admin` username is not available for creation. + :param project_id: ID of the Project in which to create the Grafana user. + :param role: Role assigned to the Grafana user. + :return: :class:`GrafanaUser ` + + Usage: + :: + + result = api.create_grafana_user( + login="example", + ) + """ + + res = self._request( + "POST", + "/cockpit/v1/grafana/users", + body=marshal_GlobalApiCreateGrafanaUserRequest( + GlobalApiCreateGrafanaUserRequest( + login=login, + project_id=project_id, + role=role, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_GrafanaUser(res.json()) + + def list_grafana_users( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListGrafanaUsersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListGrafanaUsersResponse: + """ + List Grafana users. + List all Grafana users created in your Cockpit's Grafana. By default, the Grafana users returned in the list are ordered in ascending order. + :param page: Page number. + :param page_size: Page size. + :param order_by: Order of the Grafana users. + :param project_id: ID of the Project to target. + :return: :class:`ListGrafanaUsersResponse ` + + Usage: + :: + + result = api.list_grafana_users() + """ + + res = self._request( + "GET", + "/cockpit/v1/grafana/users", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListGrafanaUsersResponse(res.json()) + + def list_grafana_users_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListGrafanaUsersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[GrafanaUser]: + """ + List Grafana users. + List all Grafana users created in your Cockpit's Grafana. By default, the Grafana users returned in the list are ordered in ascending order. + :param page: Page number. + :param page_size: Page size. + :param order_by: Order of the Grafana users. + :param project_id: ID of the Project to target. + :return: :class:`List[GrafanaUser] ` + + Usage: + :: + + result = api.list_grafana_users_all() + """ + + return fetch_all_pages( + type=ListGrafanaUsersResponse, + key="grafana_users", + fetcher=self.list_grafana_users, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def delete_grafana_user( + self, + *, + project_id: Optional[str] = None, + grafana_user_id: int, + ) -> None: + """ + Delete a Grafana user. + Delete a Grafana user from your Cockpit's Grafana, specified by the ID of the Project the Cockpit belongs to, and the ID of the Grafana user. + :param project_id: ID of the Project to target. + :param grafana_user_id: ID of the Grafana user. + + Usage: + :: + + result = api.delete_grafana_user( + grafana_user_id=1, + ) + """ + + param_grafana_user_id = validate_path_param("grafana_user_id", grafana_user_id) + + res = self._request( + "DELETE", + f"/cockpit/v1/grafana/users/{param_grafana_user_id}", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + + def reset_grafana_user_password( + self, + *, + project_id: Optional[str] = None, + grafana_user_id: int, + ) -> GrafanaUser: + """ + Reset a Grafana user password. + Reset the password of a Grafana user, specified by the ID of the Project the Cockpit belongs to, and the ID of the Grafana user. + A new password regenerates and only displays once. Make sure that you save it. + :param project_id: ID of the Project to target. + :param grafana_user_id: ID of the Grafana user. + :return: :class:`GrafanaUser ` + + Usage: + :: + + result = api.reset_grafana_user_password( + grafana_user_id=1, + ) + """ + + param_grafana_user_id = validate_path_param("grafana_user_id", grafana_user_id) + + res = self._request( + "POST", + f"/cockpit/v1/grafana/users/{param_grafana_user_id}/reset-password", + body=marshal_GlobalApiResetGrafanaUserPasswordRequest( + GlobalApiResetGrafanaUserPasswordRequest( + project_id=project_id, + grafana_user_id=grafana_user_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_GrafanaUser(res.json()) + + def list_grafana_product_dashboards( + self, + *, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + tags: Optional[List[str]] = None, + ) -> ListGrafanaProductDashboardsResponse: + """ + List Scaleway resources dashboards. + Retrieve a list of available dashboards in Grafana, for all Scaleway resources which are integrated with Cockpit. + :param project_id: ID of the Project to target. + :param page: Page number. + :param page_size: Page size. + :param tags: Tags to filter for. + :return: :class:`ListGrafanaProductDashboardsResponse ` + + Usage: + :: + + result = api.list_grafana_product_dashboards() + """ + + res = self._request( + "GET", + "/cockpit/v1/grafana/product-dashboards", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListGrafanaProductDashboardsResponse(res.json()) + + def list_grafana_product_dashboards_all( + self, + *, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + tags: Optional[List[str]] = None, + ) -> List[GrafanaProductDashboard]: + """ + List Scaleway resources dashboards. + Retrieve a list of available dashboards in Grafana, for all Scaleway resources which are integrated with Cockpit. + :param project_id: ID of the Project to target. + :param page: Page number. + :param page_size: Page size. + :param tags: Tags to filter for. + :return: :class:`List[GrafanaProductDashboard] ` + + Usage: + :: + + result = api.list_grafana_product_dashboards_all() + """ + + return fetch_all_pages( + type=ListGrafanaProductDashboardsResponse, + key="dashboards", + fetcher=self.list_grafana_product_dashboards, + args={ + "project_id": project_id, + "page": page, + "page_size": page_size, + "tags": tags, + }, + ) + + def get_grafana_product_dashboard( + self, + *, + project_id: Optional[str] = None, + dashboard_name: str, + ) -> GrafanaProductDashboard: + """ + Get Scaleway resource dashboard. + Retrieve information about the dashboard of a Scaleway resource in Grafana, specified by the ID of the Project the Cockpit belongs to, and the name of the dashboard. + :param project_id: ID of the Project the dashboard belongs to. + :param dashboard_name: Name of the dashboard. + :return: :class:`GrafanaProductDashboard ` + + Usage: + :: + + result = api.get_grafana_product_dashboard( + dashboard_name="example", + ) + """ + + param_dashboard_name = validate_path_param("dashboard_name", dashboard_name) + + res = self._request( + "GET", + f"/cockpit/v1/grafana/product-dashboards/{param_dashboard_name}", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_GrafanaProductDashboard(res.json()) + + def list_plans( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListPlansRequestOrderBy] = None, + ) -> ListPlansResponse: + """ + List plan types. + Retrieve a list of available pricing plan types. + Deprecated: retention is now managed at the data source level. + :param page: Page number. + :param page_size: Page size. + :param order_by: + :return: :class:`ListPlansResponse ` + :deprecated + + Usage: + :: + + result = api.list_plans() + """ + + res = self._request( + "GET", + "/cockpit/v1/plans", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPlansResponse(res.json()) + + def list_plans_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListPlansRequestOrderBy] = None, + ) -> List[Plan]: + """ + List plan types. + Retrieve a list of available pricing plan types. + Deprecated: retention is now managed at the data source level. + :param page: Page number. + :param page_size: Page size. + :param order_by: + :return: :class:`List[Plan] ` + :deprecated + + Usage: + :: + + result = api.list_plans_all() + """ + + return fetch_all_pages( + type=ListPlansResponse, + key="plans", + fetcher=self.list_plans, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + def select_plan( + self, + *, + project_id: Optional[str] = None, + plan_name: Optional[PlanName] = None, + ) -> Plan: + """ + Apply a pricing plan. + Apply a pricing plan on a given Project. You must specify the ID of the pricing plan type. Note that you will be billed for the plan you apply. + Deprecated: retention is now managed at the data source level. + :param project_id: ID of the Project. + :param plan_name: Name of the pricing plan. + :return: :class:`Plan ` + :deprecated + + Usage: + :: + + result = api.select_plan() + """ + + res = self._request( + "PATCH", + "/cockpit/v1/plans", + body=marshal_GlobalApiSelectPlanRequest( + GlobalApiSelectPlanRequest( + project_id=project_id, + plan_name=plan_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + def get_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> Plan: + """ + Get current plan. + Retrieve a pricing plan for the given Project, specified by the ID of the Project. + Deprecated: retention is now managed at the data source level. + :param project_id: ID of the Project. + :return: :class:`Plan ` + :deprecated + + Usage: + :: + + result = api.get_current_plan() + """ + + res = self._request( + "GET", + "/cockpit/v1/current-plan", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + +class CockpitV1RegionalAPI(API): + """ + The Cockpit API allows you to create data sources and Cockpit tokens to store and query data types such as metrics, logs, and traces. You can also push your data into Cockpit, and send alerts to your contact points when your resources may require your attention, using the regional Alert manager. + """ + + def get_config( + self, + *, + region: Optional[ScwRegion] = None, + ) -> GetConfigResponse: + """ + Get the Cockpit configuration. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`GetConfigResponse ` + + Usage: + :: + + result = api.get_config() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/config", + ) + + self._throw_on_error(res) + return unmarshal_GetConfigResponse(res.json()) + + def create_data_source( + self, + *, + name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + type_: Optional[DataSourceType] = None, + retention_days: Optional[int] = None, + ) -> DataSource: + """ + Create a data source. + You must specify the data source type upon creation. Available data source types include: + - metrics + - logs + - traces + The name of the data source will then be used as reference to name the associated Grafana data source. + :param name: Data source name. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project the data source belongs to. + :param type_: Data source type. + :param retention_days: Default values are 30 days for metrics, 7 days for logs and traces. + :return: :class:`DataSource ` + + Usage: + :: + + result = api.create_data_source( + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/data-sources", + body=marshal_RegionalApiCreateDataSourceRequest( + RegionalApiCreateDataSourceRequest( + name=name, + region=region, + project_id=project_id, + type_=type_, + retention_days=retention_days, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DataSource(res.json()) + + def get_data_source( + self, + *, + data_source_id: str, + region: Optional[ScwRegion] = None, + ) -> DataSource: + """ + Get a data source. + Retrieve information about a given data source, specified by the data source ID. The data source's information such as its name, type, URL, origin, and retention period, is returned. + :param data_source_id: ID of the relevant data source. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DataSource ` + + Usage: + :: + + result = api.get_data_source( + data_source_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_data_source_id = validate_path_param("data_source_id", data_source_id) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/data-sources/{param_data_source_id}", + ) + + self._throw_on_error(res) + return unmarshal_DataSource(res.json()) + + def delete_data_source( + self, + *, + data_source_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a data source. + Delete a given data source, specified by the data source ID. Note that deleting a data source is irreversible, and cannot be undone. + :param data_source_id: ID of the data source to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_data_source( + data_source_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_data_source_id = validate_path_param("data_source_id", data_source_id) + + res = self._request( + "DELETE", + f"/cockpit/v1/regions/{param_region}/data-sources/{param_data_source_id}", + ) + + self._throw_on_error(res) + + def list_data_sources( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDataSourcesRequestOrderBy] = None, + project_id: Optional[str] = None, + origin: Optional[DataSourceOrigin] = None, + types: Optional[List[DataSourceType]] = None, + ) -> ListDataSourcesResponse: + """ + List data sources. + Retrieve the list of data sources available in the specified region. By default, the data sources returned in the list are ordered by creation date, in ascending order. + You can list data sources by Project, type and origin. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Number of data sources to return per page. + :param order_by: Sort order for data sources in the response. + :param project_id: Project ID to filter for, only data sources from this Project will be returned. + :param origin: Origin to filter for, only data sources with matching origin will be returned. + :param types: Types to filter for, only data sources with matching types will be returned. + :return: :class:`ListDataSourcesResponse ` + + Usage: + :: + + result = api.list_data_sources() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/data-sources", + params={ + "order_by": order_by, + "origin": origin, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "types": types, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDataSourcesResponse(res.json()) + + def list_data_sources_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDataSourcesRequestOrderBy] = None, + project_id: Optional[str] = None, + origin: Optional[DataSourceOrigin] = None, + types: Optional[List[DataSourceType]] = None, + ) -> List[DataSource]: + """ + List data sources. + Retrieve the list of data sources available in the specified region. By default, the data sources returned in the list are ordered by creation date, in ascending order. + You can list data sources by Project, type and origin. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Number of data sources to return per page. + :param order_by: Sort order for data sources in the response. + :param project_id: Project ID to filter for, only data sources from this Project will be returned. + :param origin: Origin to filter for, only data sources with matching origin will be returned. + :param types: Types to filter for, only data sources with matching types will be returned. + :return: :class:`List[DataSource] ` + + Usage: + :: + + result = api.list_data_sources_all() + """ + + return fetch_all_pages( + type=ListDataSourcesResponse, + key="data_sources", + fetcher=self.list_data_sources, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "origin": origin, + "types": types, + }, + ) + + def update_data_source( + self, + *, + data_source_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + retention_days: Optional[int] = None, + ) -> DataSource: + """ + Update a data source. + Update a given data source name, specified by the data source ID. + :param data_source_id: ID of the data source to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Updated name of the data source. + :param retention_days: BETA - Duration for which the data will be retained in the data source. + :return: :class:`DataSource ` + + Usage: + :: + + result = api.update_data_source( + data_source_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_data_source_id = validate_path_param("data_source_id", data_source_id) + + res = self._request( + "PATCH", + f"/cockpit/v1/regions/{param_region}/data-sources/{param_data_source_id}", + body=marshal_RegionalApiUpdateDataSourceRequest( + RegionalApiUpdateDataSourceRequest( + data_source_id=data_source_id, + region=region, + name=name, + retention_days=retention_days, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DataSource(res.json()) + + def get_usage_overview( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + interval: Optional[str] = None, + ) -> UsageOverview: + """ + Get data source usage overview. + Retrieve the data source usage overview per type for the specified Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: + :param interval: + :return: :class:`UsageOverview ` + + Usage: + :: + + result = api.get_usage_overview() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/usage-overview", + params={ + "interval": interval, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_UsageOverview(res.json()) + + def create_token( + self, + *, + name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + token_scopes: Optional[List[TokenScope]] = None, + ) -> Token: + """ + Create a token. + Give your token the relevant scopes to ensure it has the right permissions to interact with your data sources and the Alert manager. Make sure that you create your token in the same regions as the data sources you want to use it for. + Upon creation, your token's secret key display only once. Make sure that you save it. + :param name: Name of the token. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project the token belongs to. + :param token_scopes: Token permission scopes. + :return: :class:`Token ` + + Usage: + :: + + result = api.create_token( + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/tokens", + body=marshal_RegionalApiCreateTokenRequest( + RegionalApiCreateTokenRequest( + name=name, + region=region, + project_id=project_id, + token_scopes=token_scopes, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Token(res.json()) + + def list_tokens( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListTokensRequestOrderBy] = None, + project_id: Optional[str] = None, + token_scopes: Optional[List[TokenScope]] = None, + ) -> ListTokensResponse: + """ + List tokens. + Retrieve a list of all tokens in the specified region. By default, tokens returned in the list are ordered by creation date, in ascending order. + You can filter tokens by Project ID and token scopes. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Number of tokens to return per page. + :param order_by: Order in which to return results. + :param project_id: ID of the Project the tokens belong to. + :param token_scopes: Token scopes to filter for. + :return: :class:`ListTokensResponse ` + + Usage: + :: + + result = api.list_tokens() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/tokens", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "token_scopes": token_scopes, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListTokensResponse(res.json()) + + def list_tokens_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListTokensRequestOrderBy] = None, + project_id: Optional[str] = None, + token_scopes: Optional[List[TokenScope]] = None, + ) -> List[Token]: + """ + List tokens. + Retrieve a list of all tokens in the specified region. By default, tokens returned in the list are ordered by creation date, in ascending order. + You can filter tokens by Project ID and token scopes. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Number of tokens to return per page. + :param order_by: Order in which to return results. + :param project_id: ID of the Project the tokens belong to. + :param token_scopes: Token scopes to filter for. + :return: :class:`List[Token] ` + + Usage: + :: + + result = api.list_tokens_all() + """ + + return fetch_all_pages( + type=ListTokensResponse, + key="tokens", + fetcher=self.list_tokens, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "token_scopes": token_scopes, + }, + ) + + def get_token( + self, + *, + token_id: str, + region: Optional[ScwRegion] = None, + ) -> Token: + """ + Get a token. + Retrieve information about a given token, specified by the token ID. The token's information such as its scopes, is returned. + :param token_id: Token ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Token ` + + Usage: + :: + + result = api.get_token( + token_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_token_id = validate_path_param("token_id", token_id) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/tokens/{param_token_id}", + ) + + self._throw_on_error(res) + return unmarshal_Token(res.json()) + + def delete_token( + self, + *, + token_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a token. + Delete a given token, specified by the token ID. Deleting a token is irreversible and cannot be undone. + :param token_id: ID of the token to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_token( + token_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_token_id = validate_path_param("token_id", token_id) + + res = self._request( + "DELETE", + f"/cockpit/v1/regions/{param_region}/tokens/{param_token_id}", + ) + + self._throw_on_error(res) + + def get_alert_manager( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AlertManager: + """ + Get the Alert manager. + Retrieve information about the Alert manager which is unique per Project and region. By default the Alert manager is disabled. + The output returned displays a URL to access the Alert manager, and whether the Alert manager and managed alerts are enabled. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: Project ID of the requested Alert manager. + :return: :class:`AlertManager ` + + Usage: + :: + + result = api.get_alert_manager() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/alert-manager", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_AlertManager(res.json()) + + def enable_alert_manager( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AlertManager: + """ + Enable the Alert manager. + Enabling the Alert manager allows you to enable managed alerts and create contact points in the specified Project and region, to be notified when your Scaleway resources may require your attention. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to enable the Alert manager in. + :return: :class:`AlertManager ` + + Usage: + :: + + result = api.enable_alert_manager() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/enable", + body=marshal_RegionalApiEnableAlertManagerRequest( + RegionalApiEnableAlertManagerRequest( + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AlertManager(res.json()) + + def disable_alert_manager( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AlertManager: + """ + Disable the Alert manager. + Disabling the Alert manager deletes the contact points you have created and disables managed alerts in the specified Project and region. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to disable the Alert manager in. + :return: :class:`AlertManager ` + + Usage: + :: + + result = api.disable_alert_manager() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/disable", + body=marshal_RegionalApiDisableAlertManagerRequest( + RegionalApiDisableAlertManagerRequest( + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AlertManager(res.json()) + + def create_contact_point( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + email: Optional[ContactPointEmail] = None, + send_resolved_notifications: Optional[bool] = None, + ) -> ContactPoint: + """ + Create a contact point. + Contact points are email addresses associated with the default receiver, that the Alert manager sends alerts to. + The source of the alerts are data sources within the same Project and region as the Alert manager. + If you need to receive alerts for other receivers, you can create additional contact points and receivers in Grafana. Make sure that you select the Scaleway Alert manager. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to create the contact point in. + :param email: Email address of the contact point to create. + One-Of ('configuration'): at most one of 'email' could be set. + :param send_resolved_notifications: Send an email notification when an alert is marked as resolved. + :return: :class:`ContactPoint ` + + Usage: + :: + + result = api.create_contact_point() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/contact-points", + body=marshal_RegionalApiCreateContactPointRequest( + RegionalApiCreateContactPointRequest( + region=region, + project_id=project_id, + send_resolved_notifications=send_resolved_notifications, + email=email, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ContactPoint(res.json()) + + def list_contact_points( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> ListContactPointsResponse: + """ + List contact points. + Retrieve a list of contact points for the specified Project. The response lists all contact points and receivers created in Grafana or via the API. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Total count of contact points to return per page. + :param project_id: ID of the Project containing the contact points to list. + :return: :class:`ListContactPointsResponse ` + + Usage: + :: + + result = api.list_contact_points() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/alert-manager/contact-points", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListContactPointsResponse(res.json()) + + def list_contact_points_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> List[ContactPoint]: + """ + List contact points. + Retrieve a list of contact points for the specified Project. The response lists all contact points and receivers created in Grafana or via the API. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results. + :param page_size: Total count of contact points to return per page. + :param project_id: ID of the Project containing the contact points to list. + :return: :class:`List[ContactPoint] ` + + Usage: + :: + + result = api.list_contact_points_all() + """ + + return fetch_all_pages( + type=ListContactPointsResponse, + key="contact_points", + fetcher=self.list_contact_points, + args={ + "region": region, + "page": page, + "page_size": page_size, + "project_id": project_id, + }, + ) + + def update_contact_point( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + email: Optional[ContactPointEmail] = None, + send_resolved_notifications: Optional[bool] = None, + ) -> ContactPoint: + """ + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project containing the contact point to update. + :param email: Email address of the contact point to update. + One-Of ('configuration'): at most one of 'email' could be set. + :param send_resolved_notifications: Enable or disable notifications when alert is resolved. + :return: :class:`ContactPoint ` + + Usage: + :: + + result = api.update_contact_point() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "PATCH", + f"/cockpit/v1/regions/{param_region}/alert-manager/contact-points", + body=marshal_RegionalApiUpdateContactPointRequest( + RegionalApiUpdateContactPointRequest( + region=region, + project_id=project_id, + send_resolved_notifications=send_resolved_notifications, + email=email, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ContactPoint(res.json()) + + def delete_contact_point( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + email: Optional[ContactPointEmail] = None, + ) -> None: + """ + Delete a contact point. + Delete a contact point associated with the default receiver. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project containing the contact point to delete. + :param email: Email address of the contact point to delete. + One-Of ('configuration'): at most one of 'email' could be set. + + Usage: + :: + + result = api.delete_contact_point() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/contact-points/delete", + body=marshal_RegionalApiDeleteContactPointRequest( + RegionalApiDeleteContactPointRequest( + region=region, + project_id=project_id, + email=email, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def list_alerts( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + is_enabled: Optional[bool] = None, + is_preconfigured: Optional[bool] = None, + state: Optional[AlertState] = None, + data_source_id: Optional[str] = None, + ) -> ListAlertsResponse: + """ + List alerts. + List preconfigured and/or custom alerts for the specified Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: Project ID to filter for, only alerts from this Project will be returned. + :param is_enabled: True returns only enabled alerts. False returns only disabled alerts. If omitted, no alert filtering is applied. Other filters may still apply. + :param is_preconfigured: True returns only preconfigured alerts. False returns only custom alerts. If omitted, no filtering is applied on alert types. Other filters may still apply. + :param state: Valid values to filter on are `inactive`, `pending` and `firing`. If omitted, no filtering is applied on alert states. Other filters may still apply. + :param data_source_id: If omitted, only alerts from the default scaleway data source will be listed. + :return: :class:`ListAlertsResponse ` + + Usage: + :: + + result = api.list_alerts() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/cockpit/v1/regions/{param_region}/alerts", + params={ + "data_source_id": data_source_id, + "is_enabled": is_enabled, + "is_preconfigured": is_preconfigured, + "project_id": project_id or self.client.default_project_id, + "state": state, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListAlertsResponse(res.json()) + + def enable_managed_alerts( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AlertManager: + """ + Enable managed alerts. + Enable the sending of managed alerts for the specified Project. Managed alerts are predefined alerts that apply to Scaleway recources integrated with Cockpit by default. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :return: :class:`AlertManager ` + + Usage: + :: + + result = api.enable_managed_alerts() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/managed-alerts/enable", + body=marshal_RegionalApiEnableManagedAlertsRequest( + RegionalApiEnableManagedAlertsRequest( + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AlertManager(res.json()) + + def disable_managed_alerts( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AlertManager: + """ + Disable managed alerts. + Disable the sending of managed alerts for the specified Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :return: :class:`AlertManager ` + + Usage: + :: + + result = api.disable_managed_alerts() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/managed-alerts/disable", + body=marshal_RegionalApiDisableManagedAlertsRequest( + RegionalApiDisableManagedAlertsRequest( + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AlertManager(res.json()) + + def enable_alert_rules( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + rule_ids: Optional[List[str]] = None, + ) -> EnableAlertRulesResponse: + """ + Enable preconfigured alert rules. + Enable alert rules from the list of available preconfigured rules. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: + :param rule_ids: + :return: :class:`EnableAlertRulesResponse ` + + Usage: + :: + + result = api.enable_alert_rules() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/enable-alert-rules", + body=marshal_RegionalApiEnableAlertRulesRequest( + RegionalApiEnableAlertRulesRequest( + region=region, + project_id=project_id, + rule_ids=rule_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_EnableAlertRulesResponse(res.json()) + + def disable_alert_rules( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + rule_ids: Optional[List[str]] = None, + ) -> DisableAlertRulesResponse: + """ + Disable preconfigured alert rules. + Disable alert rules from the list of available preconfigured rules. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: + :param rule_ids: + :return: :class:`DisableAlertRulesResponse ` + + Usage: + :: + + result = api.disable_alert_rules() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/disable-alert-rules", + body=marshal_RegionalApiDisableAlertRulesRequest( + RegionalApiDisableAlertRulesRequest( + region=region, + project_id=project_id, + rule_ids=rule_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DisableAlertRulesResponse(res.json()) + + def trigger_test_alert( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> None: + """ + Trigger a test alert. + Send a test alert to the Alert manager to make sure your contact points get notified. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + + Usage: + :: + + result = api.trigger_test_alert() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/cockpit/v1/regions/{param_region}/alert-manager/trigger-test-alert", + body=marshal_RegionalApiTriggerTestAlertRequest( + RegionalApiTriggerTestAlertRequest( + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/cockpit/v1/marshalling.py b/scaleway/scaleway/cockpit/v1/marshalling.py new file mode 100644 index 00000000..ae31225c --- /dev/null +++ b/scaleway/scaleway/cockpit/v1/marshalling.py @@ -0,0 +1,1051 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + TokenScope, + ContactPointEmail, + ContactPoint, + DataSource, + GrafanaProductDashboard, + GrafanaUser, + Plan, + Token, + AlertManager, + DisableAlertRulesResponse, + EnableAlertRulesResponse, + GetConfigResponseRetention, + GetConfigResponse, + Grafana, + PreconfiguredAlertData, + Alert, + ListAlertsResponse, + ListContactPointsResponse, + ListDataSourcesResponse, + ListGrafanaProductDashboardsResponse, + ListGrafanaUsersResponse, + ListPlansResponse, + ListTokensResponse, + Usage, + UsageOverview, + GlobalApiCreateGrafanaUserRequest, + GlobalApiResetGrafanaUserPasswordRequest, + GlobalApiSelectPlanRequest, + GlobalApiSyncGrafanaDataSourcesRequest, + RegionalApiCreateContactPointRequest, + RegionalApiCreateDataSourceRequest, + RegionalApiCreateTokenRequest, + RegionalApiDeleteContactPointRequest, + RegionalApiDisableAlertManagerRequest, + RegionalApiDisableAlertRulesRequest, + RegionalApiDisableManagedAlertsRequest, + RegionalApiEnableAlertManagerRequest, + RegionalApiEnableAlertRulesRequest, + RegionalApiEnableManagedAlertsRequest, + RegionalApiTriggerTestAlertRequest, + RegionalApiUpdateContactPointRequest, + RegionalApiUpdateDataSourceRequest, +) + + +def unmarshal_ContactPointEmail(data: Any) -> ContactPointEmail: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContactPointEmail' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("to", None) + if field is not None: + args["to"] = field + + return ContactPointEmail(**args) + + +def unmarshal_ContactPoint(data: Any) -> ContactPoint: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContactPoint' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("send_resolved_notifications", None) + if field is not None: + args["send_resolved_notifications"] = field + + field = data.get("email", None) + if field is not None: + args["email"] = unmarshal_ContactPointEmail(field) + else: + args["email"] = None + + return ContactPoint(**args) + + +def unmarshal_DataSource(data: Any) -> DataSource: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DataSource' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("url", None) + if field is not None: + args["url"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("origin", None) + if field is not None: + args["origin"] = field + + field = data.get("synchronized_with_grafana", None) + if field is not None: + args["synchronized_with_grafana"] = field + + field = data.get("retention_days", None) + if field is not None: + args["retention_days"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return DataSource(**args) + + +def unmarshal_GrafanaProductDashboard(data: Any) -> GrafanaProductDashboard: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GrafanaProductDashboard' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("title", None) + if field is not None: + args["title"] = field + + field = data.get("url", None) + if field is not None: + args["url"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("variables", None) + if field is not None: + args["variables"] = field + + return GrafanaProductDashboard(**args) + + +def unmarshal_GrafanaUser(data: Any) -> GrafanaUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GrafanaUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("login", None) + if field is not None: + args["login"] = field + + field = data.get("role", None) + if field is not None: + args["role"] = field + + field = data.get("password", None) + if field is not None: + args["password"] = field + else: + args["password"] = None + + return GrafanaUser(**args) + + +def unmarshal_Plan(data: Any) -> Plan: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Plan' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("sample_ingestion_price", None) + if field is not None: + args["sample_ingestion_price"] = field + + field = data.get("logs_ingestion_price", None) + if field is not None: + args["logs_ingestion_price"] = field + + field = data.get("traces_ingestion_price", None) + if field is not None: + args["traces_ingestion_price"] = field + + field = data.get("monthly_price", None) + if field is not None: + args["monthly_price"] = field + + field = data.get("retention_metrics_interval", None) + if field is not None: + args["retention_metrics_interval"] = field + else: + args["retention_metrics_interval"] = None + + field = data.get("retention_logs_interval", None) + if field is not None: + args["retention_logs_interval"] = field + else: + args["retention_logs_interval"] = None + + field = data.get("retention_traces_interval", None) + if field is not None: + args["retention_traces_interval"] = field + else: + args["retention_traces_interval"] = None + + return Plan(**args) + + +def unmarshal_Token(data: Any) -> Token: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Token' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("scopes", None) + if field is not None: + args["scopes"] = [TokenScope(v) for v in field] if field is not None else None + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("secret_key", None) + if field is not None: + args["secret_key"] = field + else: + args["secret_key"] = None + + return Token(**args) + + +def unmarshal_AlertManager(data: Any) -> AlertManager: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AlertManager' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("alert_manager_enabled", None) + if field is not None: + args["alert_manager_enabled"] = field + + field = data.get("managed_alerts_enabled", None) + if field is not None: + args["managed_alerts_enabled"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("alert_manager_url", None) + if field is not None: + args["alert_manager_url"] = field + else: + args["alert_manager_url"] = None + + return AlertManager(**args) + + +def unmarshal_DisableAlertRulesResponse(data: Any) -> DisableAlertRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DisableAlertRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("disabled_rule_ids", None) + if field is not None: + args["disabled_rule_ids"] = field + + return DisableAlertRulesResponse(**args) + + +def unmarshal_EnableAlertRulesResponse(data: Any) -> EnableAlertRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EnableAlertRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enabled_rule_ids", None) + if field is not None: + args["enabled_rule_ids"] = field + + return EnableAlertRulesResponse(**args) + + +def unmarshal_GetConfigResponseRetention(data: Any) -> GetConfigResponseRetention: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetConfigResponseRetention' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("min_days", None) + if field is not None: + args["min_days"] = field + + field = data.get("max_days", None) + if field is not None: + args["max_days"] = field + + field = data.get("default_days", None) + if field is not None: + args["default_days"] = field + + return GetConfigResponseRetention(**args) + + +def unmarshal_GetConfigResponse(data: Any) -> GetConfigResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetConfigResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("custom_metrics_retention", None) + if field is not None: + args["custom_metrics_retention"] = unmarshal_GetConfigResponseRetention(field) + else: + args["custom_metrics_retention"] = None + + field = data.get("custom_logs_retention", None) + if field is not None: + args["custom_logs_retention"] = unmarshal_GetConfigResponseRetention(field) + else: + args["custom_logs_retention"] = None + + field = data.get("custom_traces_retention", None) + if field is not None: + args["custom_traces_retention"] = unmarshal_GetConfigResponseRetention(field) + else: + args["custom_traces_retention"] = None + + field = data.get("product_metrics_retention", None) + if field is not None: + args["product_metrics_retention"] = unmarshal_GetConfigResponseRetention(field) + else: + args["product_metrics_retention"] = None + + field = data.get("product_logs_retention", None) + if field is not None: + args["product_logs_retention"] = unmarshal_GetConfigResponseRetention(field) + else: + args["product_logs_retention"] = None + + return GetConfigResponse(**args) + + +def unmarshal_Grafana(data: Any) -> Grafana: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Grafana' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("grafana_url", None) + if field is not None: + args["grafana_url"] = field + + return Grafana(**args) + + +def unmarshal_PreconfiguredAlertData(data: Any) -> PreconfiguredAlertData: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PreconfiguredAlertData' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("preconfigured_rule_id", None) + if field is not None: + args["preconfigured_rule_id"] = field + + field = data.get("display_name", None) + if field is not None: + args["display_name"] = field + + field = data.get("display_description", None) + if field is not None: + args["display_description"] = field + + return PreconfiguredAlertData(**args) + + +def unmarshal_Alert(data: Any) -> Alert: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Alert' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("preconfigured", None) + if field is not None: + args["preconfigured"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("rule", None) + if field is not None: + args["rule"] = field + + field = data.get("duration", None) + if field is not None: + args["duration"] = field + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + field = data.get("annotations", None) + if field is not None: + args["annotations"] = field + + field = data.get("data_source_id", None) + if field is not None: + args["data_source_id"] = field + + field = data.get("state", None) + if field is not None: + args["state"] = field + else: + args["state"] = None + + field = data.get("preconfigured_data", None) + if field is not None: + args["preconfigured_data"] = unmarshal_PreconfiguredAlertData(field) + else: + args["preconfigured_data"] = None + + return Alert(**args) + + +def unmarshal_ListAlertsResponse(data: Any) -> ListAlertsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListAlertsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("alerts", None) + if field is not None: + args["alerts"] = ( + [unmarshal_Alert(v) for v in field] if field is not None else None + ) + + return ListAlertsResponse(**args) + + +def unmarshal_ListContactPointsResponse(data: Any) -> ListContactPointsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListContactPointsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("contact_points", None) + if field is not None: + args["contact_points"] = ( + [unmarshal_ContactPoint(v) for v in field] if field is not None else None + ) + + field = data.get("has_additional_receivers", None) + if field is not None: + args["has_additional_receivers"] = field + + field = data.get("has_additional_contact_points", None) + if field is not None: + args["has_additional_contact_points"] = field + + return ListContactPointsResponse(**args) + + +def unmarshal_ListDataSourcesResponse(data: Any) -> ListDataSourcesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDataSourcesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("data_sources", None) + if field is not None: + args["data_sources"] = ( + [unmarshal_DataSource(v) for v in field] if field is not None else None + ) + + return ListDataSourcesResponse(**args) + + +def unmarshal_ListGrafanaProductDashboardsResponse( + data: Any, +) -> ListGrafanaProductDashboardsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGrafanaProductDashboardsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("dashboards", None) + if field is not None: + args["dashboards"] = ( + [unmarshal_GrafanaProductDashboard(v) for v in field] + if field is not None + else None + ) + + return ListGrafanaProductDashboardsResponse(**args) + + +def unmarshal_ListGrafanaUsersResponse(data: Any) -> ListGrafanaUsersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGrafanaUsersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("grafana_users", None) + if field is not None: + args["grafana_users"] = ( + [unmarshal_GrafanaUser(v) for v in field] if field is not None else None + ) + + return ListGrafanaUsersResponse(**args) + + +def unmarshal_ListPlansResponse(data: Any) -> ListPlansResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPlansResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("plans", None) + if field is not None: + args["plans"] = ( + [unmarshal_Plan(v) for v in field] if field is not None else None + ) + + return ListPlansResponse(**args) + + +def unmarshal_ListTokensResponse(data: Any) -> ListTokensResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListTokensResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("tokens", None) + if field is not None: + args["tokens"] = ( + [unmarshal_Token(v) for v in field] if field is not None else None + ) + + return ListTokensResponse(**args) + + +def unmarshal_Usage(data: Any) -> Usage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Usage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("data_source_origin", None) + if field is not None: + args["data_source_origin"] = field + + field = data.get("data_source_type", None) + if field is not None: + args["data_source_type"] = field + + field = data.get("unit", None) + if field is not None: + args["unit"] = field + + field = data.get("quantity_over_interval", None) + if field is not None: + args["quantity_over_interval"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("data_source_id", None) + if field is not None: + args["data_source_id"] = field + else: + args["data_source_id"] = None + + field = data.get("interval", None) + if field is not None: + args["interval"] = field + else: + args["interval"] = None + + return Usage(**args) + + +def unmarshal_UsageOverview(data: Any) -> UsageOverview: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'UsageOverview' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("scaleway_metrics_usage", None) + if field is not None: + args["scaleway_metrics_usage"] = unmarshal_Usage(field) + else: + args["scaleway_metrics_usage"] = None + + field = data.get("scaleway_logs_usage", None) + if field is not None: + args["scaleway_logs_usage"] = unmarshal_Usage(field) + else: + args["scaleway_logs_usage"] = None + + field = data.get("external_metrics_usage", None) + if field is not None: + args["external_metrics_usage"] = unmarshal_Usage(field) + else: + args["external_metrics_usage"] = None + + field = data.get("external_logs_usage", None) + if field is not None: + args["external_logs_usage"] = unmarshal_Usage(field) + else: + args["external_logs_usage"] = None + + field = data.get("external_traces_usage", None) + if field is not None: + args["external_traces_usage"] = unmarshal_Usage(field) + else: + args["external_traces_usage"] = None + + return UsageOverview(**args) + + +def marshal_GlobalApiCreateGrafanaUserRequest( + request: GlobalApiCreateGrafanaUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.login is not None: + output["login"] = request.login + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.role is not None: + output["role"] = str(request.role) + + return output + + +def marshal_GlobalApiResetGrafanaUserPasswordRequest( + request: GlobalApiResetGrafanaUserPasswordRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_GlobalApiSelectPlanRequest( + request: GlobalApiSelectPlanRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.plan_name is not None: + output["plan_name"] = str(request.plan_name) + + return output + + +def marshal_GlobalApiSyncGrafanaDataSourcesRequest( + request: GlobalApiSyncGrafanaDataSourcesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ContactPointEmail( + request: ContactPointEmail, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.to is not None: + output["to"] = request.to + + return output + + +def marshal_RegionalApiCreateContactPointRequest( + request: RegionalApiCreateContactPointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("email", request.email), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.send_resolved_notifications is not None: + output["send_resolved_notifications"] = request.send_resolved_notifications + + return output + + +def marshal_RegionalApiCreateDataSourceRequest( + request: RegionalApiCreateDataSourceRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.retention_days is not None: + output["retention_days"] = request.retention_days + + return output + + +def marshal_RegionalApiCreateTokenRequest( + request: RegionalApiCreateTokenRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.token_scopes is not None: + output["token_scopes"] = [str(item) for item in request.token_scopes] + + return output + + +def marshal_RegionalApiDeleteContactPointRequest( + request: RegionalApiDeleteContactPointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("email", request.email), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiDisableAlertManagerRequest( + request: RegionalApiDisableAlertManagerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiDisableAlertRulesRequest( + request: RegionalApiDisableAlertRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.rule_ids is not None: + output["rule_ids"] = request.rule_ids + + return output + + +def marshal_RegionalApiDisableManagedAlertsRequest( + request: RegionalApiDisableManagedAlertsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiEnableAlertManagerRequest( + request: RegionalApiEnableAlertManagerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiEnableAlertRulesRequest( + request: RegionalApiEnableAlertRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.rule_ids is not None: + output["rule_ids"] = request.rule_ids + + return output + + +def marshal_RegionalApiEnableManagedAlertsRequest( + request: RegionalApiEnableManagedAlertsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiTriggerTestAlertRequest( + request: RegionalApiTriggerTestAlertRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RegionalApiUpdateContactPointRequest( + request: RegionalApiUpdateContactPointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("email", request.email), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.send_resolved_notifications is not None: + output["send_resolved_notifications"] = request.send_resolved_notifications + + return output + + +def marshal_RegionalApiUpdateDataSourceRequest( + request: RegionalApiUpdateDataSourceRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.retention_days is not None: + output["retention_days"] = request.retention_days + + return output diff --git a/scaleway/scaleway/cockpit/v1/types.py b/scaleway/scaleway/cockpit/v1/types.py new file mode 100644 index 00000000..17ca2ebe --- /dev/null +++ b/scaleway/scaleway/cockpit/v1/types.py @@ -0,0 +1,1437 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class AlertState(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATE = "unknown_state" + INACTIVE = "inactive" + PENDING = "pending" + FIRING = "firing" + + def __str__(self) -> str: + return str(self.value) + + +class DataSourceOrigin(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ORIGIN = "unknown_origin" + SCALEWAY = "scaleway" + EXTERNAL = "external" + CUSTOM = "custom" + + def __str__(self) -> str: + return str(self.value) + + +class DataSourceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + METRICS = "metrics" + LOGS = "logs" + TRACES = "traces" + + def __str__(self) -> str: + return str(self.value) + + +class GrafanaUserRole(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ROLE = "unknown_role" + EDITOR = "editor" + VIEWER = "viewer" + + def __str__(self) -> str: + return str(self.value) + + +class ListDataSourcesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + TYPE_ASC = "type_asc" + TYPE_DESC = "type_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListGrafanaUsersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + LOGIN_ASC = "login_asc" + LOGIN_DESC = "login_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPlansRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListTokensRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class PlanName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + FREE = "free" + PREMIUM = "premium" + CUSTOM = "custom" + + def __str__(self) -> str: + return str(self.value) + + +class TokenScope(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SCOPE = "unknown_scope" + READ_ONLY_METRICS = "read_only_metrics" + WRITE_ONLY_METRICS = "write_only_metrics" + FULL_ACCESS_METRICS_RULES = "full_access_metrics_rules" + READ_ONLY_LOGS = "read_only_logs" + WRITE_ONLY_LOGS = "write_only_logs" + FULL_ACCESS_LOGS_RULES = "full_access_logs_rules" + FULL_ACCESS_ALERT_MANAGER = "full_access_alert_manager" + READ_ONLY_TRACES = "read_only_traces" + WRITE_ONLY_TRACES = "write_only_traces" + + def __str__(self) -> str: + return str(self.value) + + +class UsageUnit(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_UNIT = "unknown_unit" + BYTES = "bytes" + SAMPLES = "samples" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class PreconfiguredAlertData: + """ + Structure for additional data relative to preconfigured alerts. + """ + + preconfigured_rule_id: str + """ + ID of the preconfigured rule if the alert is preconfigured. + """ + + display_name: str + """ + Human readable name of the alert. + """ + + display_description: str + """ + Human readable description of the alert. + """ + + +@dataclass +class ContactPointEmail: + to: str + + +@dataclass +class GetConfigResponseRetention: + min_days: int + + max_days: int + + default_days: int + + +@dataclass +class Alert: + """ + Structure representing an alert. + """ + + region: ScwRegion + """ + The region in which the alert is defined. + """ + + preconfigured: bool + """ + Indicates if the alert is preconfigured or custom. + """ + + name: str + """ + Name of the alert. + """ + + rule: str + """ + Rule defining the alert condition. + """ + + duration: str + """ + Duration for which the alert must be active before firing. The format of this duration follows the prometheus duration format. + """ + + enabled: bool + """ + Indicates if the alert is enabled or disabled. Only preconfigured alerts can be disabled. + """ + + annotations: Dict[str, str] + """ + Annotations for the alert, used to provide additional information about the alert. + """ + + data_source_id: str + """ + ID of the data source containing the alert rule. + """ + + state: Optional[AlertState] + """ + Current state of the alert. Possible states are `inactive`, `pending`, and `firing`. + """ + + preconfigured_data: Optional[PreconfiguredAlertData] + """ + Contains additional data for preconfigured alerts, such as the rule ID, display name, and description. Only present if the alert is preconfigured. + """ + + +@dataclass +class ContactPoint: + """ + Contact point. + """ + + region: ScwRegion + """ + Region. + """ + + send_resolved_notifications: bool + """ + Send an email notification when an alert is marked as resolved. + """ + + email: Optional[ContactPointEmail] + + +@dataclass +class DataSource: + """ + Data source. + """ + + id: str + """ + ID of the data source. + """ + + project_id: str + """ + ID of the Project the data source belongs to. + """ + + name: str + """ + Data source name. + """ + + url: str + """ + Data source URL. + """ + + type_: DataSourceType + """ + Data source type. + """ + + origin: DataSourceOrigin + """ + Data source origin. + """ + + synchronized_with_grafana: bool + """ + Indicates whether the data source is synchronized with Grafana. + """ + + retention_days: int + """ + BETA - Duration for which the data will be retained in the data source. + """ + + region: ScwRegion + """ + Region of the data source. + """ + + created_at: Optional[datetime] + """ + Date the data source was created. + """ + + updated_at: Optional[datetime] + """ + Date the data source was last updated. + """ + + +@dataclass +class GrafanaProductDashboard: + """ + Grafana dashboard. + """ + + name: str + """ + Dashboard name. + """ + + title: str + """ + Dashboard title. + """ + + url: str + """ + Dashboard URL. + """ + + tags: List[str] + """ + Dashboard tags. + """ + + variables: List[str] + """ + Dashboard variables. + """ + + +@dataclass +class GrafanaUser: + """ + Grafana user. + """ + + id: int + """ + ID of the Grafana user. + """ + + login: str + """ + Username of the Grafana user. + """ + + role: GrafanaUserRole + """ + Role assigned to the Grafana user. + """ + + password: Optional[str] + """ + Grafana user's password. + """ + + +@dataclass +class Plan: + """ + Type of pricing plan. + """ + + name: PlanName + """ + Name of a given pricing plan. + """ + + sample_ingestion_price: int + """ + Ingestion price in cents for 1 million samples. + """ + + logs_ingestion_price: int + """ + Ingestion price in cents for 1 GB of logs. + """ + + traces_ingestion_price: int + """ + Ingestion price in cents for 1 GB of traces. + """ + + monthly_price: int + """ + Retention price in euros per month. + """ + + retention_metrics_interval: Optional[str] + """ + Interval of time during which Scaleway's Cockpit keeps your metrics. + """ + + retention_logs_interval: Optional[str] + """ + Interval of time during which Scaleway's Cockpit keeps your logs. + """ + + retention_traces_interval: Optional[str] + """ + Interval of time during which Scaleway's Cockpit keeps your traces. + """ + + +@dataclass +class Token: + """ + Token. + """ + + id: str + """ + ID of the token. + """ + + project_id: str + """ + ID of the Project the token belongs to. + """ + + name: str + """ + Name of the token. + """ + + scopes: List[TokenScope] + """ + Token permission scopes. + """ + + region: ScwRegion + """ + Regions where the token is located. + """ + + created_at: Optional[datetime] + """ + Token creation date. + """ + + updated_at: Optional[datetime] + """ + Token last modification date. + """ + + secret_key: Optional[str] + """ + Token secret key. + """ + + +@dataclass +class Usage: + """ + Data source usage. + """ + + project_id: str + """ + ID of the Project the data source belongs to. + """ + + data_source_origin: DataSourceOrigin + """ + Origin of the data source. + """ + + data_source_type: DataSourceType + """ + Type of the data source. + """ + + unit: UsageUnit + """ + Unit of the data source usage. + """ + + quantity_over_interval: int + """ + Data source usage for the given interval. + """ + + region: ScwRegion + """ + Region of the data source usage. + """ + + data_source_id: Optional[str] + """ + ID of the data source. + """ + + interval: Optional[str] + """ + Interval for the data source usage. + """ + + +@dataclass +class AlertManager: + """ + Alert manager information. + """ + + alert_manager_enabled: bool + """ + The Alert manager is enabled. + """ + + managed_alerts_enabled: bool + """ + Managed alerts are enabled. + """ + + region: ScwRegion + """ + Regions where the Alert manager is enabled. + """ + + alert_manager_url: Optional[str] + """ + Alert manager URL. + """ + + +@dataclass +class DisableAlertRulesResponse: + disabled_rule_ids: List[str] + + +@dataclass +class EnableAlertRulesResponse: + enabled_rule_ids: List[str] + + +@dataclass +class GetConfigResponse: + """ + Cockpit configuration. + """ + + custom_metrics_retention: Optional[GetConfigResponseRetention] + """ + Custom metrics retention configuration. + """ + + custom_logs_retention: Optional[GetConfigResponseRetention] + """ + Custom logs retention configuration. + """ + + custom_traces_retention: Optional[GetConfigResponseRetention] + """ + Custom traces retention configuration. + """ + + product_metrics_retention: Optional[GetConfigResponseRetention] + """ + Scaleway metrics retention configuration. + """ + + product_logs_retention: Optional[GetConfigResponseRetention] + """ + Scaleway logs retention configuration. + """ + + +@dataclass +class GlobalApiCreateGrafanaUserRequest: + """ + Create a Grafana user. + """ + + login: str + """ + Username of the Grafana user. Note that the `admin` username is not available for creation. + """ + + project_id: Optional[str] + """ + ID of the Project in which to create the Grafana user. + """ + + role: Optional[GrafanaUserRole] + """ + Role assigned to the Grafana user. + """ + + +@dataclass +class GlobalApiDeleteGrafanaUserRequest: + """ + Delete a Grafana user. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + grafana_user_id: int + """ + ID of the Grafana user. + """ + + +@dataclass +class GlobalApiGetCurrentPlanRequest: + """ + Retrieve a pricing plan for the given Project. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class GlobalApiGetGrafanaProductDashboardRequest: + """ + Retrieve a specific dashboard. + """ + + project_id: Optional[str] + """ + ID of the Project the dashboard belongs to. + """ + + dashboard_name: str + """ + Name of the dashboard. + """ + + +@dataclass +class GlobalApiGetGrafanaRequest: + """ + Request a Grafana. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class GlobalApiListGrafanaProductDashboardsRequest: + """ + Retrieve a list of available product dashboards. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size. + """ + + tags: Optional[List[str]] + """ + Tags to filter for. + """ + + +@dataclass +class GlobalApiListGrafanaUsersRequest: + """ + List all Grafana users. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size. + """ + + order_by: Optional[ListGrafanaUsersRequestOrderBy] + """ + Order of the Grafana users. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + +@dataclass +class GlobalApiListPlansRequest: + """ + Retrieve a list of available pricing plans. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Page size. + """ + + order_by: Optional[ListPlansRequestOrderBy] + + +@dataclass +class GlobalApiResetGrafanaUserPasswordRequest: + """ + Reset a Grafana user's password. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + grafana_user_id: int + """ + ID of the Grafana user. + """ + + +@dataclass +class GlobalApiSelectPlanRequest: + """ + Select a specific pricing plan. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + plan_name: Optional[PlanName] + """ + Name of the pricing plan. + """ + + +@dataclass +class GlobalApiSyncGrafanaDataSourcesRequest: + """ + Trigger the synchronization of all data sources created in the relevant regions. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + +@dataclass +class Grafana: + """ + Grafana user. + """ + + grafana_url: str + """ + URL to access your Cockpit's Grafana. + """ + + +@dataclass +class ListAlertsResponse: + """ + Retrieve a list of alerts matching the request. + """ + + total_count: int + """ + Total count of alerts matching the request. + """ + + alerts: List[Alert] + """ + List of alerts matching the applied filters. + """ + + +@dataclass +class ListContactPointsResponse: + """ + Response returned when listing contact points. + """ + + total_count: int + """ + Total count of contact points associated with the default receiver. + """ + + contact_points: List[ContactPoint] + """ + List of contact points associated with the default receiver. + """ + + has_additional_receivers: bool + """ + Indicates whether the Alert manager has other receivers than the default one. + """ + + has_additional_contact_points: bool + """ + Indicates whether there are unmanaged contact points on the default receiver. + """ + + +@dataclass +class ListDataSourcesResponse: + """ + Response returned when listing data sources. + """ + + total_count: int + """ + Total count of data sources matching the request. + """ + + data_sources: List[DataSource] + """ + Data sources matching the request within the pagination. + """ + + +@dataclass +class ListGrafanaProductDashboardsResponse: + """ + Output returned when listing dashboards. + """ + + total_count: int + """ + Total count of Grafana dashboards. + """ + + dashboards: List[GrafanaProductDashboard] + """ + Grafana dashboards information. + """ + + +@dataclass +class ListGrafanaUsersResponse: + """ + Ouptut returned when listing Grafana users. + """ + + total_count: int + """ + Total count of Grafana users. + """ + + grafana_users: List[GrafanaUser] + """ + Grafana users information. + """ + + +@dataclass +class ListPlansResponse: + """ + Output returned when listing pricing plans. + """ + + total_count: int + """ + Total count of available pricing plans. + """ + + plans: List[Plan] + """ + Plan types information. + """ + + +@dataclass +class ListTokensResponse: + """ + Response returned when listing tokens. + """ + + total_count: int + """ + Total count of tokens matching the request. + """ + + tokens: List[Token] + """ + Tokens matching the request within the pagination. + """ + + +@dataclass +class RegionalApiCreateContactPointRequest: + """ + Create a contact point. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to create the contact point in. + """ + + send_resolved_notifications: Optional[bool] + """ + Send an email notification when an alert is marked as resolved. + """ + + email: Optional[ContactPointEmail] + + +@dataclass +class RegionalApiCreateDataSourceRequest: + """ + Create a data source. + """ + + name: str + """ + Data source name. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project the data source belongs to. + """ + + type_: Optional[DataSourceType] + """ + Data source type. + """ + + retention_days: Optional[int] + """ + Default values are 30 days for metrics, 7 days for logs and traces. + """ + + +@dataclass +class RegionalApiCreateTokenRequest: + """ + Create a token. + """ + + name: str + """ + Name of the token. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project the token belongs to. + """ + + token_scopes: Optional[List[TokenScope]] + """ + Token permission scopes. + """ + + +@dataclass +class RegionalApiDeleteContactPointRequest: + """ + Delete a contact point. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project containing the contact point to delete. + """ + + email: Optional[ContactPointEmail] + + +@dataclass +class RegionalApiDeleteDataSourceRequest: + """ + Delete a data source. + """ + + data_source_id: str + """ + ID of the data source to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RegionalApiDeleteTokenRequest: + """ + Delete a token. + """ + + token_id: str + """ + ID of the token to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RegionalApiDisableAlertManagerRequest: + """ + Disable the Alert manager. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to disable the Alert manager in. + """ + + +@dataclass +class RegionalApiDisableAlertRulesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + + rule_ids: Optional[List[str]] + + +@dataclass +class RegionalApiDisableManagedAlertsRequest: + """ + Disable the sending of managed alerts. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class RegionalApiEnableAlertManagerRequest: + """ + Enable the Alert manager. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to enable the Alert manager in. + """ + + +@dataclass +class RegionalApiEnableAlertRulesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + + rule_ids: Optional[List[str]] + + +@dataclass +class RegionalApiEnableManagedAlertsRequest: + """ + Enable the sending of managed alerts. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class RegionalApiGetAlertManagerRequest: + """ + Get the Alert manager. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + Project ID of the requested Alert manager. + """ + + +@dataclass +class RegionalApiGetConfigRequest: + """ + Get Cockpit configuration. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RegionalApiGetDataSourceRequest: + """ + Retrieve a data source. + """ + + data_source_id: str + """ + ID of the relevant data source. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RegionalApiGetTokenRequest: + """ + Get a token. + """ + + token_id: str + """ + Token ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RegionalApiGetUsageOverviewRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + + interval: Optional[str] + + +@dataclass +class RegionalApiListAlertsRequest: + """ + Retrieve a list of alerts. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only alerts from this Project will be returned. + """ + + is_enabled: Optional[bool] + """ + True returns only enabled alerts. False returns only disabled alerts. If omitted, no alert filtering is applied. Other filters may still apply. + """ + + is_preconfigured: Optional[bool] + """ + True returns only preconfigured alerts. False returns only custom alerts. If omitted, no filtering is applied on alert types. Other filters may still apply. + """ + + state: Optional[AlertState] + """ + Valid values to filter on are `inactive`, `pending` and `firing`. If omitted, no filtering is applied on alert states. Other filters may still apply. + """ + + data_source_id: Optional[str] + """ + If omitted, only alerts from the default scaleway data source will be listed. + """ + + +@dataclass +class RegionalApiListContactPointsRequest: + """ + List contact points. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Total count of contact points to return per page. + """ + + project_id: Optional[str] + """ + ID of the Project containing the contact points to list. + """ + + +@dataclass +class RegionalApiListDataSourcesRequest: + """ + List data sources. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of data sources to return per page. + """ + + order_by: Optional[ListDataSourcesRequestOrderBy] + """ + Sort order for data sources in the response. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only data sources from this Project will be returned. + """ + + origin: Optional[DataSourceOrigin] + """ + Origin to filter for, only data sources with matching origin will be returned. + """ + + types: Optional[List[DataSourceType]] + """ + Types to filter for, only data sources with matching types will be returned. + """ + + +@dataclass +class RegionalApiListTokensRequest: + """ + List tokens. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of tokens to return per page. + """ + + order_by: Optional[ListTokensRequestOrderBy] + """ + Order in which to return results. + """ + + project_id: Optional[str] + """ + ID of the Project the tokens belong to. + """ + + token_scopes: Optional[List[TokenScope]] + """ + Token scopes to filter for. + """ + + +@dataclass +class RegionalApiTriggerTestAlertRequest: + """ + Request to trigger a test alert. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class RegionalApiUpdateContactPointRequest: + """ + Update a contact point. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project containing the contact point to update. + """ + + send_resolved_notifications: Optional[bool] + """ + Enable or disable notifications when alert is resolved. + """ + + email: Optional[ContactPointEmail] + + +@dataclass +class RegionalApiUpdateDataSourceRequest: + """ + Update a data source name. + """ + + data_source_id: str + """ + ID of the data source to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Updated name of the data source. + """ + + retention_days: Optional[int] + """ + BETA - Duration for which the data will be retained in the data source. + """ + + +@dataclass +class UsageOverview: + scaleway_metrics_usage: Optional[Usage] + + scaleway_logs_usage: Optional[Usage] + + external_metrics_usage: Optional[Usage] + + external_logs_usage: Optional[Usage] + + external_traces_usage: Optional[Usage] diff --git a/scaleway/scaleway/cockpit/v1beta1/api.py b/scaleway/scaleway/cockpit/v1beta1/api.py index aa1002cd..49d4e86a 100644 --- a/scaleway/scaleway/cockpit/v1beta1/api.py +++ b/scaleway/scaleway/cockpit/v1beta1/api.py @@ -85,7 +85,7 @@ class CockpitV1Beta1API(API): """ - The Cockpit API allows you to activate your Cockpit to store metrics and logs. It also provides you with a dedicated Grafana for dashboarding to visualize your metrics and logs. + This API allows you to manage your Scaleway Cockpit, for storing and visualizing metrics and logs. """ def activate_cockpit( diff --git a/scaleway/scaleway/cockpit/v1beta1/marshalling.py b/scaleway/scaleway/cockpit/v1beta1/marshalling.py index edf291af..916db34e 100644 --- a/scaleway/scaleway/cockpit/v1beta1/marshalling.py +++ b/scaleway/scaleway/cockpit/v1beta1/marshalling.py @@ -73,6 +73,8 @@ def unmarshal_ContactPoint(data: Any) -> ContactPoint: field = data.get("email", None) if field is not None: args["email"] = unmarshal_ContactPointEmail(field) + else: + args["email"] = None return ContactPoint(**args) @@ -101,7 +103,7 @@ def unmarshal_Datasource(data: Any) -> Datasource: if field is not None: args["url"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -166,6 +168,8 @@ def unmarshal_GrafanaUser(data: Any) -> GrafanaUser: field = data.get("password", None) if field is not None: args["password"] = field + else: + args["password"] = None return GrafanaUser(**args) @@ -240,18 +244,26 @@ def unmarshal_Token(data: Any) -> Token: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("scopes", None) if field is not None: args["scopes"] = unmarshal_TokenScopes(field) + else: + args["scopes"] = None field = data.get("secret_key", None) if field is not None: args["secret_key"] = field + else: + args["secret_key"] = None return Token(**args) @@ -322,14 +334,20 @@ def unmarshal_Plan(data: Any) -> Plan: field = data.get("retention_metrics_interval", None) if field is not None: args["retention_metrics_interval"] = field + else: + args["retention_metrics_interval"] = None field = data.get("retention_logs_interval", None) if field is not None: args["retention_logs_interval"] = field + else: + args["retention_logs_interval"] = None field = data.get("retention_traces_interval", None) if field is not None: args["retention_traces_interval"] = field + else: + args["retention_traces_interval"] = None return Plan(**args) @@ -357,18 +375,26 @@ def unmarshal_Cockpit(data: Any) -> Cockpit: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("endpoints", None) if field is not None: args["endpoints"] = unmarshal_CockpitEndpoints(field) + else: + args["endpoints"] = None field = data.get("plan", None) if field is not None: args["plan"] = unmarshal_Plan(field) + else: + args["plan"] = None return Cockpit(**args) @@ -589,9 +615,7 @@ def marshal_CreateContactPointRequest( output["project_id"] = request.project_id or defaults.default_project_id if request.contact_point is not None: - output["contact_point"] = ( - marshal_ContactPoint(request.contact_point, defaults), - ) + output["contact_point"] = marshal_ContactPoint(request.contact_point, defaults) return output @@ -684,7 +708,7 @@ def marshal_CreateTokenRequest( output["name"] = request.name if request.scopes is not None: - output["scopes"] = (marshal_TokenScopes(request.scopes, defaults),) + output["scopes"] = marshal_TokenScopes(request.scopes, defaults) return output @@ -711,9 +735,7 @@ def marshal_DeleteContactPointRequest( output["project_id"] = request.project_id or defaults.default_project_id if request.contact_point is not None: - output["contact_point"] = ( - marshal_ContactPoint(request.contact_point, defaults), - ) + output["contact_point"] = marshal_ContactPoint(request.contact_point, defaults) return output diff --git a/scaleway/scaleway/container/v1beta1/__init__.py b/scaleway/scaleway/container/v1beta1/__init__.py index e4706cb5..a1de41c3 100644 --- a/scaleway/scaleway/container/v1beta1/__init__.py +++ b/scaleway/scaleway/container/v1beta1/__init__.py @@ -3,6 +3,7 @@ from .types import ContainerHttpOption from .types import ContainerPrivacy from .types import ContainerProtocol +from .types import ContainerSandbox from .types import ContainerStatus from .content import CONTAINER_TRANSIENT_STATUSES from .types import CronStatus @@ -22,6 +23,10 @@ from .types import TriggerInputType from .types import TriggerStatus from .content import TRIGGER_TRANSIENT_STATUSES +from .types import ContainerHealthCheckSpecHTTPProbe +from .types import ContainerHealthCheckSpecTCPProbe +from .types import ContainerHealthCheckSpec +from .types import ContainerScalingOption from .types import SecretHashedValue from .types import TriggerMnqNatsClientConfig from .types import TriggerMnqSqsClientConfig @@ -56,7 +61,6 @@ from .types import GetNamespaceRequest from .types import GetTokenRequest from .types import GetTriggerRequest -from .types import IssueJWTRequest from .types import ListContainersRequest from .types import ListContainersResponse from .types import ListCronsRequest @@ -79,6 +83,7 @@ "ContainerHttpOption", "ContainerPrivacy", "ContainerProtocol", + "ContainerSandbox", "ContainerStatus", "CONTAINER_TRANSIENT_STATUSES", "CronStatus", @@ -98,6 +103,10 @@ "TriggerInputType", "TriggerStatus", "TRIGGER_TRANSIENT_STATUSES", + "ContainerHealthCheckSpecHTTPProbe", + "ContainerHealthCheckSpecTCPProbe", + "ContainerHealthCheckSpec", + "ContainerScalingOption", "SecretHashedValue", "TriggerMnqNatsClientConfig", "TriggerMnqSqsClientConfig", @@ -132,7 +141,6 @@ "GetNamespaceRequest", "GetTokenRequest", "GetTriggerRequest", - "IssueJWTRequest", "ListContainersRequest", "ListContainersResponse", "ListCronsRequest", diff --git a/scaleway/scaleway/container/v1beta1/api.py b/scaleway/scaleway/container/v1beta1/api.py index 5b28226e..c157950c 100644 --- a/scaleway/scaleway/container/v1beta1/api.py +++ b/scaleway/scaleway/container/v1beta1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( OneOfPossibility, @@ -21,6 +21,7 @@ ContainerHttpOption, ContainerPrivacy, ContainerProtocol, + ContainerSandbox, ListContainersRequestOrderBy, ListCronsRequestOrderBy, ListDomainsRequestOrderBy, @@ -28,6 +29,8 @@ ListTokensRequestOrderBy, ListTriggersRequestOrderBy, Container, + ContainerHealthCheckSpec, + ContainerScalingOption, CreateContainerRequest, CreateCronRequest, CreateDomainRequest, @@ -91,13 +94,13 @@ class ContainerV1Beta1API(API): """ - Serverless Containers API. + This API allows you to manage your Serverless Containers. """ def list_namespaces( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -147,7 +150,7 @@ def list_namespaces( def list_namespaces_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -192,7 +195,7 @@ def get_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Get a namespace. @@ -226,7 +229,7 @@ def wait_for_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Namespace, bool]] = None, ) -> Namespace: """ @@ -262,12 +265,13 @@ def wait_for_namespace( def create_namespace( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, environment_variables: Optional[Dict[str, str]] = None, project_id: Optional[str] = None, description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, + tags: Optional[List[str]] = None, ) -> Namespace: """ Create a new namespace. @@ -278,6 +282,7 @@ def create_namespace( :param project_id: UUID of the Project in which the namespace will be created. :param description: Description of the namespace to create. :param secret_environment_variables: Secret environment variables of the namespace to create. + :param tags: Tags of the Serverless Container Namespace. :return: :class:`Namespace ` Usage: @@ -301,6 +306,7 @@ def create_namespace( project_id=project_id, description=description, secret_environment_variables=secret_environment_variables, + tags=tags, ), self.client, ), @@ -313,10 +319,11 @@ def update_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, environment_variables: Optional[Dict[str, str]] = None, description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, + tags: Optional[List[str]] = None, ) -> Namespace: """ Update an existing namespace. @@ -326,6 +333,7 @@ def update_namespace( :param environment_variables: Environment variables of the namespace to update. :param description: Description of the namespace to update. :param secret_environment_variables: Secret environment variables of the namespace to update. + :param tags: Tags of the Serverless Container Namespace. :return: :class:`Namespace ` Usage: @@ -351,6 +359,7 @@ def update_namespace( environment_variables=environment_variables, description=description, secret_environment_variables=secret_environment_variables, + tags=tags, ), self.client, ), @@ -363,7 +372,7 @@ def delete_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Delete an existing namespace. @@ -397,7 +406,7 @@ def list_containers( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListContainersRequestOrderBy] = None, @@ -452,7 +461,7 @@ def list_containers_all( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListContainersRequestOrderBy] = None, @@ -501,7 +510,7 @@ def get_container( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Container: """ Get a container. @@ -535,7 +544,7 @@ def wait_for_container( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Container, bool]] = None, ) -> Container: """ @@ -573,7 +582,7 @@ def create_container( *, namespace_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, environment_variables: Optional[Dict[str, str]] = None, min_scale: Optional[int] = None, max_scale: Optional[int] = None, @@ -588,6 +597,11 @@ def create_container( port: Optional[int] = None, secret_environment_variables: Optional[List[Secret]] = None, http_option: Optional[ContainerHttpOption] = None, + sandbox: Optional[ContainerSandbox] = None, + local_storage_limit: Optional[int] = None, + scaling_option: Optional[ContainerScalingOption] = None, + health_check: Optional[ContainerHealthCheckSpec] = None, + tags: Optional[List[str]] = None, ) -> Container: """ Create a new container. @@ -611,6 +625,14 @@ def create_container( :param http_option: Possible values: - redirected: Responds to HTTP request with a 301 redirect to ask the clients to use HTTPS. - enabled: Serve both HTTP and HTTPS traffic. + :param sandbox: Execution environment of the container. + :param local_storage_limit: Local storage limit of the container (in MB). + :param scaling_option: Possible values: + - concurrent_requests_threshold: Scale depending on the number of concurrent requests being processed per container instance. + - cpu_usage_threshold: Scale depending on the CPU usage of a container instance. + - memory_usage_threshold: Scale depending on the memory usage of a container instance. + :param health_check: Health check configuration of the container. + :param tags: Tags of the Serverless Container. :return: :class:`Container ` Usage: @@ -648,6 +670,11 @@ def create_container( port=port, secret_environment_variables=secret_environment_variables, http_option=http_option, + sandbox=sandbox, + local_storage_limit=local_storage_limit, + scaling_option=scaling_option, + health_check=health_check, + tags=tags, ), self.client, ), @@ -660,7 +687,7 @@ def update_container( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, environment_variables: Optional[Dict[str, str]] = None, min_scale: Optional[int] = None, max_scale: Optional[int] = None, @@ -676,6 +703,11 @@ def update_container( port: Optional[int] = None, secret_environment_variables: Optional[List[Secret]] = None, http_option: Optional[ContainerHttpOption] = None, + sandbox: Optional[ContainerSandbox] = None, + local_storage_limit: Optional[int] = None, + scaling_option: Optional[ContainerScalingOption] = None, + health_check: Optional[ContainerHealthCheckSpec] = None, + tags: Optional[List[str]] = None, ) -> Container: """ Update an existing container. @@ -699,6 +731,14 @@ def update_container( :param http_option: Possible values: - redirected: Responds to HTTP request with a 301 redirect to ask the clients to use HTTPS. - enabled: Serve both HTTP and HTTPS traffic. + :param sandbox: Execution environment of the container. + :param local_storage_limit: Local storage limit of the container (in MB). + :param scaling_option: Possible values: + - concurrent_requests_threshold: Scale depending on the number of concurrent requests being processed per container instance. + - cpu_usage_threshold: Scale depending on the CPU usage of a container instance. + - memory_usage_threshold: Scale depending on the memory usage of a container instance. + :param health_check: Health check configuration of the container. + :param tags: Tags of the Serverless Container. :return: :class:`Container ` Usage: @@ -736,6 +776,11 @@ def update_container( port=port, secret_environment_variables=secret_environment_variables, http_option=http_option, + sandbox=sandbox, + local_storage_limit=local_storage_limit, + scaling_option=scaling_option, + health_check=health_check, + tags=tags, ), self.client, ), @@ -748,7 +793,7 @@ def delete_container( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Container: """ Delete a container. @@ -782,7 +827,7 @@ def deploy_container( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Container: """ Deploy a container. @@ -817,7 +862,7 @@ def list_crons( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListCronsRequestOrderBy] = None, @@ -861,7 +906,7 @@ def list_crons_all( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListCronsRequestOrderBy] = None, @@ -900,7 +945,7 @@ def get_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cron: """ Get a cron. @@ -934,7 +979,7 @@ def wait_for_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Cron, bool]] = None, ) -> Cron: """ @@ -972,7 +1017,7 @@ def create_cron( *, container_id: str, schedule: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, args: Optional[Dict[str, Any]] = None, name: Optional[str] = None, ) -> Cron: @@ -1020,7 +1065,7 @@ def update_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, container_id: Optional[str] = None, schedule: Optional[str] = None, args: Optional[Dict[str, Any]] = None, @@ -1073,7 +1118,7 @@ def delete_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cron: """ Delete an existing cron. @@ -1107,14 +1152,14 @@ def list_domains( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDomainsRequestOrderBy] = None, ) -> ListDomainsResponse: """ - List all domain name bindings. - List all domain name bindings in a specified region. + List all custom domains. + List all custom domains in a specified region. :param container_id: UUID of the container the domain belongs to. :param region: Region to target. If none is passed will use default region from the config. :param page: Page number. @@ -1152,14 +1197,14 @@ def list_domains_all( self, *, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDomainsRequestOrderBy] = None, ) -> List[Domain]: """ - List all domain name bindings. - List all domain name bindings in a specified region. + List all custom domains. + List all custom domains in a specified region. :param container_id: UUID of the container the domain belongs to. :param region: Region to target. If none is passed will use default region from the config. :param page: Page number. @@ -1192,11 +1237,11 @@ def get_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ - Get a domain name binding. - Get a domain name binding for the container with the specified ID. + Get a custom domain. + Get a custom domain for the container with the specified ID. :param domain_id: UUID of the domain to get. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Domain ` @@ -1226,12 +1271,12 @@ def wait_for_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Domain, bool]] = None, ) -> Domain: """ - Get a domain name binding. - Get a domain name binding for the container with the specified ID. + Get a custom domain. + Get a custom domain for the container with the specified ID. :param domain_id: UUID of the domain to get. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Domain ` @@ -1264,11 +1309,11 @@ def create_domain( *, hostname: str, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ - Create a domain name binding. - Create a domain name binding for the container with the specified ID. + Create a custom domain. + Create a custom domain for the container with the specified ID. :param hostname: Domain to assign. :param container_id: UUID of the container to assign the domain to. :param region: Region to target. If none is passed will use default region from the config. @@ -1307,11 +1352,11 @@ def delete_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ - Delete a domain name binding. - Delete the domain name binding with the specific ID. + Delete a custom domain. + Delete the custom domain with the specific ID. :param domain_id: UUID of the domain to delete. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Domain ` @@ -1337,57 +1382,10 @@ def delete_domain( self._throw_on_error(res) return unmarshal_Domain(res.json()) - def issue_jwt( - self, - *, - region: Optional[Region] = None, - container_id: Optional[str] = None, - namespace_id: Optional[str] = None, - expires_at: Optional[datetime] = None, - ) -> Token: - """ - Create a JWT token. - Deprecated in favor of CreateToken. - :param region: Region to target. If none is passed will use default region from the config. - :param container_id: - One-Of ('scope'): at most one of 'container_id', 'namespace_id' could be set. - :param namespace_id: - One-Of ('scope'): at most one of 'container_id', 'namespace_id' could be set. - :param expires_at: - :return: :class:`Token ` - :deprecated - - Usage: - :: - - result = api.issue_jwt() - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - - res = self._request( - "GET", - f"/containers/v1beta1/regions/{param_region}/issue-jwt", - params={ - "expires_at": expires_at, - **resolve_one_of( - [ - OneOfPossibility("container_id", container_id), - OneOfPossibility("namespace_id", namespace_id), - ] - ), - }, - ) - - self._throw_on_error(res) - return unmarshal_Token(res.json()) - def create_token( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, container_id: Optional[str] = None, namespace_id: Optional[str] = None, description: Optional[str] = None, @@ -1436,7 +1434,7 @@ def get_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Token: """ Get a token. @@ -1470,7 +1468,7 @@ def wait_for_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Token, bool]] = None, ) -> Token: """ @@ -1506,7 +1504,7 @@ def wait_for_token( def list_tokens( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTokensRequestOrderBy] = None, @@ -1552,7 +1550,7 @@ def list_tokens( def list_tokens_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTokensRequestOrderBy] = None, @@ -1594,7 +1592,7 @@ def delete_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Token: """ Delete a token. @@ -1629,7 +1627,7 @@ def create_trigger( *, name: str, container_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, scw_sqs_config: Optional[CreateTriggerRequestMnqSqsClientConfig] = None, scw_nats_config: Optional[CreateTriggerRequestMnqNatsClientConfig] = None, @@ -1687,7 +1685,7 @@ def get_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Trigger: """ Get a trigger. @@ -1721,7 +1719,7 @@ def wait_for_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Trigger, bool]] = None, ) -> Trigger: """ @@ -1757,7 +1755,7 @@ def wait_for_trigger( def list_triggers( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTriggersRequestOrderBy] = None, @@ -1813,7 +1811,7 @@ def list_triggers( def list_triggers_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTriggersRequestOrderBy] = None, @@ -1861,7 +1859,7 @@ def update_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, description: Optional[str] = None, sqs_config: Optional[UpdateTriggerRequestSqsClientConfig] = None, @@ -1912,7 +1910,7 @@ def delete_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Trigger: """ Delete a trigger. diff --git a/scaleway/scaleway/container/v1beta1/marshalling.py b/scaleway/scaleway/container/v1beta1/marshalling.py index 224844ea..95e0e527 100644 --- a/scaleway/scaleway/container/v1beta1/marshalling.py +++ b/scaleway/scaleway/container/v1beta1/marshalling.py @@ -10,6 +10,10 @@ resolve_one_of, ) from .types import ( + ContainerHealthCheckSpecHTTPProbe, + ContainerHealthCheckSpecTCPProbe, + ContainerHealthCheckSpec, + ContainerScalingOption, SecretHashedValue, Container, Cron, @@ -44,6 +48,98 @@ ) +def unmarshal_ContainerHealthCheckSpecHTTPProbe( + data: Any, +) -> ContainerHealthCheckSpecHTTPProbe: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContainerHealthCheckSpecHTTPProbe' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("path", None) + if field is not None: + args["path"] = field + + return ContainerHealthCheckSpecHTTPProbe(**args) + + +def unmarshal_ContainerHealthCheckSpecTCPProbe( + data: Any, +) -> ContainerHealthCheckSpecTCPProbe: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContainerHealthCheckSpecTCPProbe' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return ContainerHealthCheckSpecTCPProbe(**args) + + +def unmarshal_ContainerHealthCheckSpec(data: Any) -> ContainerHealthCheckSpec: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContainerHealthCheckSpec' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("failure_threshold", None) + if field is not None: + args["failure_threshold"] = field + + field = data.get("http", None) + if field is not None: + args["http"] = unmarshal_ContainerHealthCheckSpecHTTPProbe(field) + else: + args["http"] = None + + field = data.get("tcp", None) + if field is not None: + args["tcp"] = unmarshal_ContainerHealthCheckSpecTCPProbe(field) + else: + args["tcp"] = None + + field = data.get("interval", None) + if field is not None: + args["interval"] = field + else: + args["interval"] = None + + return ContainerHealthCheckSpec(**args) + + +def unmarshal_ContainerScalingOption(data: Any) -> ContainerScalingOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ContainerScalingOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("concurrent_requests_threshold", None) + if field is not None: + args["concurrent_requests_threshold"] = field + else: + args["concurrent_requests_threshold"] = None + + field = data.get("cpu_usage_threshold", None) + if field is not None: + args["cpu_usage_threshold"] = field + else: + args["cpu_usage_threshold"] = None + + field = data.get("memory_usage_threshold", None) + if field is not None: + args["memory_usage_threshold"] = field + else: + args["memory_usage_threshold"] = None + + return ContainerScalingOption(**args) + + def unmarshal_SecretHashedValue(data: Any) -> SecretHashedValue: if not isinstance(data, dict): raise TypeError( @@ -115,21 +211,27 @@ def unmarshal_Container(data: Any) -> Container: if field is not None: args["registry_image"] = field - field = data.get("max_concurrency", None) - if field is not None: - args["max_concurrency"] = field - field = data.get("timeout", None) if field is not None: args["timeout"] = field + else: + args["timeout"] = None field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None + + field = data.get("max_concurrency", None) + if field is not None: + args["max_concurrency"] = field field = data.get("domain_name", None) if field is not None: @@ -155,10 +257,52 @@ def unmarshal_Container(data: Any) -> Container: if field is not None: args["http_option"] = field + field = data.get("sandbox", None) + if field is not None: + args["sandbox"] = field + + field = data.get("local_storage_limit", None) + if field is not None: + args["local_storage_limit"] = field + field = data.get("region", None) if field is not None: args["region"] = field + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("scaling_option", None) + if field is not None: + args["scaling_option"] = unmarshal_ContainerScalingOption(field) + else: + args["scaling_option"] = None + + field = data.get("health_check", None) + if field is not None: + args["health_check"] = unmarshal_ContainerHealthCheckSpec(field) + else: + args["health_check"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("ready_at", None) + if field is not None: + args["ready_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["ready_at"] = None + return Container(**args) @@ -193,6 +337,8 @@ def unmarshal_Cron(data: Any) -> Cron: field = data.get("args", None) if field is not None: args["args"] = field + else: + args["args"] = None return Cron(**args) @@ -228,6 +374,8 @@ def unmarshal_Domain(data: Any) -> Domain: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None return Domain(**args) @@ -284,13 +432,33 @@ def unmarshal_Namespace(data: Any) -> Namespace: if field is not None: args["region"] = field + field = data.get("tags", None) + if field is not None: + args["tags"] = field + field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Namespace(**args) @@ -318,22 +486,32 @@ def unmarshal_Token(data: Any) -> Token: field = data.get("container_id", None) if field is not None: args["container_id"] = field + else: + args["container_id"] = None field = data.get("namespace_id", None) if field is not None: args["namespace_id"] = field + else: + args["namespace_id"] = None field = data.get("public_key", None) if field is not None: args["public_key"] = field + else: + args["public_key"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None return Token(**args) @@ -365,6 +543,8 @@ def unmarshal_TriggerMnqNatsClientConfig(data: Any) -> TriggerMnqNatsClientConfi field = data.get("mnq_credential_id", None) if field is not None: args["mnq_credential_id"] = field + else: + args["mnq_credential_id"] = None return TriggerMnqNatsClientConfig(**args) @@ -392,6 +572,8 @@ def unmarshal_TriggerMnqSqsClientConfig(data: Any) -> TriggerMnqSqsClientConfig: field = data.get("mnq_credential_id", None) if field is not None: args["mnq_credential_id"] = field + else: + args["mnq_credential_id"] = None return TriggerMnqSqsClientConfig(**args) @@ -458,18 +640,26 @@ def unmarshal_Trigger(data: Any) -> Trigger: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("scw_sqs_config", None) if field is not None: args["scw_sqs_config"] = unmarshal_TriggerMnqSqsClientConfig(field) + else: + args["scw_sqs_config"] = None field = data.get("scw_nats_config", None) if field is not None: args["scw_nats_config"] = unmarshal_TriggerMnqNatsClientConfig(field) + else: + args["scw_nats_config"] = None field = data.get("sqs_config", None) if field is not None: args["sqs_config"] = unmarshal_TriggerSqsClientConfig(field) + else: + args["sqs_config"] = None return Trigger(**args) @@ -600,6 +790,73 @@ def unmarshal_ListTriggersResponse(data: Any) -> ListTriggersResponse: return ListTriggersResponse(**args) +def marshal_ContainerHealthCheckSpecHTTPProbe( + request: ContainerHealthCheckSpecHTTPProbe, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.path is not None: + output["path"] = request.path + + return output + + +def marshal_ContainerHealthCheckSpecTCPProbe( + request: ContainerHealthCheckSpecTCPProbe, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_ContainerHealthCheckSpec( + request: ContainerHealthCheckSpec, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("http", request.http), + OneOfPossibility("tcp", request.tcp), + ] + ), + ) + + if request.failure_threshold is not None: + output["failure_threshold"] = request.failure_threshold + + if request.interval is not None: + output["interval"] = request.interval + + return output + + +def marshal_ContainerScalingOption( + request: ContainerScalingOption, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility( + "concurrent_requests_threshold", + request.concurrent_requests_threshold, + ), + OneOfPossibility("cpu_usage_threshold", request.cpu_usage_threshold), + OneOfPossibility( + "memory_usage_threshold", request.memory_usage_threshold + ), + ] + ), + ) + + return output + + def marshal_Secret( request: Secret, defaults: ProfileDefaults, @@ -672,6 +929,25 @@ def marshal_CreateContainerRequest( if request.http_option is not None: output["http_option"] = str(request.http_option) + if request.sandbox is not None: + output["sandbox"] = str(request.sandbox) + + if request.local_storage_limit is not None: + output["local_storage_limit"] = request.local_storage_limit + + if request.scaling_option is not None: + output["scaling_option"] = marshal_ContainerScalingOption( + request.scaling_option, defaults + ) + + if request.health_check is not None: + output["health_check"] = marshal_ContainerHealthCheckSpec( + request.health_check, defaults + ) + + if request.tags is not None: + output["tags"] = request.tags + return output @@ -735,6 +1011,9 @@ def marshal_CreateNamespaceRequest( for item in request.secret_environment_variables ] + if request.tags is not None: + output["tags"] = request.tags + return output @@ -756,7 +1035,7 @@ def marshal_CreateTokenRequest( output["description"] = request.description if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -902,6 +1181,25 @@ def marshal_UpdateContainerRequest( if request.http_option is not None: output["http_option"] = str(request.http_option) + if request.sandbox is not None: + output["sandbox"] = str(request.sandbox) + + if request.local_storage_limit is not None: + output["local_storage_limit"] = request.local_storage_limit + + if request.scaling_option is not None: + output["scaling_option"] = marshal_ContainerScalingOption( + request.scaling_option, defaults + ) + + if request.health_check is not None: + output["health_check"] = marshal_ContainerHealthCheckSpec( + request.health_check, defaults + ) + + if request.tags is not None: + output["tags"] = request.tags + return output @@ -944,6 +1242,9 @@ def marshal_UpdateNamespaceRequest( for item in request.secret_environment_variables ] + if request.tags is not None: + output["tags"] = request.tags + return output diff --git a/scaleway/scaleway/container/v1beta1/types.py b/scaleway/scaleway/container/v1beta1/types.py index 6d3f779a..f4e775dc 100644 --- a/scaleway/scaleway/container/v1beta1/types.py +++ b/scaleway/scaleway/container/v1beta1/types.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -42,6 +42,15 @@ def __str__(self) -> str: return str(self.value) +class ContainerSandbox(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SANDBOX = "unknown_sandbox" + V1 = "v1" + V2 = "v2" + + def __str__(self) -> str: + return str(self.value) + + class ContainerStatus(str, Enum, metaclass=StrEnumMeta): UNKNOWN = "unknown" READY = "ready" @@ -182,6 +191,46 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class ContainerHealthCheckSpecHTTPProbe: + path: str + """ + Path to use for the HTTP health check. + """ + + +@dataclass +class ContainerHealthCheckSpecTCPProbe: + pass + + +@dataclass +class ContainerHealthCheckSpec: + failure_threshold: int + """ + During a deployment, if a newly created container fails to pass the health check, the deployment is aborted. +As a result, lowering this value can help to reduce the time it takes to detect a failed deployment. + """ + + interval: Optional[str] + """ + Period between health checks. + """ + + http: Optional[ContainerHealthCheckSpecHTTPProbe] + + tcp: Optional[ContainerHealthCheckSpecTCPProbe] + + +@dataclass +class ContainerScalingOption: + concurrent_requests_threshold: Optional[int] + + cpu_usage_threshold: Optional[int] + + memory_usage_threshold: Optional[int] + + @dataclass class SecretHashedValue: key: str @@ -367,11 +416,6 @@ class Container: Name of the registry image (e.g. "rg.fr-par.scw.cloud/something/image:tag"). """ - max_concurrency: int - """ - Number of maximum concurrent executions of the container. - """ - timeout: Optional[str] """ Processing time limit for the container. @@ -387,6 +431,11 @@ class Container: Description of the container. """ + max_concurrency: int + """ + Number of maximum concurrent executions of the container. + """ + domain_name: str """ Domain name attributed to the contaioner. @@ -414,11 +463,54 @@ class Container: - enabled: Serve both HTTP and HTTPS traffic. """ - region: Region + sandbox: ContainerSandbox + """ + Execution environment of the container. + """ + + local_storage_limit: int + """ + Local storage limit of the container (in MB). + """ + + region: ScwRegion """ Region in which the container will be deployed. """ + tags: List[str] + """ + List of tags applied to the Serverless Container. + """ + + scaling_option: Optional[ContainerScalingOption] + """ + Possible values: +- concurrent_requests_threshold: Scale depending on the number of concurrent requests being processed per container instance. +- cpu_usage_threshold: Scale depending on the CPU usage of a container instance. +- memory_usage_threshold: Scale depending on the memory usage of a container instance. + """ + + health_check: Optional[ContainerHealthCheckSpec] + """ + Health check configuration of the container. + """ + + created_at: Optional[datetime] + """ + Creation date of the container. + """ + + updated_at: Optional[datetime] + """ + Last update date of the container. + """ + + ready_at: Optional[datetime] + """ + Last date when the container was successfully deployed and set to ready. + """ + @dataclass class Cron: @@ -533,11 +625,16 @@ class Namespace: Secret environment variables of the namespace. """ - region: Region + region: ScwRegion """ Region in which the namespace will be created. """ + tags: List[str] + """ + List of tags applied to the Serverless Container Namespace. + """ + error_message: Optional[str] """ Last error message of the namesace. @@ -548,6 +645,16 @@ class Namespace: Description of the endpoint. """ + created_at: Optional[datetime] + """ + Creation date of the namespace. + """ + + updated_at: Optional[datetime] + """ + Last update date of the namespace. + """ + @dataclass class Token: @@ -649,7 +756,7 @@ class CreateContainerRequest: Name of the container. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -726,6 +833,34 @@ class CreateContainerRequest: - enabled: Serve both HTTP and HTTPS traffic. """ + sandbox: Optional[ContainerSandbox] + """ + Execution environment of the container. + """ + + local_storage_limit: Optional[int] + """ + Local storage limit of the container (in MB). + """ + + scaling_option: Optional[ContainerScalingOption] + """ + Possible values: +- concurrent_requests_threshold: Scale depending on the number of concurrent requests being processed per container instance. +- cpu_usage_threshold: Scale depending on the CPU usage of a container instance. +- memory_usage_threshold: Scale depending on the memory usage of a container instance. + """ + + health_check: Optional[ContainerHealthCheckSpec] + """ + Health check configuration of the container. + """ + + tags: Optional[List[str]] + """ + Tags of the Serverless Container. + """ + @dataclass class CreateCronRequest: @@ -739,7 +874,7 @@ class CreateCronRequest: UNIX cron shedule. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -767,7 +902,7 @@ class CreateDomainRequest: UUID of the container to assign the domain to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -775,7 +910,7 @@ class CreateDomainRequest: @dataclass class CreateNamespaceRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -805,10 +940,15 @@ class CreateNamespaceRequest: Secret environment variables of the namespace to create. """ + tags: Optional[List[str]] + """ + Tags of the Serverless Container Namespace. + """ + @dataclass class CreateTokenRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -840,7 +980,7 @@ class CreateTriggerRequest: ID of the container to trigger. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -864,7 +1004,7 @@ class DeleteContainerRequest: UUID of the container to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -877,7 +1017,7 @@ class DeleteCronRequest: UUID of the cron to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -890,7 +1030,7 @@ class DeleteDomainRequest: UUID of the domain to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -903,7 +1043,7 @@ class DeleteNamespaceRequest: UUID of the namespace to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -916,7 +1056,7 @@ class DeleteTokenRequest: UUID of the token to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -929,7 +1069,7 @@ class DeleteTriggerRequest: ID of the trigger to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -942,7 +1082,7 @@ class DeployContainerRequest: UUID of the container to deploy. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -955,7 +1095,7 @@ class GetContainerRequest: UUID of the container to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -968,7 +1108,7 @@ class GetCronRequest: UUID of the cron to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -981,7 +1121,7 @@ class GetDomainRequest: UUID of the domain to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -994,7 +1134,7 @@ class GetNamespaceRequest: UUID of the namespace to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1007,7 +1147,7 @@ class GetTokenRequest: UUID of the token to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1020,26 +1160,12 @@ class GetTriggerRequest: ID of the trigger to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ -@dataclass -class IssueJWTRequest: - region: Optional[Region] - """ - Region to target. If none is passed will use default region from the config. - """ - - expires_at: Optional[datetime] - - container_id: Optional[str] - - namespace_id: Optional[str] - - @dataclass class ListContainersRequest: namespace_id: str @@ -1047,7 +1173,7 @@ class ListContainersRequest: UUID of the namespace the container belongs to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1103,7 +1229,7 @@ class ListCronsRequest: UUID of the container invoked by the cron. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1144,7 +1270,7 @@ class ListDomainsRequest: UUID of the container the domain belongs to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1180,7 +1306,7 @@ class ListDomainsResponse: @dataclass class ListNamespacesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1231,7 +1357,7 @@ class ListNamespacesResponse: @dataclass class ListTokensRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1271,7 +1397,7 @@ class ListTokensResponse: @dataclass class ListTriggersRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1318,7 +1444,7 @@ class UpdateContainerRequest: UUID of the container to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1391,6 +1517,34 @@ class UpdateContainerRequest: - enabled: Serve both HTTP and HTTPS traffic. """ + sandbox: Optional[ContainerSandbox] + """ + Execution environment of the container. + """ + + local_storage_limit: Optional[int] + """ + Local storage limit of the container (in MB). + """ + + scaling_option: Optional[ContainerScalingOption] + """ + Possible values: +- concurrent_requests_threshold: Scale depending on the number of concurrent requests being processed per container instance. +- cpu_usage_threshold: Scale depending on the CPU usage of a container instance. +- memory_usage_threshold: Scale depending on the memory usage of a container instance. + """ + + health_check: Optional[ContainerHealthCheckSpec] + """ + Health check configuration of the container. + """ + + tags: Optional[List[str]] + """ + Tags of the Serverless Container. + """ + @dataclass class UpdateCronRequest: @@ -1399,7 +1553,7 @@ class UpdateCronRequest: UUID of the cron to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1432,7 +1586,7 @@ class UpdateNamespaceRequest: UUID of the namespace to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1452,6 +1606,11 @@ class UpdateNamespaceRequest: Secret environment variables of the namespace to update. """ + tags: Optional[List[str]] + """ + Tags of the Serverless Container Namespace. + """ + @dataclass class UpdateTriggerRequest: @@ -1460,7 +1619,7 @@ class UpdateTriggerRequest: ID of the trigger to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/scaleway/dedibox/__init__.py b/scaleway/scaleway/dedibox/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway/scaleway/dedibox/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/dedibox/v1/__init__.py b/scaleway/scaleway/dedibox/v1/__init__.py new file mode 100644 index 00000000..e6b1144a --- /dev/null +++ b/scaleway/scaleway/dedibox/v1/__init__.py @@ -0,0 +1,541 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import AttachFailoverIPToMacAddressRequestMacType +from .types import BMCAccessStatus +from .content import BMC_ACCESS_TRANSIENT_STATUSES +from .types import BackupStatus +from .types import FailoverBlockVersion +from .types import FailoverIPInterfaceType +from .types import FailoverIPStatus +from .types import FailoverIPVersion +from .types import GetRpnStatusResponseStatus +from .types import IPSemantic +from .types import IPStatus +from .types import IPVersion +from .types import IPv6BlockDelegationStatus +from .content import I_PV6_BLOCK_DELEGATION_TRANSIENT_STATUSES +from .types import InvoicePaymentMethod +from .types import InvoiceStatus +from .types import ListFailoverIPsRequestOrderBy +from .types import ListInvoicesRequestOrderBy +from .types import ListOSRequestOrderBy +from .types import ListOffersRequestOrderBy +from .types import ListRefundsRequestOrderBy +from .types import ListRpnCapableSanServersRequestOrderBy +from .types import ListRpnCapableServersRequestOrderBy +from .types import ListRpnGroupMembersRequestOrderBy +from .types import ListRpnGroupsRequestOrderBy +from .types import ListRpnInvitesRequestOrderBy +from .types import ListRpnSansRequestOrderBy +from .types import ListRpnServerCapabilitiesRequestOrderBy +from .types import ListRpnV2CapableResourcesRequestOrderBy +from .types import ListRpnV2GroupLogsRequestOrderBy +from .types import ListRpnV2GroupsRequestOrderBy +from .types import ListRpnV2MembersRequestOrderBy +from .types import ListRpnV2MembersRequestType +from .types import ListServerDisksRequestOrderBy +from .types import ListServerEventsRequestOrderBy +from .types import ListServersRequestOrderBy +from .types import ListServicesRequestOrderBy +from .types import LogAction +from .types import LogStatus +from .types import MemoryType +from .types import NetworkInterfaceInterfaceType +from .types import OSArch +from .types import OSType +from .types import OfferAntiDosInfoType +from .types import OfferCatalog +from .types import OfferPaymentFrequency +from .types import OfferSANInfoType +from .types import OfferServerInfoStock +from .types import PartitionFileSystem +from .types import PartitionType +from .types import RaidArrayRaidLevel +from .types import RefundMethod +from .types import RefundStatus +from .types import RescueProtocol +from .types import RpnGroupMemberStatus +from .content import RPN_GROUP_MEMBER_TRANSIENT_STATUSES +from .types import RpnGroupType +from .types import RpnSanIpType +from .types import RpnSanStatus +from .content import RPN_SAN_TRANSIENT_STATUSES +from .types import RpnV2GroupStatus +from .content import RPN_V2_GROUP_TRANSIENT_STATUSES +from .types import RpnV2GroupType +from .types import RpnV2MemberStatus +from .content import RPN_V2_MEMBER_TRANSIENT_STATUSES +from .types import ServerDiskType +from .types import ServerInstallStatus +from .content import SERVER_INSTALL_TRANSIENT_STATUSES +from .types import ServerStatus +from .content import SERVER_TRANSIENT_STATUSES +from .types import ServiceLevelLevel +from .types import ServiceProvisioningStatus +from .content import SERVICE_PROVISIONING_TRANSIENT_STATUSES +from .types import ServiceType +from .types import OfferAntiDosInfo +from .types import OfferBackupInfo +from .types import OfferBandwidthInfo +from .types import OfferLicenseInfo +from .types import OfferRPNInfo +from .types import OfferSANInfo +from .types import OfferStorageInfo +from .types import IP +from .types import Offer +from .types import NetworkInterface +from .types import OS +from .types import ServerLocation +from .types import ServerOption +from .types import ServiceLevel +from .types import RpnSan +from .types import RpnGroup +from .types import RpnV2GroupSubnet +from .types import Server +from .types import FailoverBlock +from .types import RpnSanIpRpnV2Group +from .types import RpnSanIpServer +from .types import RpnSanServer +from .types import RpnV2Group +from .types import RpnV2Member +from .types import ServerDisk +from .types import Service +from .types import GetIPv6BlockQuotasResponseQuota +from .types import InstallPartition +from .types import FailoverIP +from .types import ListIPv6BlockSubnetsAvailableResponseSubnet +from .types import InvoiceSummary +from .types import RpnSanIp +from .types import RefundSummary +from .types import RpnGroupMember +from .types import RpnSanSummary +from .types import RpnServerCapability +from .types import Log +from .types import ServerEvent +from .types import ServerSummary +from .types import CPU +from .types import Disk +from .types import Memory +from .types import PersistentMemory +from .types import RaidController +from .types import RaidArray +from .types import Partition +from .types import UpdatableRaidArray +from .types import AttachFailoverIPToMacAddressRequest +from .types import AttachFailoverIPsRequest +from .types import BMCAccess +from .types import Backup +from .types import BillingApiCanOrderRequest +from .types import BillingApiDownloadInvoiceRequest +from .types import BillingApiDownloadRefundRequest +from .types import BillingApiGetInvoiceRequest +from .types import BillingApiGetRefundRequest +from .types import BillingApiListInvoicesRequest +from .types import BillingApiListRefundsRequest +from .types import CanOrderResponse +from .types import CancelServerInstallRequest +from .types import CreateFailoverIPsRequest +from .types import CreateFailoverIPsResponse +from .types import CreateServerRequest +from .types import DeleteFailoverIPRequest +from .types import DeleteServerRequest +from .types import DeleteServiceRequest +from .types import DetachFailoverIPFromMacAddressRequest +from .types import DetachFailoverIPsRequest +from .types import GetBMCAccessRequest +from .types import GetFailoverIPRequest +from .types import GetIPv6BlockQuotasResponse +from .types import GetOSRequest +from .types import GetOfferRequest +from .types import GetOrderedServiceRequest +from .types import GetRaidRequest +from .types import GetRemainingQuotaRequest +from .types import GetRemainingQuotaResponse +from .types import GetRescueRequest +from .types import GetRpnStatusResponse +from .types import GetServerBackupRequest +from .types import GetServerDefaultPartitioningRequest +from .types import GetServerInstallRequest +from .types import GetServerRequest +from .types import GetServiceRequest +from .types import IPv6Block +from .types import IPv6BlockApiCreateIPv6BlockRequest +from .types import IPv6BlockApiCreateIPv6BlockSubnetRequest +from .types import IPv6BlockApiDeleteIPv6BlockRequest +from .types import IPv6BlockApiGetIPv6BlockQuotasRequest +from .types import IPv6BlockApiGetIPv6BlockRequest +from .types import IPv6BlockApiListIPv6BlockSubnetsAvailableRequest +from .types import IPv6BlockApiUpdateIPv6BlockRequest +from .types import InstallServerRequest +from .types import Invoice +from .types import ListFailoverIPsRequest +from .types import ListFailoverIPsResponse +from .types import ListIPv6BlockSubnetsAvailableResponse +from .types import ListInvoicesResponse +from .types import ListIpsResponse +from .types import ListOSRequest +from .types import ListOSResponse +from .types import ListOffersRequest +from .types import ListOffersResponse +from .types import ListRefundsResponse +from .types import ListRpnCapableSanServersResponse +from .types import ListRpnCapableServersResponse +from .types import ListRpnGroupMembersResponse +from .types import ListRpnGroupsResponse +from .types import ListRpnInvitesResponse +from .types import ListRpnSansResponse +from .types import ListRpnServerCapabilitiesResponse +from .types import ListRpnV2CapableResourcesResponse +from .types import ListRpnV2GroupLogsResponse +from .types import ListRpnV2GroupsResponse +from .types import ListRpnV2MembersResponse +from .types import ListServerDisksRequest +from .types import ListServerDisksResponse +from .types import ListServerEventsRequest +from .types import ListServerEventsResponse +from .types import ListServersRequest +from .types import ListServersResponse +from .types import ListServicesRequest +from .types import ListServicesResponse +from .types import ListSubscribableServerOptionsRequest +from .types import ListSubscribableServerOptionsResponse +from .types import OfferFailoverBlockInfo +from .types import OfferFailoverIpInfo +from .types import OfferServerInfo +from .types import OfferServiceLevelInfo +from .types import Raid +from .types import RebootServerRequest +from .types import Refund +from .types import Rescue +from .types import RpnApiGetRpnStatusRequest +from .types import RpnApiListRpnServerCapabilitiesRequest +from .types import RpnSanApiAddIpRequest +from .types import RpnSanApiCreateRpnSanRequest +from .types import RpnSanApiDeleteRpnSanRequest +from .types import RpnSanApiGetRpnSanRequest +from .types import RpnSanApiListAvailableIpsRequest +from .types import RpnSanApiListIpsRequest +from .types import RpnSanApiListRpnSansRequest +from .types import RpnSanApiRemoveIpRequest +from .types import RpnV1ApiAcceptRpnInviteRequest +from .types import RpnV1ApiAddRpnGroupMembersRequest +from .types import RpnV1ApiCreateRpnGroupRequest +from .types import RpnV1ApiDeleteRpnGroupMembersRequest +from .types import RpnV1ApiDeleteRpnGroupRequest +from .types import RpnV1ApiGetRpnGroupRequest +from .types import RpnV1ApiLeaveRpnGroupRequest +from .types import RpnV1ApiListRpnCapableSanServersRequest +from .types import RpnV1ApiListRpnCapableServersRequest +from .types import RpnV1ApiListRpnGroupMembersRequest +from .types import RpnV1ApiListRpnGroupsRequest +from .types import RpnV1ApiListRpnInvitesRequest +from .types import RpnV1ApiRefuseRpnInviteRequest +from .types import RpnV1ApiRpnGroupInviteRequest +from .types import RpnV1ApiUpdateRpnGroupNameRequest +from .types import RpnV2ApiAddRpnV2MembersRequest +from .types import RpnV2ApiCreateRpnV2GroupRequest +from .types import RpnV2ApiDeleteRpnV2GroupRequest +from .types import RpnV2ApiDeleteRpnV2MembersRequest +from .types import RpnV2ApiDisableRpnV2GroupCompatibilityRequest +from .types import RpnV2ApiEnableRpnV2GroupCompatibilityRequest +from .types import RpnV2ApiGetRpnV2GroupRequest +from .types import RpnV2ApiListRpnV2CapableResourcesRequest +from .types import RpnV2ApiListRpnV2GroupLogsRequest +from .types import RpnV2ApiListRpnV2GroupsRequest +from .types import RpnV2ApiListRpnV2MembersRequest +from .types import RpnV2ApiUpdateRpnV2GroupNameRequest +from .types import RpnV2ApiUpdateRpnV2VlanForMembersRequest +from .types import ServerDefaultPartitioning +from .types import ServerInstall +from .types import StartBMCAccessRequest +from .types import StartRescueRequest +from .types import StartServerRequest +from .types import StopBMCAccessRequest +from .types import StopRescueRequest +from .types import StopServerRequest +from .types import SubscribeServerOptionRequest +from .types import SubscribeStorageOptionsRequest +from .types import SubscribeStorageOptionsResponse +from .types import UpdateRaidRequest +from .types import UpdateReverseRequest +from .types import UpdateServerBackupRequest +from .types import UpdateServerRequest +from .types import UpdateServerTagsRequest +from .api import DediboxV1API +from .api import DediboxV1BillingAPI +from .api import DediboxV1IPv6BlockAPI +from .api import DediboxV1RpnAPI +from .api import DediboxV1RpnSanAPI +from .api import DediboxV1RpnV1API +from .api import DediboxV1RpnV2API + +__all__ = [ + "AttachFailoverIPToMacAddressRequestMacType", + "BMCAccessStatus", + "BMC_ACCESS_TRANSIENT_STATUSES", + "BackupStatus", + "FailoverBlockVersion", + "FailoverIPInterfaceType", + "FailoverIPStatus", + "FailoverIPVersion", + "GetRpnStatusResponseStatus", + "IPSemantic", + "IPStatus", + "IPVersion", + "IPv6BlockDelegationStatus", + "I_PV6_BLOCK_DELEGATION_TRANSIENT_STATUSES", + "InvoicePaymentMethod", + "InvoiceStatus", + "ListFailoverIPsRequestOrderBy", + "ListInvoicesRequestOrderBy", + "ListOSRequestOrderBy", + "ListOffersRequestOrderBy", + "ListRefundsRequestOrderBy", + "ListRpnCapableSanServersRequestOrderBy", + "ListRpnCapableServersRequestOrderBy", + "ListRpnGroupMembersRequestOrderBy", + "ListRpnGroupsRequestOrderBy", + "ListRpnInvitesRequestOrderBy", + "ListRpnSansRequestOrderBy", + "ListRpnServerCapabilitiesRequestOrderBy", + "ListRpnV2CapableResourcesRequestOrderBy", + "ListRpnV2GroupLogsRequestOrderBy", + "ListRpnV2GroupsRequestOrderBy", + "ListRpnV2MembersRequestOrderBy", + "ListRpnV2MembersRequestType", + "ListServerDisksRequestOrderBy", + "ListServerEventsRequestOrderBy", + "ListServersRequestOrderBy", + "ListServicesRequestOrderBy", + "LogAction", + "LogStatus", + "MemoryType", + "NetworkInterfaceInterfaceType", + "OSArch", + "OSType", + "OfferAntiDosInfoType", + "OfferCatalog", + "OfferPaymentFrequency", + "OfferSANInfoType", + "OfferServerInfoStock", + "PartitionFileSystem", + "PartitionType", + "RaidArrayRaidLevel", + "RefundMethod", + "RefundStatus", + "RescueProtocol", + "RpnGroupMemberStatus", + "RPN_GROUP_MEMBER_TRANSIENT_STATUSES", + "RpnGroupType", + "RpnSanIpType", + "RpnSanStatus", + "RPN_SAN_TRANSIENT_STATUSES", + "RpnV2GroupStatus", + "RPN_V2_GROUP_TRANSIENT_STATUSES", + "RpnV2GroupType", + "RpnV2MemberStatus", + "RPN_V2_MEMBER_TRANSIENT_STATUSES", + "ServerDiskType", + "ServerInstallStatus", + "SERVER_INSTALL_TRANSIENT_STATUSES", + "ServerStatus", + "SERVER_TRANSIENT_STATUSES", + "ServiceLevelLevel", + "ServiceProvisioningStatus", + "SERVICE_PROVISIONING_TRANSIENT_STATUSES", + "ServiceType", + "OfferAntiDosInfo", + "OfferBackupInfo", + "OfferBandwidthInfo", + "OfferLicenseInfo", + "OfferRPNInfo", + "OfferSANInfo", + "OfferStorageInfo", + "IP", + "Offer", + "NetworkInterface", + "OS", + "ServerLocation", + "ServerOption", + "ServiceLevel", + "RpnSan", + "RpnGroup", + "RpnV2GroupSubnet", + "Server", + "FailoverBlock", + "RpnSanIpRpnV2Group", + "RpnSanIpServer", + "RpnSanServer", + "RpnV2Group", + "RpnV2Member", + "ServerDisk", + "Service", + "GetIPv6BlockQuotasResponseQuota", + "InstallPartition", + "FailoverIP", + "ListIPv6BlockSubnetsAvailableResponseSubnet", + "InvoiceSummary", + "RpnSanIp", + "RefundSummary", + "RpnGroupMember", + "RpnSanSummary", + "RpnServerCapability", + "Log", + "ServerEvent", + "ServerSummary", + "CPU", + "Disk", + "Memory", + "PersistentMemory", + "RaidController", + "RaidArray", + "Partition", + "UpdatableRaidArray", + "AttachFailoverIPToMacAddressRequest", + "AttachFailoverIPsRequest", + "BMCAccess", + "Backup", + "BillingApiCanOrderRequest", + "BillingApiDownloadInvoiceRequest", + "BillingApiDownloadRefundRequest", + "BillingApiGetInvoiceRequest", + "BillingApiGetRefundRequest", + "BillingApiListInvoicesRequest", + "BillingApiListRefundsRequest", + "CanOrderResponse", + "CancelServerInstallRequest", + "CreateFailoverIPsRequest", + "CreateFailoverIPsResponse", + "CreateServerRequest", + "DeleteFailoverIPRequest", + "DeleteServerRequest", + "DeleteServiceRequest", + "DetachFailoverIPFromMacAddressRequest", + "DetachFailoverIPsRequest", + "GetBMCAccessRequest", + "GetFailoverIPRequest", + "GetIPv6BlockQuotasResponse", + "GetOSRequest", + "GetOfferRequest", + "GetOrderedServiceRequest", + "GetRaidRequest", + "GetRemainingQuotaRequest", + "GetRemainingQuotaResponse", + "GetRescueRequest", + "GetRpnStatusResponse", + "GetServerBackupRequest", + "GetServerDefaultPartitioningRequest", + "GetServerInstallRequest", + "GetServerRequest", + "GetServiceRequest", + "IPv6Block", + "IPv6BlockApiCreateIPv6BlockRequest", + "IPv6BlockApiCreateIPv6BlockSubnetRequest", + "IPv6BlockApiDeleteIPv6BlockRequest", + "IPv6BlockApiGetIPv6BlockQuotasRequest", + "IPv6BlockApiGetIPv6BlockRequest", + "IPv6BlockApiListIPv6BlockSubnetsAvailableRequest", + "IPv6BlockApiUpdateIPv6BlockRequest", + "InstallServerRequest", + "Invoice", + "ListFailoverIPsRequest", + "ListFailoverIPsResponse", + "ListIPv6BlockSubnetsAvailableResponse", + "ListInvoicesResponse", + "ListIpsResponse", + "ListOSRequest", + "ListOSResponse", + "ListOffersRequest", + "ListOffersResponse", + "ListRefundsResponse", + "ListRpnCapableSanServersResponse", + "ListRpnCapableServersResponse", + "ListRpnGroupMembersResponse", + "ListRpnGroupsResponse", + "ListRpnInvitesResponse", + "ListRpnSansResponse", + "ListRpnServerCapabilitiesResponse", + "ListRpnV2CapableResourcesResponse", + "ListRpnV2GroupLogsResponse", + "ListRpnV2GroupsResponse", + "ListRpnV2MembersResponse", + "ListServerDisksRequest", + "ListServerDisksResponse", + "ListServerEventsRequest", + "ListServerEventsResponse", + "ListServersRequest", + "ListServersResponse", + "ListServicesRequest", + "ListServicesResponse", + "ListSubscribableServerOptionsRequest", + "ListSubscribableServerOptionsResponse", + "OfferFailoverBlockInfo", + "OfferFailoverIpInfo", + "OfferServerInfo", + "OfferServiceLevelInfo", + "Raid", + "RebootServerRequest", + "Refund", + "Rescue", + "RpnApiGetRpnStatusRequest", + "RpnApiListRpnServerCapabilitiesRequest", + "RpnSanApiAddIpRequest", + "RpnSanApiCreateRpnSanRequest", + "RpnSanApiDeleteRpnSanRequest", + "RpnSanApiGetRpnSanRequest", + "RpnSanApiListAvailableIpsRequest", + "RpnSanApiListIpsRequest", + "RpnSanApiListRpnSansRequest", + "RpnSanApiRemoveIpRequest", + "RpnV1ApiAcceptRpnInviteRequest", + "RpnV1ApiAddRpnGroupMembersRequest", + "RpnV1ApiCreateRpnGroupRequest", + "RpnV1ApiDeleteRpnGroupMembersRequest", + "RpnV1ApiDeleteRpnGroupRequest", + "RpnV1ApiGetRpnGroupRequest", + "RpnV1ApiLeaveRpnGroupRequest", + "RpnV1ApiListRpnCapableSanServersRequest", + "RpnV1ApiListRpnCapableServersRequest", + "RpnV1ApiListRpnGroupMembersRequest", + "RpnV1ApiListRpnGroupsRequest", + "RpnV1ApiListRpnInvitesRequest", + "RpnV1ApiRefuseRpnInviteRequest", + "RpnV1ApiRpnGroupInviteRequest", + "RpnV1ApiUpdateRpnGroupNameRequest", + "RpnV2ApiAddRpnV2MembersRequest", + "RpnV2ApiCreateRpnV2GroupRequest", + "RpnV2ApiDeleteRpnV2GroupRequest", + "RpnV2ApiDeleteRpnV2MembersRequest", + "RpnV2ApiDisableRpnV2GroupCompatibilityRequest", + "RpnV2ApiEnableRpnV2GroupCompatibilityRequest", + "RpnV2ApiGetRpnV2GroupRequest", + "RpnV2ApiListRpnV2CapableResourcesRequest", + "RpnV2ApiListRpnV2GroupLogsRequest", + "RpnV2ApiListRpnV2GroupsRequest", + "RpnV2ApiListRpnV2MembersRequest", + "RpnV2ApiUpdateRpnV2GroupNameRequest", + "RpnV2ApiUpdateRpnV2VlanForMembersRequest", + "ServerDefaultPartitioning", + "ServerInstall", + "StartBMCAccessRequest", + "StartRescueRequest", + "StartServerRequest", + "StopBMCAccessRequest", + "StopRescueRequest", + "StopServerRequest", + "SubscribeServerOptionRequest", + "SubscribeStorageOptionsRequest", + "SubscribeStorageOptionsResponse", + "UpdateRaidRequest", + "UpdateReverseRequest", + "UpdateServerBackupRequest", + "UpdateServerRequest", + "UpdateServerTagsRequest", + "DediboxV1API", + "DediboxV1BillingAPI", + "DediboxV1IPv6BlockAPI", + "DediboxV1RpnAPI", + "DediboxV1RpnSanAPI", + "DediboxV1RpnV1API", + "DediboxV1RpnV2API", +] diff --git a/scaleway/scaleway/dedibox/v1/api.py b/scaleway/scaleway/dedibox/v1/api.py new file mode 100644 index 00000000..12c41345 --- /dev/null +++ b/scaleway/scaleway/dedibox/v1/api.py @@ -0,0 +1,4721 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + ScwFile, + Zone as ScwZone, + unmarshal_ScwFile, +) +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + AttachFailoverIPToMacAddressRequestMacType, + ListFailoverIPsRequestOrderBy, + ListInvoicesRequestOrderBy, + ListOSRequestOrderBy, + ListOffersRequestOrderBy, + ListRefundsRequestOrderBy, + ListRpnCapableSanServersRequestOrderBy, + ListRpnCapableServersRequestOrderBy, + ListRpnGroupMembersRequestOrderBy, + ListRpnGroupsRequestOrderBy, + ListRpnInvitesRequestOrderBy, + ListRpnSansRequestOrderBy, + ListRpnServerCapabilitiesRequestOrderBy, + ListRpnV2CapableResourcesRequestOrderBy, + ListRpnV2GroupLogsRequestOrderBy, + ListRpnV2GroupsRequestOrderBy, + ListRpnV2MembersRequestOrderBy, + ListRpnV2MembersRequestType, + ListServerDisksRequestOrderBy, + ListServerEventsRequestOrderBy, + ListServersRequestOrderBy, + ListServicesRequestOrderBy, + OSType, + OfferCatalog, + RpnSanIpType, + RpnV2GroupType, + AttachFailoverIPToMacAddressRequest, + AttachFailoverIPsRequest, + BMCAccess, + Backup, + CanOrderResponse, + CreateFailoverIPsRequest, + CreateFailoverIPsResponse, + CreateServerRequest, + DetachFailoverIPsRequest, + FailoverIP, + GetIPv6BlockQuotasResponse, + GetRemainingQuotaResponse, + GetRpnStatusResponse, + IP, + IPv6Block, + IPv6BlockApiCreateIPv6BlockRequest, + IPv6BlockApiCreateIPv6BlockSubnetRequest, + IPv6BlockApiUpdateIPv6BlockRequest, + InstallPartition, + InstallServerRequest, + Invoice, + InvoiceSummary, + ListFailoverIPsResponse, + ListIPv6BlockSubnetsAvailableResponse, + ListInvoicesResponse, + ListIpsResponse, + ListOSResponse, + ListOffersResponse, + ListRefundsResponse, + ListRpnCapableSanServersResponse, + ListRpnCapableServersResponse, + ListRpnGroupMembersResponse, + ListRpnGroupsResponse, + ListRpnInvitesResponse, + ListRpnSansResponse, + ListRpnServerCapabilitiesResponse, + ListRpnV2CapableResourcesResponse, + ListRpnV2GroupLogsResponse, + ListRpnV2GroupsResponse, + ListRpnV2MembersResponse, + ListServerDisksResponse, + ListServerEventsResponse, + ListServersResponse, + ListServicesResponse, + ListSubscribableServerOptionsResponse, + Log, + OS, + Offer, + Raid, + Refund, + RefundSummary, + Rescue, + RpnGroup, + RpnGroupMember, + RpnSan, + RpnSanApiAddIpRequest, + RpnSanApiCreateRpnSanRequest, + RpnSanApiRemoveIpRequest, + RpnSanServer, + RpnSanSummary, + RpnServerCapability, + RpnV1ApiAddRpnGroupMembersRequest, + RpnV1ApiCreateRpnGroupRequest, + RpnV1ApiDeleteRpnGroupMembersRequest, + RpnV1ApiLeaveRpnGroupRequest, + RpnV1ApiRpnGroupInviteRequest, + RpnV1ApiUpdateRpnGroupNameRequest, + RpnV2ApiAddRpnV2MembersRequest, + RpnV2ApiCreateRpnV2GroupRequest, + RpnV2ApiDeleteRpnV2MembersRequest, + RpnV2ApiEnableRpnV2GroupCompatibilityRequest, + RpnV2ApiUpdateRpnV2GroupNameRequest, + RpnV2ApiUpdateRpnV2VlanForMembersRequest, + RpnV2Group, + RpnV2Member, + Server, + ServerDefaultPartitioning, + ServerDisk, + ServerEvent, + ServerInstall, + ServerSummary, + Service, + StartBMCAccessRequest, + StartRescueRequest, + SubscribeServerOptionRequest, + SubscribeStorageOptionsRequest, + SubscribeStorageOptionsResponse, + UpdatableRaidArray, + UpdateRaidRequest, + UpdateReverseRequest, + UpdateServerBackupRequest, + UpdateServerRequest, + UpdateServerTagsRequest, +) +from .content import ( + BMC_ACCESS_TRANSIENT_STATUSES, + RPN_SAN_TRANSIENT_STATUSES, + RPN_V2_GROUP_TRANSIENT_STATUSES, + SERVER_INSTALL_TRANSIENT_STATUSES, + SERVER_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_IP, + unmarshal_Offer, + unmarshal_OS, + unmarshal_RpnSan, + unmarshal_RpnGroup, + unmarshal_Server, + unmarshal_RpnV2Group, + unmarshal_Service, + unmarshal_FailoverIP, + unmarshal_BMCAccess, + unmarshal_Backup, + unmarshal_CanOrderResponse, + unmarshal_CreateFailoverIPsResponse, + unmarshal_GetIPv6BlockQuotasResponse, + unmarshal_GetRemainingQuotaResponse, + unmarshal_GetRpnStatusResponse, + unmarshal_IPv6Block, + unmarshal_Invoice, + unmarshal_ListFailoverIPsResponse, + unmarshal_ListIPv6BlockSubnetsAvailableResponse, + unmarshal_ListInvoicesResponse, + unmarshal_ListIpsResponse, + unmarshal_ListOSResponse, + unmarshal_ListOffersResponse, + unmarshal_ListRefundsResponse, + unmarshal_ListRpnCapableSanServersResponse, + unmarshal_ListRpnCapableServersResponse, + unmarshal_ListRpnGroupMembersResponse, + unmarshal_ListRpnGroupsResponse, + unmarshal_ListRpnInvitesResponse, + unmarshal_ListRpnSansResponse, + unmarshal_ListRpnServerCapabilitiesResponse, + unmarshal_ListRpnV2CapableResourcesResponse, + unmarshal_ListRpnV2GroupLogsResponse, + unmarshal_ListRpnV2GroupsResponse, + unmarshal_ListRpnV2MembersResponse, + unmarshal_ListServerDisksResponse, + unmarshal_ListServerEventsResponse, + unmarshal_ListServersResponse, + unmarshal_ListServicesResponse, + unmarshal_ListSubscribableServerOptionsResponse, + unmarshal_Raid, + unmarshal_Refund, + unmarshal_Rescue, + unmarshal_ServerDefaultPartitioning, + unmarshal_ServerInstall, + unmarshal_SubscribeStorageOptionsResponse, + marshal_AttachFailoverIPToMacAddressRequest, + marshal_AttachFailoverIPsRequest, + marshal_CreateFailoverIPsRequest, + marshal_CreateServerRequest, + marshal_DetachFailoverIPsRequest, + marshal_IPv6BlockApiCreateIPv6BlockRequest, + marshal_IPv6BlockApiCreateIPv6BlockSubnetRequest, + marshal_IPv6BlockApiUpdateIPv6BlockRequest, + marshal_InstallServerRequest, + marshal_RpnSanApiAddIpRequest, + marshal_RpnSanApiCreateRpnSanRequest, + marshal_RpnSanApiRemoveIpRequest, + marshal_RpnV1ApiAddRpnGroupMembersRequest, + marshal_RpnV1ApiCreateRpnGroupRequest, + marshal_RpnV1ApiDeleteRpnGroupMembersRequest, + marshal_RpnV1ApiLeaveRpnGroupRequest, + marshal_RpnV1ApiRpnGroupInviteRequest, + marshal_RpnV1ApiUpdateRpnGroupNameRequest, + marshal_RpnV2ApiAddRpnV2MembersRequest, + marshal_RpnV2ApiCreateRpnV2GroupRequest, + marshal_RpnV2ApiDeleteRpnV2MembersRequest, + marshal_RpnV2ApiEnableRpnV2GroupCompatibilityRequest, + marshal_RpnV2ApiUpdateRpnV2GroupNameRequest, + marshal_RpnV2ApiUpdateRpnV2VlanForMembersRequest, + marshal_StartBMCAccessRequest, + marshal_StartRescueRequest, + marshal_SubscribeServerOptionRequest, + marshal_SubscribeStorageOptionsRequest, + marshal_UpdateRaidRequest, + marshal_UpdateReverseRequest, + marshal_UpdateServerBackupRequest, + marshal_UpdateServerRequest, + marshal_UpdateServerTagsRequest, +) + + +class DediboxV1API(API): + """ + Dedibox Phoenix API. + """ + + def list_servers( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServersRequestOrderBy] = None, + project_id: Optional[str] = None, + search: Optional[str] = None, + ) -> ListServersResponse: + """ + List baremetal servers for project. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server per page. + :param order_by: Order of the servers. + :param project_id: Filter servers by project ID. + :param search: Filter servers by hostname. + :return: :class:`ListServersResponse ` + + Usage: + :: + + result = api.list_servers() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "search": search, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServersResponse(res.json()) + + def list_servers_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServersRequestOrderBy] = None, + project_id: Optional[str] = None, + search: Optional[str] = None, + ) -> List[ServerSummary]: + """ + List baremetal servers for project. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server per page. + :param order_by: Order of the servers. + :param project_id: Filter servers by project ID. + :param search: Filter servers by hostname. + :return: :class:`List[ServerSummary] ` + + Usage: + :: + + result = api.list_servers_all() + """ + + return fetch_all_pages( + type=ListServersResponse, + key="servers", + fetcher=self.list_servers, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "search": search, + }, + ) + + def get_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> Server: + """ + Get a specific baremetal server. + Get the server associated with the given ID. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Server ` + + Usage: + :: + + result = api.get_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}", + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + + def wait_for_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[Server, bool]] = None, + ) -> Server: + """ + Get a specific baremetal server. + Get the server associated with the given ID. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Server ` + + Usage: + :: + + result = api.get_server( + server_id=1, + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in SERVER_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_server, + options=options, + args={ + "server_id": server_id, + "zone": zone, + }, + ) + + def get_server_backup( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> Backup: + """ + :param server_id: Server ID of the backup. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Backup ` + + Usage: + :: + + result = api.get_server_backup( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/backups", + ) + + self._throw_on_error(res) + return unmarshal_Backup(res.json()) + + def update_server_backup( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + password: Optional[str] = None, + autologin: Optional[bool] = None, + acl_enabled: Optional[bool] = None, + ) -> Backup: + """ + :param server_id: Server ID to update backup. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param password: Password of the server backup. + :param autologin: Autologin of the server backup. + :param acl_enabled: Boolean to enable or disable ACL. + :return: :class:`Backup ` + + Usage: + :: + + result = api.update_server_backup( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/backups", + body=marshal_UpdateServerBackupRequest( + UpdateServerBackupRequest( + server_id=server_id, + zone=zone, + password=password, + autologin=autologin, + acl_enabled=acl_enabled, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Backup(res.json()) + + def list_subscribable_server_options( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListSubscribableServerOptionsResponse: + """ + List subscribable server options. + List subscribable options associated to the given server ID. + :param server_id: Server ID of the subscribable server options. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of subscribable server option per page. + :return: :class:`ListSubscribableServerOptionsResponse ` + + Usage: + :: + + result = api.list_subscribable_server_options( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/subscribable-server-options", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListSubscribableServerOptionsResponse(res.json()) + + def list_subscribable_server_options_all( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[Offer]: + """ + List subscribable server options. + List subscribable options associated to the given server ID. + :param server_id: Server ID of the subscribable server options. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of subscribable server option per page. + :return: :class:`List[Offer] ` + + Usage: + :: + + result = api.list_subscribable_server_options_all( + server_id=1, + ) + """ + + return fetch_all_pages( + type=ListSubscribableServerOptionsResponse, + key="server_options", + fetcher=self.list_subscribable_server_options, + args={ + "server_id": server_id, + "zone": zone, + "page": page, + "page_size": page_size, + }, + ) + + def subscribe_server_option( + self, + *, + server_id: int, + option_id: int, + zone: Optional[ScwZone] = None, + ) -> Service: + """ + Subscribe server option. + Subscribe option for the given server ID. + :param server_id: Server ID to subscribe server option. + :param option_id: Option ID to subscribe. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Service ` + + Usage: + :: + + result = api.subscribe_server_option( + server_id=1, + option_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/subscribe-server-option", + body=marshal_SubscribeServerOptionRequest( + SubscribeServerOptionRequest( + server_id=server_id, + option_id=option_id, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + def create_server( + self, + *, + offer_id: int, + server_option_ids: List[int], + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + datacenter_name: Optional[str] = None, + ) -> Service: + """ + Create a baremetal server. + Create a new baremetal server. The order return you a service ID to follow the provisionning status you could call GetService. + :param offer_id: Offer ID of the new server. + :param server_option_ids: Server option IDs of the new server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID of the new server. + :param datacenter_name: Datacenter name of the new server. + :return: :class:`Service ` + + Usage: + :: + + result = api.create_server( + offer_id=1, + server_option_ids=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers", + body=marshal_CreateServerRequest( + CreateServerRequest( + offer_id=offer_id, + server_option_ids=server_option_ids, + zone=zone, + project_id=project_id, + datacenter_name=datacenter_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + def subscribe_storage_options( + self, + *, + server_id: int, + options_ids: List[int], + zone: Optional[ScwZone] = None, + ) -> SubscribeStorageOptionsResponse: + """ + Subscribe storage server option. + Subscribe storage option for the given server ID. + :param server_id: Server ID of the storage options to subscribe. + :param options_ids: Option IDs of the storage options to subscribe. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`SubscribeStorageOptionsResponse ` + + Usage: + :: + + result = api.subscribe_storage_options( + server_id=1, + options_ids=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/subscribe-storage-options", + body=marshal_SubscribeStorageOptionsRequest( + SubscribeStorageOptionsRequest( + server_id=server_id, + options_ids=options_ids, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SubscribeStorageOptionsResponse(res.json()) + + def update_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + hostname: Optional[str] = None, + enable_ipv6: Optional[bool] = None, + ) -> Server: + """ + Update a baremetal server. + Update the server associated with the given ID. + :param server_id: Server ID to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param hostname: Hostname of the server to update. + :param enable_ipv6: Flag to enable or not the IPv6 of server. + :return: :class:`Server ` + + Usage: + :: + + result = api.update_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}", + body=marshal_UpdateServerRequest( + UpdateServerRequest( + server_id=server_id, + zone=zone, + hostname=hostname, + enable_ipv6=enable_ipv6, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + + def update_server_tags( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + tags: Optional[List[str]] = None, + ) -> Server: + """ + :param server_id: Server ID to update the tags. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param tags: Tags of server to update. + :return: :class:`Server ` + + Usage: + :: + + result = api.update_server_tags( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/tags", + body=marshal_UpdateServerTagsRequest( + UpdateServerTagsRequest( + server_id=server_id, + zone=zone, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + + def reboot_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Reboot a baremetal server. + Reboot the server associated with the given ID, use boot param to reboot in rescue. + :param server_id: Server ID to reboot. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.reboot_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/reboot", + body={}, + ) + + self._throw_on_error(res) + + def start_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Start a baremetal server. + Start the server associated with the given ID. + :param server_id: Server ID to start. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.start_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/start", + body={}, + ) + + self._throw_on_error(res) + + def stop_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Stop a baremetal server. + Stop the server associated with the given ID. + :param server_id: Server ID to stop. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.stop_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/stop", + body={}, + ) + + self._throw_on_error(res) + + def delete_server( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a baremetal server. + Delete the server associated with the given ID. + :param server_id: Server ID to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_server( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}", + ) + + self._throw_on_error(res) + + def list_server_events( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServerEventsRequestOrderBy] = None, + ) -> ListServerEventsResponse: + """ + List server events. + List events associated to the given server ID. + :param server_id: Server ID of the server events. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server event per page. + :param order_by: Order of the server events. + :return: :class:`ListServerEventsResponse ` + + Usage: + :: + + result = api.list_server_events( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/events", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServerEventsResponse(res.json()) + + def list_server_events_all( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServerEventsRequestOrderBy] = None, + ) -> List[ServerEvent]: + """ + List server events. + List events associated to the given server ID. + :param server_id: Server ID of the server events. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server event per page. + :param order_by: Order of the server events. + :return: :class:`List[ServerEvent] ` + + Usage: + :: + + result = api.list_server_events_all( + server_id=1, + ) + """ + + return fetch_all_pages( + type=ListServerEventsResponse, + key="events", + fetcher=self.list_server_events, + args={ + "server_id": server_id, + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + def list_server_disks( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServerDisksRequestOrderBy] = None, + ) -> ListServerDisksResponse: + """ + List server disks. + List disks associated to the given server ID. + :param server_id: Server ID of the server disks. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server disk per page. + :param order_by: Order of the server disks. + :return: :class:`ListServerDisksResponse ` + + Usage: + :: + + result = api.list_server_disks( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/disks", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServerDisksResponse(res.json()) + + def list_server_disks_all( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServerDisksRequestOrderBy] = None, + ) -> List[ServerDisk]: + """ + List server disks. + List disks associated to the given server ID. + :param server_id: Server ID of the server disks. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of server disk per page. + :param order_by: Order of the server disks. + :return: :class:`List[ServerDisk] ` + + Usage: + :: + + result = api.list_server_disks_all( + server_id=1, + ) + """ + + return fetch_all_pages( + type=ListServerDisksResponse, + key="disks", + fetcher=self.list_server_disks, + args={ + "server_id": server_id, + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + def get_ordered_service( + self, + *, + ordered_service_id: int, + zone: Optional[ScwZone] = None, + ) -> Service: + """ + :param ordered_service_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Service ` + + Usage: + :: + + result = api.get_ordered_service( + ordered_service_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ordered_service_id = validate_path_param( + "ordered_service_id", ordered_service_id + ) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/ordered-services/{param_ordered_service_id}", + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + def get_service( + self, + *, + service_id: int, + zone: Optional[ScwZone] = None, + ) -> Service: + """ + Get a specific service. + Get the service associated with the given ID. + :param service_id: ID of the service. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Service ` + + Usage: + :: + + result = api.get_service( + service_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_service_id = validate_path_param("service_id", service_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/zones/{param_zone}/services/{param_service_id}", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + def delete_service( + self, + *, + service_id: int, + zone: Optional[ScwZone] = None, + ) -> Service: + """ + Delete a specific service. + Delete the service associated with the given ID. + :param service_id: ID of the service. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Service ` + + Usage: + :: + + result = api.delete_service( + service_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_service_id = validate_path_param("service_id", service_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/zones/{param_zone}/services/{param_service_id}", + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + def list_services( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServicesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListServicesResponse: + """ + List services. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of service per page. + :param order_by: Order of the services. + :param project_id: Project ID. + :return: :class:`ListServicesResponse ` + + Usage: + :: + + result = api.list_services() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/services", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListServicesResponse(res.json()) + + def list_services_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListServicesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[Service]: + """ + List services. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of service per page. + :param order_by: Order of the services. + :param project_id: Project ID. + :return: :class:`List[Service] ` + + Usage: + :: + + result = api.list_services_all() + """ + + return fetch_all_pages( + type=ListServicesResponse, + key="services", + fetcher=self.list_services, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def install_server( + self, + *, + server_id: int, + os_id: int, + hostname: str, + zone: Optional[ScwZone] = None, + user_login: Optional[str] = None, + user_password: Optional[str] = None, + panel_password: Optional[str] = None, + root_password: Optional[str] = None, + partitions: Optional[List[InstallPartition]] = None, + ssh_key_ids: Optional[List[str]] = None, + license_offer_id: Optional[int] = None, + ip_id: Optional[int] = None, + ) -> ServerInstall: + """ + Install a baremetal server. + Install an OS on the server associated with the given ID. + :param server_id: Server ID to install. + :param os_id: OS ID to install on the server. + :param hostname: Hostname of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param user_login: User to install on the server. + :param user_password: User password to install on the server. + :param panel_password: Panel password to install on the server. + :param root_password: Root password to install on the server. + :param partitions: Partitions to install on the server. + :param ssh_key_ids: SSH key IDs authorized on the server. + :param license_offer_id: Offer ID of license to install on server. + :param ip_id: IP to link at the license to install on server. + :return: :class:`ServerInstall ` + + Usage: + :: + + result = api.install_server( + server_id=1, + os_id=1, + hostname="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/install", + body=marshal_InstallServerRequest( + InstallServerRequest( + server_id=server_id, + os_id=os_id, + hostname=hostname, + zone=zone, + user_login=user_login, + user_password=user_password, + panel_password=panel_password, + root_password=root_password, + partitions=partitions, + ssh_key_ids=ssh_key_ids, + license_offer_id=license_offer_id, + ip_id=ip_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ServerInstall(res.json()) + + def get_server_install( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> ServerInstall: + """ + Get a specific server installation status. + Get the server installation status associated with the given server ID. + :param server_id: Server ID of the server to install. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerInstall ` + + Usage: + :: + + result = api.get_server_install( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/install", + ) + + self._throw_on_error(res) + return unmarshal_ServerInstall(res.json()) + + def wait_for_server_install( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[ServerInstall, bool]] = None, + ) -> ServerInstall: + """ + Get a specific server installation status. + Get the server installation status associated with the given server ID. + :param server_id: Server ID of the server to install. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerInstall ` + + Usage: + :: + + result = api.get_server_install( + server_id=1, + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in SERVER_INSTALL_TRANSIENT_STATUSES + ) + + return wait_for_resource( + fetcher=self.get_server_install, + options=options, + args={ + "server_id": server_id, + "zone": zone, + }, + ) + + def cancel_server_install( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Cancels the current (running) server installation. + Cancels the current server installation associated with the given server ID. + :param server_id: Server ID of the server to cancel install. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.cancel_server_install( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/cancel-install", + ) + + self._throw_on_error(res) + + def get_server_default_partitioning( + self, + *, + server_id: int, + os_id: int, + zone: Optional[ScwZone] = None, + ) -> ServerDefaultPartitioning: + """ + Get server default partitioning. + Get the server default partitioning schema associated with the given server ID and OS ID. + :param server_id: ID of the server. + :param os_id: OS ID of the default partitioning. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerDefaultPartitioning ` + + Usage: + :: + + result = api.get_server_default_partitioning( + server_id=1, + os_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + param_os_id = validate_path_param("os_id", os_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/partitioning/{param_os_id}", + ) + + self._throw_on_error(res) + return unmarshal_ServerDefaultPartitioning(res.json()) + + def start_bmc_access( + self, + *, + server_id: int, + ip: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Start BMC (Baseboard Management Controller) access for a given baremetal server. + Start BMC (Baseboard Management Controller) access associated with the given ID. + The BMC (Baseboard Management Controller) access is available one hour after the installation of the server. + :param server_id: ID of the server to start the BMC access. + :param ip: The IP authorized to connect to the given server. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.start_bmc_access( + server_id=1, + ip="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/bmc-access", + body=marshal_StartBMCAccessRequest( + StartBMCAccessRequest( + server_id=server_id, + ip=ip, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def get_bmc_access( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> BMCAccess: + """ + Get BMC (Baseboard Management Controller) access for a given baremetal server. + Get the BMC (Baseboard Management Controller) access associated with the given ID. + :param server_id: ID of the server to get BMC access. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`BMCAccess ` + + Usage: + :: + + result = api.get_bmc_access( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/bmc-access", + ) + + self._throw_on_error(res) + return unmarshal_BMCAccess(res.json()) + + def wait_for_bmc_access( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[BMCAccess, bool]] = None, + ) -> BMCAccess: + """ + Get BMC (Baseboard Management Controller) access for a given baremetal server. + Get the BMC (Baseboard Management Controller) access associated with the given ID. + :param server_id: ID of the server to get BMC access. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`BMCAccess ` + + Usage: + :: + + result = api.get_bmc_access( + server_id=1, + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in BMC_ACCESS_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_bmc_access, + options=options, + args={ + "server_id": server_id, + "zone": zone, + }, + ) + + def stop_bmc_access( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Stop BMC (Baseboard Management Controller) access for a given baremetal server. + Stop BMC (Baseboard Management Controller) access associated with the given ID. + :param server_id: ID of the server to stop BMC access. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.stop_bmc_access( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/bmc-access", + ) + + self._throw_on_error(res) + + def list_offers( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOffersRequestOrderBy] = None, + commercial_range: Optional[str] = None, + catalog: Optional[OfferCatalog] = None, + project_id: Optional[str] = None, + is_failover_ip: Optional[bool] = None, + is_failover_block: Optional[bool] = None, + sold_in: Optional[List[str]] = None, + available_only: Optional[bool] = None, + is_rpn_san: Optional[bool] = None, + ) -> ListOffersResponse: + """ + List offers. + List all available server offers. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of offer per page. + :param order_by: Order of the offers. + :param commercial_range: Filter on commercial range. + :param catalog: Filter on catalog. + :param project_id: Project ID. + :param is_failover_ip: Get the current failover IP offer. + :param is_failover_block: Get the current failover IP block offer. + :param sold_in: Filter offers depending on their datacenter. + :param available_only: Set this filter to true to only return available offers. + :param is_rpn_san: Get the RPN SAN offers. + :return: :class:`ListOffersResponse ` + + Usage: + :: + + result = api.list_offers() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/offers", + params={ + "available_only": available_only, + "catalog": catalog, + "commercial_range": commercial_range, + "is_failover_block": is_failover_block, + "is_failover_ip": is_failover_ip, + "is_rpn_san": is_rpn_san, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "sold_in": ",".join(sold_in) if sold_in and len(sold_in) > 0 else None, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListOffersResponse(res.json()) + + def list_offers_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOffersRequestOrderBy] = None, + commercial_range: Optional[str] = None, + catalog: Optional[OfferCatalog] = None, + project_id: Optional[str] = None, + is_failover_ip: Optional[bool] = None, + is_failover_block: Optional[bool] = None, + sold_in: Optional[List[str]] = None, + available_only: Optional[bool] = None, + is_rpn_san: Optional[bool] = None, + ) -> List[Offer]: + """ + List offers. + List all available server offers. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of offer per page. + :param order_by: Order of the offers. + :param commercial_range: Filter on commercial range. + :param catalog: Filter on catalog. + :param project_id: Project ID. + :param is_failover_ip: Get the current failover IP offer. + :param is_failover_block: Get the current failover IP block offer. + :param sold_in: Filter offers depending on their datacenter. + :param available_only: Set this filter to true to only return available offers. + :param is_rpn_san: Get the RPN SAN offers. + :return: :class:`List[Offer] ` + + Usage: + :: + + result = api.list_offers_all() + """ + + return fetch_all_pages( + type=ListOffersResponse, + key="offers", + fetcher=self.list_offers, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + "commercial_range": commercial_range, + "catalog": catalog, + "project_id": project_id, + "is_failover_ip": is_failover_ip, + "is_failover_block": is_failover_block, + "sold_in": sold_in, + "available_only": available_only, + "is_rpn_san": is_rpn_san, + }, + ) + + def get_offer( + self, + *, + offer_id: int, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + ) -> Offer: + """ + Get offer. + Return specific offer for the given ID. + :param offer_id: ID of offer. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID. + :return: :class:`Offer ` + + Usage: + :: + + result = api.get_offer( + offer_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_offer_id = validate_path_param("offer_id", offer_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/offers/{param_offer_id}", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Offer(res.json()) + + def list_os( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOSRequestOrderBy] = None, + type_: Optional[OSType] = None, + project_id: Optional[str] = None, + ) -> ListOSResponse: + """ + List all available OS that can be install on a baremetal server. + :param server_id: Filter OS by compatible server ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of OS per page. + :param order_by: Order of the OS. + :param type_: Type of the OS. + :param project_id: Project ID. + :return: :class:`ListOSResponse ` + + Usage: + :: + + result = api.list_os( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/os", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "server_id": server_id, + "type": type_, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListOSResponse(res.json()) + + def list_os_all( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOSRequestOrderBy] = None, + type_: Optional[OSType] = None, + project_id: Optional[str] = None, + ) -> List[OS]: + """ + List all available OS that can be install on a baremetal server. + :param server_id: Filter OS by compatible server ID. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of OS per page. + :param order_by: Order of the OS. + :param type_: Type of the OS. + :param project_id: Project ID. + :return: :class:`List[OS] ` + + Usage: + :: + + result = api.list_os_all( + server_id=1, + ) + """ + + return fetch_all_pages( + type=ListOSResponse, + key="os", + fetcher=self.list_os, + args={ + "server_id": server_id, + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + "type_": type_, + "project_id": project_id, + }, + ) + + def get_os( + self, + *, + os_id: int, + server_id: int, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + ) -> OS: + """ + Get an OS with a given ID. + Return specific OS for the given ID. + :param os_id: ID of the OS. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID. + :return: :class:`OS ` + + Usage: + :: + + result = api.get_os( + os_id=1, + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_os_id = validate_path_param("os_id", os_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/os/{param_os_id}", + params={ + "project_id": project_id or self.client.default_project_id, + "server_id": server_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_OS(res.json()) + + def update_reverse( + self, + *, + ip_id: int, + reverse: str, + zone: Optional[ScwZone] = None, + ) -> IP: + """ + Update reverse of ip. + Update reverse of ip associated with the given ID. + :param ip_id: ID of the IP. + :param reverse: Reverse to apply on the IP. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`IP ` + + Usage: + :: + + result = api.update_reverse( + ip_id=1, + reverse="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/zones/{param_zone}/reverses/{param_ip_id}", + body=marshal_UpdateReverseRequest( + UpdateReverseRequest( + ip_id=ip_id, + reverse=reverse, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + def create_failover_i_ps( + self, + *, + offer_id: int, + quantity: int, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + ) -> CreateFailoverIPsResponse: + """ + Order failover IPs. + Order X failover IPs. + :param offer_id: Failover IP offer ID. + :param quantity: Quantity. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID. + :return: :class:`CreateFailoverIPsResponse ` + + Usage: + :: + + result = api.create_failover_i_ps( + offer_id=1, + quantity=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/failover-ips", + body=marshal_CreateFailoverIPsRequest( + CreateFailoverIPsRequest( + offer_id=offer_id, + quantity=quantity, + zone=zone, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CreateFailoverIPsResponse(res.json()) + + def attach_failover_i_ps( + self, + *, + server_id: int, + fips_ids: List[int], + zone: Optional[ScwZone] = None, + ) -> None: + """ + Attach failovers on baremetal server. + Attach failovers on the server associated with the given ID. + :param server_id: ID of the server. + :param fips_ids: List of ID of failovers IP to attach. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.attach_failover_i_ps( + server_id=1, + fips_ids=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/failover-ips/attach", + body=marshal_AttachFailoverIPsRequest( + AttachFailoverIPsRequest( + server_id=server_id, + fips_ids=fips_ids, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def detach_failover_i_ps( + self, + *, + fips_ids: List[int], + zone: Optional[ScwZone] = None, + ) -> None: + """ + Detach failovers on baremetal server. + Detach failovers on the server associated with the given ID. + :param fips_ids: List of IDs of failovers IP to detach. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.detach_failover_i_ps( + fips_ids=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/failover-ips/detach", + body=marshal_DetachFailoverIPsRequest( + DetachFailoverIPsRequest( + fips_ids=fips_ids, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def attach_failover_ip_to_mac_address( + self, + *, + ip_id: int, + zone: Optional[ScwZone] = None, + type_: Optional[AttachFailoverIPToMacAddressRequestMacType] = None, + mac: Optional[str] = None, + ) -> IP: + """ + Attach a failover IP to a MAC address. + :param ip_id: ID of the failover IP. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param type_: A mac type. + :param mac: A valid mac address (existing or not). + :return: :class:`IP ` + + Usage: + :: + + result = api.attach_failover_ip_to_mac_address( + ip_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/failover-ips/{param_ip_id}/attach-to-mac-address", + body=marshal_AttachFailoverIPToMacAddressRequest( + AttachFailoverIPToMacAddressRequest( + ip_id=ip_id, + zone=zone, + type_=type_, + mac=mac, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + def detach_failover_ip_from_mac_address( + self, + *, + ip_id: int, + zone: Optional[ScwZone] = None, + ) -> IP: + """ + Detach a failover IP from a MAC address. + :param ip_id: ID of the failover IP. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`IP ` + + Usage: + :: + + result = api.detach_failover_ip_from_mac_address( + ip_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/failover-ips/{param_ip_id}/detach-from-mac-address", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + def delete_failover_ip( + self, + *, + ip_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a failover server. + Delete the failover associated with the given ID. + :param ip_id: ID of the failover IP to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_failover_ip( + ip_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/zones/{param_zone}/failover-ips/{param_ip_id}", + ) + + self._throw_on_error(res) + + def list_failover_i_ps( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListFailoverIPsRequestOrderBy] = None, + project_id: Optional[str] = None, + search: Optional[str] = None, + only_available: Optional[bool] = None, + ) -> ListFailoverIPsResponse: + """ + List failovers for project. + List failovers servers for project. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of failovers IP per page. + :param order_by: Order of the failovers IP. + :param project_id: Filter failovers IP by project ID. + :param search: Filter failovers IP which matching with this field. + :param only_available: True: return all failovers IP not attached on server + false: return all failovers IP attached on server. + :return: :class:`ListFailoverIPsResponse ` + + Usage: + :: + + result = api.list_failover_i_ps() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/failover-ips", + params={ + "only_available": only_available, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "search": search, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListFailoverIPsResponse(res.json()) + + def list_failover_i_ps_all( + self, + *, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListFailoverIPsRequestOrderBy] = None, + project_id: Optional[str] = None, + search: Optional[str] = None, + only_available: Optional[bool] = None, + ) -> List[FailoverIP]: + """ + List failovers for project. + List failovers servers for project. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param page: Page number. + :param page_size: Number of failovers IP per page. + :param order_by: Order of the failovers IP. + :param project_id: Filter failovers IP by project ID. + :param search: Filter failovers IP which matching with this field. + :param only_available: True: return all failovers IP not attached on server + false: return all failovers IP attached on server. + :return: :class:`List[FailoverIP] ` + + Usage: + :: + + result = api.list_failover_i_ps_all() + """ + + return fetch_all_pages( + type=ListFailoverIPsResponse, + key="failover_ips", + fetcher=self.list_failover_i_ps, + args={ + "zone": zone, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "search": search, + "only_available": only_available, + }, + ) + + def get_failover_ip( + self, + *, + ip_id: int, + zone: Optional[ScwZone] = None, + ) -> FailoverIP: + """ + Get a specific baremetal server. + Get the server associated with the given ID. + :param ip_id: ID of the failover IP. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`FailoverIP ` + + Usage: + :: + + result = api.get_failover_ip( + ip_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/failover-ips/{param_ip_id}", + ) + + self._throw_on_error(res) + return unmarshal_FailoverIP(res.json()) + + def get_remaining_quota( + self, + *, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + ) -> GetRemainingQuotaResponse: + """ + Get remaining quota. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project ID. + :return: :class:`GetRemainingQuotaResponse ` + + Usage: + :: + + result = api.get_remaining_quota() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/remaining-quota", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_GetRemainingQuotaResponse(res.json()) + + def get_raid( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> Raid: + """ + Get raid. + Return raid for the given server ID. + :param server_id: ID of the server. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Raid ` + + Usage: + :: + + result = api.get_raid( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/raid", + ) + + self._throw_on_error(res) + return unmarshal_Raid(res.json()) + + def update_raid( + self, + *, + server_id: int, + raid_arrays: List[UpdatableRaidArray], + zone: Optional[ScwZone] = None, + ) -> None: + """ + Update RAID. + Update RAID associated with the given server ID. + :param server_id: ID of the server. + :param raid_arrays: RAIDs to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.update_raid( + server_id=1, + raid_arrays=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/update-raid", + body=marshal_UpdateRaidRequest( + UpdateRaidRequest( + server_id=server_id, + raid_arrays=raid_arrays, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def start_rescue( + self, + *, + server_id: int, + os_id: int, + zone: Optional[ScwZone] = None, + ) -> Rescue: + """ + Start in rescue baremetal server. + Start in rescue the server associated with the given ID. + :param server_id: ID of the server to start rescue. + :param os_id: OS ID to use to start rescue. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Rescue ` + + Usage: + :: + + result = api.start_rescue( + server_id=1, + os_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/rescue", + body=marshal_StartRescueRequest( + StartRescueRequest( + server_id=server_id, + os_id=os_id, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Rescue(res.json()) + + def get_rescue( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> Rescue: + """ + Get rescue information. + Return rescue information for the given server ID. + :param server_id: ID of the server to get rescue. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Rescue ` + + Usage: + :: + + result = api.get_rescue( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/rescue", + ) + + self._throw_on_error(res) + return unmarshal_Rescue(res.json()) + + def stop_rescue( + self, + *, + server_id: int, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Stop rescue on baremetal server. + Stop rescue on the server associated with the given ID. + :param server_id: ID of the server to stop rescue. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.stop_rescue( + server_id=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/zones/{param_zone}/servers/{param_server_id}/rescue", + ) + + self._throw_on_error(res) + + +class DediboxV1BillingAPI(API): + """ + Dedibox Phoenix Billing API. + """ + + def list_invoices( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListInvoicesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListInvoicesResponse: + """ + :param page: + :param page_size: + :param order_by: + :param project_id: + :return: :class:`ListInvoicesResponse ` + + Usage: + :: + + result = api.list_invoices() + """ + + res = self._request( + "GET", + "/dedibox/v1/invoices", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInvoicesResponse(res.json()) + + def list_invoices_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListInvoicesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[InvoiceSummary]: + """ + :param page: + :param page_size: + :param order_by: + :param project_id: + :return: :class:`List[InvoiceSummary] ` + + Usage: + :: + + result = api.list_invoices_all() + """ + + return fetch_all_pages( + type=ListInvoicesResponse, + key="invoices", + fetcher=self.list_invoices, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def get_invoice( + self, + *, + invoice_id: int, + ) -> Invoice: + """ + :param invoice_id: + :return: :class:`Invoice ` + + Usage: + :: + + result = api.get_invoice( + invoice_id=1, + ) + """ + + param_invoice_id = validate_path_param("invoice_id", invoice_id) + + res = self._request( + "GET", + f"/dedibox/v1/invoices/{param_invoice_id}", + ) + + self._throw_on_error(res) + return unmarshal_Invoice(res.json()) + + def download_invoice( + self, + *, + invoice_id: int, + ) -> ScwFile: + """ + :param invoice_id: + :return: :class:`ScwFile ` + + Usage: + :: + + result = api.download_invoice( + invoice_id=1, + ) + """ + + param_invoice_id = validate_path_param("invoice_id", invoice_id) + + res = self._request( + "GET", + f"/dedibox/v1/invoices/{param_invoice_id}/download", + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + def list_refunds( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRefundsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRefundsResponse: + """ + :param page: + :param page_size: + :param order_by: + :param project_id: + :return: :class:`ListRefundsResponse ` + + Usage: + :: + + result = api.list_refunds() + """ + + res = self._request( + "GET", + "/dedibox/v1/refunds", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRefundsResponse(res.json()) + + def list_refunds_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRefundsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RefundSummary]: + """ + :param page: + :param page_size: + :param order_by: + :param project_id: + :return: :class:`List[RefundSummary] ` + + Usage: + :: + + result = api.list_refunds_all() + """ + + return fetch_all_pages( + type=ListRefundsResponse, + key="refunds", + fetcher=self.list_refunds, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def get_refund( + self, + *, + refund_id: int, + ) -> Refund: + """ + :param refund_id: + :return: :class:`Refund ` + + Usage: + :: + + result = api.get_refund( + refund_id=1, + ) + """ + + param_refund_id = validate_path_param("refund_id", refund_id) + + res = self._request( + "GET", + f"/dedibox/v1/refunds/{param_refund_id}", + ) + + self._throw_on_error(res) + return unmarshal_Refund(res.json()) + + def download_refund( + self, + *, + refund_id: int, + ) -> ScwFile: + """ + :param refund_id: + :return: :class:`ScwFile ` + + Usage: + :: + + result = api.download_refund( + refund_id=1, + ) + """ + + param_refund_id = validate_path_param("refund_id", refund_id) + + res = self._request( + "GET", + f"/dedibox/v1/refunds/{param_refund_id}/download", + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + def can_order( + self, + *, + project_id: Optional[str] = None, + ) -> CanOrderResponse: + """ + :param project_id: + :return: :class:`CanOrderResponse ` + + Usage: + :: + + result = api.can_order() + """ + + res = self._request( + "GET", + "/dedibox/v1/can-order", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_CanOrderResponse(res.json()) + + +class DediboxV1IPv6BlockAPI(API): + """ + Dedibox Phoenix IPv6 Block API. + """ + + def get_i_pv6_block_quotas( + self, + *, + project_id: Optional[str] = None, + ) -> GetIPv6BlockQuotasResponse: + """ + Get IPv6 block quota. + Get IPv6 block quota with the given project ID. + /48 one per organization. + /56 link to your number of server. + /64 link to your number of failover IP. + :param project_id: ID of the project. + :return: :class:`GetIPv6BlockQuotasResponse ` + + Usage: + :: + + result = api.get_i_pv6_block_quotas() + """ + + res = self._request( + "GET", + "/dedibox/v1/ipv6-block-quotas", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_GetIPv6BlockQuotasResponse(res.json()) + + def create_i_pv6_block( + self, + *, + project_id: Optional[str] = None, + ) -> IPv6Block: + """ + Create IPv6 block for baremetal server. + Create IPv6 block associated with the given project ID. + :param project_id: ID of the project. + :return: :class:`IPv6Block ` + + Usage: + :: + + result = api.create_i_pv6_block() + """ + + res = self._request( + "POST", + "/dedibox/v1/ipv6-block", + body=marshal_IPv6BlockApiCreateIPv6BlockRequest( + IPv6BlockApiCreateIPv6BlockRequest( + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IPv6Block(res.json()) + + def get_i_pv6_block( + self, + *, + project_id: Optional[str] = None, + ) -> IPv6Block: + """ + Get a specific IPv6 block. + Get the IPv6 block associated with the given ID. + :param project_id: ID of the project. + :return: :class:`IPv6Block ` + + Usage: + :: + + result = api.get_i_pv6_block() + """ + + res = self._request( + "GET", + "/dedibox/v1/ipv6-block", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_IPv6Block(res.json()) + + def update_i_pv6_block( + self, + *, + block_id: int, + nameservers: Optional[List[str]] = None, + ) -> IPv6Block: + """ + Update IPv6 block. + Update DNS associated to IPv6 block. + If DNS is used, minimum of 2 is necessary and maximum of 5 (no duplicate). + :param block_id: ID of the IPv6 block. + :param nameservers: DNS to link to the IPv6. + :return: :class:`IPv6Block ` + + Usage: + :: + + result = api.update_i_pv6_block( + block_id=1, + ) + """ + + param_block_id = validate_path_param("block_id", block_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/ipv6-blocks/{param_block_id}", + body=marshal_IPv6BlockApiUpdateIPv6BlockRequest( + IPv6BlockApiUpdateIPv6BlockRequest( + block_id=block_id, + nameservers=nameservers, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IPv6Block(res.json()) + + def delete_i_pv6_block( + self, + *, + block_id: int, + ) -> None: + """ + Delete IPv6 block. + Delete IPv6 block subnet with the given ID. + :param block_id: ID of the IPv6 block to delete. + + Usage: + :: + + result = api.delete_i_pv6_block( + block_id=1, + ) + """ + + param_block_id = validate_path_param("block_id", block_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/ipv6-blocks/{param_block_id}", + ) + + self._throw_on_error(res) + + def create_i_pv6_block_subnet( + self, + *, + block_id: int, + address: str, + cidr: int, + ) -> IPv6Block: + """ + Create IPv6 block subnet. + Create IPv6 block subnet for the given IP ID. + /48 could create subnet in /56 (quota link to your number of server). + /56 could create subnet in /64 (quota link to your number of failover IP). + :param block_id: ID of the IPv6 block. + :param address: Address of the IPv6. + :param cidr: Classless InterDomain Routing notation of the IPv6. + :return: :class:`IPv6Block ` + + Usage: + :: + + result = api.create_i_pv6_block_subnet( + block_id=1, + address="example", + cidr=1, + ) + """ + + param_block_id = validate_path_param("block_id", block_id) + + res = self._request( + "POST", + f"/dedibox/v1/ipv6-blocks/{param_block_id}/subnets", + body=marshal_IPv6BlockApiCreateIPv6BlockSubnetRequest( + IPv6BlockApiCreateIPv6BlockSubnetRequest( + block_id=block_id, + address=address, + cidr=cidr, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IPv6Block(res.json()) + + def list_i_pv6_block_subnets_available( + self, + *, + block_id: int, + ) -> ListIPv6BlockSubnetsAvailableResponse: + """ + List available IPv6 block subnets. + List all available IPv6 block subnets for given IP ID. + :param block_id: ID of the IPv6 block. + :return: :class:`ListIPv6BlockSubnetsAvailableResponse ` + + Usage: + :: + + result = api.list_i_pv6_block_subnets_available( + block_id=1, + ) + """ + + param_block_id = validate_path_param("block_id", block_id) + + res = self._request( + "GET", + f"/dedibox/v1/ipv6-blocks/{param_block_id}/subnets", + ) + + self._throw_on_error(res) + return unmarshal_ListIPv6BlockSubnetsAvailableResponse(res.json()) + + +class DediboxV1RpnAPI(API): + """ + Dedibox Phoenix RPN API. + """ + + def list_rpn_server_capabilities( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnServerCapabilitiesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnServerCapabilitiesResponse: + """ + :param page: Page number. + :param page_size: Number of servers per page. + :param order_by: Order of the servers. + :param project_id: Filter servers by project ID. + :return: :class:`ListRpnServerCapabilitiesResponse ` + + Usage: + :: + + result = api.list_rpn_server_capabilities() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpn/server-capabilities", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnServerCapabilitiesResponse(res.json()) + + def list_rpn_server_capabilities_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnServerCapabilitiesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnServerCapability]: + """ + :param page: Page number. + :param page_size: Number of servers per page. + :param order_by: Order of the servers. + :param project_id: Filter servers by project ID. + :return: :class:`List[RpnServerCapability] ` + + Usage: + :: + + result = api.list_rpn_server_capabilities_all() + """ + + return fetch_all_pages( + type=ListRpnServerCapabilitiesResponse, + key="servers", + fetcher=self.list_rpn_server_capabilities, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def get_rpn_status( + self, + *, + project_id: Optional[str] = None, + rpnv1_group_id: Optional[int] = None, + rpnv2_group_id: Optional[int] = None, + ) -> GetRpnStatusResponse: + """ + :param project_id: A project ID. + :param rpnv1_group_id: An RPN v1 group ID. + :param rpnv2_group_id: An RPN v2 group ID. + :return: :class:`GetRpnStatusResponse ` + + Usage: + :: + + result = api.get_rpn_status() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpn/status", + params={ + "project_id": project_id or self.client.default_project_id, + "rpnv1_group_id": rpnv1_group_id, + "rpnv2_group_id": rpnv2_group_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_GetRpnStatusResponse(res.json()) + + +class DediboxV1RpnSanAPI(API): + """ + Dedibox Phoenix RPN SAN API. + """ + + def list_rpn_sans( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnSansRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnSansResponse: + """ + :param page: Page number. + :param page_size: Number of RPN SANs per page. + :param order_by: Order of the RPN SANs. + :param project_id: Filter RPN SANs by project ID. + :return: :class:`ListRpnSansResponse ` + + Usage: + :: + + result = api.list_rpn_sans() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpn-sans", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnSansResponse(res.json()) + + def list_rpn_sans_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnSansRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnSanSummary]: + """ + :param page: Page number. + :param page_size: Number of RPN SANs per page. + :param order_by: Order of the RPN SANs. + :param project_id: Filter RPN SANs by project ID. + :return: :class:`List[RpnSanSummary] ` + + Usage: + :: + + result = api.list_rpn_sans_all() + """ + + return fetch_all_pages( + type=ListRpnSansResponse, + key="rpn_sans", + fetcher=self.list_rpn_sans, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def get_rpn_san( + self, + *, + rpn_san_id: int, + ) -> RpnSan: + """ + :param rpn_san_id: RPN SAN ID. + :return: :class:`RpnSan ` + + Usage: + :: + + result = api.get_rpn_san( + rpn_san_id=1, + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}", + ) + + self._throw_on_error(res) + return unmarshal_RpnSan(res.json()) + + def wait_for_rpn_san( + self, + *, + rpn_san_id: int, + options: Optional[WaitForOptions[RpnSan, bool]] = None, + ) -> RpnSan: + """ + :param rpn_san_id: RPN SAN ID. + :return: :class:`RpnSan ` + + Usage: + :: + + result = api.get_rpn_san( + rpn_san_id=1, + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in RPN_SAN_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_rpn_san, + options=options, + args={ + "rpn_san_id": rpn_san_id, + }, + ) + + def delete_rpn_san( + self, + *, + rpn_san_id: int, + ) -> None: + """ + :param rpn_san_id: RPN SAN ID. + + Usage: + :: + + result = api.delete_rpn_san( + rpn_san_id=1, + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}", + ) + + self._throw_on_error(res) + + def create_rpn_san( + self, + *, + offer_id: int, + project_id: Optional[str] = None, + ) -> Service: + """ + :param offer_id: Offer ID. + :param project_id: Your project ID. + :return: :class:`Service ` + + Usage: + :: + + result = api.create_rpn_san( + offer_id=1, + ) + """ + + res = self._request( + "POST", + "/dedibox/v1/rpn-sans", + body=marshal_RpnSanApiCreateRpnSanRequest( + RpnSanApiCreateRpnSanRequest( + offer_id=offer_id, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Service(res.json()) + + def list_ips( + self, + *, + rpn_san_id: int, + type_: Optional[RpnSanIpType] = None, + ) -> ListIpsResponse: + """ + :param rpn_san_id: RPN SAN ID. + :param type_: Filter by IP type (server | rpnv2_subnet). + :return: :class:`ListIpsResponse ` + + Usage: + :: + + result = api.list_ips( + rpn_san_id=1, + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}/ips", + params={ + "type": type_, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListIpsResponse(res.json()) + + def add_ip( + self, + *, + rpn_san_id: int, + ip_ids: List[int], + ) -> None: + """ + :param rpn_san_id: RPN SAN ID. + :param ip_ids: An array of IP ID. + + Usage: + :: + + result = api.add_ip( + rpn_san_id=1, + ip_ids=[], + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}/ips", + body=marshal_RpnSanApiAddIpRequest( + RpnSanApiAddIpRequest( + rpn_san_id=rpn_san_id, + ip_ids=ip_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def remove_ip( + self, + *, + rpn_san_id: int, + ip_ids: List[int], + ) -> None: + """ + :param rpn_san_id: RPN SAN ID. + :param ip_ids: An array of IP ID. + + Usage: + :: + + result = api.remove_ip( + rpn_san_id=1, + ip_ids=[], + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}/ips", + body=marshal_RpnSanApiRemoveIpRequest( + RpnSanApiRemoveIpRequest( + rpn_san_id=rpn_san_id, + ip_ids=ip_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def list_available_ips( + self, + *, + rpn_san_id: int, + type_: Optional[RpnSanIpType] = None, + ) -> ListIpsResponse: + """ + :param rpn_san_id: RPN SAN ID. + :param type_: Filter by IP type (server | rpnv2_subnet). + :return: :class:`ListIpsResponse ` + + Usage: + :: + + result = api.list_available_ips( + rpn_san_id=1, + ) + """ + + param_rpn_san_id = validate_path_param("rpn_san_id", rpn_san_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpn-sans/{param_rpn_san_id}/available-ips", + params={ + "type": type_, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListIpsResponse(res.json()) + + +class DediboxV1RpnV1API(API): + """ + Dedibox Phoenix RPN v1 API. + """ + + def list_rpn_groups( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnGroupsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnGroupsResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v1 groups per page. + :param order_by: Order of the rpn v1 groups. + :param project_id: Filter rpn v1 groups by project ID. + :return: :class:`ListRpnGroupsResponse ` + + Usage: + :: + + result = api.list_rpn_groups() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv1/groups", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnGroupsResponse(res.json()) + + def list_rpn_groups_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnGroupsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnGroup]: + """ + :param page: Page number. + :param page_size: Number of rpn v1 groups per page. + :param order_by: Order of the rpn v1 groups. + :param project_id: Filter rpn v1 groups by project ID. + :return: :class:`List[RpnGroup] ` + + Usage: + :: + + result = api.list_rpn_groups_all() + """ + + return fetch_all_pages( + type=ListRpnGroupsResponse, + key="rpn_groups", + fetcher=self.list_rpn_groups, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def get_rpn_group( + self, + *, + group_id: int, + ) -> RpnGroup: + """ + :param group_id: Rpn v1 group ID. + :return: :class:`RpnGroup ` + + Usage: + :: + + result = api.get_rpn_group( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpnv1/groups/{param_group_id}", + ) + + self._throw_on_error(res) + return unmarshal_RpnGroup(res.json()) + + def create_rpn_group( + self, + *, + name: str, + server_ids: Optional[List[int]] = None, + san_server_ids: Optional[List[int]] = None, + project_id: Optional[str] = None, + ) -> RpnGroup: + """ + :param name: Rpn v1 group name. + :param server_ids: A collection of rpn v1 capable servers. + :param san_server_ids: A collection of rpn v1 capable rpn sans servers. + :param project_id: A project ID. + :return: :class:`RpnGroup ` + + Usage: + :: + + result = api.create_rpn_group( + name="example", + ) + """ + + res = self._request( + "POST", + "/dedibox/v1/rpnv1/groups", + body=marshal_RpnV1ApiCreateRpnGroupRequest( + RpnV1ApiCreateRpnGroupRequest( + name=name, + server_ids=server_ids, + san_server_ids=san_server_ids, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnGroup(res.json()) + + def delete_rpn_group( + self, + *, + group_id: int, + ) -> None: + """ + :param group_id: Rpn v1 group ID. + + Usage: + :: + + result = api.delete_rpn_group( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpnv1/groups/{param_group_id}", + ) + + self._throw_on_error(res) + + def update_rpn_group_name( + self, + *, + group_id: int, + name: Optional[str] = None, + ) -> RpnGroup: + """ + :param group_id: Rpn v1 group ID. + :param name: New rpn v1 group name. + :return: :class:`RpnGroup ` + + Usage: + :: + + result = api.update_rpn_group_name( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/rpnv1/groups/{param_group_id}", + body=marshal_RpnV1ApiUpdateRpnGroupNameRequest( + RpnV1ApiUpdateRpnGroupNameRequest( + group_id=group_id, + name=name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnGroup(res.json()) + + def list_rpn_group_members( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnGroupMembersRequestOrderBy] = None, + group_id: int, + project_id: Optional[str] = None, + ) -> ListRpnGroupMembersResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v1 group members per page. + :param order_by: Order of the rpn v1 group members. + :param group_id: Filter rpn v1 group members by group ID. + :param project_id: A project ID. + :return: :class:`ListRpnGroupMembersResponse ` + + Usage: + :: + + result = api.list_rpn_group_members( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpnv1/groups/{param_group_id}/members", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnGroupMembersResponse(res.json()) + + def list_rpn_group_members_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnGroupMembersRequestOrderBy] = None, + group_id: int, + project_id: Optional[str] = None, + ) -> List[RpnGroupMember]: + """ + :param page: Page number. + :param page_size: Number of rpn v1 group members per page. + :param order_by: Order of the rpn v1 group members. + :param group_id: Filter rpn v1 group members by group ID. + :param project_id: A project ID. + :return: :class:`List[RpnGroupMember] ` + + Usage: + :: + + result = api.list_rpn_group_members_all( + group_id=1, + ) + """ + + return fetch_all_pages( + type=ListRpnGroupMembersResponse, + key="members", + fetcher=self.list_rpn_group_members, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "group_id": group_id, + "project_id": project_id, + }, + ) + + def rpn_group_invite( + self, + *, + group_id: int, + server_ids: List[int], + project_id: Optional[str] = None, + ) -> None: + """ + :param group_id: The RPN V1 group ID. + :param server_ids: A collection of external server IDs. + :param project_id: A project ID. + + Usage: + :: + + result = api.rpn_group_invite( + group_id=1, + server_ids=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv1/groups/{param_group_id}/invite", + body=marshal_RpnV1ApiRpnGroupInviteRequest( + RpnV1ApiRpnGroupInviteRequest( + group_id=group_id, + server_ids=server_ids, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def leave_rpn_group( + self, + *, + group_id: int, + member_ids: List[int], + project_id: Optional[str] = None, + ) -> None: + """ + :param group_id: The RPN V1 group ID. + :param member_ids: A collection of rpn v1 group members IDs. + :param project_id: A project ID. + + Usage: + :: + + result = api.leave_rpn_group( + group_id=1, + member_ids=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv1/groups/{param_group_id}/leave", + body=marshal_RpnV1ApiLeaveRpnGroupRequest( + RpnV1ApiLeaveRpnGroupRequest( + group_id=group_id, + member_ids=member_ids, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def add_rpn_group_members( + self, + *, + group_id: int, + server_ids: Optional[List[int]] = None, + san_server_ids: Optional[List[int]] = None, + ) -> RpnGroup: + """ + :param group_id: The rpn v1 group ID. + :param server_ids: A collection of rpn v1 capable server IDs. + :param san_server_ids: A collection of rpn v1 capable RPN SAN server IDs. + :return: :class:`RpnGroup ` + + Usage: + :: + + result = api.add_rpn_group_members( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv1/groups/{param_group_id}/members", + body=marshal_RpnV1ApiAddRpnGroupMembersRequest( + RpnV1ApiAddRpnGroupMembersRequest( + group_id=group_id, + server_ids=server_ids, + san_server_ids=san_server_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnGroup(res.json()) + + def delete_rpn_group_members( + self, + *, + group_id: int, + member_ids: List[int], + ) -> RpnGroup: + """ + :param group_id: The rpn v1 group ID. + :param member_ids: A collection of rpn v1 group members IDs. + :return: :class:`RpnGroup ` + + Usage: + :: + + result = api.delete_rpn_group_members( + group_id=1, + member_ids=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpnv1/groups/{param_group_id}/members", + body=marshal_RpnV1ApiDeleteRpnGroupMembersRequest( + RpnV1ApiDeleteRpnGroupMembersRequest( + group_id=group_id, + member_ids=member_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnGroup(res.json()) + + def list_rpn_capable_servers( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnCapableServersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnCapableServersResponse: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`ListRpnCapableServersResponse ` + + Usage: + :: + + result = api.list_rpn_capable_servers() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv1/capable-servers", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnCapableServersResponse(res.json()) + + def list_rpn_capable_servers_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnCapableServersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[Server]: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`List[Server] ` + + Usage: + :: + + result = api.list_rpn_capable_servers_all() + """ + + return fetch_all_pages( + type=ListRpnCapableServersResponse, + key="servers", + fetcher=self.list_rpn_capable_servers, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def list_rpn_capable_san_servers( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnCapableSanServersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnCapableSanServersResponse: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`ListRpnCapableSanServersResponse ` + + Usage: + :: + + result = api.list_rpn_capable_san_servers() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv1/capable-san-servers", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnCapableSanServersResponse(res.json()) + + def list_rpn_capable_san_servers_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnCapableSanServersRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnSanServer]: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`List[RpnSanServer] ` + + Usage: + :: + + result = api.list_rpn_capable_san_servers_all() + """ + + return fetch_all_pages( + type=ListRpnCapableSanServersResponse, + key="san_servers", + fetcher=self.list_rpn_capable_san_servers, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def list_rpn_invites( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnInvitesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnInvitesResponse: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`ListRpnInvitesResponse ` + + Usage: + :: + + result = api.list_rpn_invites() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv1/invites", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnInvitesResponse(res.json()) + + def list_rpn_invites_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnInvitesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnGroupMember]: + """ + :param page: Page number. + :param page_size: Number of rpn capable resources per page. + :param order_by: Order of the rpn capable resources. + :param project_id: Filter rpn capable resources by project ID. + :return: :class:`List[RpnGroupMember] ` + + Usage: + :: + + result = api.list_rpn_invites_all() + """ + + return fetch_all_pages( + type=ListRpnInvitesResponse, + key="members", + fetcher=self.list_rpn_invites, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def accept_rpn_invite( + self, + *, + member_id: int, + ) -> None: + """ + :param member_id: The member ID. + + Usage: + :: + + result = api.accept_rpn_invite( + member_id=1, + ) + """ + + param_member_id = validate_path_param("member_id", member_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv1/invites/{param_member_id}/accept", + ) + + self._throw_on_error(res) + + def refuse_rpn_invite( + self, + *, + member_id: int, + ) -> None: + """ + :param member_id: The member ID. + + Usage: + :: + + result = api.refuse_rpn_invite( + member_id=1, + ) + """ + + param_member_id = validate_path_param("member_id", member_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv1/invites/{param_member_id}/refuse", + ) + + self._throw_on_error(res) + + +class DediboxV1RpnV2API(API): + """ + Dedibox Phoenix RPN v2 API. + """ + + def list_rpn_v2_groups( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2GroupsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnV2GroupsResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v2 groups per page. + :param order_by: Order of the rpn v2 groups. + :param project_id: Filter rpn v2 groups by project ID. + :return: :class:`ListRpnV2GroupsResponse ` + + Usage: + :: + + result = api.list_rpn_v2_groups() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv2/groups", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnV2GroupsResponse(res.json()) + + def list_rpn_v2_groups_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2GroupsRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[RpnV2Group]: + """ + :param page: Page number. + :param page_size: Number of rpn v2 groups per page. + :param order_by: Order of the rpn v2 groups. + :param project_id: Filter rpn v2 groups by project ID. + :return: :class:`List[RpnV2Group] ` + + Usage: + :: + + result = api.list_rpn_v2_groups_all() + """ + + return fetch_all_pages( + type=ListRpnV2GroupsResponse, + key="rpn_groups", + fetcher=self.list_rpn_v2_groups, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def list_rpn_v2_members( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2MembersRequestOrderBy] = None, + group_id: int, + type_: Optional[ListRpnV2MembersRequestType] = None, + ) -> ListRpnV2MembersResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v2 group members per page. + :param order_by: Order of the rpn v2 group members. + :param group_id: RPN V2 group ID. + :param type_: Filter members by type. + :return: :class:`ListRpnV2MembersResponse ` + + Usage: + :: + + result = api.list_rpn_v2_members( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/members", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "type": type_, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnV2MembersResponse(res.json()) + + def list_rpn_v2_members_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2MembersRequestOrderBy] = None, + group_id: int, + type_: Optional[ListRpnV2MembersRequestType] = None, + ) -> List[RpnV2Member]: + """ + :param page: Page number. + :param page_size: Number of rpn v2 group members per page. + :param order_by: Order of the rpn v2 group members. + :param group_id: RPN V2 group ID. + :param type_: Filter members by type. + :return: :class:`List[RpnV2Member] ` + + Usage: + :: + + result = api.list_rpn_v2_members_all( + group_id=1, + ) + """ + + return fetch_all_pages( + type=ListRpnV2MembersResponse, + key="members", + fetcher=self.list_rpn_v2_members, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "group_id": group_id, + "type_": type_, + }, + ) + + def get_rpn_v2_group( + self, + *, + group_id: int, + ) -> RpnV2Group: + """ + :param group_id: RPN V2 group ID. + :return: :class:`RpnV2Group ` + + Usage: + :: + + result = api.get_rpn_v2_group( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpnv2/groups/{param_group_id}", + ) + + self._throw_on_error(res) + return unmarshal_RpnV2Group(res.json()) + + def wait_for_rpn_v2_group( + self, + *, + group_id: int, + options: Optional[WaitForOptions[RpnV2Group, bool]] = None, + ) -> RpnV2Group: + """ + :param group_id: RPN V2 group ID. + :return: :class:`RpnV2Group ` + + Usage: + :: + + result = api.get_rpn_v2_group( + group_id=1, + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in RPN_V2_GROUP_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_rpn_v2_group, + options=options, + args={ + "group_id": group_id, + }, + ) + + def create_rpn_v2_group( + self, + *, + name: str, + servers: List[int], + project_id: Optional[str] = None, + type_: Optional[RpnV2GroupType] = None, + ) -> RpnV2Group: + """ + :param name: RPN V2 group name. + :param servers: A collection of server IDs. + :param project_id: Project ID of the RPN V2 group. + :param type_: RPN V2 group type (qing / standard). + :return: :class:`RpnV2Group ` + + Usage: + :: + + result = api.create_rpn_v2_group( + name="example", + servers=[], + ) + """ + + res = self._request( + "POST", + "/dedibox/v1/rpnv2/groups", + body=marshal_RpnV2ApiCreateRpnV2GroupRequest( + RpnV2ApiCreateRpnV2GroupRequest( + name=name, + servers=servers, + project_id=project_id, + type_=type_, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnV2Group(res.json()) + + def delete_rpn_v2_group( + self, + *, + group_id: int, + ) -> None: + """ + :param group_id: RPN V2 group ID. + + Usage: + :: + + result = api.delete_rpn_v2_group( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpnv2/groups/{param_group_id}", + ) + + self._throw_on_error(res) + + def update_rpn_v2_group_name( + self, + *, + group_id: int, + name: Optional[str] = None, + ) -> RpnV2Group: + """ + :param group_id: RPN V2 group ID. + :param name: RPN V2 group name. + :return: :class:`RpnV2Group ` + + Usage: + :: + + result = api.update_rpn_v2_group_name( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/rpnv2/groups/{param_group_id}", + body=marshal_RpnV2ApiUpdateRpnV2GroupNameRequest( + RpnV2ApiUpdateRpnV2GroupNameRequest( + group_id=group_id, + name=name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RpnV2Group(res.json()) + + def add_rpn_v2_members( + self, + *, + group_id: int, + servers: List[int], + ) -> None: + """ + :param group_id: RPN V2 group ID. + :param servers: A collection of server IDs. + + Usage: + :: + + result = api.add_rpn_v2_members( + group_id=1, + servers=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/members", + body=marshal_RpnV2ApiAddRpnV2MembersRequest( + RpnV2ApiAddRpnV2MembersRequest( + group_id=group_id, + servers=servers, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def delete_rpn_v2_members( + self, + *, + group_id: int, + member_ids: List[int], + ) -> None: + """ + :param group_id: RPN V2 group ID. + :param member_ids: A collection of member IDs. + + Usage: + :: + + result = api.delete_rpn_v2_members( + group_id=1, + member_ids=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "DELETE", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/members", + body=marshal_RpnV2ApiDeleteRpnV2MembersRequest( + RpnV2ApiDeleteRpnV2MembersRequest( + group_id=group_id, + member_ids=member_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def list_rpn_v2_capable_resources( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2CapableResourcesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> ListRpnV2CapableResourcesResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v2 capable resources per page. + :param order_by: Order of the rpn v2 capable resources. + :param project_id: Filter rpn v2 capable resources by project ID. + :return: :class:`ListRpnV2CapableResourcesResponse ` + + Usage: + :: + + result = api.list_rpn_v2_capable_resources() + """ + + res = self._request( + "GET", + "/dedibox/v1/rpnv2/groups/capable", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnV2CapableResourcesResponse(res.json()) + + def list_rpn_v2_capable_resources_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2CapableResourcesRequestOrderBy] = None, + project_id: Optional[str] = None, + ) -> List[Server]: + """ + :param page: Page number. + :param page_size: Number of rpn v2 capable resources per page. + :param order_by: Order of the rpn v2 capable resources. + :param project_id: Filter rpn v2 capable resources by project ID. + :return: :class:`List[Server] ` + + Usage: + :: + + result = api.list_rpn_v2_capable_resources_all() + """ + + return fetch_all_pages( + type=ListRpnV2CapableResourcesResponse, + key="servers", + fetcher=self.list_rpn_v2_capable_resources, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + }, + ) + + def list_rpn_v2_group_logs( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2GroupLogsRequestOrderBy] = None, + group_id: int, + ) -> ListRpnV2GroupLogsResponse: + """ + :param page: Page number. + :param page_size: Number of rpn v2 group logs per page. + :param order_by: Order of the rpn v2 group logs. + :param group_id: RPN V2 group ID. + :return: :class:`ListRpnV2GroupLogsResponse ` + + Usage: + :: + + result = api.list_rpn_v2_group_logs( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "GET", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/logs", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRpnV2GroupLogsResponse(res.json()) + + def list_rpn_v2_group_logs_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListRpnV2GroupLogsRequestOrderBy] = None, + group_id: int, + ) -> List[Log]: + """ + :param page: Page number. + :param page_size: Number of rpn v2 group logs per page. + :param order_by: Order of the rpn v2 group logs. + :param group_id: RPN V2 group ID. + :return: :class:`List[Log] ` + + Usage: + :: + + result = api.list_rpn_v2_group_logs_all( + group_id=1, + ) + """ + + return fetch_all_pages( + type=ListRpnV2GroupLogsResponse, + key="logs", + fetcher=self.list_rpn_v2_group_logs, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "group_id": group_id, + }, + ) + + def update_rpn_v2_vlan_for_members( + self, + *, + group_id: int, + member_ids: List[int], + vlan: Optional[int] = None, + ) -> None: + """ + :param group_id: RPN V2 group ID. + :param member_ids: RPN V2 member IDs. + :param vlan: Min: 0. + Max: 3967. + + Usage: + :: + + result = api.update_rpn_v2_vlan_for_members( + group_id=1, + member_ids=[], + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "PATCH", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/vlan", + body=marshal_RpnV2ApiUpdateRpnV2VlanForMembersRequest( + RpnV2ApiUpdateRpnV2VlanForMembersRequest( + group_id=group_id, + member_ids=member_ids, + vlan=vlan, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def enable_rpn_v2_group_compatibility( + self, + *, + group_id: int, + rpnv1_group_id: int, + ) -> None: + """ + :param group_id: RPN V2 group ID. + :param rpnv1_group_id: RPN V1 group ID. + + Usage: + :: + + result = api.enable_rpn_v2_group_compatibility( + group_id=1, + rpnv1_group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/enable-compatibility", + body=marshal_RpnV2ApiEnableRpnV2GroupCompatibilityRequest( + RpnV2ApiEnableRpnV2GroupCompatibilityRequest( + group_id=group_id, + rpnv1_group_id=rpnv1_group_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def disable_rpn_v2_group_compatibility( + self, + *, + group_id: int, + ) -> None: + """ + :param group_id: RPN V2 group ID. + + Usage: + :: + + result = api.disable_rpn_v2_group_compatibility( + group_id=1, + ) + """ + + param_group_id = validate_path_param("group_id", group_id) + + res = self._request( + "POST", + f"/dedibox/v1/rpnv2/groups/{param_group_id}/disable-compatibility", + body={}, + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/dedibox/v1/content.py b/scaleway/scaleway/dedibox/v1/content.py new file mode 100644 index 00000000..44306732 --- /dev/null +++ b/scaleway/scaleway/dedibox/v1/content.py @@ -0,0 +1,86 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + BMCAccessStatus, + IPv6BlockDelegationStatus, + RpnGroupMemberStatus, + RpnSanStatus, + RpnV2GroupStatus, + RpnV2MemberStatus, + ServerInstallStatus, + ServerStatus, + ServiceProvisioningStatus, +) + +BMC_ACCESS_TRANSIENT_STATUSES: List[BMCAccessStatus] = [ + BMCAccessStatus.CREATING, + BMCAccessStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`BMCAccessStatus `. +""" +I_PV6_BLOCK_DELEGATION_TRANSIENT_STATUSES: List[IPv6BlockDelegationStatus] = [ + IPv6BlockDelegationStatus.UPDATING, +] +""" +Lists transient statutes of the enum :class:`IPv6BlockDelegationStatus `. +""" +RPN_GROUP_MEMBER_TRANSIENT_STATUSES: List[RpnGroupMemberStatus] = [ + RpnGroupMemberStatus.CREATING, + RpnGroupMemberStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`RpnGroupMemberStatus `. +""" +RPN_SAN_TRANSIENT_STATUSES: List[RpnSanStatus] = [ + RpnSanStatus.CREATING, + RpnSanStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`RpnSanStatus `. +""" +RPN_V2_GROUP_TRANSIENT_STATUSES: List[RpnV2GroupStatus] = [ + RpnV2GroupStatus.CREATING, + RpnV2GroupStatus.UPDATING, + RpnV2GroupStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`RpnV2GroupStatus `. +""" +RPN_V2_MEMBER_TRANSIENT_STATUSES: List[RpnV2MemberStatus] = [ + RpnV2MemberStatus.CREATING, + RpnV2MemberStatus.UPDATING, + RpnV2MemberStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`RpnV2MemberStatus `. +""" +SERVER_INSTALL_TRANSIENT_STATUSES: List[ServerInstallStatus] = [ + ServerInstallStatus.BOOTING, + ServerInstallStatus.SETTING_UP_RAID, + ServerInstallStatus.PARTITIONING, + ServerInstallStatus.FORMATTING, + ServerInstallStatus.INSTALLING, + ServerInstallStatus.CONFIGURING, + ServerInstallStatus.CONFIGURING_BOOTLOADER, + ServerInstallStatus.REBOOTING, +] +""" +Lists transient statutes of the enum :class:`ServerInstallStatus `. +""" +SERVER_TRANSIENT_STATUSES: List[ServerStatus] = [ + ServerStatus.DELIVERING, + ServerStatus.INSTALLING, +] +""" +Lists transient statutes of the enum :class:`ServerStatus `. +""" +SERVICE_PROVISIONING_TRANSIENT_STATUSES: List[ServiceProvisioningStatus] = [ + ServiceProvisioningStatus.DELIVERING, + ServiceProvisioningStatus.EXPIRING, +] +""" +Lists transient statutes of the enum :class:`ServiceProvisioningStatus `. +""" diff --git a/scaleway/scaleway/dedibox/v1/marshalling.py b/scaleway/scaleway/dedibox/v1/marshalling.py new file mode 100644 index 00000000..8bdd9b9b --- /dev/null +++ b/scaleway/scaleway/dedibox/v1/marshalling.py @@ -0,0 +1,3725 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from .types import ( + OfferServerInfoStock, + PartitionFileSystem, + IP, + CPU, + Disk, + Memory, + PersistentMemory, + RaidController, + OfferAntiDosInfo, + OfferBackupInfo, + OfferBandwidthInfo, + OfferFailoverBlockInfo, + OfferFailoverIpInfo, + OfferLicenseInfo, + OfferRPNInfo, + OfferSANInfo, + OfferServerInfo, + OfferServiceLevelInfo, + OfferStorageInfo, + Offer, + OS, + RpnSan, + RpnGroup, + NetworkInterface, + ServerLocation, + ServerOption, + ServiceLevel, + Server, + RpnV2GroupSubnet, + RpnV2Group, + Service, + FailoverBlock, + FailoverIP, + BMCAccess, + Backup, + CanOrderResponse, + CreateFailoverIPsResponse, + GetIPv6BlockQuotasResponseQuota, + GetIPv6BlockQuotasResponse, + GetRemainingQuotaResponse, + GetRpnStatusResponse, + IPv6Block, + Invoice, + ListFailoverIPsResponse, + ListIPv6BlockSubnetsAvailableResponseSubnet, + ListIPv6BlockSubnetsAvailableResponse, + InvoiceSummary, + ListInvoicesResponse, + RpnSanIpRpnV2Group, + RpnSanIpServer, + RpnSanIp, + ListIpsResponse, + ListOSResponse, + ListOffersResponse, + RefundSummary, + ListRefundsResponse, + RpnSanServer, + ListRpnCapableSanServersResponse, + ListRpnCapableServersResponse, + RpnGroupMember, + ListRpnGroupMembersResponse, + ListRpnGroupsResponse, + ListRpnInvitesResponse, + RpnSanSummary, + ListRpnSansResponse, + RpnServerCapability, + ListRpnServerCapabilitiesResponse, + ListRpnV2CapableResourcesResponse, + RpnV2Member, + Log, + ListRpnV2GroupLogsResponse, + ListRpnV2GroupsResponse, + ListRpnV2MembersResponse, + ServerDisk, + ListServerDisksResponse, + ServerEvent, + ListServerEventsResponse, + ServerSummary, + ListServersResponse, + ListServicesResponse, + ListSubscribableServerOptionsResponse, + RaidArray, + Raid, + Refund, + Rescue, + Partition, + ServerDefaultPartitioning, + ServerInstall, + SubscribeStorageOptionsResponse, + AttachFailoverIPToMacAddressRequest, + AttachFailoverIPsRequest, + CreateFailoverIPsRequest, + CreateServerRequest, + DetachFailoverIPsRequest, + IPv6BlockApiCreateIPv6BlockRequest, + IPv6BlockApiCreateIPv6BlockSubnetRequest, + IPv6BlockApiUpdateIPv6BlockRequest, + InstallPartition, + InstallServerRequest, + RpnSanApiAddIpRequest, + RpnSanApiCreateRpnSanRequest, + RpnSanApiRemoveIpRequest, + RpnV1ApiAddRpnGroupMembersRequest, + RpnV1ApiCreateRpnGroupRequest, + RpnV1ApiDeleteRpnGroupMembersRequest, + RpnV1ApiLeaveRpnGroupRequest, + RpnV1ApiRpnGroupInviteRequest, + RpnV1ApiUpdateRpnGroupNameRequest, + RpnV2ApiAddRpnV2MembersRequest, + RpnV2ApiCreateRpnV2GroupRequest, + RpnV2ApiDeleteRpnV2MembersRequest, + RpnV2ApiEnableRpnV2GroupCompatibilityRequest, + RpnV2ApiUpdateRpnV2GroupNameRequest, + RpnV2ApiUpdateRpnV2VlanForMembersRequest, + StartBMCAccessRequest, + StartRescueRequest, + SubscribeServerOptionRequest, + SubscribeStorageOptionsRequest, + UpdatableRaidArray, + UpdateRaidRequest, + UpdateReverseRequest, + UpdateServerBackupRequest, + UpdateServerRequest, + UpdateServerTagsRequest, +) + + +def unmarshal_IP(data: Any) -> IP: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'IP' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("ip_id", None) + if field is not None: + args["ip_id"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("reverse", None) + if field is not None: + args["reverse"] = field + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + field = data.get("netmask", None) + if field is not None: + args["netmask"] = field + + field = data.get("semantic", None) + if field is not None: + args["semantic"] = field + + field = data.get("gateway", None) + if field is not None: + args["gateway"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + return IP(**args) + + +def unmarshal_CPU(data: Any) -> CPU: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CPU' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("core_count", None) + if field is not None: + args["core_count"] = field + + field = data.get("thread_count", None) + if field is not None: + args["thread_count"] = field + + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + + return CPU(**args) + + +def unmarshal_Disk(data: Any) -> Disk: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Disk' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return Disk(**args) + + +def unmarshal_Memory(data: Any) -> Memory: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Memory' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + + field = data.get("is_ecc", None) + if field is not None: + args["is_ecc"] = field + + return Memory(**args) + + +def unmarshal_PersistentMemory(data: Any) -> PersistentMemory: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PersistentMemory' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = field + + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + + field = data.get("model", None) + if field is not None: + args["model"] = field + + return PersistentMemory(**args) + + +def unmarshal_RaidController(data: Any) -> RaidController: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RaidController' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("model", None) + if field is not None: + args["model"] = field + + field = data.get("raid_level", None) + if field is not None: + args["raid_level"] = field + + return RaidController(**args) + + +def unmarshal_OfferAntiDosInfo(data: Any) -> OfferAntiDosInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferAntiDosInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return OfferAntiDosInfo(**args) + + +def unmarshal_OfferBackupInfo(data: Any) -> OfferBackupInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferBackupInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("size", None) + if field is not None: + args["size"] = field + + return OfferBackupInfo(**args) + + +def unmarshal_OfferBandwidthInfo(data: Any) -> OfferBandwidthInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferBandwidthInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("speed", None) + if field is not None: + args["speed"] = field + + return OfferBandwidthInfo(**args) + + +def unmarshal_OfferFailoverBlockInfo(data: Any) -> OfferFailoverBlockInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferFailoverBlockInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("onetime_fees", None) + if field is not None: + args["onetime_fees"] = unmarshal_Offer(field) + else: + args["onetime_fees"] = None + + return OfferFailoverBlockInfo(**args) + + +def unmarshal_OfferFailoverIpInfo(data: Any) -> OfferFailoverIpInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferFailoverIpInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("onetime_fees", None) + if field is not None: + args["onetime_fees"] = unmarshal_Offer(field) + else: + args["onetime_fees"] = None + + return OfferFailoverIpInfo(**args) + + +def unmarshal_OfferLicenseInfo(data: Any) -> OfferLicenseInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferLicenseInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bound_to_ip", None) + if field is not None: + args["bound_to_ip"] = field + + return OfferLicenseInfo(**args) + + +def unmarshal_OfferRPNInfo(data: Any) -> OfferRPNInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferRPNInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("speed", None) + if field is not None: + args["speed"] = field + + return OfferRPNInfo(**args) + + +def unmarshal_OfferSANInfo(data: Any) -> OfferSANInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferSANInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("ha", None) + if field is not None: + args["ha"] = field + + field = data.get("device_type", None) + if field is not None: + args["device_type"] = field + + return OfferSANInfo(**args) + + +def unmarshal_OfferServerInfo(data: Any) -> OfferServerInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferServerInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bandwidth", None) + if field is not None: + args["bandwidth"] = field + + field = data.get("stock", None) + if field is not None: + args["stock"] = field + + field = data.get("commercial_range", None) + if field is not None: + args["commercial_range"] = field + + field = data.get("disks", None) + if field is not None: + args["disks"] = ( + [unmarshal_Disk(v) for v in field] if field is not None else None + ) + + field = data.get("cpus", None) + if field is not None: + args["cpus"] = [unmarshal_CPU(v) for v in field] if field is not None else None + + field = data.get("memories", None) + if field is not None: + args["memories"] = ( + [unmarshal_Memory(v) for v in field] if field is not None else None + ) + + field = data.get("persistent_memories", None) + if field is not None: + args["persistent_memories"] = ( + [unmarshal_PersistentMemory(v) for v in field] + if field is not None + else None + ) + + field = data.get("raid_controllers", None) + if field is not None: + args["raid_controllers"] = ( + [unmarshal_RaidController(v) for v in field] if field is not None else None + ) + + field = data.get("available_options", None) + if field is not None: + args["available_options"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + field = data.get("connectivity", None) + if field is not None: + args["connectivity"] = field + + field = data.get("stock_by_datacenter", None) + if field is not None: + args["stock_by_datacenter"] = ( + {key: OfferServerInfoStock(value) for key, value in field.items()} + if field is not None + else None + ) + + field = data.get("rpn_version", None) + if field is not None: + args["rpn_version"] = field + else: + args["rpn_version"] = None + + field = data.get("onetime_fees", None) + if field is not None: + args["onetime_fees"] = unmarshal_Offer(field) + else: + args["onetime_fees"] = None + + return OfferServerInfo(**args) + + +def unmarshal_OfferServiceLevelInfo(data: Any) -> OfferServiceLevelInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferServiceLevelInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("support_ticket", None) + if field is not None: + args["support_ticket"] = field + + field = data.get("support_phone", None) + if field is not None: + args["support_phone"] = field + + field = data.get("sales_support", None) + if field is not None: + args["sales_support"] = field + + field = data.get("git", None) + if field is not None: + args["git"] = field + + field = data.get("sla", None) + if field is not None: + args["sla"] = field + + field = data.get("priority_support", None) + if field is not None: + args["priority_support"] = field + + field = data.get("high_rpn_bandwidth", None) + if field is not None: + args["high_rpn_bandwidth"] = field + + field = data.get("customization", None) + if field is not None: + args["customization"] = field + + field = data.get("antidos", None) + if field is not None: + args["antidos"] = field + + field = data.get("extra_failover_quota", None) + if field is not None: + args["extra_failover_quota"] = field + + field = data.get("available_options", None) + if field is not None: + args["available_options"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return OfferServiceLevelInfo(**args) + + +def unmarshal_OfferStorageInfo(data: Any) -> OfferStorageInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferStorageInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("max_quota", None) + if field is not None: + args["max_quota"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + return OfferStorageInfo(**args) + + +def unmarshal_Offer(data: Any) -> Offer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Offer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("catalog", None) + if field is not None: + args["catalog"] = field + + field = data.get("payment_frequency", None) + if field is not None: + args["payment_frequency"] = field + + field = data.get("pricing", None) + if field is not None: + args["pricing"] = unmarshal_Money(field) + else: + args["pricing"] = None + + field = data.get("server_info", None) + if field is not None: + args["server_info"] = unmarshal_OfferServerInfo(field) + else: + args["server_info"] = None + + field = data.get("service_level_info", None) + if field is not None: + args["service_level_info"] = unmarshal_OfferServiceLevelInfo(field) + else: + args["service_level_info"] = None + + field = data.get("rpn_info", None) + if field is not None: + args["rpn_info"] = unmarshal_OfferRPNInfo(field) + else: + args["rpn_info"] = None + + field = data.get("san_info", None) + if field is not None: + args["san_info"] = unmarshal_OfferSANInfo(field) + else: + args["san_info"] = None + + field = data.get("antidos_info", None) + if field is not None: + args["antidos_info"] = unmarshal_OfferAntiDosInfo(field) + else: + args["antidos_info"] = None + + field = data.get("backup_info", None) + if field is not None: + args["backup_info"] = unmarshal_OfferBackupInfo(field) + else: + args["backup_info"] = None + + field = data.get("usb_storage_info", None) + if field is not None: + args["usb_storage_info"] = unmarshal_OfferStorageInfo(field) + else: + args["usb_storage_info"] = None + + field = data.get("storage_info", None) + if field is not None: + args["storage_info"] = unmarshal_OfferStorageInfo(field) + else: + args["storage_info"] = None + + field = data.get("license_info", None) + if field is not None: + args["license_info"] = unmarshal_OfferLicenseInfo(field) + else: + args["license_info"] = None + + field = data.get("failover_ip_info", None) + if field is not None: + args["failover_ip_info"] = unmarshal_OfferFailoverIpInfo(field) + else: + args["failover_ip_info"] = None + + field = data.get("failover_block_info", None) + if field is not None: + args["failover_block_info"] = unmarshal_OfferFailoverBlockInfo(field) + else: + args["failover_block_info"] = None + + field = data.get("bandwidth_info", None) + if field is not None: + args["bandwidth_info"] = unmarshal_OfferBandwidthInfo(field) + else: + args["bandwidth_info"] = None + + return Offer(**args) + + +def unmarshal_OS(data: Any) -> OS: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OS' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("arch", None) + if field is not None: + args["arch"] = field + + field = data.get("allow_custom_partitioning", None) + if field is not None: + args["allow_custom_partitioning"] = field + + field = data.get("allow_ssh_keys", None) + if field is not None: + args["allow_ssh_keys"] = field + + field = data.get("requires_user", None) + if field is not None: + args["requires_user"] = field + + field = data.get("requires_admin_password", None) + if field is not None: + args["requires_admin_password"] = field + + field = data.get("requires_panel_password", None) + if field is not None: + args["requires_panel_password"] = field + + field = data.get("allowed_filesystems", None) + if field is not None: + args["allowed_filesystems"] = ( + [PartitionFileSystem(v) for v in field] if field is not None else None + ) + + field = data.get("requires_license", None) + if field is not None: + args["requires_license"] = field + + field = data.get("license_offers", None) + if field is not None: + args["license_offers"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + field = data.get("display_name", None) + if field is not None: + args["display_name"] = field + + field = data.get("password_regex", None) + if field is not None: + args["password_regex"] = field + + field = data.get("hostname_max_length", None) + if field is not None: + args["hostname_max_length"] = field + + field = data.get("max_partitions", None) + if field is not None: + args["max_partitions"] = field + else: + args["max_partitions"] = None + + field = data.get("panel_password_regex", None) + if field is not None: + args["panel_password_regex"] = field + else: + args["panel_password_regex"] = None + + field = data.get("requires_valid_hostname", None) + if field is not None: + args["requires_valid_hostname"] = field + else: + args["requires_valid_hostname"] = None + + field = data.get("hostname_regex", None) + if field is not None: + args["hostname_regex"] = field + else: + args["hostname_regex"] = None + + field = data.get("released_at", None) + if field is not None: + args["released_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["released_at"] = None + + return OS(**args) + + +def unmarshal_RpnSan(data: Any) -> RpnSan: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSan' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("server_hostname", None) + if field is not None: + args["server_hostname"] = field + + field = data.get("iqn_suffix", None) + if field is not None: + args["iqn_suffix"] = field + + field = data.get("offer_id", None) + if field is not None: + args["offer_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("storage_size", None) + if field is not None: + args["storage_size"] = field + + field = data.get("iqn", None) + if field is not None: + args["iqn"] = field + + field = data.get("rpnv1_compatible", None) + if field is not None: + args["rpnv1_compatible"] = field + + field = data.get("rpnv1_implicit", None) + if field is not None: + args["rpnv1_implicit"] = field + + field = data.get("offer", None) + if field is not None: + args["offer"] = unmarshal_Offer(field) + else: + args["offer"] = None + + field = data.get("delivered_at", None) + if field is not None: + args["delivered_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["delivered_at"] = None + + field = data.get("terminated_at", None) + if field is not None: + args["terminated_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["terminated_at"] = None + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + return RpnSan(**args) + + +def unmarshal_RpnGroup(data: Any) -> RpnGroup: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnGroup' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("active", None) + if field is not None: + args["active"] = field + + field = data.get("owner", None) + if field is not None: + args["owner"] = field + + field = data.get("members_count", None) + if field is not None: + args["members_count"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + return RpnGroup(**args) + + +def unmarshal_NetworkInterface(data: Any) -> NetworkInterface: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NetworkInterface' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("card_id", None) + if field is not None: + args["card_id"] = field + + field = data.get("device_id", None) + if field is not None: + args["device_id"] = field + + field = data.get("mac", None) + if field is not None: + args["mac"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("ips", None) + if field is not None: + args["ips"] = [unmarshal_IP(v) for v in field] if field is not None else None + + return NetworkInterface(**args) + + +def unmarshal_ServerLocation(data: Any) -> ServerLocation: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerLocation' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rack", None) + if field is not None: + args["rack"] = field + + field = data.get("room", None) + if field is not None: + args["room"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + return ServerLocation(**args) + + +def unmarshal_ServerOption(data: Any) -> ServerOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("options", None) + if field is not None: + args["options"] = ( + [unmarshal_ServerOption(v) for v in field] if field is not None else None + ) + + field = data.get("offer", None) + if field is not None: + args["offer"] = unmarshal_Offer(field) + else: + args["offer"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("expired_at", None) + if field is not None: + args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None + + return ServerOption(**args) + + +def unmarshal_ServiceLevel(data: Any) -> ServiceLevel: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServiceLevel' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("offer_id", None) + if field is not None: + args["offer_id"] = field + + field = data.get("level", None) + if field is not None: + args["level"] = field + + return ServiceLevel(**args) + + +def unmarshal_Server(data: Any) -> Server: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Server' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("rebooted_at", None) + if field is not None: + args["rebooted_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["rebooted_at"] = None + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("abuse_contact", None) + if field is not None: + args["abuse_contact"] = field + + field = data.get("interfaces", None) + if field is not None: + args["interfaces"] = ( + [unmarshal_NetworkInterface(v) for v in field] + if field is not None + else None + ) + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("options", None) + if field is not None: + args["options"] = ( + [unmarshal_ServerOption(v) for v in field] if field is not None else None + ) + + field = data.get("has_bmc", None) + if field is not None: + args["has_bmc"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("is_outsourced", None) + if field is not None: + args["is_outsourced"] = field + + field = data.get("ipv6_slaac", None) + if field is not None: + args["ipv6_slaac"] = field + + field = data.get("qinq", None) + if field is not None: + args["qinq"] = field + + field = data.get("is_rpnv2_member", None) + if field is not None: + args["is_rpnv2_member"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("expired_at", None) + if field is not None: + args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None + + field = data.get("offer", None) + if field is not None: + args["offer"] = unmarshal_Offer(field) + else: + args["offer"] = None + + field = data.get("location", None) + if field is not None: + args["location"] = unmarshal_ServerLocation(field) + else: + args["location"] = None + + field = data.get("os", None) + if field is not None: + args["os"] = unmarshal_OS(field) + else: + args["os"] = None + + field = data.get("level", None) + if field is not None: + args["level"] = unmarshal_ServiceLevel(field) + else: + args["level"] = None + + field = data.get("rescue_os", None) + if field is not None: + args["rescue_os"] = unmarshal_OS(field) + else: + args["rescue_os"] = None + + return Server(**args) + + +def unmarshal_RpnV2GroupSubnet(data: Any) -> RpnV2GroupSubnet: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnV2GroupSubnet' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + return RpnV2GroupSubnet(**args) + + +def unmarshal_RpnV2Group(data: Any) -> RpnV2Group: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnV2Group' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("compatible_rpnv1", None) + if field is not None: + args["compatible_rpnv1"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("owner", None) + if field is not None: + args["owner"] = field + + field = data.get("members_count", None) + if field is not None: + args["members_count"] = field + + field = data.get("gateway", None) + if field is not None: + args["gateway"] = field + + field = data.get("subnet", None) + if field is not None: + args["subnet"] = unmarshal_RpnV2GroupSubnet(field) + else: + args["subnet"] = None + + field = data.get("rpnv1_group", None) + if field is not None: + args["rpnv1_group"] = unmarshal_RpnGroup(field) + else: + args["rpnv1_group"] = None + + return RpnV2Group(**args) + + +def unmarshal_Service(data: Any) -> Service: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Service' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("provisioning_status", None) + if field is not None: + args["provisioning_status"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("resource_id", None) + if field is not None: + args["resource_id"] = field + else: + args["resource_id"] = None + + field = data.get("offer", None) + if field is not None: + args["offer"] = unmarshal_Offer(field) + else: + args["offer"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("delivered_at", None) + if field is not None: + args["delivered_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["delivered_at"] = None + + field = data.get("terminated_at", None) + if field is not None: + args["terminated_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["terminated_at"] = None + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + return Service(**args) + + +def unmarshal_FailoverBlock(data: Any) -> FailoverBlock: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'FailoverBlock' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("nameservers", None) + if field is not None: + args["nameservers"] = field + + field = data.get("ip_version", None) + if field is not None: + args["ip_version"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + field = data.get("netmask", None) + if field is not None: + args["netmask"] = field + + field = data.get("gateway_ip", None) + if field is not None: + args["gateway_ip"] = field + + return FailoverBlock(**args) + + +def unmarshal_FailoverIP(data: Any) -> FailoverIP: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'FailoverIP' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("reverse", None) + if field is not None: + args["reverse"] = field + + field = data.get("ip_version", None) + if field is not None: + args["ip_version"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + field = data.get("netmask", None) + if field is not None: + args["netmask"] = field + + field = data.get("gateway_ip", None) + if field is not None: + args["gateway_ip"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("mac", None) + if field is not None: + args["mac"] = field + else: + args["mac"] = None + + field = data.get("server_id", None) + if field is not None: + args["server_id"] = field + else: + args["server_id"] = None + + field = data.get("block", None) + if field is not None: + args["block"] = unmarshal_FailoverBlock(field) + else: + args["block"] = None + + field = data.get("server_zone", None) + if field is not None: + args["server_zone"] = field + else: + args["server_zone"] = None + + return FailoverIP(**args) + + +def unmarshal_BMCAccess(data: Any) -> BMCAccess: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BMCAccess' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("url", None) + if field is not None: + args["url"] = field + + field = data.get("login", None) + if field is not None: + args["login"] = field + + field = data.get("password", None) + if field is not None: + args["password"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + return BMCAccess(**args) + + +def unmarshal_Backup(data: Any) -> Backup: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Backup' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("login", None) + if field is not None: + args["login"] = field + + field = data.get("server", None) + if field is not None: + args["server"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("acl_enabled", None) + if field is not None: + args["acl_enabled"] = field + + field = data.get("autologin", None) + if field is not None: + args["autologin"] = field + + field = data.get("quota_space", None) + if field is not None: + args["quota_space"] = field + + field = data.get("quota_space_used", None) + if field is not None: + args["quota_space_used"] = field + + field = data.get("quota_files", None) + if field is not None: + args["quota_files"] = field + + field = data.get("quota_files_used", None) + if field is not None: + args["quota_files_used"] = field + + return Backup(**args) + + +def unmarshal_CanOrderResponse(data: Any) -> CanOrderResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CanOrderResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("can_order", None) + if field is not None: + args["can_order"] = field + + field = data.get("quota_ok", None) + if field is not None: + args["quota_ok"] = field + + field = data.get("phone_confirmed", None) + if field is not None: + args["phone_confirmed"] = field + + field = data.get("email_confirmed", None) + if field is not None: + args["email_confirmed"] = field + + field = data.get("user_confirmed", None) + if field is not None: + args["user_confirmed"] = field + + field = data.get("payment_mode", None) + if field is not None: + args["payment_mode"] = field + + field = data.get("billing_ok", None) + if field is not None: + args["billing_ok"] = field + + field = data.get("message", None) + if field is not None: + args["message"] = field + else: + args["message"] = None + + return CanOrderResponse(**args) + + +def unmarshal_CreateFailoverIPsResponse(data: Any) -> CreateFailoverIPsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CreateFailoverIPsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("services", None) + if field is not None: + args["services"] = ( + [unmarshal_Service(v) for v in field] if field is not None else None + ) + + return CreateFailoverIPsResponse(**args) + + +def unmarshal_GetIPv6BlockQuotasResponseQuota( + data: Any, +) -> GetIPv6BlockQuotasResponseQuota: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetIPv6BlockQuotasResponseQuota' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("quota", None) + if field is not None: + args["quota"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + return GetIPv6BlockQuotasResponseQuota(**args) + + +def unmarshal_GetIPv6BlockQuotasResponse(data: Any) -> GetIPv6BlockQuotasResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetIPv6BlockQuotasResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("quotas", None) + if field is not None: + args["quotas"] = ( + [unmarshal_GetIPv6BlockQuotasResponseQuota(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return GetIPv6BlockQuotasResponse(**args) + + +def unmarshal_GetRemainingQuotaResponse(data: Any) -> GetRemainingQuotaResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetRemainingQuotaResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("failover_ip_quota", None) + if field is not None: + args["failover_ip_quota"] = field + + field = data.get("failover_ip_remaining_quota", None) + if field is not None: + args["failover_ip_remaining_quota"] = field + + field = data.get("failover_block_quota", None) + if field is not None: + args["failover_block_quota"] = field + + field = data.get("failover_block_remaining_quota", None) + if field is not None: + args["failover_block_remaining_quota"] = field + + return GetRemainingQuotaResponse(**args) + + +def unmarshal_GetRpnStatusResponse(data: Any) -> GetRpnStatusResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetRpnStatusResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("operations_left", None) + if field is not None: + args["operations_left"] = field + else: + args["operations_left"] = None + + return GetRpnStatusResponse(**args) + + +def unmarshal_IPv6Block(data: Any) -> IPv6Block: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'IPv6Block' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("duid", None) + if field is not None: + args["duid"] = field + + field = data.get("nameservers", None) + if field is not None: + args["nameservers"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + field = data.get("subnets", None) + if field is not None: + args["subnets"] = ( + [unmarshal_IPv6Block(v) for v in field] if field is not None else None + ) + + field = data.get("delegation_status", None) + if field is not None: + args["delegation_status"] = field + + return IPv6Block(**args) + + +def unmarshal_Invoice(data: Any) -> Invoice: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Invoice' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("payment_method", None) + if field is not None: + args["payment_method"] = field + + field = data.get("content", None) + if field is not None: + args["content"] = field + + field = data.get("transaction_id", None) + if field is not None: + args["transaction_id"] = field + + field = data.get("total_with_taxes", None) + if field is not None: + args["total_with_taxes"] = unmarshal_Money(field) + else: + args["total_with_taxes"] = None + + field = data.get("total_without_taxes", None) + if field is not None: + args["total_without_taxes"] = unmarshal_Money(field) + else: + args["total_without_taxes"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("paid_at", None) + if field is not None: + args["paid_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["paid_at"] = None + + return Invoice(**args) + + +def unmarshal_ListFailoverIPsResponse(data: Any) -> ListFailoverIPsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListFailoverIPsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("failover_ips", None) + if field is not None: + args["failover_ips"] = ( + [unmarshal_FailoverIP(v) for v in field] if field is not None else None + ) + + return ListFailoverIPsResponse(**args) + + +def unmarshal_ListIPv6BlockSubnetsAvailableResponseSubnet( + data: Any, +) -> ListIPv6BlockSubnetsAvailableResponseSubnet: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListIPv6BlockSubnetsAvailableResponseSubnet' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("cidr", None) + if field is not None: + args["cidr"] = field + + return ListIPv6BlockSubnetsAvailableResponseSubnet(**args) + + +def unmarshal_ListIPv6BlockSubnetsAvailableResponse( + data: Any, +) -> ListIPv6BlockSubnetsAvailableResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListIPv6BlockSubnetsAvailableResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("subnet_availables", None) + if field is not None: + args["subnet_availables"] = ( + [unmarshal_ListIPv6BlockSubnetsAvailableResponseSubnet(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListIPv6BlockSubnetsAvailableResponse(**args) + + +def unmarshal_InvoiceSummary(data: Any) -> InvoiceSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InvoiceSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("payment_method", None) + if field is not None: + args["payment_method"] = field + + field = data.get("transaction_id", None) + if field is not None: + args["transaction_id"] = field + + field = data.get("total_with_taxes", None) + if field is not None: + args["total_with_taxes"] = unmarshal_Money(field) + else: + args["total_with_taxes"] = None + + field = data.get("total_without_taxes", None) + if field is not None: + args["total_without_taxes"] = unmarshal_Money(field) + else: + args["total_without_taxes"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("paid_at", None) + if field is not None: + args["paid_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["paid_at"] = None + + return InvoiceSummary(**args) + + +def unmarshal_ListInvoicesResponse(data: Any) -> ListInvoicesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInvoicesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("invoices", None) + if field is not None: + args["invoices"] = ( + [unmarshal_InvoiceSummary(v) for v in field] if field is not None else None + ) + + return ListInvoicesResponse(**args) + + +def unmarshal_RpnSanIpRpnV2Group(data: Any) -> RpnSanIpRpnV2Group: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSanIpRpnV2Group' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + return RpnSanIpRpnV2Group(**args) + + +def unmarshal_RpnSanIpServer(data: Any) -> RpnSanIpServer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSanIpServer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + return RpnSanIpServer(**args) + + +def unmarshal_RpnSanIp(data: Any) -> RpnSanIp: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSanIp' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("server", None) + if field is not None: + args["server"] = unmarshal_RpnSanIpServer(field) + else: + args["server"] = None + + field = data.get("rpnv2_group", None) + if field is not None: + args["rpnv2_group"] = unmarshal_RpnSanIpRpnV2Group(field) + else: + args["rpnv2_group"] = None + + field = data.get("ip", None) + if field is not None: + args["ip"] = unmarshal_IP(field) + else: + args["ip"] = None + + return RpnSanIp(**args) + + +def unmarshal_ListIpsResponse(data: Any) -> ListIpsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListIpsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("ips", None) + if field is not None: + args["ips"] = ( + [unmarshal_RpnSanIp(v) for v in field] if field is not None else None + ) + + return ListIpsResponse(**args) + + +def unmarshal_ListOSResponse(data: Any) -> ListOSResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOSResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("os", None) + if field is not None: + args["os"] = [unmarshal_OS(v) for v in field] if field is not None else None + + return ListOSResponse(**args) + + +def unmarshal_ListOffersResponse(data: Any) -> ListOffersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOffersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offers", None) + if field is not None: + args["offers"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return ListOffersResponse(**args) + + +def unmarshal_RefundSummary(data: Any) -> RefundSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RefundSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("method", None) + if field is not None: + args["method"] = field + + field = data.get("total_with_taxes", None) + if field is not None: + args["total_with_taxes"] = unmarshal_Money(field) + else: + args["total_with_taxes"] = None + + field = data.get("total_without_taxes", None) + if field is not None: + args["total_without_taxes"] = unmarshal_Money(field) + else: + args["total_without_taxes"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("refunded_at", None) + if field is not None: + args["refunded_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["refunded_at"] = None + + return RefundSummary(**args) + + +def unmarshal_ListRefundsResponse(data: Any) -> ListRefundsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRefundsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("refunds", None) + if field is not None: + args["refunds"] = ( + [unmarshal_RefundSummary(v) for v in field] if field is not None else None + ) + + return ListRefundsResponse(**args) + + +def unmarshal_RpnSanServer(data: Any) -> RpnSanServer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSanServer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("sans", None) + if field is not None: + args["sans"] = ( + [unmarshal_RpnSan(v) for v in field] if field is not None else None + ) + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + return RpnSanServer(**args) + + +def unmarshal_ListRpnCapableSanServersResponse( + data: Any, +) -> ListRpnCapableSanServersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnCapableSanServersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("san_servers", None) + if field is not None: + args["san_servers"] = ( + [unmarshal_RpnSanServer(v) for v in field] if field is not None else None + ) + + return ListRpnCapableSanServersResponse(**args) + + +def unmarshal_ListRpnCapableServersResponse(data: Any) -> ListRpnCapableServersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnCapableServersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("servers", None) + if field is not None: + args["servers"] = ( + [unmarshal_Server(v) for v in field] if field is not None else None + ) + + return ListRpnCapableServersResponse(**args) + + +def unmarshal_RpnGroupMember(data: Any) -> RpnGroupMember: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnGroupMember' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("group_id", None) + if field is not None: + args["group_id"] = field + + field = data.get("group_name", None) + if field is not None: + args["group_name"] = field + + field = data.get("group_owner", None) + if field is not None: + args["group_owner"] = field + + field = data.get("owner", None) + if field is not None: + args["owner"] = field + + field = data.get("san_server", None) + if field is not None: + args["san_server"] = unmarshal_RpnSanServer(field) + else: + args["san_server"] = None + + field = data.get("server", None) + if field is not None: + args["server"] = unmarshal_Server(field) + else: + args["server"] = None + + field = data.get("speed", None) + if field is not None: + args["speed"] = field + else: + args["speed"] = None + + return RpnGroupMember(**args) + + +def unmarshal_ListRpnGroupMembersResponse(data: Any) -> ListRpnGroupMembersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnGroupMembersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("members", None) + if field is not None: + args["members"] = ( + [unmarshal_RpnGroupMember(v) for v in field] if field is not None else None + ) + + return ListRpnGroupMembersResponse(**args) + + +def unmarshal_ListRpnGroupsResponse(data: Any) -> ListRpnGroupsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnGroupsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("rpn_groups", None) + if field is not None: + args["rpn_groups"] = ( + [unmarshal_RpnGroup(v) for v in field] if field is not None else None + ) + + return ListRpnGroupsResponse(**args) + + +def unmarshal_ListRpnInvitesResponse(data: Any) -> ListRpnInvitesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnInvitesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("members", None) + if field is not None: + args["members"] = ( + [unmarshal_RpnGroupMember(v) for v in field] if field is not None else None + ) + + return ListRpnInvitesResponse(**args) + + +def unmarshal_RpnSanSummary(data: Any) -> RpnSanSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnSanSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("server_hostname", None) + if field is not None: + args["server_hostname"] = field + + field = data.get("iqn_suffix", None) + if field is not None: + args["iqn_suffix"] = field + + field = data.get("offer_id", None) + if field is not None: + args["offer_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("storage_size", None) + if field is not None: + args["storage_size"] = field + + field = data.get("rpnv1_compatible", None) + if field is not None: + args["rpnv1_compatible"] = field + + field = data.get("rpnv1_implicit", None) + if field is not None: + args["rpnv1_implicit"] = field + + field = data.get("delivered_at", None) + if field is not None: + args["delivered_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["delivered_at"] = None + + field = data.get("terminated_at", None) + if field is not None: + args["terminated_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["terminated_at"] = None + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + return RpnSanSummary(**args) + + +def unmarshal_ListRpnSansResponse(data: Any) -> ListRpnSansResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnSansResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("rpn_sans", None) + if field is not None: + args["rpn_sans"] = ( + [unmarshal_RpnSanSummary(v) for v in field] if field is not None else None + ) + + return ListRpnSansResponse(**args) + + +def unmarshal_RpnServerCapability(data: Any) -> RpnServerCapability: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnServerCapability' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("compatible_qinq", None) + if field is not None: + args["compatible_qinq"] = field + + field = data.get("can_join_qinq_group", None) + if field is not None: + args["can_join_qinq_group"] = field + + field = data.get("rpnv1_group_count", None) + if field is not None: + args["rpnv1_group_count"] = field + + field = data.get("rpnv2_group_count", None) + if field is not None: + args["rpnv2_group_count"] = field + + field = data.get("can_join_rpnv2_group", None) + if field is not None: + args["can_join_rpnv2_group"] = field + + field = data.get("ip_address", None) + if field is not None: + args["ip_address"] = field + else: + args["ip_address"] = None + + field = data.get("rpn_version", None) + if field is not None: + args["rpn_version"] = field + else: + args["rpn_version"] = None + + return RpnServerCapability(**args) + + +def unmarshal_ListRpnServerCapabilitiesResponse( + data: Any, +) -> ListRpnServerCapabilitiesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnServerCapabilitiesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("servers", None) + if field is not None: + args["servers"] = ( + [unmarshal_RpnServerCapability(v) for v in field] + if field is not None + else None + ) + + return ListRpnServerCapabilitiesResponse(**args) + + +def unmarshal_ListRpnV2CapableResourcesResponse( + data: Any, +) -> ListRpnV2CapableResourcesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnV2CapableResourcesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("servers", None) + if field is not None: + args["servers"] = ( + [unmarshal_Server(v) for v in field] if field is not None else None + ) + + return ListRpnV2CapableResourcesResponse(**args) + + +def unmarshal_RpnV2Member(data: Any) -> RpnV2Member: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RpnV2Member' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("vlan", None) + if field is not None: + args["vlan"] = field + + field = data.get("server", None) + if field is not None: + args["server"] = unmarshal_Server(field) + else: + args["server"] = None + + field = data.get("rpnv1_group", None) + if field is not None: + args["rpnv1_group"] = unmarshal_RpnGroup(field) + else: + args["rpnv1_group"] = None + + field = data.get("speed", None) + if field is not None: + args["speed"] = field + else: + args["speed"] = None + + return RpnV2Member(**args) + + +def unmarshal_Log(data: Any) -> Log: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Log' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("action", None) + if field is not None: + args["action"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("group", None) + if field is not None: + args["group"] = unmarshal_RpnV2Group(field) + else: + args["group"] = None + + field = data.get("member", None) + if field is not None: + args["member"] = unmarshal_RpnV2Member(field) + else: + args["member"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("finished_at", None) + if field is not None: + args["finished_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["finished_at"] = None + + return Log(**args) + + +def unmarshal_ListRpnV2GroupLogsResponse(data: Any) -> ListRpnV2GroupLogsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnV2GroupLogsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("logs", None) + if field is not None: + args["logs"] = [unmarshal_Log(v) for v in field] if field is not None else None + + return ListRpnV2GroupLogsResponse(**args) + + +def unmarshal_ListRpnV2GroupsResponse(data: Any) -> ListRpnV2GroupsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnV2GroupsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("rpn_groups", None) + if field is not None: + args["rpn_groups"] = ( + [unmarshal_RpnV2Group(v) for v in field] if field is not None else None + ) + + return ListRpnV2GroupsResponse(**args) + + +def unmarshal_ListRpnV2MembersResponse(data: Any) -> ListRpnV2MembersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRpnV2MembersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("members", None) + if field is not None: + args["members"] = ( + [unmarshal_RpnV2Member(v) for v in field] if field is not None else None + ) + + return ListRpnV2MembersResponse(**args) + + +def unmarshal_ServerDisk(data: Any) -> ServerDisk: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerDisk' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("connector", None) + if field is not None: + args["connector"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = field + + field = data.get("is_addon", None) + if field is not None: + args["is_addon"] = field + + return ServerDisk(**args) + + +def unmarshal_ListServerDisksResponse(data: Any) -> ListServerDisksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServerDisksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("disks", None) + if field is not None: + args["disks"] = ( + [unmarshal_ServerDisk(v) for v in field] if field is not None else None + ) + + return ListServerDisksResponse(**args) + + +def unmarshal_ServerEvent(data: Any) -> ServerEvent: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerEvent' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("event_id", None) + if field is not None: + args["event_id"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("date", None) + if field is not None: + args["date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["date"] = None + + return ServerEvent(**args) + + +def unmarshal_ListServerEventsResponse(data: Any) -> ListServerEventsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServerEventsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("events", None) + if field is not None: + args["events"] = ( + [unmarshal_ServerEvent(v) for v in field] if field is not None else None + ) + + return ListServerEventsResponse(**args) + + +def unmarshal_ServerSummary(data: Any) -> ServerSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("datacenter_name", None) + if field is not None: + args["datacenter_name"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("expired_at", None) + if field is not None: + args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None + + field = data.get("offer_id", None) + if field is not None: + args["offer_id"] = field + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("interfaces", None) + if field is not None: + args["interfaces"] = ( + [unmarshal_NetworkInterface(v) for v in field] + if field is not None + else None + ) + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("is_outsourced", None) + if field is not None: + args["is_outsourced"] = field + + field = data.get("qinq", None) + if field is not None: + args["qinq"] = field + + field = data.get("os_id", None) + if field is not None: + args["os_id"] = field + else: + args["os_id"] = None + + field = data.get("level", None) + if field is not None: + args["level"] = unmarshal_ServiceLevel(field) + else: + args["level"] = None + + field = data.get("rpn_version", None) + if field is not None: + args["rpn_version"] = field + else: + args["rpn_version"] = None + + return ServerSummary(**args) + + +def unmarshal_ListServersResponse(data: Any) -> ListServersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("servers", None) + if field is not None: + args["servers"] = ( + [unmarshal_ServerSummary(v) for v in field] if field is not None else None + ) + + return ListServersResponse(**args) + + +def unmarshal_ListServicesResponse(data: Any) -> ListServicesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListServicesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("services", None) + if field is not None: + args["services"] = ( + [unmarshal_Service(v) for v in field] if field is not None else None + ) + + return ListServicesResponse(**args) + + +def unmarshal_ListSubscribableServerOptionsResponse( + data: Any, +) -> ListSubscribableServerOptionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSubscribableServerOptionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("server_options", None) + if field is not None: + args["server_options"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return ListSubscribableServerOptionsResponse(**args) + + +def unmarshal_RaidArray(data: Any) -> RaidArray: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RaidArray' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("raid_level", None) + if field is not None: + args["raid_level"] = field + + field = data.get("disks", None) + if field is not None: + args["disks"] = ( + [unmarshal_ServerDisk(v) for v in field] if field is not None else None + ) + + return RaidArray(**args) + + +def unmarshal_Raid(data: Any) -> Raid: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Raid' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("raid_arrays", None) + if field is not None: + args["raid_arrays"] = ( + [unmarshal_RaidArray(v) for v in field] if field is not None else None + ) + + return Raid(**args) + + +def unmarshal_Refund(data: Any) -> Refund: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Refund' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("method", None) + if field is not None: + args["method"] = field + + field = data.get("content", None) + if field is not None: + args["content"] = field + + field = data.get("total_with_taxes", None) + if field is not None: + args["total_with_taxes"] = unmarshal_Money(field) + else: + args["total_with_taxes"] = None + + field = data.get("total_without_taxes", None) + if field is not None: + args["total_without_taxes"] = unmarshal_Money(field) + else: + args["total_without_taxes"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("refunded_at", None) + if field is not None: + args["refunded_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["refunded_at"] = None + + return Refund(**args) + + +def unmarshal_Rescue(data: Any) -> Rescue: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Rescue' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("os_id", None) + if field is not None: + args["os_id"] = field + + field = data.get("login", None) + if field is not None: + args["login"] = field + + field = data.get("password", None) + if field is not None: + args["password"] = field + + field = data.get("protocol", None) + if field is not None: + args["protocol"] = field + + return Rescue(**args) + + +def unmarshal_Partition(data: Any) -> Partition: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Partition' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("file_system", None) + if field is not None: + args["file_system"] = field + + field = data.get("raid_level", None) + if field is not None: + args["raid_level"] = field + + field = data.get("capacity", None) + if field is not None: + args["capacity"] = field + + field = data.get("connectors", None) + if field is not None: + args["connectors"] = field + + field = data.get("mount_point", None) + if field is not None: + args["mount_point"] = field + else: + args["mount_point"] = None + + return Partition(**args) + + +def unmarshal_ServerDefaultPartitioning(data: Any) -> ServerDefaultPartitioning: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerDefaultPartitioning' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("partitions", None) + if field is not None: + args["partitions"] = ( + [unmarshal_Partition(v) for v in field] if field is not None else None + ) + + return ServerDefaultPartitioning(**args) + + +def unmarshal_ServerInstall(data: Any) -> ServerInstall: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerInstall' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("os_id", None) + if field is not None: + args["os_id"] = field + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("partitions", None) + if field is not None: + args["partitions"] = ( + [unmarshal_Partition(v) for v in field] if field is not None else None + ) + + field = data.get("ssh_key_ids", None) + if field is not None: + args["ssh_key_ids"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("user_login", None) + if field is not None: + args["user_login"] = field + else: + args["user_login"] = None + + field = data.get("panel_url", None) + if field is not None: + args["panel_url"] = field + else: + args["panel_url"] = None + + return ServerInstall(**args) + + +def unmarshal_SubscribeStorageOptionsResponse( + data: Any, +) -> SubscribeStorageOptionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SubscribeStorageOptionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("services", None) + if field is not None: + args["services"] = ( + [unmarshal_Service(v) for v in field] if field is not None else None + ) + + return SubscribeStorageOptionsResponse(**args) + + +def marshal_AttachFailoverIPToMacAddressRequest( + request: AttachFailoverIPToMacAddressRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.mac is not None: + output["mac"] = request.mac + + return output + + +def marshal_AttachFailoverIPsRequest( + request: AttachFailoverIPsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.server_id is not None: + output["server_id"] = request.server_id + + if request.fips_ids is not None: + output["fips_ids"] = request.fips_ids + + return output + + +def marshal_CreateFailoverIPsRequest( + request: CreateFailoverIPsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.quantity is not None: + output["quantity"] = request.quantity + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_CreateServerRequest( + request: CreateServerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.server_option_ids is not None: + output["server_option_ids"] = request.server_option_ids + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.datacenter_name is not None: + output["datacenter_name"] = request.datacenter_name + + return output + + +def marshal_DetachFailoverIPsRequest( + request: DetachFailoverIPsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.fips_ids is not None: + output["fips_ids"] = request.fips_ids + + return output + + +def marshal_IPv6BlockApiCreateIPv6BlockRequest( + request: IPv6BlockApiCreateIPv6BlockRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id + + return output + + +def marshal_IPv6BlockApiCreateIPv6BlockSubnetRequest( + request: IPv6BlockApiCreateIPv6BlockSubnetRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.address is not None: + output["address"] = request.address + + if request.cidr is not None: + output["cidr"] = request.cidr + + return output + + +def marshal_IPv6BlockApiUpdateIPv6BlockRequest( + request: IPv6BlockApiUpdateIPv6BlockRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.nameservers is not None: + output["nameservers"] = request.nameservers + + return output + + +def marshal_InstallPartition( + request: InstallPartition, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.file_system is not None: + output["file_system"] = str(request.file_system) + + if request.raid_level is not None: + output["raid_level"] = str(request.raid_level) + + if request.capacity is not None: + output["capacity"] = request.capacity + + if request.connectors is not None: + output["connectors"] = request.connectors + + if request.mount_point is not None: + output["mount_point"] = request.mount_point + + return output + + +def marshal_InstallServerRequest( + request: InstallServerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.os_id is not None: + output["os_id"] = request.os_id + + if request.hostname is not None: + output["hostname"] = request.hostname + + if request.user_login is not None: + output["user_login"] = request.user_login + + if request.user_password is not None: + output["user_password"] = request.user_password + + if request.panel_password is not None: + output["panel_password"] = request.panel_password + + if request.root_password is not None: + output["root_password"] = request.root_password + + if request.partitions is not None: + output["partitions"] = [ + marshal_InstallPartition(item, defaults) for item in request.partitions + ] + + if request.ssh_key_ids is not None: + output["ssh_key_ids"] = request.ssh_key_ids + + if request.license_offer_id is not None: + output["license_offer_id"] = request.license_offer_id + + if request.ip_id is not None: + output["ip_id"] = request.ip_id + + return output + + +def marshal_RpnSanApiAddIpRequest( + request: RpnSanApiAddIpRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip_ids is not None: + output["ip_ids"] = request.ip_ids + + return output + + +def marshal_RpnSanApiCreateRpnSanRequest( + request: RpnSanApiCreateRpnSanRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RpnSanApiRemoveIpRequest( + request: RpnSanApiRemoveIpRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip_ids is not None: + output["ip_ids"] = request.ip_ids + + return output + + +def marshal_RpnV1ApiAddRpnGroupMembersRequest( + request: RpnV1ApiAddRpnGroupMembersRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.server_ids is not None: + output["server_ids"] = request.server_ids + + if request.san_server_ids is not None: + output["san_server_ids"] = request.san_server_ids + + return output + + +def marshal_RpnV1ApiCreateRpnGroupRequest( + request: RpnV1ApiCreateRpnGroupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.server_ids is not None: + output["server_ids"] = request.server_ids + + if request.san_server_ids is not None: + output["san_server_ids"] = request.san_server_ids + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RpnV1ApiDeleteRpnGroupMembersRequest( + request: RpnV1ApiDeleteRpnGroupMembersRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.member_ids is not None: + output["member_ids"] = request.member_ids + + return output + + +def marshal_RpnV1ApiLeaveRpnGroupRequest( + request: RpnV1ApiLeaveRpnGroupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.member_ids is not None: + output["member_ids"] = request.member_ids + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RpnV1ApiRpnGroupInviteRequest( + request: RpnV1ApiRpnGroupInviteRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.server_ids is not None: + output["server_ids"] = request.server_ids + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_RpnV1ApiUpdateRpnGroupNameRequest( + request: RpnV1ApiUpdateRpnGroupNameRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + return output + + +def marshal_RpnV2ApiAddRpnV2MembersRequest( + request: RpnV2ApiAddRpnV2MembersRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.servers is not None: + output["servers"] = request.servers + + return output + + +def marshal_RpnV2ApiCreateRpnV2GroupRequest( + request: RpnV2ApiCreateRpnV2GroupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.servers is not None: + output["servers"] = request.servers + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.type_ is not None: + output["type"] = str(request.type_) + + return output + + +def marshal_RpnV2ApiDeleteRpnV2MembersRequest( + request: RpnV2ApiDeleteRpnV2MembersRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.member_ids is not None: + output["member_ids"] = request.member_ids + + return output + + +def marshal_RpnV2ApiEnableRpnV2GroupCompatibilityRequest( + request: RpnV2ApiEnableRpnV2GroupCompatibilityRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.rpnv1_group_id is not None: + output["rpnv1_group_id"] = request.rpnv1_group_id + + return output + + +def marshal_RpnV2ApiUpdateRpnV2GroupNameRequest( + request: RpnV2ApiUpdateRpnV2GroupNameRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + return output + + +def marshal_RpnV2ApiUpdateRpnV2VlanForMembersRequest( + request: RpnV2ApiUpdateRpnV2VlanForMembersRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.member_ids is not None: + output["member_ids"] = request.member_ids + + if request.vlan is not None: + output["vlan"] = request.vlan + + return output + + +def marshal_StartBMCAccessRequest( + request: StartBMCAccessRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip is not None: + output["ip"] = request.ip + + return output + + +def marshal_StartRescueRequest( + request: StartRescueRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.os_id is not None: + output["os_id"] = request.os_id + + return output + + +def marshal_SubscribeServerOptionRequest( + request: SubscribeServerOptionRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.option_id is not None: + output["option_id"] = request.option_id + + return output + + +def marshal_SubscribeStorageOptionsRequest( + request: SubscribeStorageOptionsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.options_ids is not None: + output["options_ids"] = request.options_ids + + return output + + +def marshal_UpdatableRaidArray( + request: UpdatableRaidArray, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.raid_level is not None: + output["raid_level"] = str(request.raid_level) + + if request.disk_ids is not None: + output["disk_ids"] = request.disk_ids + + return output + + +def marshal_UpdateRaidRequest( + request: UpdateRaidRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.raid_arrays is not None: + output["raid_arrays"] = [ + marshal_UpdatableRaidArray(item, defaults) for item in request.raid_arrays + ] + + return output + + +def marshal_UpdateReverseRequest( + request: UpdateReverseRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.reverse is not None: + output["reverse"] = request.reverse + + return output + + +def marshal_UpdateServerBackupRequest( + request: UpdateServerBackupRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + if request.autologin is not None: + output["autologin"] = request.autologin + + if request.acl_enabled is not None: + output["acl_enabled"] = request.acl_enabled + + return output + + +def marshal_UpdateServerRequest( + request: UpdateServerRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.hostname is not None: + output["hostname"] = request.hostname + + if request.enable_ipv6 is not None: + output["enable_ipv6"] = request.enable_ipv6 + + return output + + +def marshal_UpdateServerTagsRequest( + request: UpdateServerTagsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.tags is not None: + output["tags"] = request.tags + + return output diff --git a/scaleway/scaleway/dedibox/v1/types.py b/scaleway/scaleway/dedibox/v1/types.py new file mode 100644 index 00000000..8fba972c --- /dev/null +++ b/scaleway/scaleway/dedibox/v1/types.py @@ -0,0 +1,4453 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Money, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class AttachFailoverIPToMacAddressRequestMacType(str, Enum, metaclass=StrEnumMeta): + MAC_TYPE_UNKNOWN = "mac_type_unknown" + VMWARE = "vmware" + KVM = "kvm" + XEN = "xen" + + def __str__(self) -> str: + return str(self.value) + + +class BMCAccessStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + CREATING = "creating" + CREATED = "created" + DELETING = "deleting" + + def __str__(self) -> str: + return str(self.value) + + +class BackupStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_BACKUP_STATUS = "unknown_backup_status" + UNINITIALIZED = "uninitialized" + INACTIVE = "inactive" + READY = "ready" + + def __str__(self) -> str: + return str(self.value) + + +class FailoverBlockVersion(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_VERSION = "unknown_version" + IPV4 = "ipv4" + IPV6 = "ipv6" + + def __str__(self) -> str: + return str(self.value) + + +class FailoverIPInterfaceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + NORMAL = "normal" + IPMI = "ipmi" + VIRTUAL = "virtual" + + def __str__(self) -> str: + return str(self.value) + + +class FailoverIPStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + BUSY = "busy" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class FailoverIPVersion(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_VERSION = "unknown_version" + IPV4 = "ipv4" + IPV6 = "ipv6" + + def __str__(self) -> str: + return str(self.value) + + +class GetRpnStatusResponseStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + BUSY = "busy" + OPERATIONAL = "operational" + + def __str__(self) -> str: + return str(self.value) + + +class IPSemantic(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + PROXAD = "proxad" + EXT = "ext" + PUBLIC = "public" + PRIVATE = "private" + IPMI = "ipmi" + ADM = "adm" + REDIRECT = "redirect" + MIGRATION = "migration" + + def __str__(self) -> str: + return str(self.value) + + +class IPStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + BUSY = "busy" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class IPVersion(str, Enum, metaclass=StrEnumMeta): + IPV4 = "ipv4" + IPV6 = "ipv6" + + def __str__(self) -> str: + return str(self.value) + + +class IPv6BlockDelegationStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + UPDATING = "updating" + DONE = "done" + + def __str__(self) -> str: + return str(self.value) + + +class InvoicePaymentMethod(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PAYMENT_METHOD = "unknown_payment_method" + CREDIT_CARD = "credit_card" + AMEX = "amex" + PAYPAL = "paypal" + TRANSFER = "transfer" + DIRECT_DEBIT = "direct_debit" + + def __str__(self) -> str: + return str(self.value) + + +class InvoiceStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_INVOICE_STATUS = "unknown_invoice_status" + UNPAID = "unpaid" + PAID = "paid" + ERRORED = "errored" + + def __str__(self) -> str: + return str(self.value) + + +class ListFailoverIPsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + IP_ASC = "ip_asc" + IP_DESC = "ip_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListInvoicesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListOSRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + RELEASED_AT_ASC = "released_at_asc" + RELEASED_AT_DESC = "released_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListOffersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + PRICE_ASC = "price_asc" + PRICE_DESC = "price_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRefundsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnCapableSanServersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnCapableServersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnGroupMembersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnGroupsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnInvitesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnSansRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnServerCapabilitiesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnV2CapableResourcesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnV2GroupLogsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnV2GroupsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnV2MembersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRpnV2MembersRequestType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + RPNV1_GROUP = "rpnv1_group" + SERVER = "server" + + def __str__(self) -> str: + return str(self.value) + + +class ListServerDisksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListServerEventsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListServersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListServicesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class LogAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_LOG_ACTION = "unknown_log_action" + GROUP_CREATED = "group_created" + GROUP_DELETED = "group_deleted" + MEMBERS_ADDED = "members_added" + MEMBERS_DELETED = "members_deleted" + DESCRIPTION_UPDATED = "description_updated" + RPNV1_MEMBERS_ADDED = "rpnv1_members_added" + RPNV1_MEMBERS_DELETED = "rpnv1_members_deleted" + VLAN_UPDATED = "vlan_updated" + VLAN_UPDATED_ON_ALL_SERVERS = "vlan_updated_on_all_servers" + + def __str__(self) -> str: + return str(self.value) + + +class LogStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_LOG_STATUS = "unknown_log_status" + SUCCESS = "success" + IN_PROGRESS = "in_progress" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class MemoryType(str, Enum, metaclass=StrEnumMeta): + DDR2 = "ddr2" + DDR3 = "ddr3" + DDR4 = "ddr4" + DDR5 = "ddr5" + + def __str__(self) -> str: + return str(self.value) + + +class NetworkInterfaceInterfaceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + NORMAL = "normal" + IPMI = "ipmi" + VIRTUAL = "virtual" + + def __str__(self) -> str: + return str(self.value) + + +class OSArch(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ARCH = "unknown_arch" + AMD64 = "amd64" + X86 = "x86" + ARM = "arm" + ARM64 = "arm64" + + def __str__(self) -> str: + return str(self.value) + + +class OSType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + SERVER = "server" + VIRTU = "virtu" + PANEL = "panel" + DESKTOP = "desktop" + CUSTOM = "custom" + RESCUE = "rescue" + + def __str__(self) -> str: + return str(self.value) + + +class OfferAntiDosInfoType(str, Enum, metaclass=StrEnumMeta): + MINIMAL = "minimal" + PREVENTIVE = "preventive" + CURATIVE = "curative" + + def __str__(self) -> str: + return str(self.value) + + +class OfferCatalog(str, Enum, metaclass=StrEnumMeta): + ALL = "all" + DEFAULT = "default" + BETA = "beta" + RESELLER = "reseller" + PREMIUM = "premium" + VOLUME = "volume" + ADMIN = "admin" + INACTIVE = "inactive" + + def __str__(self) -> str: + return str(self.value) + + +class OfferPaymentFrequency(str, Enum, metaclass=StrEnumMeta): + MONTHLY = "monthly" + ONESHOT = "oneshot" + + def __str__(self) -> str: + return str(self.value) + + +class OfferSANInfoType(str, Enum, metaclass=StrEnumMeta): + HDD = "hdd" + SSD = "ssd" + + def __str__(self) -> str: + return str(self.value) + + +class OfferServerInfoStock(str, Enum, metaclass=StrEnumMeta): + EMPTY = "empty" + LOW = "low" + AVAILABLE = "available" + + def __str__(self) -> str: + return str(self.value) + + +class PartitionFileSystem(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + EFI = "efi" + SWAP = "swap" + EXT4 = "ext4" + EXT3 = "ext3" + EXT2 = "ext2" + XFS = "xfs" + NTFS = "ntfs" + FAT32 = "fat32" + UFS = "ufs" + + def __str__(self) -> str: + return str(self.value) + + +class PartitionType(str, Enum, metaclass=StrEnumMeta): + PRIMARY = "primary" + EXTENDED = "extended" + LOGICAL = "logical" + + def __str__(self) -> str: + return str(self.value) + + +class RaidArrayRaidLevel(str, Enum, metaclass=StrEnumMeta): + NO_RAID = "no_raid" + RAID0 = "raid0" + RAID1 = "raid1" + RAID5 = "raid5" + RAID6 = "raid6" + RAID10 = "raid10" + + def __str__(self) -> str: + return str(self.value) + + +class RefundMethod(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_REFUND_METHOD = "unknown_refund_method" + CREDIT_CARD = "credit_card" + AMEX = "amex" + PAYPAL = "paypal" + TRANSFER = "transfer" + + def __str__(self) -> str: + return str(self.value) + + +class RefundStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_REFUND_STATUS = "unknown_refund_status" + UNPAID = "unpaid" + PAID = "paid" + ERRORED = "errored" + + def __str__(self) -> str: + return str(self.value) + + +class RescueProtocol(str, Enum, metaclass=StrEnumMeta): + VNC = "vnc" + SSH = "ssh" + + def __str__(self) -> str: + return str(self.value) + + +class RpnGroupMemberStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_RPN_MEMBER_STATUS = "unknown_rpn_member_status" + PENDING_INVITATION = "pending_invitation" + ACTIVE = "active" + CREATING = "creating" + DELETING = "deleting" + DELETED = "deleted" + + def __str__(self) -> str: + return str(self.value) + + +class RpnGroupType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + LOCAL = "local" + SHARED = "shared" + + def __str__(self) -> str: + return str(self.value) + + +class RpnSanIpType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + SERVER_IP = "server_ip" + RPNV2_SUBNET = "rpnv2_subnet" + + def __str__(self) -> str: + return str(self.value) + + +class RpnSanStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + ACTIVE = "active" + DELETING = "deleting" + MAINTENANCE = "maintenance" + + def __str__(self) -> str: + return str(self.value) + + +class RpnV2GroupStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_GROUP_STATUS = "unknown_group_status" + CREATING = "creating" + ACTIVE = "active" + UPDATING = "updating" + DELETING = "deleting" + + def __str__(self) -> str: + return str(self.value) + + +class RpnV2GroupType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + STANDARD = "standard" + QINQ = "qinq" + + def __str__(self) -> str: + return str(self.value) + + +class RpnV2MemberStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_MEMBER_STATUS = "unknown_member_status" + CREATING = "creating" + ACTIVE = "active" + UPDATING = "updating" + DELETING = "deleting" + + def __str__(self) -> str: + return str(self.value) + + +class ServerDiskType(str, Enum, metaclass=StrEnumMeta): + SATA = "sata" + SSD = "ssd" + SAS = "sas" + SSHD = "sshd" + USB = "usb" + NVME = "nvme" + + def __str__(self) -> str: + return str(self.value) + + +class ServerInstallStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + BOOTING = "booting" + SETTING_UP_RAID = "setting_up_raid" + PARTITIONING = "partitioning" + FORMATTING = "formatting" + INSTALLING = "installing" + CONFIGURING = "configuring" + CONFIGURING_BOOTLOADER = "configuring_bootloader" + REBOOTING = "rebooting" + INSTALLED = "installed" + + def __str__(self) -> str: + return str(self.value) + + +class ServerStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + DELIVERING = "delivering" + INSTALLING = "installing" + READY = "ready" + STOPPED = "stopped" + ERROR = "error" + LOCKED = "locked" + RESCUE = "rescue" + BUSY = "busy" + + def __str__(self) -> str: + return str(self.value) + + +class ServiceLevelLevel(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + BASIC = "basic" + BUSINESS = "business" + + def __str__(self) -> str: + return str(self.value) + + +class ServiceProvisioningStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + DELIVERING = "delivering" + READY = "ready" + ERROR = "error" + EXPIRING = "expiring" + EXPIRED = "expired" + + def __str__(self) -> str: + return str(self.value) + + +class ServiceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + SERVICE = "service" + ORDER = "order" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class OfferAntiDosInfo: + type_: OfferAntiDosInfoType + + +@dataclass +class OfferBackupInfo: + size: int + + +@dataclass +class OfferBandwidthInfo: + speed: int + + +@dataclass +class OfferLicenseInfo: + bound_to_ip: bool + + +@dataclass +class OfferRPNInfo: + speed: int + + +@dataclass +class OfferSANInfo: + size: int + """ + SAN size (in bytes). + """ + + ha: bool + """ + High availability offer. + """ + + device_type: OfferSANInfoType + """ + Type of SAN device (hdd / ssd). + """ + + +@dataclass +class OfferStorageInfo: + max_quota: int + + size: int + + +@dataclass +class IP: + ip_id: int + """ + ID of the IP. + """ + + address: str + """ + Address of the IP. + """ + + reverse: str + """ + Reverse IP value. + """ + + version: IPVersion + """ + Version of IP (v4 or v6). + """ + + cidr: int + """ + Classless InterDomain Routing notation of the IP. + """ + + netmask: str + """ + Network mask of IP. + """ + + semantic: IPSemantic + """ + Semantic of IP. + """ + + gateway: str + """ + Gateway of IP. + """ + + status: IPStatus + """ + Status of the IP. + """ + + +@dataclass +class Offer: + id: int + """ + ID of the offer. + """ + + name: str + """ + Name of the offer. + """ + + catalog: OfferCatalog + """ + Catalog of the offer. + """ + + payment_frequency: OfferPaymentFrequency + """ + Payment frequency of the offer. + """ + + pricing: Optional[Money] + """ + Price of the offer. + """ + + server_info: Optional[OfferServerInfo] + + service_level_info: Optional[OfferServiceLevelInfo] + + rpn_info: Optional[OfferRPNInfo] + + san_info: Optional[OfferSANInfo] + + antidos_info: Optional[OfferAntiDosInfo] + + backup_info: Optional[OfferBackupInfo] + + usb_storage_info: Optional[OfferStorageInfo] + + storage_info: Optional[OfferStorageInfo] + + license_info: Optional[OfferLicenseInfo] + + failover_ip_info: Optional[OfferFailoverIpInfo] + + failover_block_info: Optional[OfferFailoverBlockInfo] + + bandwidth_info: Optional[OfferBandwidthInfo] + + +@dataclass +class NetworkInterface: + card_id: int + """ + Card ID of the network interface. + """ + + device_id: int + """ + Device ID of the network interface. + """ + + mac: str + """ + MAC address of the network interface. + """ + + type_: NetworkInterfaceInterfaceType + """ + Network interface type. + """ + + ips: List[IP] + """ + IPs of the network interface. + """ + + +@dataclass +class OS: + id: int + """ + ID of the OS. + """ + + name: str + """ + Name of the OS. + """ + + type_: OSType + """ + Type of the OS. + """ + + version: str + """ + Version of the OS. + """ + + arch: OSArch + """ + Architecture of the OS. + """ + + allow_custom_partitioning: bool + """ + True if the OS allow custom partitioning. + """ + + allow_ssh_keys: bool + """ + True if the OS allow SSH Keys. + """ + + requires_user: bool + """ + True if the OS requires user. + """ + + requires_admin_password: bool + """ + True if the OS requires admin password. + """ + + requires_panel_password: bool + """ + True if the OS requires panel password. + """ + + allowed_filesystems: List[PartitionFileSystem] + """ + True if the OS allow file systems. + """ + + requires_license: bool + """ + True if the OS requires license. + """ + + license_offers: List[Offer] + """ + License offers available with the OS. + """ + + display_name: str + """ + Display name of the OS. + """ + + password_regex: str + """ + Regex used to validate the installation passwords. + """ + + hostname_max_length: int + """ + Hostname max length. + """ + + max_partitions: Optional[int] + """ + Maximum number of partitions which can be created. + """ + + panel_password_regex: Optional[str] + """ + Regex used to validate the panel installation password. + """ + + requires_valid_hostname: Optional[bool] + """ + If both requires_valid_hostname & hostname_regex are set, it means that at least one of the criteria must be valid. + """ + + hostname_regex: Optional[str] + """ + If both requires_valid_hostname & hostname_regex are set, it means that at least one of the criteria must be valid. + """ + + released_at: Optional[datetime] + """ + OS release date. + """ + + +@dataclass +class ServerLocation: + rack: str + + room: str + + datacenter_name: str + + +@dataclass +class ServerOption: + options: List[ServerOption] + + offer: Optional[Offer] + + created_at: Optional[datetime] + + updated_at: Optional[datetime] + + expired_at: Optional[datetime] + + +@dataclass +class ServiceLevel: + offer_id: int + """ + Offer ID of service level. + """ + + level: ServiceLevelLevel + """ + Level type of service level. + """ + + +@dataclass +class RpnSan: + id: int + """ + RPN SAN ID. + """ + + datacenter_name: str + """ + Datacenter location. + """ + + organization_id: str + """ + Organization ID. + """ + + project_id: str + """ + Project ID. + """ + + server_hostname: str + """ + RPN SAN server hostname. + """ + + iqn_suffix: str + """ + IQN suffix. + """ + + offer_id: int + """ + Offer ID. + """ + + created_at: Optional[datetime] + """ + Date of creation of the RPN SAN. + """ + + offer_name: str + """ + Offer description. + """ + + status: RpnSanStatus + """ + Status. + """ + + storage_size: int + """ + RPN SAN storage size. + """ + + iqn: str + + rpnv1_compatible: bool + """ + True if the SAN is compatible with the RPNv1 technology. + """ + + rpnv1_implicit: bool + """ + True if the offer supports the RPNv1 implicitly, false if it must to be added to a group to support RPNv1. + """ + + offer: Optional[Offer] + + delivered_at: Optional[datetime] + """ + RPN SAN delivery date. + """ + + terminated_at: Optional[datetime] + """ + RPN SAN termination date. + """ + + expires_at: Optional[datetime] + """ + RPN SAN expiration date. + """ + + +@dataclass +class RpnGroup: + id: int + """ + Rpn group member ID. + """ + + name: str + """ + Rpn group name. + """ + + type_: RpnGroupType + """ + Rpn group type (local or shared). + """ + + active: bool + """ + Whether the group is active or not. + """ + + owner: str + """ + RPN group owner. + """ + + members_count: int + """ + Total number of members. + """ + + organization_id: str + """ + Rpn group organization ID. + """ + + project_id: str + """ + Rpn group project ID. + """ + + created_at: Optional[datetime] + """ + Rpn group creation date. + """ + + +@dataclass +class RpnV2GroupSubnet: + address: str + + cidr: int + + +@dataclass +class Server: + id: int + """ + ID of the server. + """ + + organization_id: str + """ + Organization ID the server is attached to. + """ + + project_id: str + """ + Project ID the server is attached to. + """ + + hostname: str + """ + Hostname of the server. + """ + + rebooted_at: Optional[datetime] + """ + Date of last reboot of the server. + """ + + status: ServerStatus + """ + Status of the server. + """ + + abuse_contact: str + """ + Abuse contact of the server. + """ + + interfaces: List[NetworkInterface] + """ + Network interfaces of the server. + """ + + zone: ScwZone + """ + The zone in which is the server. + """ + + options: List[ServerOption] + """ + Options subscribe on the server. + """ + + has_bmc: bool + """ + Boolean if the server has a BMC. + """ + + tags: List[str] + """ + Array of customs tags attached to the server. + """ + + is_outsourced: bool + """ + Whether the server is outsourced or not. + """ + + ipv6_slaac: bool + """ + Whether or not you can enable/disable the IPv6. + """ + + qinq: bool + """ + Whether the server is compatible with QinQ. + """ + + is_rpnv2_member: bool + """ + Whether or not the server is already part of an rpnv2 group. + """ + + created_at: Optional[datetime] + """ + Date of creation of the server. + """ + + updated_at: Optional[datetime] + """ + Date of last modification of the server. + """ + + expired_at: Optional[datetime] + """ + Date of release of the server. + """ + + offer: Optional[Offer] + """ + Offer of the server. + """ + + location: Optional[ServerLocation] + """ + Location of the server. + """ + + os: Optional[OS] + """ + OS installed on the server. + """ + + level: Optional[ServiceLevel] + """ + Service level of the server. + """ + + rescue_os: Optional[OS] + """ + Rescue OS of the server. + """ + + +@dataclass +class FailoverBlock: + id: int + """ + ID of the failover block. + """ + + address: str + """ + IP of the failover block. + """ + + nameservers: List[str] + """ + Name servers. + """ + + ip_version: FailoverBlockVersion + """ + IP version of the failover block. + """ + + cidr: int + """ + Classless InterDomain Routing notation of the failover block. + """ + + netmask: str + """ + Netmask of the failover block. + """ + + gateway_ip: str + """ + Gateway IP of the failover block. + """ + + +@dataclass +class RpnSanIpRpnV2Group: + id: int + + name: str + + +@dataclass +class RpnSanIpServer: + id: int + + hostname: str + + datacenter_name: str + + +@dataclass +class RpnSanServer: + id: int + """ + The RPN SAN server ID. + """ + + datacenter_name: str + """ + The RPN SAN server datacenter name. + """ + + hostname: str + """ + The RPN SAN server hostname. + """ + + sans: List[RpnSan] + """ + RPN SANs linked to the RPN SAN server. + """ + + zone: ScwZone + """ + The RPN SAN server zone. + """ + + +@dataclass +class RpnV2Group: + id: int + """ + RPN V2 group ID. + """ + + name: str + """ + RPN V2 group name. + """ + + compatible_rpnv1: bool + """ + Whether or not the RPN V1 compatibility was enabled. + """ + + organization_id: str + """ + Organization ID of the RPN V2 group. + """ + + project_id: str + """ + Project ID of the RPN V2 group. + """ + + type_: RpnV2GroupType + """ + RPN V2 group type (qing / standard). + """ + + status: RpnV2GroupStatus + """ + RPN V2 group status. + """ + + owner: str + """ + RPN V2 group owner. + """ + + members_count: int + """ + Total number of members. + """ + + gateway: str + """ + RPN V2 gateway. + """ + + subnet: Optional[RpnV2GroupSubnet] + """ + RPN V2 subnet. + """ + + rpnv1_group: Optional[RpnGroup] + """ + The RPNv1 group (if the compatibility was enabled). + """ + + +@dataclass +class RpnV2Member: + id: int + """ + RPN V2 member ID. + """ + + status: RpnV2MemberStatus + """ + RPN V2 member status. + """ + + vlan: str + """ + RPN V2 member VLAN. + """ + + speed: Optional[int] + """ + RPN speed. + """ + + server: Optional[Server] + + rpnv1_group: Optional[RpnGroup] + + +@dataclass +class ServerDisk: + id: int + + connector: str + + type_: ServerDiskType + + capacity: int + + is_addon: bool + + +@dataclass +class Service: + id: int + """ + ID of the service. + """ + + provisioning_status: ServiceProvisioningStatus + """ + Provisioning status of the service. + """ + + type_: ServiceType + """ + Service type, either order or service. + """ + + resource_id: Optional[int] + """ + Resource ID of the service. + """ + + offer: Optional[Offer] + """ + Offer of the service. + """ + + created_at: Optional[datetime] + """ + Creation date of the service. + """ + + delivered_at: Optional[datetime] + """ + Delivery date of the service. + """ + + terminated_at: Optional[datetime] + """ + Terminatation date of the service. + """ + + expires_at: Optional[datetime] + """ + Expiration date of the service. + """ + + +@dataclass +class GetIPv6BlockQuotasResponseQuota: + quota: int + + cidr: int + + +@dataclass +class InstallPartition: + file_system: PartitionFileSystem + """ + File system of the installation partition. + """ + + raid_level: RaidArrayRaidLevel + """ + RAID level of the installation partition. + """ + + capacity: int + """ + Capacity of the installation partition. + """ + + connectors: List[str] + """ + Connectors of the installation partition. + """ + + mount_point: Optional[str] + """ + Mount point of the installation partition. + """ + + +@dataclass +class FailoverIP: + id: int + """ + ID of the failover IP. + """ + + address: str + """ + IP of the failover IP. + """ + + reverse: str + """ + Reverse IP value. + """ + + ip_version: FailoverIPVersion + """ + IP version of the failover IP. + """ + + cidr: int + """ + Classless InterDomain Routing notation of the failover IP. + """ + + netmask: str + """ + Netmask of the failover IP. + """ + + gateway_ip: str + """ + Gateway IP of the failover IP. + """ + + status: FailoverIPStatus + """ + Status of the IP failover. + """ + + type_: FailoverIPInterfaceType + """ + The interface type. + """ + + mac: Optional[str] + """ + MAC address of the IP failover. + """ + + server_id: Optional[int] + """ + Server ID linked to the IP failover. + """ + + block: Optional[FailoverBlock] + """ + Block of the IP failover. + """ + + server_zone: Optional[str] + """ + The server zone (if assigned). + """ + + +@dataclass +class ListIPv6BlockSubnetsAvailableResponseSubnet: + address: str + + cidr: int + + +@dataclass +class InvoiceSummary: + id: int + + status: InvoiceStatus + + payment_method: InvoicePaymentMethod + + transaction_id: int + + total_with_taxes: Optional[Money] + + total_without_taxes: Optional[Money] + + created_at: Optional[datetime] + + paid_at: Optional[datetime] + + +@dataclass +class RpnSanIp: + type_: RpnSanIpType + """ + IP type (server | rpnv2_subnet). + """ + + ip: Optional[IP] + """ + An IP object. + """ + + server: Optional[RpnSanIpServer] + + rpnv2_group: Optional[RpnSanIpRpnV2Group] + + +@dataclass +class RefundSummary: + id: int + + status: RefundStatus + + method: RefundMethod + + total_with_taxes: Optional[Money] + + total_without_taxes: Optional[Money] + + created_at: Optional[datetime] + + refunded_at: Optional[datetime] + + +@dataclass +class RpnGroupMember: + id: int + """ + Rpn group member ID. + """ + + status: RpnGroupMemberStatus + """ + RPN group member status. + """ + + group_id: int + """ + RPN group ID. + """ + + group_name: str + """ + RPN group name. + """ + + group_owner: str + """ + RPN group owner. + """ + + owner: str + """ + RPN member owner. + """ + + san_server: Optional[RpnSanServer] + """ + Authorized RPN SAN server. + """ + + server: Optional[Server] + """ + Authorized rpn v1 capable server. + """ + + speed: Optional[int] + """ + RPN speed. + """ + + +@dataclass +class RpnSanSummary: + id: int + """ + RPN SAN ID. + """ + + datacenter_name: str + """ + Datacenter location. + """ + + organization_id: str + """ + Organization ID. + """ + + project_id: str + """ + Project ID. + """ + + server_hostname: str + """ + RPN SAN server hostname. + """ + + iqn_suffix: str + """ + IQN suffix. + """ + + offer_id: int + """ + Offer ID. + """ + + created_at: Optional[datetime] + """ + Date of creation of the RPN SAN. + """ + + offer_name: str + """ + Offer description. + """ + + status: RpnSanStatus + """ + Status. + """ + + storage_size: int + """ + RPN SAN storage size. + """ + + rpnv1_compatible: bool + """ + True if the SAN is compatible with the RPNv1 technology. + """ + + rpnv1_implicit: bool + """ + True if the offer supports the RPNv1 implicitly, false if it must to be added to a group to support RPNv1. + """ + + delivered_at: Optional[datetime] + """ + RPN SAN delivery date. + """ + + terminated_at: Optional[datetime] + """ + RPN SAN termination date. + """ + + expires_at: Optional[datetime] + """ + RPN SAN expiration date. + """ + + +@dataclass +class RpnServerCapability: + id: int + """ + Server ID. + """ + + hostname: str + """ + Server hostname. + """ + + datacenter_name: str + """ + Server datacenter name. + """ + + zone: ScwZone + """ + Server zone. + """ + + compatible_qinq: bool + """ + True if server is compatible with QinQ protocol (rpn v2). + """ + + can_join_qinq_group: bool + """ + True if server can join a QinQ group. + """ + + rpnv1_group_count: int + """ + Times server is linked in a rpnv1 group. + """ + + rpnv2_group_count: int + """ + Times server is linked in a rpnv2 group. + """ + + can_join_rpnv2_group: bool + """ + True if server can join an rpnv2 group. + """ + + ip_address: Optional[str] + """ + Private IP address (if rpn compatiblle). + """ + + rpn_version: Optional[int] + """ + Supported rpn version. + """ + + +@dataclass +class Log: + id: int + """ + RPN V2 log ID. + """ + + action: LogAction + """ + Which action was performed. + """ + + status: LogStatus + """ + Action status. + """ + + group: Optional[RpnV2Group] + """ + RPN V2 group. + """ + + member: Optional[RpnV2Member] + """ + RPN V2 member (if appliable). + """ + + created_at: Optional[datetime] + """ + Creation date. + """ + + finished_at: Optional[datetime] + """ + Completion date. + """ + + +@dataclass +class ServerEvent: + event_id: int + """ + ID of the event. + """ + + description: str + """ + Description of the event. + """ + + date: Optional[datetime] + """ + Date of the event. + """ + + +@dataclass +class ServerSummary: + id: int + """ + ID of the server. + """ + + datacenter_name: str + """ + Datacenter of the server. + """ + + organization_id: str + """ + Organization ID the server is attached to. + """ + + project_id: str + """ + Project ID the server is attached to. + """ + + hostname: str + """ + Hostname of the server. + """ + + created_at: Optional[datetime] + """ + Date of creation of the server. + """ + + updated_at: Optional[datetime] + """ + Date of last modification of the server. + """ + + expired_at: Optional[datetime] + """ + Date of release of the server. + """ + + offer_id: int + """ + Offer ID of the server. + """ + + offer_name: str + """ + Offer name of the server. + """ + + status: ServerStatus + """ + Status of the server. + """ + + interfaces: List[NetworkInterface] + """ + Network interfaces of the server. + """ + + zone: ScwZone + """ + The zone in which is the server. + """ + + is_outsourced: bool + """ + Whether the server is outsourced or not. + """ + + qinq: bool + """ + Whether the server is compatible with QinQ. + """ + + os_id: Optional[int] + """ + OS ID installed on server. + """ + + level: Optional[ServiceLevel] + """ + Service level of the server. + """ + + rpn_version: Optional[int] + """ + Supported RPN version. + """ + + +@dataclass +class CPU: + name: str + """ + Name of CPU. + """ + + core_count: int + """ + Number of cores of the CPU. + """ + + thread_count: int + """ + Number of threads of the CPU. + """ + + frequency: int + """ + Frequency of the CPU. + """ + + +@dataclass +class Disk: + capacity: int + """ + Capacity of the disk. + """ + + type_: ServerDiskType + """ + Type of the disk. + """ + + +@dataclass +class Memory: + capacity: int + """ + Capacity of the memory. + """ + + type_: MemoryType + """ + Type of the memory. + """ + + frequency: int + """ + Frequency of the memory. + """ + + is_ecc: bool + """ + True if the memory is an error-correcting code memory. + """ + + +@dataclass +class PersistentMemory: + capacity: int + """ + Capacity of the persistent memory. + """ + + frequency: int + """ + Frequency of the persistent memory. + """ + + model: str + """ + Model of the persistent memory. + """ + + +@dataclass +class RaidController: + model: str + """ + Model of the RAID controller. + """ + + raid_level: List[str] + """ + RAID level of the RAID controller. + """ + + +@dataclass +class RaidArray: + raid_level: RaidArrayRaidLevel + """ + The RAID level. + """ + + disks: List[ServerDisk] + """ + Disks on the RAID controller. + """ + + +@dataclass +class Partition: + type_: PartitionType + """ + Type of the partition. + """ + + file_system: PartitionFileSystem + """ + File system of the partition. + """ + + raid_level: RaidArrayRaidLevel + """ + Raid level of the partition. + """ + + capacity: int + """ + Capacity of the partition. + """ + + connectors: List[str] + """ + Connectors of the partition. + """ + + mount_point: Optional[str] + """ + Mount point of the partition. + """ + + +@dataclass +class UpdatableRaidArray: + raid_level: RaidArrayRaidLevel + """ + The RAID level. + """ + + disk_ids: List[int] + """ + The list of Disk ID of the updatable RAID. + """ + + +@dataclass +class AttachFailoverIPToMacAddressRequest: + ip_id: int + """ + ID of the failover IP. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + type_: Optional[AttachFailoverIPToMacAddressRequestMacType] + """ + A mac type. + """ + + mac: Optional[str] + """ + A valid mac address (existing or not). + """ + + +@dataclass +class AttachFailoverIPsRequest: + server_id: int + """ + ID of the server. + """ + + fips_ids: List[int] + """ + List of ID of failovers IP to attach. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class BMCAccess: + url: str + """ + URL to access to the server console. + """ + + login: str + """ + The login to use for the BMC (Baseboard Management Controller) access authentification. + """ + + password: str + """ + The password to use for the BMC (Baseboard Management Controller) access authentification. + """ + + status: BMCAccessStatus + """ + Status of the connection. + """ + + expires_at: Optional[datetime] + """ + The date after which the BMC (Baseboard Management Controller) access will be closed. + """ + + +@dataclass +class Backup: + id: int + """ + ID of the backup. + """ + + login: str + """ + Login of the backup. + """ + + server: str + """ + Server of the backup. + """ + + status: BackupStatus + """ + Status of the backup. + """ + + acl_enabled: bool + """ + ACL enable boolean of the backup. + """ + + autologin: bool + """ + Autologin boolean of the backup. + """ + + quota_space: int + """ + Total quota space of the backup. + """ + + quota_space_used: int + """ + Quota space used of the backup. + """ + + quota_files: int + """ + Total quota files of the backup. + """ + + quota_files_used: int + """ + Quota files used of the backup. + """ + + +@dataclass +class BillingApiCanOrderRequest: + project_id: Optional[str] + + +@dataclass +class BillingApiDownloadInvoiceRequest: + invoice_id: int + + +@dataclass +class BillingApiDownloadRefundRequest: + refund_id: int + + +@dataclass +class BillingApiGetInvoiceRequest: + invoice_id: int + + +@dataclass +class BillingApiGetRefundRequest: + refund_id: int + + +@dataclass +class BillingApiListInvoicesRequest: + page: Optional[int] + + page_size: Optional[int] + + order_by: Optional[ListInvoicesRequestOrderBy] + + project_id: Optional[str] + + +@dataclass +class BillingApiListRefundsRequest: + page: Optional[int] + + page_size: Optional[int] + + order_by: Optional[ListRefundsRequestOrderBy] + + project_id: Optional[str] + + +@dataclass +class CanOrderResponse: + can_order: bool + + quota_ok: bool + + phone_confirmed: bool + + email_confirmed: bool + + user_confirmed: bool + + payment_mode: bool + + billing_ok: bool + + message: Optional[str] + + +@dataclass +class CancelServerInstallRequest: + server_id: int + """ + Server ID of the server to cancel install. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class CreateFailoverIPsRequest: + offer_id: int + """ + Failover IP offer ID. + """ + + quantity: int + """ + Quantity. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class CreateFailoverIPsResponse: + total_count: int + + services: List[Service] + + +@dataclass +class CreateServerRequest: + offer_id: int + """ + Offer ID of the new server. + """ + + server_option_ids: List[int] + """ + Server option IDs of the new server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID of the new server. + """ + + datacenter_name: Optional[str] + """ + Datacenter name of the new server. + """ + + +@dataclass +class DeleteFailoverIPRequest: + ip_id: int + """ + ID of the failover IP to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteServerRequest: + server_id: int + """ + Server ID to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteServiceRequest: + service_id: int + """ + ID of the service. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DetachFailoverIPFromMacAddressRequest: + ip_id: int + """ + ID of the failover IP. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DetachFailoverIPsRequest: + fips_ids: List[int] + """ + List of IDs of failovers IP to detach. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetBMCAccessRequest: + server_id: int + """ + ID of the server to get BMC access. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetFailoverIPRequest: + ip_id: int + """ + ID of the failover IP. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetIPv6BlockQuotasResponse: + quotas: List[GetIPv6BlockQuotasResponseQuota] + """ + Quota for each CIDR of IPv6 block. + """ + + total_count: int + """ + Total count of quotas. + """ + + +@dataclass +class GetOSRequest: + os_id: int + """ + ID of the OS. + """ + + server_id: int + """ + ID of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class GetOfferRequest: + offer_id: int + """ + ID of offer. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class GetOrderedServiceRequest: + ordered_service_id: int + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetRaidRequest: + server_id: int + """ + ID of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetRemainingQuotaRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class GetRemainingQuotaResponse: + failover_ip_quota: int + """ + Current failover IP quota. + """ + + failover_ip_remaining_quota: int + """ + Remaining failover IP quota. + """ + + failover_block_quota: int + """ + Current failover block quota. + """ + + failover_block_remaining_quota: int + """ + Remaining failover block quota. + """ + + +@dataclass +class GetRescueRequest: + server_id: int + """ + ID of the server to get rescue. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetRpnStatusResponse: + status: GetRpnStatusResponseStatus + """ + If status = 'operational', you can perform rpn actions in write. + """ + + operations_left: Optional[int] + """ + Number of operations left to perform before being operational. + """ + + +@dataclass +class GetServerBackupRequest: + server_id: int + """ + Server ID of the backup. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetServerDefaultPartitioningRequest: + server_id: int + """ + ID of the server. + """ + + os_id: int + """ + OS ID of the default partitioning. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetServerInstallRequest: + server_id: int + """ + Server ID of the server to install. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetServerRequest: + server_id: int + """ + ID of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetServiceRequest: + service_id: int + """ + ID of the service. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class IPv6Block: + id: int + """ + ID of the IPv6. + """ + + address: str + """ + Address of the IPv6. + """ + + duid: str + """ + DUID of the IPv6. + """ + + nameservers: List[str] + """ + DNS linked to the IPv6. + """ + + cidr: int + """ + Classless InterDomain Routing notation of the IPv6. + """ + + subnets: List[IPv6Block] + """ + All IPv6 subnets. + """ + + delegation_status: IPv6BlockDelegationStatus + """ + The nameservers delegation status. + """ + + +@dataclass +class IPv6BlockApiCreateIPv6BlockRequest: + project_id: Optional[str] + """ + ID of the project. + """ + + +@dataclass +class IPv6BlockApiCreateIPv6BlockSubnetRequest: + block_id: int + """ + ID of the IPv6 block. + """ + + address: str + """ + Address of the IPv6. + """ + + cidr: int + """ + Classless InterDomain Routing notation of the IPv6. + """ + + +@dataclass +class IPv6BlockApiDeleteIPv6BlockRequest: + block_id: int + """ + ID of the IPv6 block to delete. + """ + + +@dataclass +class IPv6BlockApiGetIPv6BlockQuotasRequest: + project_id: Optional[str] + """ + ID of the project. + """ + + +@dataclass +class IPv6BlockApiGetIPv6BlockRequest: + project_id: Optional[str] + """ + ID of the project. + """ + + +@dataclass +class IPv6BlockApiListIPv6BlockSubnetsAvailableRequest: + block_id: int + """ + ID of the IPv6 block. + """ + + +@dataclass +class IPv6BlockApiUpdateIPv6BlockRequest: + block_id: int + """ + ID of the IPv6 block. + """ + + nameservers: Optional[List[str]] + """ + DNS to link to the IPv6. + """ + + +@dataclass +class InstallServerRequest: + server_id: int + """ + Server ID to install. + """ + + os_id: int + """ + OS ID to install on the server. + """ + + hostname: str + """ + Hostname of the server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + user_login: Optional[str] + """ + User to install on the server. + """ + + user_password: Optional[str] + """ + User password to install on the server. + """ + + panel_password: Optional[str] + """ + Panel password to install on the server. + """ + + root_password: Optional[str] + """ + Root password to install on the server. + """ + + partitions: Optional[List[InstallPartition]] + """ + Partitions to install on the server. + """ + + ssh_key_ids: Optional[List[str]] + """ + SSH key IDs authorized on the server. + """ + + license_offer_id: Optional[int] + """ + Offer ID of license to install on server. + """ + + ip_id: Optional[int] + """ + IP to link at the license to install on server. + """ + + +@dataclass +class Invoice: + id: int + + status: InvoiceStatus + + payment_method: InvoicePaymentMethod + + content: str + + transaction_id: int + + total_with_taxes: Optional[Money] + + total_without_taxes: Optional[Money] + + created_at: Optional[datetime] + + paid_at: Optional[datetime] + + +@dataclass +class ListFailoverIPsRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of failovers IP per page. + """ + + order_by: Optional[ListFailoverIPsRequestOrderBy] + """ + Order of the failovers IP. + """ + + project_id: Optional[str] + """ + Filter failovers IP by project ID. + """ + + search: Optional[str] + """ + Filter failovers IP which matching with this field. + """ + + only_available: Optional[bool] + """ + True: return all failovers IP not attached on server +false: return all failovers IP attached on server. + """ + + +@dataclass +class ListFailoverIPsResponse: + total_count: int + """ + Total count of matching failovers IP. + """ + + failover_ips: List[FailoverIP] + """ + List of failover IPs that match filters. + """ + + +@dataclass +class ListIPv6BlockSubnetsAvailableResponse: + subnet_availables: List[ListIPv6BlockSubnetsAvailableResponseSubnet] + """ + All available address and CIDR available in subnet. + """ + + total_count: int + """ + Total count of available subnets. + """ + + +@dataclass +class ListInvoicesResponse: + total_count: int + + invoices: List[InvoiceSummary] + + +@dataclass +class ListIpsResponse: + total_count: int + """ + Total count of authorized IPs. + """ + + ips: List[RpnSanIp] + """ + List of authorized IPs. + """ + + +@dataclass +class ListOSRequest: + server_id: int + """ + Filter OS by compatible server ID. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of OS per page. + """ + + order_by: Optional[ListOSRequestOrderBy] + """ + Order of the OS. + """ + + type_: Optional[OSType] + """ + Type of the OS. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class ListOSResponse: + total_count: int + """ + Total count of matching OS. + """ + + os: List[OS] + """ + OS that match filters. + """ + + +@dataclass +class ListOffersRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of offer per page. + """ + + order_by: Optional[ListOffersRequestOrderBy] + """ + Order of the offers. + """ + + commercial_range: Optional[str] + """ + Filter on commercial range. + """ + + catalog: Optional[OfferCatalog] + """ + Filter on catalog. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + is_failover_ip: Optional[bool] + """ + Get the current failover IP offer. + """ + + is_failover_block: Optional[bool] + """ + Get the current failover IP block offer. + """ + + sold_in: Optional[List[str]] + """ + Filter offers depending on their datacenter. + """ + + available_only: Optional[bool] + """ + Set this filter to true to only return available offers. + """ + + is_rpn_san: Optional[bool] + """ + Get the RPN SAN offers. + """ + + +@dataclass +class ListOffersResponse: + total_count: int + """ + Total count of matching offers. + """ + + offers: List[Offer] + """ + Offers that match filters. + """ + + +@dataclass +class ListRefundsResponse: + total_count: int + + refunds: List[RefundSummary] + + +@dataclass +class ListRpnCapableSanServersResponse: + total_count: int + """ + Total count of rpn capable san servers. + """ + + san_servers: List[RpnSanServer] + """ + List of san servers. + """ + + +@dataclass +class ListRpnCapableServersResponse: + total_count: int + """ + Total count of rpn capable servers. + """ + + servers: List[Server] + """ + List of servers. + """ + + +@dataclass +class ListRpnGroupMembersResponse: + total_count: int + """ + Total count of rpn v1 group members. + """ + + members: List[RpnGroupMember] + """ + List of rpn v1 group members. + """ + + +@dataclass +class ListRpnGroupsResponse: + total_count: int + """ + Total count of rpn groups. + """ + + rpn_groups: List[RpnGroup] + """ + List of rpn v1 groups. + """ + + +@dataclass +class ListRpnInvitesResponse: + total_count: int + """ + Total count of invites. + """ + + members: List[RpnGroupMember] + """ + List of invites. + """ + + +@dataclass +class ListRpnSansResponse: + total_count: int + """ + Total count of matching RPN SANs. + """ + + rpn_sans: List[RpnSanSummary] + """ + List of RPN SANs that match filters. + """ + + +@dataclass +class ListRpnServerCapabilitiesResponse: + total_count: int + """ + Total count of servers. + """ + + servers: List[RpnServerCapability] + """ + List of servers and their RPN capabilities. + """ + + +@dataclass +class ListRpnV2CapableResourcesResponse: + total_count: int + """ + Total count of matching rpn v2 capable resources. + """ + + servers: List[Server] + """ + List of rpn v2 capable resources that match filters. + """ + + +@dataclass +class ListRpnV2GroupLogsResponse: + total_count: int + """ + Total count of matching rpn v2 logs. + """ + + logs: List[Log] + """ + List of rpn v2 logs that match filters. + """ + + +@dataclass +class ListRpnV2GroupsResponse: + total_count: int + """ + Total count of matching rpn v2 groups. + """ + + rpn_groups: List[RpnV2Group] + """ + List of rpn v2 groups that match filters. + """ + + +@dataclass +class ListRpnV2MembersResponse: + total_count: int + """ + Total count of matching rpn v2 group members. + """ + + members: List[RpnV2Member] + """ + List of rpn v2 group members that match filters. + """ + + +@dataclass +class ListServerDisksRequest: + server_id: int + """ + Server ID of the server disks. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of server disk per page. + """ + + order_by: Optional[ListServerDisksRequestOrderBy] + """ + Order of the server disks. + """ + + +@dataclass +class ListServerDisksResponse: + total_count: int + """ + Total count of matching server disks. + """ + + disks: List[ServerDisk] + """ + Server disks that match filters. + """ + + +@dataclass +class ListServerEventsRequest: + server_id: int + """ + Server ID of the server events. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of server event per page. + """ + + order_by: Optional[ListServerEventsRequestOrderBy] + """ + Order of the server events. + """ + + +@dataclass +class ListServerEventsResponse: + total_count: int + """ + Total count of matching server events. + """ + + events: List[ServerEvent] + """ + Server events that match filters. + """ + + +@dataclass +class ListServersRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of server per page. + """ + + order_by: Optional[ListServersRequestOrderBy] + """ + Order of the servers. + """ + + project_id: Optional[str] + """ + Filter servers by project ID. + """ + + search: Optional[str] + """ + Filter servers by hostname. + """ + + +@dataclass +class ListServersResponse: + total_count: int + """ + Total count of matching servers. + """ + + servers: List[ServerSummary] + """ + Servers that match filters. + """ + + +@dataclass +class ListServicesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of service per page. + """ + + order_by: Optional[ListServicesRequestOrderBy] + """ + Order of the services. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + +@dataclass +class ListServicesResponse: + total_count: int + """ + Total count of matching services. + """ + + services: List[Service] + """ + Services that match filters. + """ + + +@dataclass +class ListSubscribableServerOptionsRequest: + server_id: int + """ + Server ID of the subscribable server options. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of subscribable server option per page. + """ + + +@dataclass +class ListSubscribableServerOptionsResponse: + total_count: int + """ + Total count of matching subscribable server options. + """ + + server_options: List[Offer] + """ + Server options that match filters. + """ + + +@dataclass +class OfferFailoverBlockInfo: + onetime_fees: Optional[Offer] + + +@dataclass +class OfferFailoverIpInfo: + onetime_fees: Optional[Offer] + + +@dataclass +class OfferServerInfo: + bandwidth: int + + stock: OfferServerInfoStock + + commercial_range: str + + disks: List[Disk] + + cpus: List[CPU] + + memories: List[Memory] + + persistent_memories: List[PersistentMemory] + + raid_controllers: List[RaidController] + + available_options: List[Offer] + + connectivity: int + + stock_by_datacenter: Dict[str, OfferServerInfoStock] + + rpn_version: Optional[int] + + onetime_fees: Optional[Offer] + + +@dataclass +class OfferServiceLevelInfo: + support_ticket: bool + + support_phone: bool + + sales_support: bool + + git: str + + sla: float + + priority_support: bool + + high_rpn_bandwidth: bool + + customization: bool + + antidos: bool + + extra_failover_quota: int + + available_options: List[Offer] + + +@dataclass +class Raid: + raid_arrays: List[RaidArray] + """ + Details about the RAID controller. + """ + + +@dataclass +class RebootServerRequest: + server_id: int + """ + Server ID to reboot. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class Refund: + id: int + + status: RefundStatus + + method: RefundMethod + + content: str + + total_with_taxes: Optional[Money] + + total_without_taxes: Optional[Money] + + created_at: Optional[datetime] + + refunded_at: Optional[datetime] + + +@dataclass +class Rescue: + os_id: int + """ + OS ID of the rescue. + """ + + login: str + """ + Login of the rescue. + """ + + password: str + """ + Password of the rescue. + """ + + protocol: RescueProtocol + """ + Protocol of the resuce. + """ + + +@dataclass +class RpnApiGetRpnStatusRequest: + project_id: Optional[str] + """ + A project ID. + """ + + rpnv1_group_id: Optional[int] + """ + An RPN v1 group ID. + """ + + rpnv2_group_id: Optional[int] + """ + An RPN v2 group ID. + """ + + +@dataclass +class RpnApiListRpnServerCapabilitiesRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of servers per page. + """ + + order_by: Optional[ListRpnServerCapabilitiesRequestOrderBy] + """ + Order of the servers. + """ + + project_id: Optional[str] + """ + Filter servers by project ID. + """ + + +@dataclass +class RpnSanApiAddIpRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + ip_ids: List[int] + """ + An array of IP ID. + """ + + +@dataclass +class RpnSanApiCreateRpnSanRequest: + offer_id: int + """ + Offer ID. + """ + + project_id: Optional[str] + """ + Your project ID. + """ + + +@dataclass +class RpnSanApiDeleteRpnSanRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + +@dataclass +class RpnSanApiGetRpnSanRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + +@dataclass +class RpnSanApiListAvailableIpsRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + type_: Optional[RpnSanIpType] + """ + Filter by IP type (server | rpnv2_subnet). + """ + + +@dataclass +class RpnSanApiListIpsRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + type_: Optional[RpnSanIpType] + """ + Filter by IP type (server | rpnv2_subnet). + """ + + +@dataclass +class RpnSanApiListRpnSansRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of RPN SANs per page. + """ + + order_by: Optional[ListRpnSansRequestOrderBy] + """ + Order of the RPN SANs. + """ + + project_id: Optional[str] + """ + Filter RPN SANs by project ID. + """ + + +@dataclass +class RpnSanApiRemoveIpRequest: + rpn_san_id: int + """ + RPN SAN ID. + """ + + ip_ids: List[int] + """ + An array of IP ID. + """ + + +@dataclass +class RpnV1ApiAcceptRpnInviteRequest: + member_id: int + """ + The member ID. + """ + + +@dataclass +class RpnV1ApiAddRpnGroupMembersRequest: + group_id: int + """ + The rpn v1 group ID. + """ + + server_ids: Optional[List[int]] + """ + A collection of rpn v1 capable server IDs. + """ + + san_server_ids: Optional[List[int]] + """ + A collection of rpn v1 capable RPN SAN server IDs. + """ + + +@dataclass +class RpnV1ApiCreateRpnGroupRequest: + name: str + """ + Rpn v1 group name. + """ + + server_ids: Optional[List[int]] + """ + A collection of rpn v1 capable servers. + """ + + san_server_ids: Optional[List[int]] + """ + A collection of rpn v1 capable rpn sans servers. + """ + + project_id: Optional[str] + """ + A project ID. + """ + + +@dataclass +class RpnV1ApiDeleteRpnGroupMembersRequest: + group_id: int + """ + The rpn v1 group ID. + """ + + member_ids: List[int] + """ + A collection of rpn v1 group members IDs. + """ + + +@dataclass +class RpnV1ApiDeleteRpnGroupRequest: + group_id: int + """ + Rpn v1 group ID. + """ + + +@dataclass +class RpnV1ApiGetRpnGroupRequest: + group_id: int + """ + Rpn v1 group ID. + """ + + +@dataclass +class RpnV1ApiLeaveRpnGroupRequest: + group_id: int + """ + The RPN V1 group ID. + """ + + member_ids: List[int] + """ + A collection of rpn v1 group members IDs. + """ + + project_id: Optional[str] + """ + A project ID. + """ + + +@dataclass +class RpnV1ApiListRpnCapableSanServersRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn capable resources per page. + """ + + order_by: Optional[ListRpnCapableSanServersRequestOrderBy] + """ + Order of the rpn capable resources. + """ + + project_id: Optional[str] + """ + Filter rpn capable resources by project ID. + """ + + +@dataclass +class RpnV1ApiListRpnCapableServersRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn capable resources per page. + """ + + order_by: Optional[ListRpnCapableServersRequestOrderBy] + """ + Order of the rpn capable resources. + """ + + project_id: Optional[str] + """ + Filter rpn capable resources by project ID. + """ + + +@dataclass +class RpnV1ApiListRpnGroupMembersRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v1 group members per page. + """ + + order_by: Optional[ListRpnGroupMembersRequestOrderBy] + """ + Order of the rpn v1 group members. + """ + + group_id: int + """ + Filter rpn v1 group members by group ID. + """ + + project_id: Optional[str] + """ + A project ID. + """ + + +@dataclass +class RpnV1ApiListRpnGroupsRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v1 groups per page. + """ + + order_by: Optional[ListRpnGroupsRequestOrderBy] + """ + Order of the rpn v1 groups. + """ + + project_id: Optional[str] + """ + Filter rpn v1 groups by project ID. + """ + + +@dataclass +class RpnV1ApiListRpnInvitesRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn capable resources per page. + """ + + order_by: Optional[ListRpnInvitesRequestOrderBy] + """ + Order of the rpn capable resources. + """ + + project_id: Optional[str] + """ + Filter rpn capable resources by project ID. + """ + + +@dataclass +class RpnV1ApiRefuseRpnInviteRequest: + member_id: int + """ + The member ID. + """ + + +@dataclass +class RpnV1ApiRpnGroupInviteRequest: + group_id: int + """ + The RPN V1 group ID. + """ + + server_ids: List[int] + """ + A collection of external server IDs. + """ + + project_id: Optional[str] + """ + A project ID. + """ + + +@dataclass +class RpnV1ApiUpdateRpnGroupNameRequest: + group_id: int + """ + Rpn v1 group ID. + """ + + name: Optional[str] + """ + New rpn v1 group name. + """ + + +@dataclass +class RpnV2ApiAddRpnV2MembersRequest: + group_id: int + """ + RPN V2 group ID. + """ + + servers: List[int] + """ + A collection of server IDs. + """ + + +@dataclass +class RpnV2ApiCreateRpnV2GroupRequest: + name: str + """ + RPN V2 group name. + """ + + servers: List[int] + """ + A collection of server IDs. + """ + + project_id: Optional[str] + """ + Project ID of the RPN V2 group. + """ + + type_: Optional[RpnV2GroupType] + """ + RPN V2 group type (qing / standard). + """ + + +@dataclass +class RpnV2ApiDeleteRpnV2GroupRequest: + group_id: int + """ + RPN V2 group ID. + """ + + +@dataclass +class RpnV2ApiDeleteRpnV2MembersRequest: + group_id: int + """ + RPN V2 group ID. + """ + + member_ids: List[int] + """ + A collection of member IDs. + """ + + +@dataclass +class RpnV2ApiDisableRpnV2GroupCompatibilityRequest: + group_id: int + """ + RPN V2 group ID. + """ + + +@dataclass +class RpnV2ApiEnableRpnV2GroupCompatibilityRequest: + group_id: int + """ + RPN V2 group ID. + """ + + rpnv1_group_id: int + """ + RPN V1 group ID. + """ + + +@dataclass +class RpnV2ApiGetRpnV2GroupRequest: + group_id: int + """ + RPN V2 group ID. + """ + + +@dataclass +class RpnV2ApiListRpnV2CapableResourcesRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v2 capable resources per page. + """ + + order_by: Optional[ListRpnV2CapableResourcesRequestOrderBy] + """ + Order of the rpn v2 capable resources. + """ + + project_id: Optional[str] + """ + Filter rpn v2 capable resources by project ID. + """ + + +@dataclass +class RpnV2ApiListRpnV2GroupLogsRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v2 group logs per page. + """ + + order_by: Optional[ListRpnV2GroupLogsRequestOrderBy] + """ + Order of the rpn v2 group logs. + """ + + group_id: int + """ + RPN V2 group ID. + """ + + +@dataclass +class RpnV2ApiListRpnV2GroupsRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v2 groups per page. + """ + + order_by: Optional[ListRpnV2GroupsRequestOrderBy] + """ + Order of the rpn v2 groups. + """ + + project_id: Optional[str] + """ + Filter rpn v2 groups by project ID. + """ + + +@dataclass +class RpnV2ApiListRpnV2MembersRequest: + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + Number of rpn v2 group members per page. + """ + + order_by: Optional[ListRpnV2MembersRequestOrderBy] + """ + Order of the rpn v2 group members. + """ + + group_id: int + """ + RPN V2 group ID. + """ + + type_: Optional[ListRpnV2MembersRequestType] + """ + Filter members by type. + """ + + +@dataclass +class RpnV2ApiUpdateRpnV2GroupNameRequest: + group_id: int + """ + RPN V2 group ID. + """ + + name: Optional[str] + """ + RPN V2 group name. + """ + + +@dataclass +class RpnV2ApiUpdateRpnV2VlanForMembersRequest: + group_id: int + """ + RPN V2 group ID. + """ + + member_ids: List[int] + """ + RPN V2 member IDs. + """ + + vlan: Optional[int] + """ + Min: 0. +Max: 3967. + """ + + +@dataclass +class ServerDefaultPartitioning: + partitions: List[Partition] + """ + Default partitions. + """ + + +@dataclass +class ServerInstall: + os_id: int + + hostname: str + + partitions: List[Partition] + + ssh_key_ids: List[str] + + status: ServerInstallStatus + + user_login: Optional[str] + + panel_url: Optional[str] + + +@dataclass +class StartBMCAccessRequest: + server_id: int + """ + ID of the server to start the BMC access. + """ + + ip: str + """ + The IP authorized to connect to the given server. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StartRescueRequest: + server_id: int + """ + ID of the server to start rescue. + """ + + os_id: int + """ + OS ID to use to start rescue. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StartServerRequest: + server_id: int + """ + Server ID to start. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StopBMCAccessRequest: + server_id: int + """ + ID of the server to stop BMC access. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StopRescueRequest: + server_id: int + """ + ID of the server to stop rescue. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class StopServerRequest: + server_id: int + """ + Server ID to stop. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SubscribeServerOptionRequest: + server_id: int + """ + Server ID to subscribe server option. + """ + + option_id: int + """ + Option ID to subscribe. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SubscribeStorageOptionsRequest: + server_id: int + """ + Server ID of the storage options to subscribe. + """ + + options_ids: List[int] + """ + Option IDs of the storage options to subscribe. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SubscribeStorageOptionsResponse: + services: List[Service] + """ + Services subscribe storage options. + """ + + +@dataclass +class UpdateRaidRequest: + server_id: int + """ + ID of the server. + """ + + raid_arrays: List[UpdatableRaidArray] + """ + RAIDs to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class UpdateReverseRequest: + ip_id: int + """ + ID of the IP. + """ + + reverse: str + """ + Reverse to apply on the IP. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class UpdateServerBackupRequest: + server_id: int + """ + Server ID to update backup. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + password: Optional[str] + """ + Password of the server backup. + """ + + autologin: Optional[bool] + """ + Autologin of the server backup. + """ + + acl_enabled: Optional[bool] + """ + Boolean to enable or disable ACL. + """ + + +@dataclass +class UpdateServerRequest: + server_id: int + """ + Server ID to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + hostname: Optional[str] + """ + Hostname of the server to update. + """ + + enable_ipv6: Optional[bool] + """ + Flag to enable or not the IPv6 of server. + """ + + +@dataclass +class UpdateServerTagsRequest: + server_id: int + """ + Server ID to update the tags. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + tags: Optional[List[str]] + """ + Tags of server to update. + """ diff --git a/scaleway/scaleway/document_db/v1beta1/api.py b/scaleway/scaleway/document_db/v1beta1/api.py index 2fa2aae4..ce0b5d3c 100644 --- a/scaleway/scaleway/document_db/v1beta1/api.py +++ b/scaleway/scaleway/document_db/v1beta1/api.py @@ -143,7 +143,9 @@ class DocumentDbV1Beta1API(API): - """ """ + """ + This API allows you to manage your Document Databases. + """ def list_database_engines( self, diff --git a/scaleway/scaleway/document_db/v1beta1/marshalling.py b/scaleway/scaleway/document_db/v1beta1/marshalling.py index 8efeb6af..0ed12b87 100644 --- a/scaleway/scaleway/document_db/v1beta1/marshalling.py +++ b/scaleway/scaleway/document_db/v1beta1/marshalling.py @@ -155,26 +155,38 @@ def unmarshal_Endpoint(data: Any) -> Endpoint: field = data.get("ip", None) if field is not None: args["ip"] = field + else: + args["ip"] = None field = data.get("name", None) if field is not None: args["name"] = field + else: + args["name"] = None field = data.get("private_network", None) if field is not None: args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None field = data.get("load_balancer", None) if field is not None: args["load_balancer"] = unmarshal_EndpointLoadBalancerDetails(field) + else: + args["load_balancer"] = None field = data.get("direct_access", None) if field is not None: args["direct_access"] = unmarshal_EndpointDirectAccessDetails(field) + else: + args["direct_access"] = None field = data.get("hostname", None) if field is not None: args["hostname"] = field + else: + args["hostname"] = None return Endpoint(**args) @@ -198,18 +210,26 @@ def unmarshal_Maintenance(data: Any) -> Maintenance: field = data.get("starts_at", None) if field is not None: args["starts_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["starts_at"] = None field = data.get("stops_at", None) if field is not None: args["stops_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stops_at"] = None field = data.get("closed_at", None) if field is not None: args["closed_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["closed_at"] = None field = data.get("forced_at", None) if field is not None: args["forced_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["forced_at"] = None return Maintenance(**args) @@ -301,14 +321,20 @@ def unmarshal_InstanceLog(data: Any) -> InstanceLog: field = data.get("download_url", None) if field is not None: args["download_url"] = field + else: + args["download_url"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return InstanceLog(**args) @@ -338,6 +364,8 @@ def unmarshal_BackupSchedule(data: Any) -> BackupSchedule: args["next_run_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["next_run_at"] = None return BackupSchedule(**args) @@ -372,10 +400,14 @@ def unmarshal_LogsPolicy(data: Any) -> LogsPolicy: field = data.get("max_age_retention", None) if field is not None: args["max_age_retention"] = field + else: + args["max_age_retention"] = None field = data.get("total_disk_retention", None) if field is not None: args["total_disk_retention"] = field + else: + args["total_disk_retention"] = None return LogsPolicy(**args) @@ -415,7 +447,7 @@ def unmarshal_Volume(data: Any) -> Volume: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -423,7 +455,7 @@ def unmarshal_Volume(data: Any) -> Volume: if field is not None: args["size"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -457,10 +489,14 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None field = data.get("project_id", None) if field is not None: @@ -499,10 +535,14 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("endpoint", None) if field is not None: args["endpoint"] = unmarshal_Endpoint(field) + else: + args["endpoint"] = None field = data.get("backup_schedule", None) if field is not None: args["backup_schedule"] = unmarshal_BackupSchedule(field) + else: + args["backup_schedule"] = None field = data.get("read_replicas", None) if field is not None: @@ -539,6 +579,8 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("logs_policy", None) if field is not None: args["logs_policy"] = unmarshal_LogsPolicy(field) + else: + args["logs_policy"] = None return Instance(**args) @@ -574,11 +616,11 @@ def unmarshal_SnapshotVolumeType(data: Any) -> SnapshotVolumeType: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -624,22 +666,32 @@ def unmarshal_Snapshot(data: Any) -> Snapshot: field = data.get("size", None) if field is not None: args["size"] = field + else: + args["size"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("volume_type", None) if field is not None: args["volume_type"] = unmarshal_SnapshotVolumeType(field) + else: + args["volume_type"] = None return Snapshot(**args) @@ -694,6 +746,8 @@ def unmarshal_ACLRule(data: Any) -> ACLRule: field = data.get("port", None) if field is not None: args["port"] = field + else: + args["port"] = None return ACLRule(**args) @@ -818,26 +872,38 @@ def unmarshal_EngineSetting(data: Any) -> EngineSetting: field = data.get("unit", None) if field is not None: args["unit"] = field + else: + args["unit"] = None field = data.get("string_constraint", None) if field is not None: args["string_constraint"] = field + else: + args["string_constraint"] = None field = data.get("int_min", None) if field is not None: args["int_min"] = field + else: + args["int_min"] = None field = data.get("int_max", None) if field is not None: args["int_max"] = field + else: + args["int_max"] = None field = data.get("float_min", None) if field is not None: args["float_min"] = field + else: + args["float_min"] = None field = data.get("float_max", None) if field is not None: args["float_max"] = field + else: + args["float_max"] = None return EngineSetting(**args) @@ -883,6 +949,8 @@ def unmarshal_EngineVersion(data: Any) -> EngineVersion: args["end_of_life"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["end_of_life"] = None return EngineVersion(**args) @@ -1089,7 +1157,7 @@ def unmarshal_NodeTypeVolumeType(data: Any) -> NodeTypeVolumeType: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -1109,7 +1177,7 @@ def unmarshal_NodeTypeVolumeType(data: Any) -> NodeTypeVolumeType: if field is not None: args["chunk_size"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -1155,10 +1223,14 @@ def unmarshal_NodeType(data: Any) -> NodeType: field = data.get("volume_constraint", None) if field is not None: args["volume_constraint"] = unmarshal_NodeTypeVolumeConstraintSizes(field) + else: + args["volume_constraint"] = None field = data.get("is_bssd_compatible", None) if field is not None: args["is_bssd_compatible"] = field + else: + args["is_bssd_compatible"] = None field = data.get("available_volume_types", None) if field is not None: @@ -1452,9 +1524,7 @@ def marshal_CreateEndpointRequest( output: Dict[str, Any] = {} if request.endpoint_spec is not None: - output["endpoint_spec"] = ( - marshal_EndpointSpec(request.endpoint_spec, defaults), - ) + output["endpoint_spec"] = marshal_EndpointSpec(request.endpoint_spec, defaults) return output @@ -1644,7 +1714,7 @@ def marshal_CreateSnapshotRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -1798,7 +1868,7 @@ def marshal_UpdateInstanceRequest( output["tags"] = request.tags if request.logs_policy is not None: - output["logs_policy"] = (marshal_LogsPolicy(request.logs_policy, defaults),) + output["logs_policy"] = marshal_LogsPolicy(request.logs_policy, defaults) if request.backup_same_region is not None: output["backup_same_region"] = request.backup_same_region @@ -1819,7 +1889,7 @@ def marshal_UpdateSnapshotRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output diff --git a/scaleway/scaleway/domain/v2beta1/api.py b/scaleway/scaleway/domain/v2beta1/api.py index 3b71987c..4485c50e 100644 --- a/scaleway/scaleway/domain/v2beta1/api.py +++ b/scaleway/scaleway/domain/v2beta1/api.py @@ -170,7 +170,7 @@ class DomainV2Beta1API(API): """ - Manage your domains, DNS zones and records with the Domains and DNS API. + This API allows you to manage your domains, DNS zones and records. """ def list_dns_zones( @@ -2484,7 +2484,7 @@ def enable_domain_dnssec( ) -> Domain: """ Update domain DNSSEC. - If your domain has the default Scaleway NS and uses another registrar, you have to update the DS record manually. + If your domain uses another registrar and has the default Scaleway NS, you have to **update the DS record at your registrar**. :param domain: :param ds_record: :return: :class:`Domain ` diff --git a/scaleway/scaleway/domain/v2beta1/marshalling.py b/scaleway/scaleway/domain/v2beta1/marshalling.py index c198aad5..00214b0e 100644 --- a/scaleway/scaleway/domain/v2beta1/marshalling.py +++ b/scaleway/scaleway/domain/v2beta1/marshalling.py @@ -137,6 +137,8 @@ def unmarshal_ContactExtensionFRAssociationInfo( args["publication_jo"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["publication_jo"] = None return ContactExtensionFRAssociationInfo(**args) @@ -241,24 +243,34 @@ def unmarshal_ContactExtensionFR(data: Any) -> ContactExtensionFR: field = data.get("individual_info", None) if field is not None: args["individual_info"] = unmarshal_ContactExtensionFRIndividualInfo(field) + else: + args["individual_info"] = None field = data.get("duns_info", None) if field is not None: args["duns_info"] = unmarshal_ContactExtensionFRDunsInfo(field) + else: + args["duns_info"] = None field = data.get("association_info", None) if field is not None: args["association_info"] = unmarshal_ContactExtensionFRAssociationInfo(field) + else: + args["association_info"] = None field = data.get("trademark_info", None) if field is not None: args["trademark_info"] = unmarshal_ContactExtensionFRTrademarkInfo(field) + else: + args["trademark_info"] = None field = data.get("code_auth_afnic_info", None) if field is not None: args["code_auth_afnic_info"] = unmarshal_ContactExtensionFRCodeAuthAfnicInfo( field ) + else: + args["code_auth_afnic_info"] = None return ContactExtensionFR(**args) @@ -390,14 +402,20 @@ def unmarshal_Contact(data: Any) -> Contact: args["questions"] = ( [unmarshal_ContactQuestion(v) for v in field] if field is not None else None ) + else: + args["questions"] = None field = data.get("extension_fr", None) if field is not None: args["extension_fr"] = unmarshal_ContactExtensionFR(field) + else: + args["extension_fr"] = None field = data.get("extension_eu", None) if field is not None: args["extension_eu"] = unmarshal_ContactExtensionEU(field) + else: + args["extension_eu"] = None field = data.get("email_status", None) if field is not None: @@ -414,6 +432,8 @@ def unmarshal_Contact(data: Any) -> Contact: field = data.get("extension_nl", None) if field is not None: args["extension_nl"] = unmarshal_ContactExtensionNL(field) + else: + args["extension_nl"] = None return Contact(**args) @@ -463,10 +483,14 @@ def unmarshal_DNSZone(data: Any) -> DNSZone: field = data.get("message", None) if field is not None: args["message"] = field + else: + args["message"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return DNSZone(**args) @@ -529,10 +553,14 @@ def unmarshal_SSLCertificate(data: Any) -> SSLCertificate: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("expired_at", None) if field is not None: args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None return SSLCertificate(**args) @@ -554,6 +582,8 @@ def unmarshal_CheckContactsCompatibilityResponseContactCheckResult( field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None return CheckContactsCompatibilityResponseContactCheckResult(**args) @@ -577,18 +607,24 @@ def unmarshal_CheckContactsCompatibilityResponse( args["owner_check_result"] = ( unmarshal_CheckContactsCompatibilityResponseContactCheckResult(field) ) + else: + args["owner_check_result"] = None field = data.get("administrative_check_result", None) if field is not None: args["administrative_check_result"] = ( unmarshal_CheckContactsCompatibilityResponseContactCheckResult(field) ) + else: + args["administrative_check_result"] = None field = data.get("technical_check_result", None) if field is not None: args["technical_check_result"] = ( unmarshal_CheckContactsCompatibilityResponseContactCheckResult(field) ) + else: + args["technical_check_result"] = None return CheckContactsCompatibilityResponse(**args) @@ -660,7 +696,7 @@ def unmarshal_DSRecordDigest(data: Any) -> DSRecordDigest: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -671,6 +707,8 @@ def unmarshal_DSRecordDigest(data: Any) -> DSRecordDigest: field = data.get("public_key", None) if field is not None: args["public_key"] = unmarshal_DSRecordPublicKey(field) + else: + args["public_key"] = None return DSRecordDigest(**args) @@ -694,10 +732,14 @@ def unmarshal_DSRecord(data: Any) -> DSRecord: field = data.get("digest", None) if field is not None: args["digest"] = unmarshal_DSRecordDigest(field) + else: + args["digest"] = None field = data.get("public_key", None) if field is not None: args["public_key"] = unmarshal_DSRecordPublicKey(field) + else: + args["public_key"] = None return DSRecord(**args) @@ -721,6 +763,8 @@ def unmarshal_TldOffer(data: Any) -> TldOffer: field = data.get("price", None) if field is not None: args["price"] = unmarshal_Money(field) + else: + args["price"] = None return TldOffer(**args) @@ -870,14 +914,20 @@ def unmarshal_Domain(data: Any) -> Domain: field = data.get("dnssec", None) if field is not None: args["dnssec"] = unmarshal_DomainDNSSEC(field) + else: + args["dnssec"] = None field = data.get("expired_at", None) if field is not None: args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("status", None) if field is not None: @@ -902,30 +952,42 @@ def unmarshal_Domain(data: Any) -> Domain: field = data.get("owner_contact", None) if field is not None: args["owner_contact"] = unmarshal_Contact(field) + else: + args["owner_contact"] = None field = data.get("technical_contact", None) if field is not None: args["technical_contact"] = unmarshal_Contact(field) + else: + args["technical_contact"] = None field = data.get("administrative_contact", None) if field is not None: args["administrative_contact"] = unmarshal_Contact(field) + else: + args["administrative_contact"] = None field = data.get("external_domain_registration_status", None) if field is not None: args["external_domain_registration_status"] = ( unmarshal_DomainRegistrationStatusExternalDomain(field) ) + else: + args["external_domain_registration_status"] = None field = data.get("transfer_registration_status", None) if field is not None: args["transfer_registration_status"] = ( unmarshal_DomainRegistrationStatusTransfer(field) ) + else: + args["transfer_registration_status"] = None field = data.get("tld", None) if field is not None: args["tld"] = unmarshal_Tld(field) + else: + args["tld"] = None return Domain(**args) @@ -1062,10 +1124,14 @@ def unmarshal_RecordHTTPServiceConfig(data: Any) -> RecordHTTPServiceConfig: field = data.get("must_contain", None) if field is not None: args["must_contain"] = field + else: + args["must_contain"] = None field = data.get("user_agent", None) if field is not None: args["user_agent"] = field + else: + args["user_agent"] = None return RecordHTTPServiceConfig(**args) @@ -1132,7 +1198,7 @@ def unmarshal_Record(data: Any) -> Record: if field is not None: args["ttl"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -1143,22 +1209,32 @@ def unmarshal_Record(data: Any) -> Record: field = data.get("comment", None) if field is not None: args["comment"] = field + else: + args["comment"] = None field = data.get("geo_ip_config", None) if field is not None: args["geo_ip_config"] = unmarshal_RecordGeoIPConfig(field) + else: + args["geo_ip_config"] = None field = data.get("http_service_config", None) if field is not None: args["http_service_config"] = unmarshal_RecordHTTPServiceConfig(field) + else: + args["http_service_config"] = None field = data.get("weighted_config", None) if field is not None: args["weighted_config"] = unmarshal_RecordWeightedConfig(field) + else: + args["weighted_config"] = None field = data.get("view_config", None) if field is not None: args["view_config"] = unmarshal_RecordViewConfig(field) + else: + args["view_config"] = None return Record(**args) @@ -1175,17 +1251,21 @@ def unmarshal_RecordIdentifier(data: Any) -> RecordIdentifier: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field field = data.get("data", None) if field is not None: args["data"] = field + else: + args["data"] = None field = data.get("ttl", None) if field is not None: args["ttl"] = field + else: + args["ttl"] = None return RecordIdentifier(**args) @@ -1229,10 +1309,14 @@ def unmarshal_RecordChangeDelete(data: Any) -> RecordChangeDelete: field = data.get("id", None) if field is not None: args["id"] = field + else: + args["id"] = None field = data.get("id_fields", None) if field is not None: args["id_fields"] = unmarshal_RecordIdentifier(field) + else: + args["id_fields"] = None return RecordChangeDelete(**args) @@ -1254,10 +1338,14 @@ def unmarshal_RecordChangeSet(data: Any) -> RecordChangeSet: field = data.get("id", None) if field is not None: args["id"] = field + else: + args["id"] = None field = data.get("id_fields", None) if field is not None: args["id_fields"] = unmarshal_RecordIdentifier(field) + else: + args["id_fields"] = None return RecordChangeSet(**args) @@ -1273,18 +1361,26 @@ def unmarshal_RecordChange(data: Any) -> RecordChange: field = data.get("add", None) if field is not None: args["add"] = unmarshal_RecordChangeAdd(field) + else: + args["add"] = None - field = data.get("set_", None) + field = data.get("set", None) if field is not None: args["set_"] = unmarshal_RecordChangeSet(field) + else: + args["set_"] = None field = data.get("delete", None) if field is not None: args["delete"] = unmarshal_RecordChangeDelete(field) + else: + args["delete"] = None field = data.get("clear", None) if field is not None: args["clear"] = unmarshal_RecordChangeClear(field) + else: + args["clear"] = None return RecordChange(**args) @@ -1397,6 +1493,8 @@ def unmarshal_ContactRoles(data: Any) -> ContactRoles: field = data.get("contact", None) if field is not None: args["contact"] = unmarshal_Contact(field) + else: + args["contact"] = None return ContactRoles(**args) @@ -1519,6 +1617,8 @@ def unmarshal_DNSZoneVersion(data: Any) -> DNSZoneVersion: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return DNSZoneVersion(**args) @@ -1625,10 +1725,14 @@ def unmarshal_DomainSummary(data: Any) -> DomainSummary: field = data.get("expired_at", None) if field is not None: args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("status", None) if field is not None: @@ -1647,16 +1751,22 @@ def unmarshal_DomainSummary(data: Any) -> DomainSummary: args["external_domain_registration_status"] = ( unmarshal_DomainRegistrationStatusExternalDomain(field) ) + else: + args["external_domain_registration_status"] = None field = data.get("transfer_registration_status", None) if field is not None: args["transfer_registration_status"] = ( unmarshal_DomainRegistrationStatusTransfer(field) ) + else: + args["transfer_registration_status"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return DomainSummary(**args) @@ -1709,32 +1819,44 @@ def unmarshal_RenewableDomain(data: Any) -> RenewableDomain: field = data.get("renewable_duration_in_years", None) if field is not None: args["renewable_duration_in_years"] = field + else: + args["renewable_duration_in_years"] = None field = data.get("expired_at", None) if field is not None: args["expired_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expired_at"] = None field = data.get("limit_renew_at", None) if field is not None: args["limit_renew_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["limit_renew_at"] = None field = data.get("limit_redemption_at", None) if field is not None: args["limit_redemption_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["limit_redemption_at"] = None field = data.get("estimated_delete_at", None) if field is not None: args["estimated_delete_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["estimated_delete_at"] = None field = data.get("tld", None) if field is not None: args["tld"] = unmarshal_Tld(field) + else: + args["tld"] = None return RenewableDomain(**args) @@ -1801,7 +1923,7 @@ def unmarshal_Task(data: Any) -> Task: if field is not None: args["organization_id"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -1812,22 +1934,32 @@ def unmarshal_Task(data: Any) -> Task: field = data.get("domain", None) if field is not None: args["domain"] = field + else: + args["domain"] = None field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("message", None) if field is not None: args["message"] = field + else: + args["message"] = None field = data.get("contact_identifier", None) if field is not None: args["contact_identifier"] = field + else: + args["contact_identifier"] = None return Task(**args) @@ -1899,6 +2031,8 @@ def unmarshal_OrderResponse(data: Any) -> OrderResponse: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return OrderResponse(**args) @@ -1949,6 +2083,8 @@ def unmarshal_RegisterExternalDomainResponse( field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return RegisterExternalDomainResponse(**args) @@ -1983,6 +2119,8 @@ def unmarshal_AvailableDomain(data: Any) -> AvailableDomain: field = data.get("tld", None) if field is not None: args["tld"] = unmarshal_Tld(field) + else: + args["tld"] = None return AvailableDomain(**args) @@ -2149,8 +2287,8 @@ def marshal_ImportRawDNSZoneRequestAXFRSource( output["name_server"] = request.name_server if request.tsig_key is not None: - output["tsig_key"] = ( - marshal_ImportRawDNSZoneRequestTsigKey(request.tsig_key, defaults), + output["tsig_key"] = marshal_ImportRawDNSZoneRequestTsigKey( + request.tsig_key, defaults ) return output @@ -2219,7 +2357,7 @@ def marshal_ContactExtensionFRAssociationInfo( output["publication_jo_page"] = request.publication_jo_page if request.publication_jo is not None: - output["publication_jo"] = request.publication_jo + output["publication_jo"] = request.publication_jo.isoformat() return output @@ -2408,21 +2546,21 @@ def marshal_NewContact( ] if request.extension_fr is not None: - output["extension_fr"] = ( - marshal_ContactExtensionFR(request.extension_fr, defaults), + output["extension_fr"] = marshal_ContactExtensionFR( + request.extension_fr, defaults ) if request.extension_eu is not None: - output["extension_eu"] = ( - marshal_ContactExtensionEU(request.extension_eu, defaults), + output["extension_eu"] = marshal_ContactExtensionEU( + request.extension_eu, defaults ) if request.state is not None: output["state"] = request.state if request.extension_nl is not None: - output["extension_nl"] = ( - marshal_ContactExtensionNL(request.extension_nl, defaults), + output["extension_nl"] = marshal_ContactExtensionNL( + request.extension_nl, defaults ) return output @@ -2557,9 +2695,7 @@ def marshal_DSRecordDigest( output["digest"] = request.digest if request.public_key is not None: - output["public_key"] = ( - marshal_DSRecordPublicKey(request.public_key, defaults), - ) + output["public_key"] = marshal_DSRecordPublicKey(request.public_key, defaults) return output @@ -2594,7 +2730,7 @@ def marshal_RegistrarApiEnableDomainDNSSECRequest( output: Dict[str, Any] = {} if request.ds_record is not None: - output["ds_record"] = (marshal_DSRecord(request.ds_record, defaults),) + output["ds_record"] = marshal_DSRecord(request.ds_record, defaults) return output @@ -2780,13 +2916,13 @@ def marshal_RegistrarApiUpdateContactRequest( ] if request.extension_fr is not None: - output["extension_fr"] = ( - marshal_ContactExtensionFR(request.extension_fr, defaults), + output["extension_fr"] = marshal_ContactExtensionFR( + request.extension_fr, defaults ) if request.extension_eu is not None: - output["extension_eu"] = ( - marshal_ContactExtensionEU(request.extension_eu, defaults), + output["extension_eu"] = marshal_ContactExtensionEU( + request.extension_eu, defaults ) if request.whois_opt_in is not None: @@ -2796,8 +2932,8 @@ def marshal_RegistrarApiUpdateContactRequest( output["state"] = request.state if request.extension_nl is not None: - output["extension_nl"] = ( - marshal_ContactExtensionNL(request.extension_nl, defaults), + output["extension_nl"] = marshal_ContactExtensionNL( + request.extension_nl, defaults ) return output diff --git a/scaleway/scaleway/domain/v2beta1/types.py b/scaleway/scaleway/domain/v2beta1/types.py index c68cc41a..2b10de0a 100644 --- a/scaleway/scaleway/domain/v2beta1/types.py +++ b/scaleway/scaleway/domain/v2beta1/types.py @@ -300,6 +300,8 @@ class RecordType(str, Enum, metaclass=StrEnumMeta): DS = "ds" NAPTR = "naptr" DNAME = "dname" + SVCB = "svcb" + HTTPS = "https" def __str__(self) -> str: return str(self.value) diff --git a/scaleway/scaleway/edge_services/__init__.py b/scaleway/scaleway/edge_services/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway/scaleway/edge_services/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/edge_services/v1alpha1/__init__.py b/scaleway/scaleway/edge_services/v1alpha1/__init__.py new file mode 100644 index 00000000..a69731fd --- /dev/null +++ b/scaleway/scaleway/edge_services/v1alpha1/__init__.py @@ -0,0 +1,173 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DNSStageType +from .types import LbOriginError +from .types import ListBackendStagesRequestOrderBy +from .types import ListCacheStagesRequestOrderBy +from .types import ListDNSStagesRequestOrderBy +from .types import ListPipelinesRequestOrderBy +from .types import ListPipelinesWithStagesRequestOrderBy +from .types import ListPurgeRequestsRequestOrderBy +from .types import ListTLSStagesRequestOrderBy +from .types import PipelineErrorCode +from .types import PipelineErrorSeverity +from .types import PipelineErrorStage +from .types import PipelineErrorType +from .types import PipelineStatus +from .content import PIPELINE_TRANSIENT_STATUSES +from .types import PlanName +from .types import PurgeRequestStatus +from .content import PURGE_REQUEST_TRANSIENT_STATUSES +from .types import ScalewayLb +from .types import ScalewayLbBackendConfig +from .types import ScalewayS3BackendConfig +from .types import PipelineError +from .types import TLSSecret +from .types import BackendStage +from .types import CacheStage +from .types import DNSStage +from .types import Pipeline +from .types import TLSStage +from .types import CheckPEMChainRequestSecretChain +from .types import PlanDetails +from .types import PlanUsageDetails +from .types import PipelineStages +from .types import PurgeRequest +from .types import TLSSecretsConfig +from .types import CheckDomainRequest +from .types import CheckDomainResponse +from .types import CheckLbOriginRequest +from .types import CheckLbOriginResponse +from .types import CheckPEMChainRequest +from .types import CheckPEMChainResponse +from .types import CreateBackendStageRequest +from .types import CreateCacheStageRequest +from .types import CreateDNSStageRequest +from .types import CreatePipelineRequest +from .types import CreatePurgeRequestRequest +from .types import CreateTLSStageRequest +from .types import DeleteBackendStageRequest +from .types import DeleteCacheStageRequest +from .types import DeleteCurrentPlanRequest +from .types import DeleteDNSStageRequest +from .types import DeletePipelineRequest +from .types import DeleteTLSStageRequest +from .types import GetBackendStageRequest +from .types import GetBillingRequest +from .types import GetBillingResponse +from .types import GetCacheStageRequest +from .types import GetCurrentPlanRequest +from .types import GetDNSStageRequest +from .types import GetPipelineRequest +from .types import GetPurgeRequestRequest +from .types import GetTLSStageRequest +from .types import ListBackendStagesRequest +from .types import ListBackendStagesResponse +from .types import ListCacheStagesRequest +from .types import ListCacheStagesResponse +from .types import ListDNSStagesRequest +from .types import ListDNSStagesResponse +from .types import ListPipelinesRequest +from .types import ListPipelinesResponse +from .types import ListPipelinesWithStagesRequest +from .types import ListPipelinesWithStagesResponse +from .types import ListPlansResponse +from .types import ListPurgeRequestsRequest +from .types import ListPurgeRequestsResponse +from .types import ListTLSStagesRequest +from .types import ListTLSStagesResponse +from .types import Plan +from .types import SelectPlanRequest +from .types import UpdateBackendStageRequest +from .types import UpdateCacheStageRequest +from .types import UpdateDNSStageRequest +from .types import UpdatePipelineRequest +from .types import UpdateTLSStageRequest +from .api import EdgeServicesV1Alpha1API + +__all__ = [ + "DNSStageType", + "LbOriginError", + "ListBackendStagesRequestOrderBy", + "ListCacheStagesRequestOrderBy", + "ListDNSStagesRequestOrderBy", + "ListPipelinesRequestOrderBy", + "ListPipelinesWithStagesRequestOrderBy", + "ListPurgeRequestsRequestOrderBy", + "ListTLSStagesRequestOrderBy", + "PipelineErrorCode", + "PipelineErrorSeverity", + "PipelineErrorStage", + "PipelineErrorType", + "PipelineStatus", + "PIPELINE_TRANSIENT_STATUSES", + "PlanName", + "PurgeRequestStatus", + "PURGE_REQUEST_TRANSIENT_STATUSES", + "ScalewayLb", + "ScalewayLbBackendConfig", + "ScalewayS3BackendConfig", + "PipelineError", + "TLSSecret", + "BackendStage", + "CacheStage", + "DNSStage", + "Pipeline", + "TLSStage", + "CheckPEMChainRequestSecretChain", + "PlanDetails", + "PlanUsageDetails", + "PipelineStages", + "PurgeRequest", + "TLSSecretsConfig", + "CheckDomainRequest", + "CheckDomainResponse", + "CheckLbOriginRequest", + "CheckLbOriginResponse", + "CheckPEMChainRequest", + "CheckPEMChainResponse", + "CreateBackendStageRequest", + "CreateCacheStageRequest", + "CreateDNSStageRequest", + "CreatePipelineRequest", + "CreatePurgeRequestRequest", + "CreateTLSStageRequest", + "DeleteBackendStageRequest", + "DeleteCacheStageRequest", + "DeleteCurrentPlanRequest", + "DeleteDNSStageRequest", + "DeletePipelineRequest", + "DeleteTLSStageRequest", + "GetBackendStageRequest", + "GetBillingRequest", + "GetBillingResponse", + "GetCacheStageRequest", + "GetCurrentPlanRequest", + "GetDNSStageRequest", + "GetPipelineRequest", + "GetPurgeRequestRequest", + "GetTLSStageRequest", + "ListBackendStagesRequest", + "ListBackendStagesResponse", + "ListCacheStagesRequest", + "ListCacheStagesResponse", + "ListDNSStagesRequest", + "ListDNSStagesResponse", + "ListPipelinesRequest", + "ListPipelinesResponse", + "ListPipelinesWithStagesRequest", + "ListPipelinesWithStagesResponse", + "ListPlansResponse", + "ListPurgeRequestsRequest", + "ListPurgeRequestsResponse", + "ListTLSStagesRequest", + "ListTLSStagesResponse", + "Plan", + "SelectPlanRequest", + "UpdateBackendStageRequest", + "UpdateCacheStageRequest", + "UpdateDNSStageRequest", + "UpdatePipelineRequest", + "UpdateTLSStageRequest", + "EdgeServicesV1Alpha1API", +] diff --git a/scaleway/scaleway/edge_services/v1alpha1/api.py b/scaleway/scaleway/edge_services/v1alpha1/api.py new file mode 100644 index 00000000..44ea7a35 --- /dev/null +++ b/scaleway/scaleway/edge_services/v1alpha1/api.py @@ -0,0 +1,1823 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + ListBackendStagesRequestOrderBy, + ListCacheStagesRequestOrderBy, + ListDNSStagesRequestOrderBy, + ListPipelinesRequestOrderBy, + ListPipelinesWithStagesRequestOrderBy, + ListPurgeRequestsRequestOrderBy, + ListTLSStagesRequestOrderBy, + PlanName, + BackendStage, + CacheStage, + CheckDomainRequest, + CheckDomainResponse, + CheckLbOriginRequest, + CheckLbOriginResponse, + CheckPEMChainRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainResponse, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateTLSStageRequest, + DNSStage, + GetBillingResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListTLSStagesResponse, + Pipeline, + PipelineStages, + Plan, + PurgeRequest, + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + SelectPlanRequest, + TLSSecret, + TLSSecretsConfig, + TLSStage, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + UpdateTLSStageRequest, +) +from .content import ( + PIPELINE_TRANSIENT_STATUSES, + PURGE_REQUEST_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_BackendStage, + unmarshal_CacheStage, + unmarshal_DNSStage, + unmarshal_Pipeline, + unmarshal_TLSStage, + unmarshal_PurgeRequest, + unmarshal_CheckDomainResponse, + unmarshal_CheckLbOriginResponse, + unmarshal_CheckPEMChainResponse, + unmarshal_GetBillingResponse, + unmarshal_ListBackendStagesResponse, + unmarshal_ListCacheStagesResponse, + unmarshal_ListDNSStagesResponse, + unmarshal_ListPipelinesResponse, + unmarshal_ListPipelinesWithStagesResponse, + unmarshal_ListPlansResponse, + unmarshal_ListPurgeRequestsResponse, + unmarshal_ListTLSStagesResponse, + unmarshal_Plan, + marshal_CheckDomainRequest, + marshal_CheckLbOriginRequest, + marshal_CheckPEMChainRequest, + marshal_CreateBackendStageRequest, + marshal_CreateCacheStageRequest, + marshal_CreateDNSStageRequest, + marshal_CreatePipelineRequest, + marshal_CreatePurgeRequestRequest, + marshal_CreateTLSStageRequest, + marshal_SelectPlanRequest, + marshal_UpdateBackendStageRequest, + marshal_UpdateCacheStageRequest, + marshal_UpdateDNSStageRequest, + marshal_UpdatePipelineRequest, + marshal_UpdateTLSStageRequest, +) + + +class EdgeServicesV1Alpha1API(API): + """ """ + + def list_pipelines( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> ListPipelinesResponse: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for, only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for, only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for, only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage, only pipelines with a Load Balancer origin will be returned. + :return: :class:`ListPipelinesResponse ` + + Usage: + :: + + result = api.list_pipelines() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/pipelines", + params={ + "has_backend_stage_lb": has_backend_stage_lb, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesResponse(res.json()) + + def list_pipelines_all( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> List[Pipeline]: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for, only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for, only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for, only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage, only pipelines with a Load Balancer origin will be returned. + :return: :class:`List[Pipeline] ` + + Usage: + :: + + result = api.list_pipelines_all() + """ + + return fetch_all_pages( + type=ListPipelinesResponse, + key="pipelines", + fetcher=self.list_pipelines, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + "has_backend_stage_lb": has_backend_stage_lb, + }, + ) + + def create_pipeline( + self, + *, + name: str, + description: str, + project_id: Optional[str] = None, + dns_stage_id: Optional[str] = None, + ) -> Pipeline: + """ + Create pipeline. + Create a new pipeline. You must specify a `dns_stage_id` to form a stage-chain that goes all the way to the backend stage (origin), so the HTTP request will be processed according to the stages you created. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :param project_id: Project ID in which the pipeline will be created. + :param dns_stage_id: DNS stage ID the pipeline will be attached to. + One-Of ('head'): at most one of 'dns_stage_id' could be set. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.create_pipeline( + name="example", + description="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/pipelines", + body=marshal_CreatePipelineRequest( + CreatePipelineRequest( + name=name, + description=description, + project_id=project_id, + dns_stage_id=dns_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + def get_pipeline( + self, + *, + pipeline_id: str, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.get_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + def wait_for_pipeline( + self, + *, + pipeline_id: str, + options: Optional[WaitForOptions[Pipeline, bool]] = None, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.get_pipeline( + pipeline_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in PIPELINE_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_pipeline, + options=options, + args={ + "pipeline_id": pipeline_id, + }, + ) + + def list_pipelines_with_stages( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> ListPipelinesWithStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`ListPipelinesWithStagesResponse ` + + Usage: + :: + + result = api.list_pipelines_with_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/pipelines-stages", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesWithStagesResponse(res.json()) + + def list_pipelines_with_stages_all( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> List[PipelineStages]: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`List[PipelineStages] ` + + Usage: + :: + + result = api.list_pipelines_with_stages_all() + """ + + return fetch_all_pages( + type=ListPipelinesWithStagesResponse, + key="pipelines", + fetcher=self.list_pipelines_with_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + }, + ) + + def update_pipeline( + self, + *, + pipeline_id: str, + name: Optional[str] = None, + description: Optional[str] = None, + dns_stage_id: Optional[str] = None, + ) -> Pipeline: + """ + Update pipeline. + Update the parameters of an existing pipeline, specified by its `pipeline_id`. Parameters which can be updated include the `name`, `description` and `dns_stage_id`. + :param pipeline_id: ID of the pipeline to update. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :param dns_stage_id: DNS stage ID the pipeline will be attached to. + One-Of ('head'): at most one of 'dns_stage_id' could be set. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.update_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "PATCH", + f"/edge-services/v1alpha1/pipelines/{param_pipeline_id}", + body=marshal_UpdatePipelineRequest( + UpdatePipelineRequest( + pipeline_id=pipeline_id, + name=name, + description=description, + dns_stage_id=dns_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + def delete_pipeline( + self, + *, + pipeline_id: str, + ) -> None: + """ + Delete pipeline. + Delete an existing pipeline, specified by its `pipeline_id`. Deleting a pipeline is permanent, and cannot be undone. Note that all stages linked to the pipeline are also deleted. + :param pipeline_id: ID of the pipeline to delete. + + Usage: + :: + + result = api.delete_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + + def list_dns_stages( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + fqdn: Optional[str] = None, + ) -> ListDNSStagesResponse: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only DNS stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only DNS stages from this Project will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com), only DNS stages with this FQDN will be returned. + :return: :class:`ListDNSStagesResponse ` + + Usage: + :: + + result = api.list_dns_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/dns-stages", + params={ + "fqdn": fqdn, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDNSStagesResponse(res.json()) + + def list_dns_stages_all( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + fqdn: Optional[str] = None, + ) -> List[DNSStage]: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only DNS stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only DNS stages from this Project will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com), only DNS stages with this FQDN will be returned. + :return: :class:`List[DNSStage] ` + + Usage: + :: + + result = api.list_dns_stages_all() + """ + + return fetch_all_pages( + type=ListDNSStagesResponse, + key="stages", + fetcher=self.list_dns_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "project_id": project_id, + "fqdn": fqdn, + }, + ) + + def create_dns_stage( + self, + *, + project_id: Optional[str] = None, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> DNSStage: + """ + Create DNS stage. + Create a new DNS stage. You must specify the `fqdns` field to customize the domain endpoint, using a domain you already own. + :param project_id: Project ID in which the DNS stage will be created. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`DNSStage ` + + Usage: + :: + + result = api.create_dns_stage() + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/dns-stages", + body=marshal_CreateDNSStageRequest( + CreateDNSStageRequest( + project_id=project_id, + fqdns=fqdns, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + def get_dns_stage( + self, + *, + dns_stage_id: str, + ) -> DNSStage: + """ + Get DNS stage. + Retrieve information about an existing DNS stage, specified by its `dns_stage_id`. Its full details, including FQDNs, are returned in the response object. + :param dns_stage_id: ID of the requested DNS stage. + :return: :class:`DNSStage ` + + Usage: + :: + + result = api.get_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + def update_dns_stage( + self, + *, + dns_stage_id: str, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> DNSStage: + """ + Update DNS stage. + Update the parameters of an existing DNS stage, specified by its `dns_stage_id`. + :param dns_stage_id: ID of the DNS stage to update. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`DNSStage ` + + Usage: + :: + + result = api.update_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1alpha1/dns-stages/{param_dns_stage_id}", + body=marshal_UpdateDNSStageRequest( + UpdateDNSStageRequest( + dns_stage_id=dns_stage_id, + fqdns=fqdns, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + def delete_dns_stage( + self, + *, + dns_stage_id: str, + ) -> None: + """ + Delete DNS stage. + Delete an existing DNS stage, specified by its `dns_stage_id`. Deleting a DNS stage is permanent, and cannot be undone. + :param dns_stage_id: ID of the DNS stage to delete. + + Usage: + :: + + result = api.delete_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + + def list_tls_stages( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> ListTLSStagesResponse: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only TLS stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only TLS stages from this Project will be returned. + :param secret_id: Secret ID to filter for, only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for, only TLS stages with a Secret in this region will be returned. + :return: :class:`ListTLSStagesResponse ` + + Usage: + :: + + result = api.list_tls_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/tls-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListTLSStagesResponse(res.json()) + + def list_tls_stages_all( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> List[TLSStage]: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only TLS stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only TLS stages from this Project will be returned. + :param secret_id: Secret ID to filter for, only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for, only TLS stages with a Secret in this region will be returned. + :return: :class:`List[TLSStage] ` + + Usage: + :: + + result = api.list_tls_stages_all() + """ + + return fetch_all_pages( + type=ListTLSStagesResponse, + key="stages", + fetcher=self.list_tls_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "project_id": project_id, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + def create_tls_stage( + self, + *, + project_id: Optional[str] = None, + secrets: Optional[List[TLSSecret]] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Create TLS stage. + Create a new TLS stage. You must specify either the `secrets` or `managed_certificate` fields to customize the SSL/TLS certificate of your endpoint. Choose `secrets` if you are using a pre-existing certificate held in Scaleway Secret Manager, or `managed_certificate` to let Scaleway generate and manage a Let's Encrypt certificate for your customized endpoint. + :param project_id: Project ID in which the TLS stage will be created. + :param secrets: Secret (from Scaleway Secret Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = api.create_tls_stage() + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/tls-stages", + body=marshal_CreateTLSStageRequest( + CreateTLSStageRequest( + project_id=project_id, + secrets=secrets, + managed_certificate=managed_certificate, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + def get_tls_stage( + self, + *, + tls_stage_id: str, + ) -> TLSStage: + """ + Get TLS stage. + Retrieve information about an existing TLS stage, specified by its `tls_stage_id`. Its full details, including secrets and certificate expiration date are returned in the response object. + :param tls_stage_id: ID of the requested TLS stage. + :return: :class:`TLSStage ` + + Usage: + :: + + result = api.get_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + def update_tls_stage( + self, + *, + tls_stage_id: str, + tls_secrets_config: Optional[TLSSecretsConfig] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Update TLS stage. + Update the parameters of an existing TLS stage, specified by its `tls_stage_id`. Both `tls_secrets_config` and `managed_certificate` parameters can be updated. + :param tls_stage_id: ID of the TLS stage to update. + :param tls_secrets_config: Secret (from Scaleway Secret-Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = api.update_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1alpha1/tls-stages/{param_tls_stage_id}", + body=marshal_UpdateTLSStageRequest( + UpdateTLSStageRequest( + tls_stage_id=tls_stage_id, + tls_secrets_config=tls_secrets_config, + managed_certificate=managed_certificate, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + def delete_tls_stage( + self, + *, + tls_stage_id: str, + ) -> None: + """ + Delete TLS stage. + Delete an existing TLS stage, specified by its `tls_stage_id`. Deleting a TLS stage is permanent, and cannot be undone. + :param tls_stage_id: ID of the TLS stage to delete. + + Usage: + :: + + result = api.delete_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + + def list_cache_stages( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> ListCacheStagesResponse: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only cache stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only cache stages from this Project will be returned. + :return: :class:`ListCacheStagesResponse ` + + Usage: + :: + + result = api.list_cache_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/cache-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListCacheStagesResponse(res.json()) + + def list_cache_stages_all( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> List[CacheStage]: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only cache stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only cache stages from this Project will be returned. + :return: :class:`List[CacheStage] ` + + Usage: + :: + + result = api.list_cache_stages_all() + """ + + return fetch_all_pages( + type=ListCacheStagesResponse, + key="stages", + fetcher=self.list_cache_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "project_id": project_id, + }, + ) + + def create_cache_stage( + self, + *, + project_id: Optional[str] = None, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Create cache stage. + Create a new cache stage. You must specify the `fallback_ttl` field to customize the TTL of the cache. + :param project_id: Project ID in which the cache stage will be created. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = api.create_cache_stage() + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/cache-stages", + body=marshal_CreateCacheStageRequest( + CreateCacheStageRequest( + project_id=project_id, + fallback_ttl=fallback_ttl, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + def get_cache_stage( + self, + *, + cache_stage_id: str, + ) -> CacheStage: + """ + Get cache stage. + Retrieve information about an existing cache stage, specified by its `cache_stage_id`. Its full details, including Time To Live (TTL), are returned in the response object. + :param cache_stage_id: ID of the requested cache stage. + :return: :class:`CacheStage ` + + Usage: + :: + + result = api.get_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + def update_cache_stage( + self, + *, + cache_stage_id: str, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Update cache stage. + Update the parameters of an existing cache stage, specified by its `cache_stage_id`. Parameters which can be updated include the `fallback_ttl` and `backend_stage_id`. + :param cache_stage_id: ID of the cache stage to update. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = api.update_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1alpha1/cache-stages/{param_cache_stage_id}", + body=marshal_UpdateCacheStageRequest( + UpdateCacheStageRequest( + cache_stage_id=cache_stage_id, + fallback_ttl=fallback_ttl, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + def delete_cache_stage( + self, + *, + cache_stage_id: str, + ) -> None: + """ + Delete cache stage. + Delete an existing cache stage, specified by its `cache_stage_id`. Deleting a cache stage is permanent, and cannot be undone. + :param cache_stage_id: ID of the cache stage to delete. + + Usage: + :: + + result = api.delete_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + + def list_backend_stages( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> ListBackendStagesResponse: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only backend stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only backend stages from this Project will be returned. + :param bucket_name: Bucket name to filter for, only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for, only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for, only backend stages with this Load Balancer will be returned. + :return: :class:`ListBackendStagesResponse ` + + Usage: + :: + + result = api.list_backend_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/backend-stages", + params={ + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBackendStagesResponse(res.json()) + + def list_backend_stages_all( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: Optional[str] = None, + project_id: Optional[str] = None, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> List[BackendStage]: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for, only backend stages from this pipeline will be returned. + :param project_id: Project ID to filter for, only backend stages from this Project will be returned. + :param bucket_name: Bucket name to filter for, only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for, only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for, only backend stages with this Load Balancer will be returned. + :return: :class:`List[BackendStage] ` + + Usage: + :: + + result = api.list_backend_stages_all() + """ + + return fetch_all_pages( + type=ListBackendStagesResponse, + key="stages", + fetcher=self.list_backend_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "project_id": project_id, + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + }, + ) + + def create_backend_stage( + self, + *, + project_id: Optional[str] = None, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + ) -> BackendStage: + """ + Create backend stage. + Create a new backend stage. You must specify either a `scaleway_s3` (for a Scaleway Object Storage bucket) or `scaleway_lb` (for a Scaleway Load Balancer) field to configure the origin. + :param project_id: Project ID in which the backend stage will be created. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :return: :class:`BackendStage ` + + Usage: + :: + + result = api.create_backend_stage() + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/backend-stages", + body=marshal_CreateBackendStageRequest( + CreateBackendStageRequest( + project_id=project_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + def get_backend_stage( + self, + *, + backend_stage_id: str, + ) -> BackendStage: + """ + Get backend stage. + Retrieve information about an existing backend stage, specified by its `backend_stage_id`. Its full details, including `scaleway_s3` or `scaleway_lb`, are returned in the response object. + :param backend_stage_id: ID of the requested backend stage. + :return: :class:`BackendStage ` + + Usage: + :: + + result = api.get_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + def update_backend_stage( + self, + *, + backend_stage_id: str, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + ) -> BackendStage: + """ + Update backend stage. + Update the parameters of an existing backend stage, specified by its `backend_stage_id`. + :param backend_stage_id: ID of the backend stage to update. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :return: :class:`BackendStage ` + + Usage: + :: + + result = api.update_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "PATCH", + f"/edge-services/v1alpha1/backend-stages/{param_backend_stage_id}", + body=marshal_UpdateBackendStageRequest( + UpdateBackendStageRequest( + backend_stage_id=backend_stage_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + def delete_backend_stage( + self, + *, + backend_stage_id: str, + ) -> None: + """ + Delete backend stage. + Delete an existing backend stage, specified by its `backend_stage_id`. Deleting a backend stage is permanent, and cannot be undone. + :param backend_stage_id: ID of the backend stage to delete. + + Usage: + :: + + result = api.delete_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + + def check_domain( + self, + *, + fqdn: str, + cname: str, + project_id: Optional[str] = None, + ) -> CheckDomainResponse: + """ + :param fqdn: + :param cname: + :param project_id: + :return: :class:`CheckDomainResponse ` + + Usage: + :: + + result = api.check_domain( + fqdn="example", + cname="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/check-domain", + body=marshal_CheckDomainRequest( + CheckDomainRequest( + fqdn=fqdn, + cname=cname, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckDomainResponse(res.json()) + + def check_pem_chain( + self, + *, + fqdn: str, + project_id: Optional[str] = None, + secret: Optional[CheckPEMChainRequestSecretChain] = None, + raw: Optional[str] = None, + ) -> CheckPEMChainResponse: + """ + :param fqdn: + :param project_id: + :param secret: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :param raw: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :return: :class:`CheckPEMChainResponse ` + + Usage: + :: + + result = api.check_pem_chain( + fqdn="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/check-pem-chain", + body=marshal_CheckPEMChainRequest( + CheckPEMChainRequest( + fqdn=fqdn, + project_id=project_id, + secret=secret, + raw=raw, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckPEMChainResponse(res.json()) + + def list_purge_requests( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> ListPurgeRequestsResponse: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for, only purge requests from this Project will be returned. + :param project_id: Project ID to filter for, only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for, only purge requests from this pipeline will be returned. + :return: :class:`ListPurgeRequestsResponse ` + + Usage: + :: + + result = api.list_purge_requests() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/purge-requests", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPurgeRequestsResponse(res.json()) + + def list_purge_requests_all( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> List[PurgeRequest]: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for, only purge requests from this Project will be returned. + :param project_id: Project ID to filter for, only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for, only purge requests from this pipeline will be returned. + :return: :class:`List[PurgeRequest] ` + + Usage: + :: + + result = api.list_purge_requests_all() + """ + + return fetch_all_pages( + type=ListPurgeRequestsResponse, + key="purge_requests", + fetcher=self.list_purge_requests, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "pipeline_id": pipeline_id, + }, + ) + + def create_purge_request( + self, + *, + pipeline_id: str, + assets: Optional[List[str]] = None, + all: Optional[bool] = None, + ) -> PurgeRequest: + """ + Create purge request. + Create a new purge request. You must specify either the `all` field (to purge all content) or a list of `assets` (to define the precise assets to purge). + :param pipeline_id: Pipeline ID in which the purge request will be created. + :param assets: List of asserts to purge. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :param all: Defines whether to purge all content. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = api.create_purge_request( + pipeline_id="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/purge-requests", + body=marshal_CreatePurgeRequestRequest( + CreatePurgeRequestRequest( + pipeline_id=pipeline_id, + assets=assets, + all=all, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + def get_purge_request( + self, + *, + purge_request_id: str, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = api.get_purge_request( + purge_request_id="example", + ) + """ + + param_purge_request_id = validate_path_param( + "purge_request_id", purge_request_id + ) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/purge-requests/{param_purge_request_id}", + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + def wait_for_purge_request( + self, + *, + purge_request_id: str, + options: Optional[WaitForOptions[PurgeRequest, bool]] = None, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = api.get_purge_request( + purge_request_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in PURGE_REQUEST_TRANSIENT_STATUSES + ) + + return wait_for_resource( + fetcher=self.get_purge_request, + options=options, + args={ + "purge_request_id": purge_request_id, + }, + ) + + def check_lb_origin( + self, + *, + lb: Optional[ScalewayLb] = None, + ) -> CheckLbOriginResponse: + """ + :param lb: + :return: :class:`CheckLbOriginResponse ` + + Usage: + :: + + result = api.check_lb_origin() + """ + + res = self._request( + "POST", + "/edge-services/v1alpha1/check-lb-origin", + body=marshal_CheckLbOriginRequest( + CheckLbOriginRequest( + lb=lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckLbOriginResponse(res.json()) + + def list_plans( + self, + ) -> ListPlansResponse: + """ + + :return: :class:`ListPlansResponse ` + + Usage: + :: + + result = api.list_plans() + """ + + res = self._request( + "GET", + "/edge-services/v1alpha1/plans", + ) + + self._throw_on_error(res) + return unmarshal_ListPlansResponse(res.json()) + + def select_plan( + self, + *, + project_id: Optional[str] = None, + plan_name: Optional[PlanName] = None, + ) -> Plan: + """ + :param project_id: + :param plan_name: + :return: :class:`Plan ` + + Usage: + :: + + result = api.select_plan() + """ + + res = self._request( + "PATCH", + "/edge-services/v1alpha1/current-plan", + body=marshal_SelectPlanRequest( + SelectPlanRequest( + project_id=project_id, + plan_name=plan_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + def get_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> Plan: + """ + :param project_id: + :return: :class:`Plan ` + + Usage: + :: + + result = api.get_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + def delete_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> None: + """ + :param project_id: + + Usage: + :: + + result = api.delete_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1alpha1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + + def get_billing( + self, + *, + project_id: Optional[str] = None, + ) -> GetBillingResponse: + """ + Gives information on the currently selected Edge Services subscription plan, resource usage and associated billing information for this calendar month (including whether consumption falls within or exceeds the currently selected subscription plan.). + :param project_id: + :return: :class:`GetBillingResponse ` + + Usage: + :: + + result = api.get_billing() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1alpha1/billing/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_GetBillingResponse(res.json()) diff --git a/scaleway/scaleway/edge_services/v1alpha1/content.py b/scaleway/scaleway/edge_services/v1alpha1/content.py new file mode 100644 index 00000000..ad1b5e0e --- /dev/null +++ b/scaleway/scaleway/edge_services/v1alpha1/content.py @@ -0,0 +1,21 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + PipelineStatus, + PurgeRequestStatus, +) + +PIPELINE_TRANSIENT_STATUSES: List[PipelineStatus] = [ + PipelineStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PipelineStatus `. +""" +PURGE_REQUEST_TRANSIENT_STATUSES: List[PurgeRequestStatus] = [ + PurgeRequestStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PurgeRequestStatus `. +""" diff --git a/scaleway/scaleway/edge_services/v1alpha1/marshalling.py b/scaleway/scaleway/edge_services/v1alpha1/marshalling.py new file mode 100644 index 00000000..f9145ff0 --- /dev/null +++ b/scaleway/scaleway/edge_services/v1alpha1/marshalling.py @@ -0,0 +1,1334 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + BackendStage, + CacheStage, + DNSStage, + PipelineError, + Pipeline, + TLSSecret, + TLSStage, + PipelineStages, + PurgeRequest, + CheckDomainResponse, + CheckLbOriginResponse, + CheckPEMChainResponse, + PlanDetails, + PlanUsageDetails, + GetBillingResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListTLSStagesResponse, + Plan, + CheckDomainRequest, + CheckLbOriginRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainRequest, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateTLSStageRequest, + SelectPlanRequest, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + TLSSecretsConfig, + UpdateTLSStageRequest, +) + + +def unmarshal_ScalewayLb(data: Any) -> ScalewayLb: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLb' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("frontend_id", None) + if field is not None: + args["frontend_id"] = field + + field = data.get("is_ssl", None) + if field is not None: + args["is_ssl"] = field + else: + args["is_ssl"] = None + + field = data.get("domain_name", None) + if field is not None: + args["domain_name"] = field + else: + args["domain_name"] = None + + return ScalewayLb(**args) + + +def unmarshal_ScalewayLbBackendConfig(data: Any) -> ScalewayLbBackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLbBackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("lbs", None) + if field is not None: + args["lbs"] = ( + [unmarshal_ScalewayLb(v) for v in field] if field is not None else None + ) + + return ScalewayLbBackendConfig(**args) + + +def unmarshal_ScalewayS3BackendConfig(data: Any) -> ScalewayS3BackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayS3BackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bucket_name", None) + if field is not None: + args["bucket_name"] = field + else: + args["bucket_name"] = None + + field = data.get("bucket_region", None) + if field is not None: + args["bucket_region"] = field + else: + args["bucket_region"] = None + + field = data.get("is_website", None) + if field is not None: + args["is_website"] = field + else: + args["is_website"] = None + + return ScalewayS3BackendConfig(**args) + + +def unmarshal_BackendStage(data: Any) -> BackendStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BackendStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + else: + args["pipeline_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("scaleway_s3", None) + if field is not None: + args["scaleway_s3"] = unmarshal_ScalewayS3BackendConfig(field) + else: + args["scaleway_s3"] = None + + field = data.get("scaleway_lb", None) + if field is not None: + args["scaleway_lb"] = unmarshal_ScalewayLbBackendConfig(field) + else: + args["scaleway_lb"] = None + + return BackendStage(**args) + + +def unmarshal_CacheStage(data: Any) -> CacheStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CacheStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + else: + args["pipeline_id"] = None + + field = data.get("fallback_ttl", None) + if field is not None: + args["fallback_ttl"] = field + else: + args["fallback_ttl"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return CacheStage(**args) + + +def unmarshal_DNSStage(data: Any) -> DNSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DNSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("fqdns", None) + if field is not None: + args["fqdns"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + else: + args["pipeline_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("tls_stage_id", None) + if field is not None: + args["tls_stage_id"] = field + else: + args["tls_stage_id"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return DNSStage(**args) + + +def unmarshal_PipelineError(data: Any) -> PipelineError: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineError' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stage", None) + if field is not None: + args["stage"] = field + + field = data.get("code", None) + if field is not None: + args["code"] = field + + field = data.get("severity", None) + if field is not None: + args["severity"] = field + + field = data.get("message", None) + if field is not None: + args["message"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return PipelineError(**args) + + +def unmarshal_Pipeline(data: Any) -> Pipeline: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pipeline' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("errors", None) + if field is not None: + args["errors"] = ( + [unmarshal_PipelineError(v) for v in field] if field is not None else None + ) + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("dns_stage_id", None) + if field is not None: + args["dns_stage_id"] = field + else: + args["dns_stage_id"] = None + + return Pipeline(**args) + + +def unmarshal_TLSSecret(data: Any) -> TLSSecret: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSSecret' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secret_id", None) + if field is not None: + args["secret_id"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + return TLSSecret(**args) + + +def unmarshal_TLSStage(data: Any) -> TLSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("secrets", None) + if field is not None: + args["secrets"] = ( + [unmarshal_TLSSecret(v) for v in field] if field is not None else None + ) + + field = data.get("managed_certificate", None) + if field is not None: + args["managed_certificate"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + else: + args["pipeline_id"] = None + + field = data.get("certificate_expires_at", None) + if field is not None: + args["certificate_expires_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["certificate_expires_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return TLSStage(**args) + + +def unmarshal_PipelineStages(data: Any) -> PipelineStages: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineStages' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stages", None) + if field is not None: + args["dns_stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("tls_stages", None) + if field is not None: + args["tls_stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("cache_stages", None) + if field is not None: + args["cache_stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("backend_stages", None) + if field is not None: + args["backend_stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("pipeline", None) + if field is not None: + args["pipeline"] = unmarshal_Pipeline(field) + else: + args["pipeline"] = None + + return PipelineStages(**args) + + +def unmarshal_PurgeRequest(data: Any) -> PurgeRequest: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PurgeRequest' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("assets", None) + if field is not None: + args["assets"] = field + else: + args["assets"] = None + + field = data.get("all", None) + if field is not None: + args["all"] = field + else: + args["all"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return PurgeRequest(**args) + + +def unmarshal_CheckDomainResponse(data: Any) -> CheckDomainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckDomainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckDomainResponse(**args) + + +def unmarshal_CheckLbOriginResponse(data: Any) -> CheckLbOriginResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckLbOriginResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + field = data.get("error_type", None) + if field is not None: + args["error_type"] = field + + return CheckLbOriginResponse(**args) + + +def unmarshal_CheckPEMChainResponse(data: Any) -> CheckPEMChainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckPEMChainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckPEMChainResponse(**args) + + +def unmarshal_PlanDetails(data: Any) -> PlanDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + field = data.get("package_gb", None) + if field is not None: + args["package_gb"] = field + + field = data.get("pipeline_limit", None) + if field is not None: + args["pipeline_limit"] = field + + field = data.get("waf_requests", None) + if field is not None: + args["waf_requests"] = field + + return PlanDetails(**args) + + +def unmarshal_PlanUsageDetails(data: Any) -> PlanUsageDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanUsageDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + return PlanUsageDetails(**args) + + +def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetBillingResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("current_plan", None) + if field is not None: + args["current_plan"] = unmarshal_PlanDetails(field) + else: + args["current_plan"] = None + + field = data.get("pipeline_number", None) + if field is not None: + args["pipeline_number"] = field + + field = data.get("current_plan_cache_usage", None) + if field is not None: + args["current_plan_cache_usage"] = field + + field = data.get("extra_cache_usage", None) + if field is not None: + args["extra_cache_usage"] = field + + field = data.get("current_plan_waf_usage", None) + if field is not None: + args["current_plan_waf_usage"] = field + + field = data.get("extra_waf_usage", None) + if field is not None: + args["extra_waf_usage"] = field + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + field = data.get("extra_pipelines_cost", None) + if field is not None: + args["extra_pipelines_cost"] = unmarshal_Money(field) + else: + args["extra_pipelines_cost"] = None + + field = data.get("plans_usage_details", None) + if field is not None: + args["plans_usage_details"] = ( + {key: unmarshal_PlanUsageDetails(value) for key, value in field.items()} + if field is not None + else None + ) + + field = data.get("extra_cache_cost", None) + if field is not None: + args["extra_cache_cost"] = unmarshal_Money(field) + else: + args["extra_cache_cost"] = None + + field = data.get("extra_waf_cost", None) + if field is not None: + args["extra_waf_cost"] = unmarshal_Money(field) + else: + args["extra_waf_cost"] = None + + field = data.get("waf_add_on", None) + if field is not None: + args["waf_add_on"] = unmarshal_Money(field) + else: + args["waf_add_on"] = None + + field = data.get("total_cost", None) + if field is not None: + args["total_cost"] = unmarshal_Money(field) + else: + args["total_cost"] = None + + return GetBillingResponse(**args) + + +def unmarshal_ListBackendStagesResponse(data: Any) -> ListBackendStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListBackendStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListBackendStagesResponse(**args) + + +def unmarshal_ListCacheStagesResponse(data: Any) -> ListCacheStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListCacheStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListCacheStagesResponse(**args) + + +def unmarshal_ListDNSStagesResponse(data: Any) -> ListDNSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDNSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDNSStagesResponse(**args) + + +def unmarshal_ListPipelinesResponse(data: Any) -> ListPipelinesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_Pipeline(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesResponse(**args) + + +def unmarshal_ListPipelinesWithStagesResponse( + data: Any, +) -> ListPipelinesWithStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesWithStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_PipelineStages(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesWithStagesResponse(**args) + + +def unmarshal_ListPlansResponse(data: Any) -> ListPlansResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPlansResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("plans", None) + if field is not None: + args["plans"] = ( + [unmarshal_PlanDetails(v) for v in field] if field is not None else None + ) + + return ListPlansResponse(**args) + + +def unmarshal_ListPurgeRequestsResponse(data: Any) -> ListPurgeRequestsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPurgeRequestsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("purge_requests", None) + if field is not None: + args["purge_requests"] = ( + [unmarshal_PurgeRequest(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPurgeRequestsResponse(**args) + + +def unmarshal_ListTLSStagesResponse(data: Any) -> ListTLSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListTLSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListTLSStagesResponse(**args) + + +def unmarshal_Plan(data: Any) -> Plan: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Plan' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + return Plan(**args) + + +def marshal_CheckDomainRequest( + request: CheckDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.cname is not None: + output["cname"] = request.cname + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLb( + request: ScalewayLb, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.id is not None: + output["id"] = request.id + + if request.zone is not None: + output["zone"] = request.zone or defaults.default_zone + + if request.frontend_id is not None: + output["frontend_id"] = request.frontend_id + + if request.is_ssl is not None: + output["is_ssl"] = request.is_ssl + + if request.domain_name is not None: + output["domain_name"] = request.domain_name + + return output + + +def marshal_CheckLbOriginRequest( + request: CheckLbOriginRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lb is not None: + output["lb"] = marshal_ScalewayLb(request.lb, defaults) + + return output + + +def marshal_CheckPEMChainRequestSecretChain( + request: CheckPEMChainRequestSecretChain, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.secret_region is not None: + output["secret_region"] = request.secret_region + + return output + + +def marshal_CheckPEMChainRequest( + request: CheckPEMChainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("secret", request.secret), + OneOfPossibility("raw", request.raw), + ] + ), + ) + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLbBackendConfig( + request: ScalewayLbBackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lbs is not None: + output["lbs"] = [marshal_ScalewayLb(item, defaults) for item in request.lbs] + + return output + + +def marshal_ScalewayS3BackendConfig( + request: ScalewayS3BackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket_name is not None: + output["bucket_name"] = request.bucket_name + + if request.bucket_region is not None: + output["bucket_region"] = request.bucket_region + + if request.is_website is not None: + output["is_website"] = request.is_website + + return output + + +def marshal_CreateBackendStageRequest( + request: CreateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_CreateCacheStageRequest( + request: CreateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_CreateDNSStageRequest( + request: CreateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_CreatePipelineRequest( + request: CreatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("dns_stage_id", request.dns_stage_id), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_CreatePurgeRequestRequest( + request: CreatePurgeRequestRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("assets", request.assets), + OneOfPossibility("all", request.all), + ] + ), + ) + + if request.pipeline_id is not None: + output["pipeline_id"] = request.pipeline_id + + return output + + +def marshal_TLSSecret( + request: TLSSecret, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.region is not None: + output["region"] = request.region or defaults.default_region + + return output + + +def marshal_CreateTLSStageRequest( + request: CreateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.secrets is not None: + output["secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.secrets + ] + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output + + +def marshal_SelectPlanRequest( + request: SelectPlanRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.plan_name is not None: + output["plan_name"] = str(request.plan_name) + + return output + + +def marshal_UpdateBackendStageRequest( + request: UpdateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + return output + + +def marshal_UpdateCacheStageRequest( + request: UpdateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_UpdateDNSStageRequest( + request: UpdateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_UpdatePipelineRequest( + request: UpdatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("dns_stage_id", request.dns_stage_id), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + return output + + +def marshal_TLSSecretsConfig( + request: TLSSecretsConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.tls_secrets is not None: + output["tls_secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.tls_secrets + ] + + return output + + +def marshal_UpdateTLSStageRequest( + request: UpdateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.tls_secrets_config is not None: + output["tls_secrets_config"] = marshal_TLSSecretsConfig( + request.tls_secrets_config, defaults + ) + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output diff --git a/scaleway/scaleway/edge_services/v1alpha1/types.py b/scaleway/scaleway/edge_services/v1alpha1/types.py new file mode 100644 index 00000000..a4121656 --- /dev/null +++ b/scaleway/scaleway/edge_services/v1alpha1/types.py @@ -0,0 +1,1302 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Money, + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DNSStageType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + AUTO = "auto" + MANAGED = "managed" + CUSTOM = "custom" + + def __str__(self) -> str: + return str(self.value) + + +class LbOriginError(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + TIMEOUT = "timeout" + CONNECTION_REFUSED = "connection_refused" + TLS_ERROR = "tls_error" + + def __str__(self) -> str: + return str(self.value) + + +class ListBackendStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListCacheStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListDNSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesWithStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPurgeRequestsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListTLSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorCode(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_CODE = "unknown_code" + DNS_INVALID_FORMAT = "dns_invalid_format" + DNS_INVALID_TLD = "dns_invalid_tld" + DNS_FORBIDDEN_ROOT_DOMAIN = "dns_forbidden_root_domain" + DNS_FORBIDDEN_SCW_CLOUD = "dns_forbidden_scw_cloud" + DNS_DOMAIN_DONT_EXIST = "dns_domain_dont_exist" + DNS_CNAME_DONT_EXIST = "dns_cname_dont_exist" + DNS_CNAME_RESOLVE = "dns_cname_resolve" + DNS_FQDN_ALREADY_EXISTS = "dns_fqdn_already_exists" + DNS_FQDN_ALREADY_IN_USE = "dns_fqdn_already_in_use" + TLS_CERT_DELETED = "tls_cert_deleted" + TLS_CERT_DISABLED = "tls_cert_disabled" + TLS_CERT_EXPIRED = "tls_cert_expired" + TLS_CERT_INVALID_FORMAT = "tls_cert_invalid_format" + TLS_CERT_MISSING = "tls_cert_missing" + TLS_CHAIN_ORDER = "tls_chain_order" + TLS_KEY_INVALID_FORMAT = "tls_key_invalid_format" + TLS_KEY_MISSING = "tls_key_missing" + TLS_KEY_TOO_MANY = "tls_key_too_many" + TLS_MANAGED_DOMAIN_RATE_LIMIT = "tls_managed_domain_rate_limit" + TLS_MANAGED_INTERNAL = "tls_managed_internal" + TLS_PAIR_MISMATCH = "tls_pair_mismatch" + TLS_ROOT_INCONSISTENT = "tls_root_inconsistent" + TLS_ROOT_INCORRECT = "tls_root_incorrect" + TLS_ROOT_MISSING = "tls_root_missing" + TLS_SAN_MISMATCH = "tls_san_mismatch" + TLS_SELF_SIGNED = "tls_self_signed" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorSeverity(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SEVERITY = "unknown_severity" + WARNING = "warning" + CRITICAL = "critical" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorStage(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STAGE = "unknown_stage" + DNS = "dns" + TLS = "tls" + CACHE = "cache" + BACKEND = "backend" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + RUNTIME = "runtime" + CONFIG = "config" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + ERROR = "error" + PENDING = "pending" + WARNING = "warning" + + def __str__(self) -> str: + return str(self.value) + + +class PlanName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + STARTER = "starter" + PROFESSIONAL = "professional" + ADVANCED = "advanced" + + def __str__(self) -> str: + return str(self.value) + + +class PurgeRequestStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DONE = "done" + ERROR = "error" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ScalewayLb: + id: str + """ + ID of the Load Balancer. + """ + + zone: ScwZone + """ + Zone of the Load Balancer. + """ + + frontend_id: str + """ + ID of the frontend linked to the Load Balancer. + """ + + is_ssl: Optional[bool] + """ + Defines whether the Load Balancer's frontend handles SSL connections. + """ + + domain_name: Optional[str] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to use in HTTP requests sent towards your Load Balancer. + """ + + +@dataclass +class ScalewayLbBackendConfig: + lbs: List[ScalewayLb] + """ + Load Balancer information. + """ + + +@dataclass +class ScalewayS3BackendConfig: + bucket_name: Optional[str] + """ + Name of the Bucket. + """ + + bucket_region: Optional[str] + """ + Region of the Bucket. + """ + + is_website: Optional[bool] + """ + Defines whether the bucket website feature is enabled. + """ + + +@dataclass +class PipelineError: + stage: PipelineErrorStage + + code: PipelineErrorCode + + severity: PipelineErrorSeverity + + message: str + + type_: PipelineErrorType + + +@dataclass +class TLSSecret: + secret_id: str + """ + ID of the Secret. + """ + + region: ScwRegion + """ + Region of the Secret. + """ + + +@dataclass +class BackendStage: + id: str + """ + ID of the backend stage. + """ + + project_id: str + """ + Project ID of the backend stage. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID the backend stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the backend stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the backend stage was last updated. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CacheStage: + id: str + """ + ID of the cache stage. + """ + + project_id: str + """ + Project ID of the cache stage. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID the cache stage belongs to. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + created_at: Optional[datetime] + """ + Date the cache stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the cache stage was last updated. + """ + + backend_stage_id: Optional[str] + + +@dataclass +class DNSStage: + id: str + """ + ID of the DNS stage. + """ + + fqdns: List[str] + """ + List of Fully Qualified Domain Names attached to the stage. + """ + + type_: DNSStageType + """ + Type of the stage. + """ + + project_id: str + """ + Project ID of the DNS stage. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID the DNS stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the DNS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the DNS stage was last updated. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class Pipeline: + id: str + """ + ID of the pipeline. + """ + + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + status: PipelineStatus + """ + Status of the pipeline. + """ + + errors: List[PipelineError] + """ + Errors of the pipeline. + """ + + project_id: str + """ + Project ID of the pipeline. + """ + + organization_id: str + """ + Organization ID of the pipeline. + """ + + created_at: Optional[datetime] + """ + Date the pipeline was created. + """ + + updated_at: Optional[datetime] + """ + Date the pipeline was last updated. + """ + + dns_stage_id: Optional[str] + + +@dataclass +class TLSStage: + id: str + """ + ID of the TLS stage. + """ + + secrets: List[TLSSecret] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: bool + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + project_id: str + """ + Project ID of the TLS stage. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID the TLS stage belongs to. + """ + + certificate_expires_at: Optional[datetime] + """ + Expiration date of the certificate. + """ + + created_at: Optional[datetime] + """ + Date the TLS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the TLS stage was last updated. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class CheckPEMChainRequestSecretChain: + secret_id: str + + secret_region: str + + +@dataclass +class PlanDetails: + plan_name: PlanName + """ + Subscription plan name. + """ + + package_gb: int + """ + Amount of egress data from cache included in subscription plan. + """ + + pipeline_limit: int + """ + Number of pipelines included in subscription plan. + """ + + waf_requests: int + """ + Number of WAF requests included in subscription plan. + """ + + +@dataclass +class PlanUsageDetails: + plan_cost: Optional[Money] + """ + Cost to date (this month) for the corresponding Edge Services subscription plan. + """ + + +@dataclass +class PipelineStages: + dns_stages: List[DNSStage] + + tls_stages: List[TLSStage] + + cache_stages: List[CacheStage] + + backend_stages: List[BackendStage] + + pipeline: Optional[Pipeline] + + +@dataclass +class PurgeRequest: + id: str + """ + ID of the purge request. + """ + + pipeline_id: str + """ + Pipeline ID the purge request belongs to. + """ + + status: PurgeRequestStatus + """ + Status of the purge request. + """ + + created_at: Optional[datetime] + """ + Date the purge request was created. + """ + + updated_at: Optional[datetime] + """ + Date the purge request was last updated. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class TLSSecretsConfig: + tls_secrets: List[TLSSecret] + """ + Secret information (from Secret Manager). + """ + + +@dataclass +class CheckDomainRequest: + fqdn: str + + cname: str + + project_id: Optional[str] + + +@dataclass +class CheckDomainResponse: + is_valid: bool + + +@dataclass +class CheckLbOriginRequest: + lb: Optional[ScalewayLb] + + +@dataclass +class CheckLbOriginResponse: + is_valid: bool + + error_type: LbOriginError + + +@dataclass +class CheckPEMChainRequest: + fqdn: str + + project_id: Optional[str] + + secret: Optional[CheckPEMChainRequestSecretChain] + + raw: Optional[str] + + +@dataclass +class CheckPEMChainResponse: + is_valid: bool + + +@dataclass +class CreateBackendStageRequest: + project_id: Optional[str] + """ + Project ID in which the backend stage will be created. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CreateCacheStageRequest: + project_id: Optional[str] + """ + Project ID in which the cache stage will be created. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + backend_stage_id: Optional[str] + + +@dataclass +class CreateDNSStageRequest: + project_id: Optional[str] + """ + Project ID in which the DNS stage will be created. + """ + + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class CreatePipelineRequest: + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + project_id: Optional[str] + """ + Project ID in which the pipeline will be created. + """ + + dns_stage_id: Optional[str] + + +@dataclass +class CreatePurgeRequestRequest: + pipeline_id: str + """ + Pipeline ID in which the purge request will be created. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class CreateTLSStageRequest: + project_id: Optional[str] + """ + Project ID in which the TLS stage will be created. + """ + + secrets: Optional[List[TLSSecret]] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class DeleteBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to delete. + """ + + +@dataclass +class DeleteCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to delete. + """ + + +@dataclass +class DeleteCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class DeleteDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to delete. + """ + + +@dataclass +class DeletePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to delete. + """ + + +@dataclass +class DeleteTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to delete. + """ + + +@dataclass +class GetBackendStageRequest: + backend_stage_id: str + """ + ID of the requested backend stage. + """ + + +@dataclass +class GetBillingRequest: + project_id: Optional[str] + + +@dataclass +class GetBillingResponse: + current_plan: Optional[PlanDetails] + """ + Information on the currently-selected, active Edge Services subscription plan. + """ + + pipeline_number: int + """ + Total number of pipelines currently configured. + """ + + current_plan_cache_usage: int + """ + Total amount of data egressed from the cache in gigabytes from the beginning of the month, for the active subscription plan. + """ + + extra_cache_usage: int + """ + Total amount of extra data egressed from cache in gigabytes from the beginning of the month, not included in the subscription plans. + """ + + current_plan_waf_usage: int + """ + Total number of requests processed by the WAF since the beginning of the current month, for the active subscription plan. + """ + + extra_waf_usage: int + """ + Total number of extra requests processed by the WAF from the beginning of the month, not included in the subscription plans. + """ + + plan_cost: Optional[Money] + """ + Cost to date (this month) for Edge Service subscription plans. This comprises the pro-rata cost of the current subscription plan, and any previous subscription plans that were active earlier in the month. + """ + + extra_pipelines_cost: Optional[Money] + """ + Cost to date (this month) of pipelines not included in the subscription plans. + """ + + plans_usage_details: Dict[str, PlanUsageDetails] + """ + Detailed costs and usage for all Edge Services subscription plans that were activated during the month. + """ + + extra_cache_cost: Optional[Money] + """ + Cost to date (this month) of the data egressed from the cache that is not included in the subscription plans. + """ + + extra_waf_cost: Optional[Money] + """ + Cost to date (this month) of the extra requests processed by the WAF that were not included in the subscription plans. + """ + + waf_add_on: Optional[Money] + """ + Cost of activating WAF add-on (where subscription plan does not include WAF). + """ + + total_cost: Optional[Money] + """ + Total cost to date (this month) of all Edge Services resources including active subscription plan, previously active plans, extra pipelines and extra egress cache data. + """ + + +@dataclass +class GetCacheStageRequest: + cache_stage_id: str + """ + ID of the requested cache stage. + """ + + +@dataclass +class GetCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class GetDNSStageRequest: + dns_stage_id: str + """ + ID of the requested DNS stage. + """ + + +@dataclass +class GetPipelineRequest: + pipeline_id: str + """ + ID of the requested pipeline. + """ + + +@dataclass +class GetPurgeRequestRequest: + purge_request_id: str + """ + ID of the requested purge request. + """ + + +@dataclass +class GetTLSStageRequest: + tls_stage_id: str + """ + ID of the requested TLS stage. + """ + + +@dataclass +class ListBackendStagesRequest: + order_by: Optional[ListBackendStagesRequestOrderBy] + """ + Sort order of backend stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of backend stages to return per page. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for, only backend stages from this pipeline will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only backend stages from this Project will be returned. + """ + + bucket_name: Optional[str] + """ + Bucket name to filter for, only backend stages from this Bucket will be returned. + """ + + bucket_region: Optional[str] + """ + Bucket region to filter for, only backend stages with buckets in this region will be returned. + """ + + lb_id: Optional[str] + """ + Load Balancer ID to filter for, only backend stages with this Load Balancer will be returned. + """ + + +@dataclass +class ListBackendStagesResponse: + stages: List[BackendStage] + """ + Paginated list of backend stages. + """ + + total_count: int + """ + Count of all backend stages matching the requested criteria. + """ + + +@dataclass +class ListCacheStagesRequest: + order_by: Optional[ListCacheStagesRequestOrderBy] + """ + Sort order of cache stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of cache stages to return per page. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for, only cache stages from this pipeline will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only cache stages from this Project will be returned. + """ + + +@dataclass +class ListCacheStagesResponse: + stages: List[CacheStage] + """ + Paginated list of cache stages. + """ + + total_count: int + """ + Count of all cache stages matching the requested criteria. + """ + + +@dataclass +class ListDNSStagesRequest: + order_by: Optional[ListDNSStagesRequestOrderBy] + """ + Sort order of DNS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of DNS stages to return per page. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for, only DNS stages from this pipeline will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only DNS stages from this Project will be returned. + """ + + fqdn: Optional[str] + """ + Fully Qualified Domain Name to filter for (in the format subdomain.example.com), only DNS stages with this FQDN will be returned. + """ + + +@dataclass +class ListDNSStagesResponse: + stages: List[DNSStage] + """ + Paginated list of DNS stages. + """ + + total_count: int + """ + Count of all DNS stages matching the requested criteria. + """ + + +@dataclass +class ListPipelinesRequest: + order_by: Optional[ListPipelinesRequestOrderBy] + """ + Sort order of pipelines in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of pipelines to return per page. + """ + + name: Optional[str] + """ + Pipeline name to filter for, only pipelines with this string within their name will be returned. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for, only pipelines from this Organization will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only pipelines from this Project will be returned. + """ + + has_backend_stage_lb: Optional[bool] + """ + Filter on backend stage, only pipelines with a Load Balancer origin will be returned. + """ + + +@dataclass +class ListPipelinesResponse: + pipelines: List[Pipeline] + """ + Paginated list of pipelines. + """ + + total_count: int + """ + Count of all pipelines matching the requested criteria. + """ + + +@dataclass +class ListPipelinesWithStagesRequest: + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + name: Optional[str] + + organization_id: Optional[str] + + project_id: Optional[str] + + +@dataclass +class ListPipelinesWithStagesResponse: + pipelines: List[PipelineStages] + + total_count: int + + +@dataclass +class ListPlansResponse: + total_count: int + + plans: List[PlanDetails] + + +@dataclass +class ListPurgeRequestsRequest: + order_by: Optional[ListPurgeRequestsRequestOrderBy] + """ + Sort order of purge requests in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of purge requests to return per page. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for, only purge requests from this Project will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only purge requests from this Project will be returned. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for, only purge requests from this pipeline will be returned. + """ + + +@dataclass +class ListPurgeRequestsResponse: + purge_requests: List[PurgeRequest] + """ + Paginated list of purge requests. + """ + + total_count: int + """ + Count of all purge requests matching the requested criteria. + """ + + +@dataclass +class ListTLSStagesRequest: + order_by: Optional[ListTLSStagesRequestOrderBy] + """ + Sort order of TLS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of TLS stages to return per page. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for, only TLS stages from this pipeline will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only TLS stages from this Project will be returned. + """ + + secret_id: Optional[str] + """ + Secret ID to filter for, only TLS stages with this Secret ID will be returned. + """ + + secret_region: Optional[str] + """ + Secret region to filter for, only TLS stages with a Secret in this region will be returned. + """ + + +@dataclass +class ListTLSStagesResponse: + stages: List[TLSStage] + """ + Paginated list of TLS stages. + """ + + total_count: int + """ + Count of all TLS stages matching the requested criteria. + """ + + +@dataclass +class Plan: + plan_name: PlanName + + +@dataclass +class SelectPlanRequest: + project_id: Optional[str] + + plan_name: Optional[PlanName] + + +@dataclass +class UpdateBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to update. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class UpdateCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to update. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + backend_stage_id: Optional[str] + + +@dataclass +class UpdateDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to update. + """ + + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class UpdatePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + name: Optional[str] + """ + Name of the pipeline. + """ + + description: Optional[str] + """ + Description of the pipeline. + """ + + dns_stage_id: Optional[str] + + +@dataclass +class UpdateTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to update. + """ + + tls_secrets_config: Optional[TLSSecretsConfig] + """ + Secret (from Scaleway Secret-Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] diff --git a/scaleway/scaleway/edge_services/v1beta1/__init__.py b/scaleway/scaleway/edge_services/v1beta1/__init__.py new file mode 100644 index 00000000..c441b4ae --- /dev/null +++ b/scaleway/scaleway/edge_services/v1beta1/__init__.py @@ -0,0 +1,257 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DNSStageType +from .types import LbOriginError +from .types import ListBackendStagesRequestOrderBy +from .types import ListCacheStagesRequestOrderBy +from .types import ListDNSStagesRequestOrderBy +from .types import ListPipelinesRequestOrderBy +from .types import ListPipelinesWithStagesRequestOrderBy +from .types import ListPurgeRequestsRequestOrderBy +from .types import ListRouteStagesRequestOrderBy +from .types import ListTLSStagesRequestOrderBy +from .types import ListWafStagesRequestOrderBy +from .types import PipelineErrorCode +from .types import PipelineErrorSeverity +from .types import PipelineErrorStage +from .types import PipelineErrorType +from .types import PipelineStatus +from .content import PIPELINE_TRANSIENT_STATUSES +from .types import PlanName +from .types import PurgeRequestStatus +from .content import PURGE_REQUEST_TRANSIENT_STATUSES +from .types import RuleHttpMatchMethodFilter +from .types import RuleHttpMatchPathFilterPathFilterType +from .types import SearchBackendStagesRequestOrderBy +from .types import SearchWafStagesRequestOrderBy +from .types import WafStageMode +from .types import ScalewayLb +from .types import RuleHttpMatchPathFilter +from .types import ScalewayLbBackendConfig +from .types import ScalewayS3BackendConfig +from .types import PipelineError +from .types import TLSSecret +from .types import RuleHttpMatch +from .types import BackendStage +from .types import CacheStage +from .types import DNSStage +from .types import Pipeline +from .types import RouteStage +from .types import TLSStage +from .types import WafStage +from .types import SetRouteRulesRequestRouteRule +from .types import RouteRule +from .types import CheckPEMChainRequestSecretChain +from .types import PlanDetails +from .types import PlanUsageDetails +from .types import HeadStageResponseHeadStage +from .types import ListHeadStagesResponseHeadStage +from .types import PipelineStages +from .types import PurgeRequest +from .types import SetHeadStageRequestAddNewHeadStage +from .types import SetHeadStageRequestRemoveHeadStage +from .types import SetHeadStageRequestSwapHeadStage +from .types import TLSSecretsConfig +from .types import AddRouteRulesRequest +from .types import AddRouteRulesResponse +from .types import CheckDomainRequest +from .types import CheckDomainResponse +from .types import CheckLbOriginRequest +from .types import CheckLbOriginResponse +from .types import CheckPEMChainRequest +from .types import CheckPEMChainResponse +from .types import CreateBackendStageRequest +from .types import CreateCacheStageRequest +from .types import CreateDNSStageRequest +from .types import CreatePipelineRequest +from .types import CreatePurgeRequestRequest +from .types import CreateRouteStageRequest +from .types import CreateTLSStageRequest +from .types import CreateWafStageRequest +from .types import DeleteBackendStageRequest +from .types import DeleteCacheStageRequest +from .types import DeleteCurrentPlanRequest +from .types import DeleteDNSStageRequest +from .types import DeletePipelineRequest +from .types import DeleteRouteStageRequest +from .types import DeleteTLSStageRequest +from .types import DeleteWafStageRequest +from .types import GetBackendStageRequest +from .types import GetBillingRequest +from .types import GetBillingResponse +from .types import GetCacheStageRequest +from .types import GetCurrentPlanRequest +from .types import GetDNSStageRequest +from .types import GetPipelineRequest +from .types import GetPurgeRequestRequest +from .types import GetRouteStageRequest +from .types import GetTLSStageRequest +from .types import GetWafStageRequest +from .types import HeadStageResponse +from .types import ListBackendStagesRequest +from .types import ListBackendStagesResponse +from .types import ListCacheStagesRequest +from .types import ListCacheStagesResponse +from .types import ListDNSStagesRequest +from .types import ListDNSStagesResponse +from .types import ListHeadStagesRequest +from .types import ListHeadStagesResponse +from .types import ListPipelinesRequest +from .types import ListPipelinesResponse +from .types import ListPipelinesWithStagesRequest +from .types import ListPipelinesWithStagesResponse +from .types import ListPlansResponse +from .types import ListPurgeRequestsRequest +from .types import ListPurgeRequestsResponse +from .types import ListRouteRulesRequest +from .types import ListRouteRulesResponse +from .types import ListRouteStagesRequest +from .types import ListRouteStagesResponse +from .types import ListTLSStagesRequest +from .types import ListTLSStagesResponse +from .types import ListWafStagesRequest +from .types import ListWafStagesResponse +from .types import Plan +from .types import SearchBackendStagesRequest +from .types import SearchWafStagesRequest +from .types import SelectPlanRequest +from .types import SetHeadStageRequest +from .types import SetRouteRulesRequest +from .types import SetRouteRulesResponse +from .types import UpdateBackendStageRequest +from .types import UpdateCacheStageRequest +from .types import UpdateDNSStageRequest +from .types import UpdatePipelineRequest +from .types import UpdateRouteStageRequest +from .types import UpdateTLSStageRequest +from .types import UpdateWafStageRequest +from .api import EdgeServicesV1Beta1API + +__all__ = [ + "DNSStageType", + "LbOriginError", + "ListBackendStagesRequestOrderBy", + "ListCacheStagesRequestOrderBy", + "ListDNSStagesRequestOrderBy", + "ListPipelinesRequestOrderBy", + "ListPipelinesWithStagesRequestOrderBy", + "ListPurgeRequestsRequestOrderBy", + "ListRouteStagesRequestOrderBy", + "ListTLSStagesRequestOrderBy", + "ListWafStagesRequestOrderBy", + "PipelineErrorCode", + "PipelineErrorSeverity", + "PipelineErrorStage", + "PipelineErrorType", + "PipelineStatus", + "PIPELINE_TRANSIENT_STATUSES", + "PlanName", + "PurgeRequestStatus", + "PURGE_REQUEST_TRANSIENT_STATUSES", + "RuleHttpMatchMethodFilter", + "RuleHttpMatchPathFilterPathFilterType", + "SearchBackendStagesRequestOrderBy", + "SearchWafStagesRequestOrderBy", + "WafStageMode", + "ScalewayLb", + "RuleHttpMatchPathFilter", + "ScalewayLbBackendConfig", + "ScalewayS3BackendConfig", + "PipelineError", + "TLSSecret", + "RuleHttpMatch", + "BackendStage", + "CacheStage", + "DNSStage", + "Pipeline", + "RouteStage", + "TLSStage", + "WafStage", + "SetRouteRulesRequestRouteRule", + "RouteRule", + "CheckPEMChainRequestSecretChain", + "PlanDetails", + "PlanUsageDetails", + "HeadStageResponseHeadStage", + "ListHeadStagesResponseHeadStage", + "PipelineStages", + "PurgeRequest", + "SetHeadStageRequestAddNewHeadStage", + "SetHeadStageRequestRemoveHeadStage", + "SetHeadStageRequestSwapHeadStage", + "TLSSecretsConfig", + "AddRouteRulesRequest", + "AddRouteRulesResponse", + "CheckDomainRequest", + "CheckDomainResponse", + "CheckLbOriginRequest", + "CheckLbOriginResponse", + "CheckPEMChainRequest", + "CheckPEMChainResponse", + "CreateBackendStageRequest", + "CreateCacheStageRequest", + "CreateDNSStageRequest", + "CreatePipelineRequest", + "CreatePurgeRequestRequest", + "CreateRouteStageRequest", + "CreateTLSStageRequest", + "CreateWafStageRequest", + "DeleteBackendStageRequest", + "DeleteCacheStageRequest", + "DeleteCurrentPlanRequest", + "DeleteDNSStageRequest", + "DeletePipelineRequest", + "DeleteRouteStageRequest", + "DeleteTLSStageRequest", + "DeleteWafStageRequest", + "GetBackendStageRequest", + "GetBillingRequest", + "GetBillingResponse", + "GetCacheStageRequest", + "GetCurrentPlanRequest", + "GetDNSStageRequest", + "GetPipelineRequest", + "GetPurgeRequestRequest", + "GetRouteStageRequest", + "GetTLSStageRequest", + "GetWafStageRequest", + "HeadStageResponse", + "ListBackendStagesRequest", + "ListBackendStagesResponse", + "ListCacheStagesRequest", + "ListCacheStagesResponse", + "ListDNSStagesRequest", + "ListDNSStagesResponse", + "ListHeadStagesRequest", + "ListHeadStagesResponse", + "ListPipelinesRequest", + "ListPipelinesResponse", + "ListPipelinesWithStagesRequest", + "ListPipelinesWithStagesResponse", + "ListPlansResponse", + "ListPurgeRequestsRequest", + "ListPurgeRequestsResponse", + "ListRouteRulesRequest", + "ListRouteRulesResponse", + "ListRouteStagesRequest", + "ListRouteStagesResponse", + "ListTLSStagesRequest", + "ListTLSStagesResponse", + "ListWafStagesRequest", + "ListWafStagesResponse", + "Plan", + "SearchBackendStagesRequest", + "SearchWafStagesRequest", + "SelectPlanRequest", + "SetHeadStageRequest", + "SetRouteRulesRequest", + "SetRouteRulesResponse", + "UpdateBackendStageRequest", + "UpdateCacheStageRequest", + "UpdateDNSStageRequest", + "UpdatePipelineRequest", + "UpdateRouteStageRequest", + "UpdateTLSStageRequest", + "UpdateWafStageRequest", + "EdgeServicesV1Beta1API", +] diff --git a/scaleway/scaleway/edge_services/v1beta1/api.py b/scaleway/scaleway/edge_services/v1beta1/api.py new file mode 100644 index 00000000..6446a5fa --- /dev/null +++ b/scaleway/scaleway/edge_services/v1beta1/api.py @@ -0,0 +1,2646 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + ListBackendStagesRequestOrderBy, + ListCacheStagesRequestOrderBy, + ListDNSStagesRequestOrderBy, + ListPipelinesRequestOrderBy, + ListPipelinesWithStagesRequestOrderBy, + ListPurgeRequestsRequestOrderBy, + ListRouteStagesRequestOrderBy, + ListTLSStagesRequestOrderBy, + ListWafStagesRequestOrderBy, + PlanName, + SearchBackendStagesRequestOrderBy, + SearchWafStagesRequestOrderBy, + WafStageMode, + AddRouteRulesRequest, + AddRouteRulesResponse, + BackendStage, + CacheStage, + CheckDomainRequest, + CheckDomainResponse, + CheckLbOriginRequest, + CheckLbOriginResponse, + CheckPEMChainRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainResponse, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateRouteStageRequest, + CreateTLSStageRequest, + CreateWafStageRequest, + DNSStage, + GetBillingResponse, + HeadStageResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListHeadStagesResponse, + ListHeadStagesResponseHeadStage, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListRouteRulesResponse, + ListRouteStagesResponse, + ListTLSStagesResponse, + ListWafStagesResponse, + Pipeline, + PipelineStages, + Plan, + PurgeRequest, + RouteStage, + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + SelectPlanRequest, + SetHeadStageRequest, + SetHeadStageRequestAddNewHeadStage, + SetHeadStageRequestRemoveHeadStage, + SetHeadStageRequestSwapHeadStage, + SetRouteRulesRequest, + SetRouteRulesRequestRouteRule, + SetRouteRulesResponse, + TLSSecret, + TLSSecretsConfig, + TLSStage, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + UpdateRouteStageRequest, + UpdateTLSStageRequest, + UpdateWafStageRequest, + WafStage, +) +from .content import ( + PIPELINE_TRANSIENT_STATUSES, + PURGE_REQUEST_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_BackendStage, + unmarshal_CacheStage, + unmarshal_DNSStage, + unmarshal_Pipeline, + unmarshal_RouteStage, + unmarshal_TLSStage, + unmarshal_WafStage, + unmarshal_PurgeRequest, + unmarshal_AddRouteRulesResponse, + unmarshal_CheckDomainResponse, + unmarshal_CheckLbOriginResponse, + unmarshal_CheckPEMChainResponse, + unmarshal_GetBillingResponse, + unmarshal_HeadStageResponse, + unmarshal_ListBackendStagesResponse, + unmarshal_ListCacheStagesResponse, + unmarshal_ListDNSStagesResponse, + unmarshal_ListHeadStagesResponse, + unmarshal_ListPipelinesResponse, + unmarshal_ListPipelinesWithStagesResponse, + unmarshal_ListPlansResponse, + unmarshal_ListPurgeRequestsResponse, + unmarshal_ListRouteRulesResponse, + unmarshal_ListRouteStagesResponse, + unmarshal_ListTLSStagesResponse, + unmarshal_ListWafStagesResponse, + unmarshal_Plan, + unmarshal_SetRouteRulesResponse, + marshal_AddRouteRulesRequest, + marshal_CheckDomainRequest, + marshal_CheckLbOriginRequest, + marshal_CheckPEMChainRequest, + marshal_CreateBackendStageRequest, + marshal_CreateCacheStageRequest, + marshal_CreateDNSStageRequest, + marshal_CreatePipelineRequest, + marshal_CreatePurgeRequestRequest, + marshal_CreateRouteStageRequest, + marshal_CreateTLSStageRequest, + marshal_CreateWafStageRequest, + marshal_SelectPlanRequest, + marshal_SetHeadStageRequest, + marshal_SetRouteRulesRequest, + marshal_UpdateBackendStageRequest, + marshal_UpdateCacheStageRequest, + marshal_UpdateDNSStageRequest, + marshal_UpdatePipelineRequest, + marshal_UpdateRouteStageRequest, + marshal_UpdateTLSStageRequest, + marshal_UpdateWafStageRequest, +) + + +class EdgeServicesV1Beta1API(API): + """ """ + + def list_pipelines( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> ListPipelinesResponse: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for. Only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for. Only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for. Only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + :return: :class:`ListPipelinesResponse ` + + Usage: + :: + + result = api.list_pipelines() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/pipelines", + params={ + "has_backend_stage_lb": has_backend_stage_lb, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesResponse(res.json()) + + def list_pipelines_all( + self, + *, + order_by: Optional[ListPipelinesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + has_backend_stage_lb: Optional[bool] = None, + ) -> List[Pipeline]: + """ + List pipelines. + List all pipelines, for a Scaleway Organization or Scaleway Project. By default, the pipelines returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of pipelines in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of pipelines to return per page. + :param name: Pipeline name to filter for. Only pipelines with this string within their name will be returned. + :param organization_id: Organization ID to filter for. Only pipelines from this Organization will be returned. + :param project_id: Project ID to filter for. Only pipelines from this Project will be returned. + :param has_backend_stage_lb: Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + :return: :class:`List[Pipeline] ` + + Usage: + :: + + result = api.list_pipelines_all() + """ + + return fetch_all_pages( + type=ListPipelinesResponse, + key="pipelines", + fetcher=self.list_pipelines, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + "has_backend_stage_lb": has_backend_stage_lb, + }, + ) + + def create_pipeline( + self, + *, + name: str, + description: str, + project_id: Optional[str] = None, + ) -> Pipeline: + """ + Create pipeline. + Create a new pipeline. You must specify a `dns_stage_id` to form a stage-chain that goes all the way to the backend stage (origin), so the HTTP request will be processed according to the stages you created. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :param project_id: Project ID in which the pipeline will be created. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.create_pipeline( + name="example", + description="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/pipelines", + body=marshal_CreatePipelineRequest( + CreatePipelineRequest( + name=name, + description=description, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + def get_pipeline( + self, + *, + pipeline_id: str, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.get_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + def wait_for_pipeline( + self, + *, + pipeline_id: str, + options: Optional[WaitForOptions[Pipeline, bool]] = None, + ) -> Pipeline: + """ + Get pipeline. + Retrieve information about an existing pipeline, specified by its `pipeline_id`. Its full details, including errors, are returned in the response object. + :param pipeline_id: ID of the requested pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.get_pipeline( + pipeline_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in PIPELINE_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_pipeline, + options=options, + args={ + "pipeline_id": pipeline_id, + }, + ) + + def list_pipelines_with_stages( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> ListPipelinesWithStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`ListPipelinesWithStagesResponse ` + + Usage: + :: + + result = api.list_pipelines_with_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/pipelines-stages", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPipelinesWithStagesResponse(res.json()) + + def list_pipelines_with_stages_all( + self, + *, + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + ) -> List[PipelineStages]: + """ + :param order_by: + :param page: + :param page_size: + :param name: + :param organization_id: + :param project_id: + :return: :class:`List[PipelineStages] ` + + Usage: + :: + + result = api.list_pipelines_with_stages_all() + """ + + return fetch_all_pages( + type=ListPipelinesWithStagesResponse, + key="pipelines", + fetcher=self.list_pipelines_with_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "organization_id": organization_id, + "project_id": project_id, + }, + ) + + def update_pipeline( + self, + *, + pipeline_id: str, + name: Optional[str] = None, + description: Optional[str] = None, + ) -> Pipeline: + """ + Update pipeline. + Update the parameters of an existing pipeline, specified by its `pipeline_id`. Parameters which can be updated include the `name`, `description` and `dns_stage_id`. + :param pipeline_id: ID of the pipeline to update. + :param name: Name of the pipeline. + :param description: Description of the pipeline. + :return: :class:`Pipeline ` + + Usage: + :: + + result = api.update_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + body=marshal_UpdatePipelineRequest( + UpdatePipelineRequest( + pipeline_id=pipeline_id, + name=name, + description=description, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Pipeline(res.json()) + + def delete_pipeline( + self, + *, + pipeline_id: str, + ) -> None: + """ + Delete pipeline. + Delete an existing pipeline, specified by its `pipeline_id`. Deleting a pipeline is permanent, and cannot be undone. Note that all stages linked to the pipeline are also deleted. + :param pipeline_id: ID of the pipeline to delete. + + Usage: + :: + + result = api.delete_pipeline( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}", + ) + + self._throw_on_error(res) + + def list_head_stages( + self, + *, + pipeline_id: str, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListHeadStagesResponse: + """ + :param pipeline_id: ID of the pipeline to update. + :param page: Page number to return, from the paginated results. + :param page_size: Number of head stages to return per page. + :return: :class:`ListHeadStagesResponse ` + + Usage: + :: + + result = api.list_head_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/head-stages", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListHeadStagesResponse(res.json()) + + def list_head_stages_all( + self, + *, + pipeline_id: str, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[ListHeadStagesResponseHeadStage]: + """ + :param pipeline_id: ID of the pipeline to update. + :param page: Page number to return, from the paginated results. + :param page_size: Number of head stages to return per page. + :return: :class:`List[ListHeadStagesResponseHeadStage] ` + + Usage: + :: + + result = api.list_head_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListHeadStagesResponse, + key="head_stages", + fetcher=self.list_head_stages, + args={ + "pipeline_id": pipeline_id, + "page": page, + "page_size": page_size, + }, + ) + + def set_head_stage( + self, + *, + pipeline_id: str, + add_new_head_stage: Optional[SetHeadStageRequestAddNewHeadStage] = None, + remove_head_stage: Optional[SetHeadStageRequestRemoveHeadStage] = None, + swap_head_stage: Optional[SetHeadStageRequestSwapHeadStage] = None, + ) -> HeadStageResponse: + """ + Configure a entry point to your pipeline. You must specify a `head stage` to form a stage-chain that goes all the way to the backend stage (origin), so the HTTP request will be processed according to the stages you created. + You must specify either a `add_new_head_stage` (to add a new head stage), `remove_head_stage` (to remove a head stage) or `swap_head_stage` (to replace a head stage). + :param pipeline_id: ID of the pipeline to update. + :param add_new_head_stage: Add a new head stage. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :param remove_head_stage: Remove a head stage. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :param swap_head_stage: Replace a head stage with a new one. + One-Of ('action'): at most one of 'add_new_head_stage', 'remove_head_stage', 'swap_head_stage' could be set. + :return: :class:`HeadStageResponse ` + + Usage: + :: + + result = api.set_head_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/set-head-stage", + body=marshal_SetHeadStageRequest( + SetHeadStageRequest( + pipeline_id=pipeline_id, + add_new_head_stage=add_new_head_stage, + remove_head_stage=remove_head_stage, + swap_head_stage=swap_head_stage, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_HeadStageResponse(res.json()) + + def list_dns_stages( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + fqdn: Optional[str] = None, + ) -> ListDNSStagesResponse: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + :return: :class:`ListDNSStagesResponse ` + + Usage: + :: + + result = api.list_dns_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/dns-stages", + params={ + "fqdn": fqdn, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDNSStagesResponse(res.json()) + + def list_dns_stages_all( + self, + *, + order_by: Optional[ListDNSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + fqdn: Optional[str] = None, + ) -> List[DNSStage]: + """ + List DNS stages. + List all DNS stages, for a Scaleway Organization or Scaleway Project. By default, the DNS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of DNS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of DNS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + :param fqdn: Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + :return: :class:`List[DNSStage] ` + + Usage: + :: + + result = api.list_dns_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListDNSStagesResponse, + key="stages", + fetcher=self.list_dns_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "fqdn": fqdn, + }, + ) + + def create_dns_stage( + self, + *, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + ) -> DNSStage: + """ + Create DNS stage. + Create a new DNS stage. You must specify the `fqdns` field to customize the domain endpoint, using a domain you already own. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param pipeline_id: Pipeline ID the DNS stage belongs to. + :return: :class:`DNSStage ` + + Usage: + :: + + result = api.create_dns_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/dns-stages", + body=marshal_CreateDNSStageRequest( + CreateDNSStageRequest( + fqdns=fqdns, + pipeline_id=pipeline_id, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + def get_dns_stage( + self, + *, + dns_stage_id: str, + ) -> DNSStage: + """ + Get DNS stage. + Retrieve information about an existing DNS stage, specified by its `dns_stage_id`. Its full details, including FQDNs, are returned in the response object. + :param dns_stage_id: ID of the requested DNS stage. + :return: :class:`DNSStage ` + + Usage: + :: + + result = api.get_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + def update_dns_stage( + self, + *, + dns_stage_id: str, + fqdns: Optional[List[str]] = None, + tls_stage_id: Optional[str] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + ) -> DNSStage: + """ + Update DNS stage. + Update the parameters of an existing DNS stage, specified by its `dns_stage_id`. + :param dns_stage_id: ID of the DNS stage to update. + :param fqdns: Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + :param tls_stage_id: TLS stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param cache_stage_id: Cache stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :param backend_stage_id: Backend stage ID the DNS stage will be linked to. + One-Of ('next'): at most one of 'tls_stage_id', 'cache_stage_id', 'backend_stage_id' could be set. + :return: :class:`DNSStage ` + + Usage: + :: + + result = api.update_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + body=marshal_UpdateDNSStageRequest( + UpdateDNSStageRequest( + dns_stage_id=dns_stage_id, + fqdns=fqdns, + tls_stage_id=tls_stage_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DNSStage(res.json()) + + def delete_dns_stage( + self, + *, + dns_stage_id: str, + ) -> None: + """ + Delete DNS stage. + Delete an existing DNS stage, specified by its `dns_stage_id`. Deleting a DNS stage is permanent, and cannot be undone. + :param dns_stage_id: ID of the DNS stage to delete. + + Usage: + :: + + result = api.delete_dns_stage( + dns_stage_id="example", + ) + """ + + param_dns_stage_id = validate_path_param("dns_stage_id", dns_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/dns-stages/{param_dns_stage_id}", + ) + + self._throw_on_error(res) + + def list_tls_stages( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> ListTLSStagesResponse: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + :param secret_id: Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + :return: :class:`ListTLSStagesResponse ` + + Usage: + :: + + result = api.list_tls_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/tls-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListTLSStagesResponse(res.json()) + + def list_tls_stages_all( + self, + *, + order_by: Optional[ListTLSStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + secret_id: Optional[str] = None, + secret_region: Optional[str] = None, + ) -> List[TLSStage]: + """ + List TLS stages. + List all TLS stages, for a Scaleway Organization or Scaleway Project. By default, the TLS stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of TLS stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of TLS stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + :param secret_id: Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + :param secret_region: Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + :return: :class:`List[TLSStage] ` + + Usage: + :: + + result = api.list_tls_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListTLSStagesResponse, + key="stages", + fetcher=self.list_tls_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "secret_id": secret_id, + "secret_region": secret_region, + }, + ) + + def create_tls_stage( + self, + *, + secrets: Optional[List[TLSSecret]] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + route_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Create TLS stage. + Create a new TLS stage. You must specify either the `secrets` or `managed_certificate` fields to customize the SSL/TLS certificate of your endpoint. Choose `secrets` if you are using a pre-existing certificate held in Scaleway Secret Manager, or `managed_certificate` to let Scaleway generate and manage a Let's Encrypt certificate for your customized endpoint. + :param secrets: Secret (from Scaleway Secret Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param pipeline_id: Pipeline ID the TLS stage belongs to. + :param route_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = api.create_tls_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/tls-stages", + body=marshal_CreateTLSStageRequest( + CreateTLSStageRequest( + secrets=secrets, + managed_certificate=managed_certificate, + pipeline_id=pipeline_id, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + def get_tls_stage( + self, + *, + tls_stage_id: str, + ) -> TLSStage: + """ + Get TLS stage. + Retrieve information about an existing TLS stage, specified by its `tls_stage_id`. Its full details, including secrets and certificate expiration date are returned in the response object. + :param tls_stage_id: ID of the requested TLS stage. + :return: :class:`TLSStage ` + + Usage: + :: + + result = api.get_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + def update_tls_stage( + self, + *, + tls_stage_id: str, + tls_secrets_config: Optional[TLSSecretsConfig] = None, + managed_certificate: Optional[bool] = None, + cache_stage_id: Optional[str] = None, + backend_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + ) -> TLSStage: + """ + Update TLS stage. + Update the parameters of an existing TLS stage, specified by its `tls_stage_id`. Both `tls_secrets_config` and `managed_certificate` parameters can be updated. + :param tls_stage_id: ID of the TLS stage to update. + :param tls_secrets_config: Secret (from Scaleway Secret-Manager) containing your custom certificate. + :param managed_certificate: True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + :param cache_stage_id: Cache stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param backend_stage_id: Backend stage ID the TLS stage will be linked to. + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'cache_stage_id', 'backend_stage_id', 'route_stage_id', 'waf_stage_id' could be set. + :return: :class:`TLSStage ` + + Usage: + :: + + result = api.update_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + body=marshal_UpdateTLSStageRequest( + UpdateTLSStageRequest( + tls_stage_id=tls_stage_id, + tls_secrets_config=tls_secrets_config, + managed_certificate=managed_certificate, + cache_stage_id=cache_stage_id, + backend_stage_id=backend_stage_id, + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_TLSStage(res.json()) + + def delete_tls_stage( + self, + *, + tls_stage_id: str, + ) -> None: + """ + Delete TLS stage. + Delete an existing TLS stage, specified by its `tls_stage_id`. Deleting a TLS stage is permanent, and cannot be undone. + :param tls_stage_id: ID of the TLS stage to delete. + + Usage: + :: + + result = api.delete_tls_stage( + tls_stage_id="example", + ) + """ + + param_tls_stage_id = validate_path_param("tls_stage_id", tls_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/tls-stages/{param_tls_stage_id}", + ) + + self._throw_on_error(res) + + def list_cache_stages( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListCacheStagesResponse: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + :return: :class:`ListCacheStagesResponse ` + + Usage: + :: + + result = api.list_cache_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/cache-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListCacheStagesResponse(res.json()) + + def list_cache_stages_all( + self, + *, + order_by: Optional[ListCacheStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[CacheStage]: + """ + List cache stages. + List all cache stages, for a Scaleway Organization or Scaleway Project. By default, the cache stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of cache stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of cache stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + :return: :class:`List[CacheStage] ` + + Usage: + :: + + result = api.list_cache_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListCacheStagesResponse, + key="stages", + fetcher=self.list_cache_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + def create_cache_stage( + self, + *, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + pipeline_id: str, + waf_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Create cache stage. + Create a new cache stage. You must specify the `fallback_ttl` field to customize the TTL of the cache. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param pipeline_id: Pipeline ID the Cache stage belongs to. + :param waf_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = api.create_cache_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/cache-stages", + body=marshal_CreateCacheStageRequest( + CreateCacheStageRequest( + fallback_ttl=fallback_ttl, + pipeline_id=pipeline_id, + backend_stage_id=backend_stage_id, + waf_stage_id=waf_stage_id, + route_stage_id=route_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + def get_cache_stage( + self, + *, + cache_stage_id: str, + ) -> CacheStage: + """ + Get cache stage. + Retrieve information about an existing cache stage, specified by its `cache_stage_id`. Its full details, including Time To Live (TTL), are returned in the response object. + :param cache_stage_id: ID of the requested cache stage. + :return: :class:`CacheStage ` + + Usage: + :: + + result = api.get_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + def update_cache_stage( + self, + *, + cache_stage_id: str, + fallback_ttl: Optional[str] = None, + backend_stage_id: Optional[str] = None, + waf_stage_id: Optional[str] = None, + route_stage_id: Optional[str] = None, + ) -> CacheStage: + """ + Update cache stage. + Update the parameters of an existing cache stage, specified by its `cache_stage_id`. Parameters which can be updated include the `fallback_ttl` and `backend_stage_id`. + :param cache_stage_id: ID of the cache stage to update. + :param fallback_ttl: Time To Live (TTL) in seconds. Defines how long content is cached. + :param backend_stage_id: Backend stage ID the cache stage will be linked to. + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param waf_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :param route_stage_id: + One-Of ('next'): at most one of 'backend_stage_id', 'waf_stage_id', 'route_stage_id' could be set. + :return: :class:`CacheStage ` + + Usage: + :: + + result = api.update_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + body=marshal_UpdateCacheStageRequest( + UpdateCacheStageRequest( + cache_stage_id=cache_stage_id, + fallback_ttl=fallback_ttl, + backend_stage_id=backend_stage_id, + waf_stage_id=waf_stage_id, + route_stage_id=route_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CacheStage(res.json()) + + def delete_cache_stage( + self, + *, + cache_stage_id: str, + ) -> None: + """ + Delete cache stage. + Delete an existing cache stage, specified by its `cache_stage_id`. Deleting a cache stage is permanent, and cannot be undone. + :param cache_stage_id: ID of the cache stage to delete. + + Usage: + :: + + result = api.delete_cache_stage( + cache_stage_id="example", + ) + """ + + param_cache_stage_id = validate_path_param("cache_stage_id", cache_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/cache-stages/{param_cache_stage_id}", + ) + + self._throw_on_error(res) + + def list_backend_stages( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> ListBackendStagesResponse: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + :param bucket_name: Bucket name to filter for. Only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for. Only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + :return: :class:`ListBackendStagesResponse ` + + Usage: + :: + + result = api.list_backend_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/backend-stages", + params={ + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBackendStagesResponse(res.json()) + + def list_backend_stages_all( + self, + *, + order_by: Optional[ListBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> List[BackendStage]: + """ + List backend stages. + List all backend stages, for a Scaleway Organization or Scaleway Project. By default, the backend stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of backend stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of backend stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + :param bucket_name: Bucket name to filter for. Only backend stages from this Bucket will be returned. + :param bucket_region: Bucket region to filter for. Only backend stages with buckets in this region will be returned. + :param lb_id: Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + :return: :class:`List[BackendStage] ` + + Usage: + :: + + result = api.list_backend_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListBackendStagesResponse, + key="stages", + fetcher=self.list_backend_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + }, + ) + + def create_backend_stage( + self, + *, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + pipeline_id: str, + ) -> BackendStage: + """ + Create backend stage. + Create a new backend stage. You must specify either a `scaleway_s3` (for a Scaleway Object Storage bucket) or `scaleway_lb` (for a Scaleway Load Balancer) field to configure the origin. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param pipeline_id: Pipeline ID the Backend stage belongs to. + :return: :class:`BackendStage ` + + Usage: + :: + + result = api.create_backend_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/backend-stages", + body=marshal_CreateBackendStageRequest( + CreateBackendStageRequest( + pipeline_id=pipeline_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + def get_backend_stage( + self, + *, + backend_stage_id: str, + ) -> BackendStage: + """ + Get backend stage. + Retrieve information about an existing backend stage, specified by its `backend_stage_id`. Its full details, including `scaleway_s3` or `scaleway_lb`, are returned in the response object. + :param backend_stage_id: ID of the requested backend stage. + :return: :class:`BackendStage ` + + Usage: + :: + + result = api.get_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + def update_backend_stage( + self, + *, + backend_stage_id: str, + pipeline_id: str, + scaleway_s3: Optional[ScalewayS3BackendConfig] = None, + scaleway_lb: Optional[ScalewayLbBackendConfig] = None, + ) -> BackendStage: + """ + Update backend stage. + Update the parameters of an existing backend stage, specified by its `backend_stage_id`. + :param backend_stage_id: ID of the backend stage to update. + :param pipeline_id: Pipeline ID the Backend stage belongs to. + :param scaleway_s3: Scaleway Object Storage origin bucket (S3) linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :param scaleway_lb: Scaleway Load Balancer origin linked to the backend stage. + One-Of ('backend_config'): at most one of 'scaleway_s3', 'scaleway_lb' could be set. + :return: :class:`BackendStage ` + + Usage: + :: + + result = api.update_backend_stage( + backend_stage_id="example", + pipeline_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + body=marshal_UpdateBackendStageRequest( + UpdateBackendStageRequest( + backend_stage_id=backend_stage_id, + pipeline_id=pipeline_id, + scaleway_s3=scaleway_s3, + scaleway_lb=scaleway_lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BackendStage(res.json()) + + def delete_backend_stage( + self, + *, + backend_stage_id: str, + ) -> None: + """ + Delete backend stage. + Delete an existing backend stage, specified by its `backend_stage_id`. Deleting a backend stage is permanent, and cannot be undone. + :param backend_stage_id: ID of the backend stage to delete. + + Usage: + :: + + result = api.delete_backend_stage( + backend_stage_id="example", + ) + """ + + param_backend_stage_id = validate_path_param( + "backend_stage_id", backend_stage_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/backend-stages/{param_backend_stage_id}", + ) + + self._throw_on_error(res) + + def search_backend_stages( + self, + *, + order_by: Optional[SearchBackendStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + bucket_name: Optional[str] = None, + bucket_region: Optional[str] = None, + lb_id: Optional[str] = None, + ) -> ListBackendStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param project_id: + :param bucket_name: + :param bucket_region: + :param lb_id: + :return: :class:`ListBackendStagesResponse ` + + Usage: + :: + + result = api.search_backend_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/search-backend-stages", + params={ + "bucket_name": bucket_name, + "bucket_region": bucket_region, + "lb_id": lb_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBackendStagesResponse(res.json()) + + def list_waf_stages( + self, + *, + order_by: Optional[ListWafStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListWafStagesResponse: + """ + List WAF stages. + List all WAF stages, for a Scaleway Organization or Scaleway Project. By default, the WAF stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of WAF stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of WAF stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + :return: :class:`ListWafStagesResponse ` + + Usage: + :: + + result = api.list_waf_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/waf-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWafStagesResponse(res.json()) + + def list_waf_stages_all( + self, + *, + order_by: Optional[ListWafStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[WafStage]: + """ + List WAF stages. + List all WAF stages, for a Scaleway Organization or Scaleway Project. By default, the WAF stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of WAF stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of WAF stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + :return: :class:`List[WafStage] ` + + Usage: + :: + + result = api.list_waf_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListWafStagesResponse, + key="stages", + fetcher=self.list_waf_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + def create_waf_stage( + self, + *, + pipeline_id: str, + paranoia_level: int, + mode: Optional[WafStageMode] = None, + backend_stage_id: Optional[str] = None, + ) -> WafStage: + """ + Create WAF stage. + Create a new WAF stage. You must specify the `mode` and `paranoia_level` fields to customize the WAF. + :param pipeline_id: Pipeline ID the WAF stage belongs to. + :param paranoia_level: Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + :param mode: Mode defining WAF behavior (`disable`/`log_only`/`enable`). + :param backend_stage_id: ID of the backend stage to forward requests to after the WAF stage. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`WafStage ` + + Usage: + :: + + result = api.create_waf_stage( + pipeline_id="example", + paranoia_level=1, + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/waf-stages", + body=marshal_CreateWafStageRequest( + CreateWafStageRequest( + pipeline_id=pipeline_id, + paranoia_level=paranoia_level, + mode=mode, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + def get_waf_stage( + self, + *, + waf_stage_id: str, + ) -> WafStage: + """ + Get WAF stage. + Retrieve information about an existing WAF stage, specified by its `waf_stage_id`. Its full details are returned in the response object. + :param waf_stage_id: ID of the requested WAF stage. + :return: :class:`WafStage ` + + Usage: + :: + + result = api.get_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + def update_waf_stage( + self, + *, + waf_stage_id: str, + mode: Optional[WafStageMode] = None, + paranoia_level: Optional[int] = None, + backend_stage_id: Optional[str] = None, + ) -> WafStage: + """ + Update WAF stage. + Update the parameters of an existing WAF stage, specified by its `waf_stage_id`. Both `mode` and `paranoia_level` parameters can be updated. + :param waf_stage_id: ID of the WAF stage to update. + :param mode: Mode defining WAF behavior (`disable`/`log_only`/`enable`). + :param paranoia_level: Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + :param backend_stage_id: ID of the backend stage to forward requests to after the WAF stage. + One-Of ('next'): at most one of 'backend_stage_id' could be set. + :return: :class:`WafStage ` + + Usage: + :: + + result = api.update_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + body=marshal_UpdateWafStageRequest( + UpdateWafStageRequest( + waf_stage_id=waf_stage_id, + mode=mode, + paranoia_level=paranoia_level, + backend_stage_id=backend_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_WafStage(res.json()) + + def delete_waf_stage( + self, + *, + waf_stage_id: str, + ) -> None: + """ + Delete WAF stage. + Delete an existing WAF stage, specified by its `waf_stage_id`. Deleting a WAF stage is permanent, and cannot be undone. + :param waf_stage_id: ID of the WAF stage to delete. + + Usage: + :: + + result = api.delete_waf_stage( + waf_stage_id="example", + ) + """ + + param_waf_stage_id = validate_path_param("waf_stage_id", waf_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/waf-stages/{param_waf_stage_id}", + ) + + self._throw_on_error(res) + + def search_waf_stages( + self, + *, + order_by: Optional[SearchWafStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> ListWafStagesResponse: + """ + :param order_by: + :param page: + :param page_size: + :param project_id: + :return: :class:`ListWafStagesResponse ` + + Usage: + :: + + result = api.search_waf_stages() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/search-waf-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWafStagesResponse(res.json()) + + def list_route_stages( + self, + *, + order_by: Optional[ListRouteStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> ListRouteStagesResponse: + """ + List route stages. + List all route stages, for a given pipeline. By default, the route stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of route stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of route stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only route stages from this pipeline will be returned. + :return: :class:`ListRouteStagesResponse ` + + Usage: + :: + + result = api.list_route_stages( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/route-stages", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRouteStagesResponse(res.json()) + + def list_route_stages_all( + self, + *, + order_by: Optional[ListRouteStagesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pipeline_id: str, + ) -> List[RouteStage]: + """ + List route stages. + List all route stages, for a given pipeline. By default, the route stages returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of route stages in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of route stages to return per page. + :param pipeline_id: Pipeline ID to filter for. Only route stages from this pipeline will be returned. + :return: :class:`List[RouteStage] ` + + Usage: + :: + + result = api.list_route_stages_all( + pipeline_id="example", + ) + """ + + return fetch_all_pages( + type=ListRouteStagesResponse, + key="stages", + fetcher=self.list_route_stages, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "pipeline_id": pipeline_id, + }, + ) + + def create_route_stage( + self, + *, + pipeline_id: str, + waf_stage_id: Optional[str] = None, + ) -> RouteStage: + """ + Create route stage. + Create a new route stage. You must specify the `waf_stage_id` field to customize the route. + :param pipeline_id: Pipeline ID the route stage belongs to. + :param waf_stage_id: ID of the WAF stage HTTP requests should be forwarded to when no rules are matched. + One-Of ('next'): at most one of 'waf_stage_id' could be set. + :return: :class:`RouteStage ` + + Usage: + :: + + result = api.create_route_stage( + pipeline_id="example", + ) + """ + + param_pipeline_id = validate_path_param("pipeline_id", pipeline_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/pipelines/{param_pipeline_id}/route-stages", + body=marshal_CreateRouteStageRequest( + CreateRouteStageRequest( + pipeline_id=pipeline_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + def get_route_stage( + self, + *, + route_stage_id: str, + ) -> RouteStage: + """ + Get route stage. + Retrieve information about an existing route stage, specified by its `route_stage_id`. The summary of the route stage (without route rules) is returned in the response object. + :param route_stage_id: ID of the requested route stage. + :return: :class:`RouteStage ` + + Usage: + :: + + result = api.get_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + def update_route_stage( + self, + *, + route_stage_id: str, + waf_stage_id: Optional[str] = None, + ) -> RouteStage: + """ + Update route stage. + Update the parameters of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param waf_stage_id: ID of the WAF stage HTTP requests should be forwarded to when no rules are matched. + One-Of ('next'): at most one of 'waf_stage_id' could be set. + :return: :class:`RouteStage ` + + Usage: + :: + + result = api.update_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "PATCH", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + body=marshal_UpdateRouteStageRequest( + UpdateRouteStageRequest( + route_stage_id=route_stage_id, + waf_stage_id=waf_stage_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RouteStage(res.json()) + + def delete_route_stage( + self, + *, + route_stage_id: str, + ) -> None: + """ + Delete route stage. + Delete an existing route stage, specified by its `route_stage_id`. Deleting a route stage is permanent, and cannot be undone. + :param route_stage_id: ID of the route stage to delete. + + Usage: + :: + + result = api.delete_route_stage( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}", + ) + + self._throw_on_error(res) + + def list_route_rules( + self, + *, + route_stage_id: str, + ) -> ListRouteRulesResponse: + """ + List route rules. + List all route rules of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: Route stage ID to filter for. Only route rules from this route stage will be returned. + :return: :class:`ListRouteRulesResponse ` + + Usage: + :: + + result = api.list_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "GET", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", + ) + + self._throw_on_error(res) + return unmarshal_ListRouteRulesResponse(res.json()) + + def set_route_rules( + self, + *, + route_stage_id: str, + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] = None, + ) -> SetRouteRulesResponse: + """ + Set route rules. + Set the rules of an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param route_rules: List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + :return: :class:`SetRouteRulesResponse ` + + Usage: + :: + + result = api.set_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "PUT", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", + body=marshal_SetRouteRulesRequest( + SetRouteRulesRequest( + route_stage_id=route_stage_id, + route_rules=route_rules, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetRouteRulesResponse(res.json()) + + def add_route_rules( + self, + *, + route_stage_id: str, + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] = None, + after_position: Optional[int] = None, + before_position: Optional[int] = None, + ) -> AddRouteRulesResponse: + """ + Add route rules. + Add route rules to an existing route stage, specified by its `route_stage_id`. + :param route_stage_id: ID of the route stage to update. + :param route_rules: List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + :param after_position: Add rules after the given position. + One-Of ('position'): at most one of 'after_position', 'before_position' could be set. + :param before_position: Add rules before the given position. + One-Of ('position'): at most one of 'after_position', 'before_position' could be set. + :return: :class:`AddRouteRulesResponse ` + + Usage: + :: + + result = api.add_route_rules( + route_stage_id="example", + ) + """ + + param_route_stage_id = validate_path_param("route_stage_id", route_stage_id) + + res = self._request( + "POST", + f"/edge-services/v1beta1/route-stages/{param_route_stage_id}/route-rules", + body=marshal_AddRouteRulesRequest( + AddRouteRulesRequest( + route_stage_id=route_stage_id, + route_rules=route_rules, + after_position=after_position, + before_position=before_position, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AddRouteRulesResponse(res.json()) + + def check_domain( + self, + *, + fqdn: str, + cname: str, + project_id: Optional[str] = None, + ) -> CheckDomainResponse: + """ + :param fqdn: + :param cname: + :param project_id: + :return: :class:`CheckDomainResponse ` + + Usage: + :: + + result = api.check_domain( + fqdn="example", + cname="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-domain", + body=marshal_CheckDomainRequest( + CheckDomainRequest( + fqdn=fqdn, + cname=cname, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckDomainResponse(res.json()) + + def check_pem_chain( + self, + *, + fqdn: str, + project_id: Optional[str] = None, + secret: Optional[CheckPEMChainRequestSecretChain] = None, + raw: Optional[str] = None, + ) -> CheckPEMChainResponse: + """ + :param fqdn: + :param project_id: + :param secret: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :param raw: + One-Of ('chain'): at most one of 'secret', 'raw' could be set. + :return: :class:`CheckPEMChainResponse ` + + Usage: + :: + + result = api.check_pem_chain( + fqdn="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-pem-chain", + body=marshal_CheckPEMChainRequest( + CheckPEMChainRequest( + fqdn=fqdn, + project_id=project_id, + secret=secret, + raw=raw, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckPEMChainResponse(res.json()) + + def list_purge_requests( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> ListPurgeRequestsResponse: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for. Only purge requests from this Project will be returned. + :param project_id: Project ID to filter for. Only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + :return: :class:`ListPurgeRequestsResponse ` + + Usage: + :: + + result = api.list_purge_requests() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/purge-requests", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pipeline_id": pipeline_id, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPurgeRequestsResponse(res.json()) + + def list_purge_requests_all( + self, + *, + order_by: Optional[ListPurgeRequestsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + pipeline_id: Optional[str] = None, + ) -> List[PurgeRequest]: + """ + List purge requests. + List all purge requests, for a Scaleway Organization or Scaleway Project. This enables you to retrieve a history of all previously-made purge requests. By default, the purge requests returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param order_by: Sort order of purge requests in the response. + :param page: Page number to return, from the paginated results. + :param page_size: Number of purge requests to return per page. + :param organization_id: Organization ID to filter for. Only purge requests from this Project will be returned. + :param project_id: Project ID to filter for. Only purge requests from this Project will be returned. + :param pipeline_id: Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + :return: :class:`List[PurgeRequest] ` + + Usage: + :: + + result = api.list_purge_requests_all() + """ + + return fetch_all_pages( + type=ListPurgeRequestsResponse, + key="purge_requests", + fetcher=self.list_purge_requests, + args={ + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "pipeline_id": pipeline_id, + }, + ) + + def create_purge_request( + self, + *, + pipeline_id: str, + assets: Optional[List[str]] = None, + all: Optional[bool] = None, + ) -> PurgeRequest: + """ + Create purge request. + Create a new purge request. You must specify either the `all` field (to purge all content) or a list of `assets` (to define the precise assets to purge). + :param pipeline_id: Pipeline ID in which the purge request will be created. + :param assets: List of asserts to purge. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :param all: Defines whether to purge all content. + One-Of ('target'): at most one of 'assets', 'all' could be set. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = api.create_purge_request( + pipeline_id="example", + ) + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/purge-requests", + body=marshal_CreatePurgeRequestRequest( + CreatePurgeRequestRequest( + pipeline_id=pipeline_id, + assets=assets, + all=all, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + def get_purge_request( + self, + *, + purge_request_id: str, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = api.get_purge_request( + purge_request_id="example", + ) + """ + + param_purge_request_id = validate_path_param( + "purge_request_id", purge_request_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/purge-requests/{param_purge_request_id}", + ) + + self._throw_on_error(res) + return unmarshal_PurgeRequest(res.json()) + + def wait_for_purge_request( + self, + *, + purge_request_id: str, + options: Optional[WaitForOptions[PurgeRequest, bool]] = None, + ) -> PurgeRequest: + """ + Get purge request. + Retrieve information about a purge request, specified by its `purge_request_id`. Its full details, including `status` and `target`, are returned in the response object. + :param purge_request_id: ID of the requested purge request. + :return: :class:`PurgeRequest ` + + Usage: + :: + + result = api.get_purge_request( + purge_request_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in PURGE_REQUEST_TRANSIENT_STATUSES + ) + + return wait_for_resource( + fetcher=self.get_purge_request, + options=options, + args={ + "purge_request_id": purge_request_id, + }, + ) + + def check_lb_origin( + self, + *, + lb: Optional[ScalewayLb] = None, + ) -> CheckLbOriginResponse: + """ + :param lb: + :return: :class:`CheckLbOriginResponse ` + + Usage: + :: + + result = api.check_lb_origin() + """ + + res = self._request( + "POST", + "/edge-services/v1beta1/check-lb-origin", + body=marshal_CheckLbOriginRequest( + CheckLbOriginRequest( + lb=lb, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckLbOriginResponse(res.json()) + + def list_plans( + self, + ) -> ListPlansResponse: + """ + + :return: :class:`ListPlansResponse ` + + Usage: + :: + + result = api.list_plans() + """ + + res = self._request( + "GET", + "/edge-services/v1beta1/plans", + ) + + self._throw_on_error(res) + return unmarshal_ListPlansResponse(res.json()) + + def select_plan( + self, + *, + project_id: Optional[str] = None, + plan_name: Optional[PlanName] = None, + ) -> Plan: + """ + :param project_id: + :param plan_name: + :return: :class:`Plan ` + + Usage: + :: + + result = api.select_plan() + """ + + res = self._request( + "PATCH", + "/edge-services/v1beta1/current-plan", + body=marshal_SelectPlanRequest( + SelectPlanRequest( + project_id=project_id, + plan_name=plan_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + def get_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> Plan: + """ + :param project_id: + :return: :class:`Plan ` + + Usage: + :: + + result = api.get_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_Plan(res.json()) + + def delete_current_plan( + self, + *, + project_id: Optional[str] = None, + ) -> None: + """ + :param project_id: + + Usage: + :: + + result = api.delete_current_plan() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "DELETE", + f"/edge-services/v1beta1/current-plan/{param_project_id}", + ) + + self._throw_on_error(res) + + def get_billing( + self, + *, + project_id: Optional[str] = None, + ) -> GetBillingResponse: + """ + Gives information on the currently selected Edge Services subscription plan, resource usage and associated billing information for this calendar month (including whether consumption falls within or exceeds the currently selected subscription plan.). + :param project_id: + :return: :class:`GetBillingResponse ` + + Usage: + :: + + result = api.get_billing() + """ + + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/edge-services/v1beta1/billing/{param_project_id}", + ) + + self._throw_on_error(res) + return unmarshal_GetBillingResponse(res.json()) diff --git a/scaleway/scaleway/edge_services/v1beta1/content.py b/scaleway/scaleway/edge_services/v1beta1/content.py new file mode 100644 index 00000000..ad1b5e0e --- /dev/null +++ b/scaleway/scaleway/edge_services/v1beta1/content.py @@ -0,0 +1,21 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + PipelineStatus, + PurgeRequestStatus, +) + +PIPELINE_TRANSIENT_STATUSES: List[PipelineStatus] = [ + PipelineStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PipelineStatus `. +""" +PURGE_REQUEST_TRANSIENT_STATUSES: List[PurgeRequestStatus] = [ + PurgeRequestStatus.PENDING, +] +""" +Lists transient statutes of the enum :class:`PurgeRequestStatus `. +""" diff --git a/scaleway/scaleway/edge_services/v1beta1/marshalling.py b/scaleway/scaleway/edge_services/v1beta1/marshalling.py new file mode 100644 index 00000000..b01c7d7c --- /dev/null +++ b/scaleway/scaleway/edge_services/v1beta1/marshalling.py @@ -0,0 +1,1901 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + RuleHttpMatchMethodFilter, + ScalewayLb, + ScalewayLbBackendConfig, + ScalewayS3BackendConfig, + BackendStage, + CacheStage, + DNSStage, + PipelineError, + Pipeline, + RouteStage, + TLSSecret, + TLSStage, + WafStage, + PipelineStages, + PurgeRequest, + RuleHttpMatchPathFilter, + RuleHttpMatch, + RouteRule, + AddRouteRulesResponse, + CheckDomainResponse, + CheckLbOriginResponse, + CheckPEMChainResponse, + PlanDetails, + PlanUsageDetails, + GetBillingResponse, + HeadStageResponseHeadStage, + HeadStageResponse, + ListBackendStagesResponse, + ListCacheStagesResponse, + ListDNSStagesResponse, + ListHeadStagesResponseHeadStage, + ListHeadStagesResponse, + ListPipelinesResponse, + ListPipelinesWithStagesResponse, + ListPlansResponse, + ListPurgeRequestsResponse, + ListRouteRulesResponse, + ListRouteStagesResponse, + ListTLSStagesResponse, + ListWafStagesResponse, + Plan, + SetRouteRulesResponse, + SetRouteRulesRequestRouteRule, + AddRouteRulesRequest, + CheckDomainRequest, + CheckLbOriginRequest, + CheckPEMChainRequestSecretChain, + CheckPEMChainRequest, + CreateBackendStageRequest, + CreateCacheStageRequest, + CreateDNSStageRequest, + CreatePipelineRequest, + CreatePurgeRequestRequest, + CreateRouteStageRequest, + CreateTLSStageRequest, + CreateWafStageRequest, + SelectPlanRequest, + SetHeadStageRequestAddNewHeadStage, + SetHeadStageRequestRemoveHeadStage, + SetHeadStageRequestSwapHeadStage, + SetHeadStageRequest, + SetRouteRulesRequest, + UpdateBackendStageRequest, + UpdateCacheStageRequest, + UpdateDNSStageRequest, + UpdatePipelineRequest, + UpdateRouteStageRequest, + TLSSecretsConfig, + UpdateTLSStageRequest, + UpdateWafStageRequest, +) + + +def unmarshal_ScalewayLb(data: Any) -> ScalewayLb: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLb' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("frontend_id", None) + if field is not None: + args["frontend_id"] = field + + field = data.get("is_ssl", None) + if field is not None: + args["is_ssl"] = field + else: + args["is_ssl"] = None + + field = data.get("domain_name", None) + if field is not None: + args["domain_name"] = field + else: + args["domain_name"] = None + + return ScalewayLb(**args) + + +def unmarshal_ScalewayLbBackendConfig(data: Any) -> ScalewayLbBackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayLbBackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("lbs", None) + if field is not None: + args["lbs"] = ( + [unmarshal_ScalewayLb(v) for v in field] if field is not None else None + ) + + return ScalewayLbBackendConfig(**args) + + +def unmarshal_ScalewayS3BackendConfig(data: Any) -> ScalewayS3BackendConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ScalewayS3BackendConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bucket_name", None) + if field is not None: + args["bucket_name"] = field + else: + args["bucket_name"] = None + + field = data.get("bucket_region", None) + if field is not None: + args["bucket_region"] = field + else: + args["bucket_region"] = None + + field = data.get("is_website", None) + if field is not None: + args["is_website"] = field + else: + args["is_website"] = None + + return ScalewayS3BackendConfig(**args) + + +def unmarshal_BackendStage(data: Any) -> BackendStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BackendStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("scaleway_s3", None) + if field is not None: + args["scaleway_s3"] = unmarshal_ScalewayS3BackendConfig(field) + else: + args["scaleway_s3"] = None + + field = data.get("scaleway_lb", None) + if field is not None: + args["scaleway_lb"] = unmarshal_ScalewayLbBackendConfig(field) + else: + args["scaleway_lb"] = None + + return BackendStage(**args) + + +def unmarshal_CacheStage(data: Any) -> CacheStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CacheStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("fallback_ttl", None) + if field is not None: + args["fallback_ttl"] = field + else: + args["fallback_ttl"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + else: + args["route_stage_id"] = None + + return CacheStage(**args) + + +def unmarshal_DNSStage(data: Any) -> DNSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DNSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("fqdns", None) + if field is not None: + args["fqdns"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("tls_stage_id", None) + if field is not None: + args["tls_stage_id"] = field + else: + args["tls_stage_id"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return DNSStage(**args) + + +def unmarshal_PipelineError(data: Any) -> PipelineError: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineError' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stage", None) + if field is not None: + args["stage"] = field + + field = data.get("code", None) + if field is not None: + args["code"] = field + + field = data.get("severity", None) + if field is not None: + args["severity"] = field + + field = data.get("message", None) + if field is not None: + args["message"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return PipelineError(**args) + + +def unmarshal_Pipeline(data: Any) -> Pipeline: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pipeline' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("errors", None) + if field is not None: + args["errors"] = ( + [unmarshal_PipelineError(v) for v in field] if field is not None else None + ) + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Pipeline(**args) + + +def unmarshal_RouteStage(data: Any) -> RouteStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RouteStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return RouteStage(**args) + + +def unmarshal_TLSSecret(data: Any) -> TLSSecret: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSSecret' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secret_id", None) + if field is not None: + args["secret_id"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + return TLSSecret(**args) + + +def unmarshal_TLSStage(data: Any) -> TLSStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'TLSStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("secrets", None) + if field is not None: + args["secrets"] = ( + [unmarshal_TLSSecret(v) for v in field] if field is not None else None + ) + + field = data.get("managed_certificate", None) + if field is not None: + args["managed_certificate"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("certificate_expires_at", None) + if field is not None: + args["certificate_expires_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["certificate_expires_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("cache_stage_id", None) + if field is not None: + args["cache_stage_id"] = field + else: + args["cache_stage_id"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + field = data.get("waf_stage_id", None) + if field is not None: + args["waf_stage_id"] = field + else: + args["waf_stage_id"] = None + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + else: + args["route_stage_id"] = None + + return TLSStage(**args) + + +def unmarshal_WafStage(data: Any) -> WafStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'WafStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("mode", None) + if field is not None: + args["mode"] = field + + field = data.get("paranoia_level", None) + if field is not None: + args["paranoia_level"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return WafStage(**args) + + +def unmarshal_PipelineStages(data: Any) -> PipelineStages: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PipelineStages' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stages", None) + if field is not None: + args["dns_stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("tls_stages", None) + if field is not None: + args["tls_stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("cache_stages", None) + if field is not None: + args["cache_stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("backend_stages", None) + if field is not None: + args["backend_stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("waf_stages", None) + if field is not None: + args["waf_stages"] = ( + [unmarshal_WafStage(v) for v in field] if field is not None else None + ) + + field = data.get("route_stages", None) + if field is not None: + args["route_stages"] = ( + [unmarshal_RouteStage(v) for v in field] if field is not None else None + ) + + field = data.get("pipeline", None) + if field is not None: + args["pipeline"] = unmarshal_Pipeline(field) + else: + args["pipeline"] = None + + return PipelineStages(**args) + + +def unmarshal_PurgeRequest(data: Any) -> PurgeRequest: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PurgeRequest' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("pipeline_id", None) + if field is not None: + args["pipeline_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("assets", None) + if field is not None: + args["assets"] = field + else: + args["assets"] = None + + field = data.get("all", None) + if field is not None: + args["all"] = field + else: + args["all"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return PurgeRequest(**args) + + +def unmarshal_RuleHttpMatchPathFilter(data: Any) -> RuleHttpMatchPathFilter: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RuleHttpMatchPathFilter' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("path_filter_type", None) + if field is not None: + args["path_filter_type"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + return RuleHttpMatchPathFilter(**args) + + +def unmarshal_RuleHttpMatch(data: Any) -> RuleHttpMatch: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RuleHttpMatch' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("method_filters", None) + if field is not None: + args["method_filters"] = ( + [RuleHttpMatchMethodFilter(v) for v in field] if field is not None else None + ) + + field = data.get("path_filter", None) + if field is not None: + args["path_filter"] = unmarshal_RuleHttpMatchPathFilter(field) + else: + args["path_filter"] = None + + return RuleHttpMatch(**args) + + +def unmarshal_RouteRule(data: Any) -> RouteRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RouteRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("position", None) + if field is not None: + args["position"] = field + + field = data.get("route_stage_id", None) + if field is not None: + args["route_stage_id"] = field + + field = data.get("rule_http_match", None) + if field is not None: + args["rule_http_match"] = unmarshal_RuleHttpMatch(field) + else: + args["rule_http_match"] = None + + field = data.get("backend_stage_id", None) + if field is not None: + args["backend_stage_id"] = field + else: + args["backend_stage_id"] = None + + return RouteRule(**args) + + +def unmarshal_AddRouteRulesResponse(data: Any) -> AddRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AddRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return AddRouteRulesResponse(**args) + + +def unmarshal_CheckDomainResponse(data: Any) -> CheckDomainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckDomainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckDomainResponse(**args) + + +def unmarshal_CheckLbOriginResponse(data: Any) -> CheckLbOriginResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckLbOriginResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + field = data.get("error_type", None) + if field is not None: + args["error_type"] = field + + return CheckLbOriginResponse(**args) + + +def unmarshal_CheckPEMChainResponse(data: Any) -> CheckPEMChainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckPEMChainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("is_valid", None) + if field is not None: + args["is_valid"] = field + + return CheckPEMChainResponse(**args) + + +def unmarshal_PlanDetails(data: Any) -> PlanDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + field = data.get("package_gb", None) + if field is not None: + args["package_gb"] = field + + field = data.get("pipeline_limit", None) + if field is not None: + args["pipeline_limit"] = field + + field = data.get("waf_requests", None) + if field is not None: + args["waf_requests"] = field + + return PlanDetails(**args) + + +def unmarshal_PlanUsageDetails(data: Any) -> PlanUsageDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlanUsageDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + return PlanUsageDetails(**args) + + +def unmarshal_GetBillingResponse(data: Any) -> GetBillingResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetBillingResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("current_plan", None) + if field is not None: + args["current_plan"] = unmarshal_PlanDetails(field) + else: + args["current_plan"] = None + + field = data.get("pipeline_number", None) + if field is not None: + args["pipeline_number"] = field + + field = data.get("current_plan_cache_usage", None) + if field is not None: + args["current_plan_cache_usage"] = field + + field = data.get("extra_cache_usage", None) + if field is not None: + args["extra_cache_usage"] = field + + field = data.get("current_plan_waf_usage", None) + if field is not None: + args["current_plan_waf_usage"] = field + + field = data.get("extra_waf_usage", None) + if field is not None: + args["extra_waf_usage"] = field + + field = data.get("plan_cost", None) + if field is not None: + args["plan_cost"] = unmarshal_Money(field) + else: + args["plan_cost"] = None + + field = data.get("extra_pipelines_cost", None) + if field is not None: + args["extra_pipelines_cost"] = unmarshal_Money(field) + else: + args["extra_pipelines_cost"] = None + + field = data.get("plans_usage_details", None) + if field is not None: + args["plans_usage_details"] = ( + {key: unmarshal_PlanUsageDetails(value) for key, value in field.items()} + if field is not None + else None + ) + + field = data.get("extra_cache_cost", None) + if field is not None: + args["extra_cache_cost"] = unmarshal_Money(field) + else: + args["extra_cache_cost"] = None + + field = data.get("extra_waf_cost", None) + if field is not None: + args["extra_waf_cost"] = unmarshal_Money(field) + else: + args["extra_waf_cost"] = None + + field = data.get("waf_add_on", None) + if field is not None: + args["waf_add_on"] = unmarshal_Money(field) + else: + args["waf_add_on"] = None + + field = data.get("total_cost", None) + if field is not None: + args["total_cost"] = unmarshal_Money(field) + else: + args["total_cost"] = None + + return GetBillingResponse(**args) + + +def unmarshal_HeadStageResponseHeadStage(data: Any) -> HeadStageResponseHeadStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HeadStageResponseHeadStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stage_id", None) + if field is not None: + args["dns_stage_id"] = field + else: + args["dns_stage_id"] = None + + return HeadStageResponseHeadStage(**args) + + +def unmarshal_HeadStageResponse(data: Any) -> HeadStageResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HeadStageResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("head_stage", None) + if field is not None: + args["head_stage"] = unmarshal_HeadStageResponseHeadStage(field) + else: + args["head_stage"] = None + + return HeadStageResponse(**args) + + +def unmarshal_ListBackendStagesResponse(data: Any) -> ListBackendStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListBackendStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_BackendStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListBackendStagesResponse(**args) + + +def unmarshal_ListCacheStagesResponse(data: Any) -> ListCacheStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListCacheStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_CacheStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListCacheStagesResponse(**args) + + +def unmarshal_ListDNSStagesResponse(data: Any) -> ListDNSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDNSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_DNSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDNSStagesResponse(**args) + + +def unmarshal_ListHeadStagesResponseHeadStage( + data: Any, +) -> ListHeadStagesResponseHeadStage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListHeadStagesResponseHeadStage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dns_stage_id", None) + if field is not None: + args["dns_stage_id"] = field + else: + args["dns_stage_id"] = None + + return ListHeadStagesResponseHeadStage(**args) + + +def unmarshal_ListHeadStagesResponse(data: Any) -> ListHeadStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListHeadStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("head_stages", None) + if field is not None: + args["head_stages"] = ( + [unmarshal_ListHeadStagesResponseHeadStage(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListHeadStagesResponse(**args) + + +def unmarshal_ListPipelinesResponse(data: Any) -> ListPipelinesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_Pipeline(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesResponse(**args) + + +def unmarshal_ListPipelinesWithStagesResponse( + data: Any, +) -> ListPipelinesWithStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPipelinesWithStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pipelines", None) + if field is not None: + args["pipelines"] = ( + [unmarshal_PipelineStages(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPipelinesWithStagesResponse(**args) + + +def unmarshal_ListPlansResponse(data: Any) -> ListPlansResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPlansResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("plans", None) + if field is not None: + args["plans"] = ( + [unmarshal_PlanDetails(v) for v in field] if field is not None else None + ) + + return ListPlansResponse(**args) + + +def unmarshal_ListPurgeRequestsResponse(data: Any) -> ListPurgeRequestsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPurgeRequestsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("purge_requests", None) + if field is not None: + args["purge_requests"] = ( + [unmarshal_PurgeRequest(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPurgeRequestsResponse(**args) + + +def unmarshal_ListRouteRulesResponse(data: Any) -> ListRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return ListRouteRulesResponse(**args) + + +def unmarshal_ListRouteStagesResponse(data: Any) -> ListRouteStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRouteStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_RouteStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListRouteStagesResponse(**args) + + +def unmarshal_ListTLSStagesResponse(data: Any) -> ListTLSStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListTLSStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_TLSStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListTLSStagesResponse(**args) + + +def unmarshal_ListWafStagesResponse(data: Any) -> ListWafStagesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListWafStagesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("stages", None) + if field is not None: + args["stages"] = ( + [unmarshal_WafStage(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListWafStagesResponse(**args) + + +def unmarshal_Plan(data: Any) -> Plan: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Plan' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("plan_name", None) + if field is not None: + args["plan_name"] = field + + return Plan(**args) + + +def unmarshal_SetRouteRulesResponse(data: Any) -> SetRouteRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetRouteRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("route_rules", None) + if field is not None: + args["route_rules"] = ( + [unmarshal_RouteRule(v) for v in field] if field is not None else None + ) + + return SetRouteRulesResponse(**args) + + +def marshal_RuleHttpMatchPathFilter( + request: RuleHttpMatchPathFilter, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.path_filter_type is not None: + output["path_filter_type"] = str(request.path_filter_type) + + if request.value is not None: + output["value"] = request.value + + return output + + +def marshal_RuleHttpMatch( + request: RuleHttpMatch, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.method_filters is not None: + output["method_filters"] = [str(item) for item in request.method_filters] + + if request.path_filter is not None: + output["path_filter"] = marshal_RuleHttpMatchPathFilter( + request.path_filter, defaults + ) + + return output + + +def marshal_SetRouteRulesRequestRouteRule( + request: SetRouteRulesRequestRouteRule, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("rule_http_match", request.rule_http_match), + ] + ), + ) + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + return output + + +def marshal_AddRouteRulesRequest( + request: AddRouteRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("after_position", request.after_position), + OneOfPossibility("before_position", request.before_position), + ] + ), + ) + + if request.route_rules is not None: + output["route_rules"] = [ + marshal_SetRouteRulesRequestRouteRule(item, defaults) + for item in request.route_rules + ] + + return output + + +def marshal_CheckDomainRequest( + request: CheckDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.cname is not None: + output["cname"] = request.cname + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLb( + request: ScalewayLb, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.id is not None: + output["id"] = request.id + + if request.zone is not None: + output["zone"] = request.zone or defaults.default_zone + + if request.frontend_id is not None: + output["frontend_id"] = request.frontend_id + + if request.is_ssl is not None: + output["is_ssl"] = request.is_ssl + + if request.domain_name is not None: + output["domain_name"] = request.domain_name + + return output + + +def marshal_CheckLbOriginRequest( + request: CheckLbOriginRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lb is not None: + output["lb"] = marshal_ScalewayLb(request.lb, defaults) + + return output + + +def marshal_CheckPEMChainRequestSecretChain( + request: CheckPEMChainRequestSecretChain, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.secret_region is not None: + output["secret_region"] = request.secret_region + + return output + + +def marshal_CheckPEMChainRequest( + request: CheckPEMChainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("secret", request.secret), + OneOfPossibility("raw", request.raw), + ] + ), + ) + + if request.fqdn is not None: + output["fqdn"] = request.fqdn + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_ScalewayLbBackendConfig( + request: ScalewayLbBackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.lbs is not None: + output["lbs"] = [marshal_ScalewayLb(item, defaults) for item in request.lbs] + + return output + + +def marshal_ScalewayS3BackendConfig( + request: ScalewayS3BackendConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bucket_name is not None: + output["bucket_name"] = request.bucket_name + + if request.bucket_region is not None: + output["bucket_region"] = request.bucket_region + + if request.is_website is not None: + output["is_website"] = request.is_website + + return output + + +def marshal_CreateBackendStageRequest( + request: CreateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + return output + + +def marshal_CreateCacheStageRequest( + request: CreateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + ] + ), + ) + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_CreateDNSStageRequest( + request: CreateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_CreatePipelineRequest( + request: CreatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_CreatePurgeRequestRequest( + request: CreatePurgeRequestRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("assets", request.assets), + OneOfPossibility("all", request.all), + ] + ), + ) + + if request.pipeline_id is not None: + output["pipeline_id"] = request.pipeline_id + + return output + + +def marshal_CreateRouteStageRequest( + request: CreateRouteStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + return output + + +def marshal_TLSSecret( + request: TLSSecret, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secret_id is not None: + output["secret_id"] = request.secret_id + + if request.region is not None: + output["region"] = request.region or defaults.default_region + + return output + + +def marshal_CreateTLSStageRequest( + request: CreateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + if request.secrets is not None: + output["secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.secrets + ] + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output + + +def marshal_CreateWafStageRequest( + request: CreateWafStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.paranoia_level is not None: + output["paranoia_level"] = request.paranoia_level + + if request.mode is not None: + output["mode"] = str(request.mode) + + return output + + +def marshal_SelectPlanRequest( + request: SelectPlanRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.plan_name is not None: + output["plan_name"] = str(request.plan_name) + + return output + + +def marshal_SetHeadStageRequestAddNewHeadStage( + request: SetHeadStageRequestAddNewHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.new_stage_id is not None: + output["new_stage_id"] = request.new_stage_id + + return output + + +def marshal_SetHeadStageRequestRemoveHeadStage( + request: SetHeadStageRequestRemoveHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.remove_stage_id is not None: + output["remove_stage_id"] = request.remove_stage_id + + return output + + +def marshal_SetHeadStageRequestSwapHeadStage( + request: SetHeadStageRequestSwapHeadStage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.new_stage_id is not None: + output["new_stage_id"] = request.new_stage_id + + if request.current_stage_id is not None: + output["current_stage_id"] = request.current_stage_id + + return output + + +def marshal_SetHeadStageRequest( + request: SetHeadStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("add_new_head_stage", request.add_new_head_stage), + OneOfPossibility("remove_head_stage", request.remove_head_stage), + OneOfPossibility("swap_head_stage", request.swap_head_stage), + ] + ), + ) + + return output + + +def marshal_SetRouteRulesRequest( + request: SetRouteRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.route_rules is not None: + output["route_rules"] = [ + marshal_SetRouteRulesRequestRouteRule(item, defaults) + for item in request.route_rules + ] + + return output + + +def marshal_UpdateBackendStageRequest( + request: UpdateBackendStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("scaleway_s3", request.scaleway_s3), + OneOfPossibility("scaleway_lb", request.scaleway_lb), + ] + ), + ) + + if request.pipeline_id is not None: + output["pipeline_id"] = request.pipeline_id + + return output + + +def marshal_UpdateCacheStageRequest( + request: UpdateCacheStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + ] + ), + ) + + if request.fallback_ttl is not None: + output["fallback_ttl"] = request.fallback_ttl + + return output + + +def marshal_UpdateDNSStageRequest( + request: UpdateDNSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("tls_stage_id", request.tls_stage_id), + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.fqdns is not None: + output["fqdns"] = request.fqdns + + return output + + +def marshal_UpdatePipelineRequest( + request: UpdatePipelineRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + return output + + +def marshal_UpdateRouteStageRequest( + request: UpdateRouteStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + return output + + +def marshal_TLSSecretsConfig( + request: TLSSecretsConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.tls_secrets is not None: + output["tls_secrets"] = [ + marshal_TLSSecret(item, defaults) for item in request.tls_secrets + ] + + return output + + +def marshal_UpdateTLSStageRequest( + request: UpdateTLSStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("cache_stage_id", request.cache_stage_id), + OneOfPossibility("backend_stage_id", request.backend_stage_id), + OneOfPossibility("route_stage_id", request.route_stage_id), + OneOfPossibility("waf_stage_id", request.waf_stage_id), + ] + ), + ) + + if request.tls_secrets_config is not None: + output["tls_secrets_config"] = marshal_TLSSecretsConfig( + request.tls_secrets_config, defaults + ) + + if request.managed_certificate is not None: + output["managed_certificate"] = request.managed_certificate + + return output + + +def marshal_UpdateWafStageRequest( + request: UpdateWafStageRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("backend_stage_id", request.backend_stage_id), + ] + ), + ) + + if request.mode is not None: + output["mode"] = str(request.mode) + + if request.paranoia_level is not None: + output["paranoia_level"] = request.paranoia_level + + return output diff --git a/scaleway/scaleway/edge_services/v1beta1/types.py b/scaleway/scaleway/edge_services/v1beta1/types.py new file mode 100644 index 00000000..5172a74a --- /dev/null +++ b/scaleway/scaleway/edge_services/v1beta1/types.py @@ -0,0 +1,1800 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Dict, List, Optional + +from scaleway_core.bridge import ( + Money, + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DNSStageType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + AUTO = "auto" + MANAGED = "managed" + CUSTOM = "custom" + + def __str__(self) -> str: + return str(self.value) + + +class LbOriginError(str, Enum, metaclass=StrEnumMeta): + UNKNOWN = "unknown" + TIMEOUT = "timeout" + CONNECTION_REFUSED = "connection_refused" + TLS_ERROR = "tls_error" + + def __str__(self) -> str: + return str(self.value) + + +class ListBackendStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListCacheStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListDNSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPipelinesWithStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPurgeRequestsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRouteStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListTLSStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListWafStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorCode(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_CODE = "unknown_code" + DNS_INVALID_FORMAT = "dns_invalid_format" + DNS_INVALID_TLD = "dns_invalid_tld" + DNS_FORBIDDEN_ROOT_DOMAIN = "dns_forbidden_root_domain" + DNS_FORBIDDEN_SCW_CLOUD = "dns_forbidden_scw_cloud" + DNS_DOMAIN_DONT_EXIST = "dns_domain_dont_exist" + DNS_CNAME_DONT_EXIST = "dns_cname_dont_exist" + DNS_CNAME_RESOLVE = "dns_cname_resolve" + DNS_FQDN_ALREADY_EXISTS = "dns_fqdn_already_exists" + DNS_FQDN_ALREADY_IN_USE = "dns_fqdn_already_in_use" + TLS_CERT_DELETED = "tls_cert_deleted" + TLS_CERT_DISABLED = "tls_cert_disabled" + TLS_CERT_EXPIRED = "tls_cert_expired" + TLS_CERT_INVALID_FORMAT = "tls_cert_invalid_format" + TLS_CERT_MISSING = "tls_cert_missing" + TLS_CHAIN_ORDER = "tls_chain_order" + TLS_KEY_INVALID_FORMAT = "tls_key_invalid_format" + TLS_KEY_MISSING = "tls_key_missing" + TLS_KEY_TOO_MANY = "tls_key_too_many" + TLS_MANAGED_DOMAIN_RATE_LIMIT = "tls_managed_domain_rate_limit" + TLS_MANAGED_INTERNAL = "tls_managed_internal" + TLS_PAIR_MISMATCH = "tls_pair_mismatch" + TLS_ROOT_INCONSISTENT = "tls_root_inconsistent" + TLS_ROOT_INCORRECT = "tls_root_incorrect" + TLS_ROOT_MISSING = "tls_root_missing" + TLS_SAN_MISMATCH = "tls_san_mismatch" + TLS_SELF_SIGNED = "tls_self_signed" + PIPELINE_INVALID_WORKFLOW = "pipeline_invalid_workflow" + PIPELINE_MISSING_HEAD_STAGE = "pipeline_missing_head_stage" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorSeverity(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SEVERITY = "unknown_severity" + WARNING = "warning" + CRITICAL = "critical" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorStage(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STAGE = "unknown_stage" + DNS = "dns" + TLS = "tls" + CACHE = "cache" + BACKEND = "backend" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineErrorType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + RUNTIME = "runtime" + CONFIG = "config" + + def __str__(self) -> str: + return str(self.value) + + +class PipelineStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + ERROR = "error" + PENDING = "pending" + WARNING = "warning" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class PlanName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + STARTER = "starter" + PROFESSIONAL = "professional" + ADVANCED = "advanced" + + def __str__(self) -> str: + return str(self.value) + + +class PurgeRequestStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DONE = "done" + ERROR = "error" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) + + +class RuleHttpMatchMethodFilter(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_METHOD_FILTER = "unknown_method_filter" + GET = "get" + POST = "post" + PUT = "put" + PATCH = "patch" + DELETE = "delete" + HEAD = "head" + OPTIONS = "options" + + def __str__(self) -> str: + return str(self.value) + + +class RuleHttpMatchPathFilterPathFilterType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PATH_FILTER = "unknown_path_filter" + REGEX = "regex" + + def __str__(self) -> str: + return str(self.value) + + +class SearchBackendStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class SearchWafStagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class WafStageMode(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_MODE = "unknown_mode" + DISABLE = "disable" + LOG_ONLY = "log_only" + ENABLE = "enable" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ScalewayLb: + id: str + """ + ID of the Load Balancer. + """ + + zone: ScwZone + """ + Zone of the Load Balancer. + """ + + frontend_id: str + """ + ID of the frontend linked to the Load Balancer. + """ + + is_ssl: Optional[bool] + """ + Defines whether the Load Balancer's frontend handles SSL connections. + """ + + domain_name: Optional[str] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to use in HTTP requests sent towards your Load Balancer. + """ + + +@dataclass +class RuleHttpMatchPathFilter: + path_filter_type: RuleHttpMatchPathFilterPathFilterType + """ + Type of filter to match for the HTTP URL path. For now, all path filters must be written in regex and use the `regex` type. + """ + + value: str + """ + Value to be matched for the HTTP URL path. + """ + + +@dataclass +class ScalewayLbBackendConfig: + lbs: List[ScalewayLb] + """ + Load Balancer information. + """ + + +@dataclass +class ScalewayS3BackendConfig: + bucket_name: Optional[str] + """ + Name of the Bucket. + """ + + bucket_region: Optional[str] + """ + Region of the Bucket. + """ + + is_website: Optional[bool] + """ + Defines whether the bucket website feature is enabled. + """ + + +@dataclass +class PipelineError: + stage: PipelineErrorStage + + code: PipelineErrorCode + + severity: PipelineErrorSeverity + + message: str + + type_: PipelineErrorType + + +@dataclass +class TLSSecret: + secret_id: str + """ + ID of the Secret. + """ + + region: ScwRegion + """ + Region of the Secret. + """ + + +@dataclass +class RuleHttpMatch: + method_filters: List[RuleHttpMatchMethodFilter] + """ + HTTP methods to filter for. A request using any of these methods will be considered to match the rule. Possible values are `get`, `post`, `put`, `patch`, `delete`, `head`, `options`. All methods will match if none is provided. + """ + + path_filter: Optional[RuleHttpMatchPathFilter] + """ + HTTP URL path to filter for. A request whose path matches the given filter will be considered to match the rule. All paths will match if none is provided. + """ + + +@dataclass +class BackendStage: + id: str + """ + ID of the backend stage. + """ + + pipeline_id: str + """ + Pipeline ID the backend stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the backend stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the backend stage was last updated. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CacheStage: + id: str + """ + ID of the cache stage. + """ + + pipeline_id: str + """ + Pipeline ID the cache stage belongs to. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + created_at: Optional[datetime] + """ + Date the cache stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the cache stage was last updated. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class DNSStage: + id: str + """ + ID of the DNS stage. + """ + + fqdns: List[str] + """ + List of Fully Qualified Domain Names attached to the stage. + """ + + type_: DNSStageType + """ + Type of the stage. + """ + + pipeline_id: str + """ + Pipeline ID the DNS stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the DNS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the DNS stage was last updated. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class Pipeline: + id: str + """ + ID of the pipeline. + """ + + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + status: PipelineStatus + """ + Status of the pipeline. + """ + + errors: List[PipelineError] + """ + Errors of the pipeline. + """ + + project_id: str + """ + Project ID of the pipeline. + """ + + organization_id: str + """ + Organization ID of the pipeline. + """ + + created_at: Optional[datetime] + """ + Date the pipeline was created. + """ + + updated_at: Optional[datetime] + """ + Date the pipeline was last updated. + """ + + +@dataclass +class RouteStage: + id: str + """ + ID of the route stage. + """ + + pipeline_id: str + """ + Pipeline ID the route stage belongs to. + """ + + created_at: Optional[datetime] + """ + Date the route stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the route stage was last updated. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class TLSStage: + id: str + """ + ID of the TLS stage. + """ + + secrets: List[TLSSecret] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: bool + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + pipeline_id: str + """ + Pipeline ID the TLS stage belongs to. + """ + + certificate_expires_at: Optional[datetime] + """ + Expiration date of the certificate. + """ + + created_at: Optional[datetime] + """ + Date the TLS stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the TLS stage was last updated. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class WafStage: + id: str + """ + ID of the WAF stage. + """ + + pipeline_id: str + """ + Pipeline ID the WAF stage belongs to. + """ + + mode: WafStageMode + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + paranoia_level: int + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + created_at: Optional[datetime] + """ + Date the WAF stage was created. + """ + + updated_at: Optional[datetime] + """ + Date the WAF stage was last updated. + """ + + backend_stage_id: Optional[str] + + +@dataclass +class SetRouteRulesRequestRouteRule: + rule_http_match: Optional[RuleHttpMatch] + + backend_stage_id: Optional[str] + + +@dataclass +class RouteRule: + position: int + """ + Position of the rule which determines the order of processing within the route stage. + """ + + route_stage_id: str + """ + Route stage ID the route rule belongs to. + """ + + rule_http_match: Optional[RuleHttpMatch] + + backend_stage_id: Optional[str] + + +@dataclass +class CheckPEMChainRequestSecretChain: + secret_id: str + + secret_region: str + + +@dataclass +class PlanDetails: + plan_name: PlanName + """ + Subscription plan name. + """ + + package_gb: int + """ + Amount of egress data from cache included in subscription plan. + """ + + pipeline_limit: int + """ + Number of pipelines included in subscription plan. + """ + + waf_requests: int + """ + Number of WAF requests included in subscription plan. + """ + + +@dataclass +class PlanUsageDetails: + plan_cost: Optional[Money] + """ + Cost to date (this month) for the corresponding Edge Services subscription plan. + """ + + +@dataclass +class HeadStageResponseHeadStage: + dns_stage_id: Optional[str] + + +@dataclass +class ListHeadStagesResponseHeadStage: + dns_stage_id: Optional[str] + + +@dataclass +class PipelineStages: + dns_stages: List[DNSStage] + + tls_stages: List[TLSStage] + + cache_stages: List[CacheStage] + + backend_stages: List[BackendStage] + + waf_stages: List[WafStage] + + route_stages: List[RouteStage] + + pipeline: Optional[Pipeline] + + +@dataclass +class PurgeRequest: + id: str + """ + ID of the purge request. + """ + + pipeline_id: str + """ + Pipeline ID the purge request belongs to. + """ + + status: PurgeRequestStatus + """ + Status of the purge request. + """ + + created_at: Optional[datetime] + """ + Date the purge request was created. + """ + + updated_at: Optional[datetime] + """ + Date the purge request was last updated. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class SetHeadStageRequestAddNewHeadStage: + new_stage_id: str + + +@dataclass +class SetHeadStageRequestRemoveHeadStage: + remove_stage_id: str + + +@dataclass +class SetHeadStageRequestSwapHeadStage: + new_stage_id: str + + current_stage_id: str + + +@dataclass +class TLSSecretsConfig: + tls_secrets: List[TLSSecret] + """ + Secret information (from Secret Manager). + """ + + +@dataclass +class AddRouteRulesRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + after_position: Optional[int] + + before_position: Optional[int] + + +@dataclass +class AddRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class CheckDomainRequest: + fqdn: str + + cname: str + + project_id: Optional[str] + + +@dataclass +class CheckDomainResponse: + is_valid: bool + + +@dataclass +class CheckLbOriginRequest: + lb: Optional[ScalewayLb] + + +@dataclass +class CheckLbOriginResponse: + is_valid: bool + + error_type: LbOriginError + + +@dataclass +class CheckPEMChainRequest: + fqdn: str + + project_id: Optional[str] + + secret: Optional[CheckPEMChainRequestSecretChain] + + raw: Optional[str] + + +@dataclass +class CheckPEMChainResponse: + is_valid: bool + + +@dataclass +class CreateBackendStageRequest: + pipeline_id: str + """ + Pipeline ID the Backend stage belongs to. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class CreateCacheStageRequest: + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + pipeline_id: str + """ + Pipeline ID the Cache stage belongs to. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class CreateDNSStageRequest: + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) to attach to the stage. + """ + + pipeline_id: str + """ + Pipeline ID the DNS stage belongs to. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class CreatePipelineRequest: + name: str + """ + Name of the pipeline. + """ + + description: str + """ + Description of the pipeline. + """ + + project_id: Optional[str] + """ + Project ID in which the pipeline will be created. + """ + + +@dataclass +class CreatePurgeRequestRequest: + pipeline_id: str + """ + Pipeline ID in which the purge request will be created. + """ + + assets: Optional[List[str]] + + all: Optional[bool] + + +@dataclass +class CreateRouteStageRequest: + pipeline_id: str + """ + Pipeline ID the route stage belongs to. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class CreateTLSStageRequest: + secrets: Optional[List[TLSSecret]] + """ + Secret (from Scaleway Secret Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + pipeline_id: str + """ + Pipeline ID the TLS stage belongs to. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + route_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + +@dataclass +class CreateWafStageRequest: + pipeline_id: str + """ + Pipeline ID the WAF stage belongs to. + """ + + paranoia_level: int + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + mode: Optional[WafStageMode] + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + backend_stage_id: Optional[str] + + +@dataclass +class DeleteBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to delete. + """ + + +@dataclass +class DeleteCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to delete. + """ + + +@dataclass +class DeleteCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class DeleteDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to delete. + """ + + +@dataclass +class DeletePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to delete. + """ + + +@dataclass +class DeleteRouteStageRequest: + route_stage_id: str + """ + ID of the route stage to delete. + """ + + +@dataclass +class DeleteTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to delete. + """ + + +@dataclass +class DeleteWafStageRequest: + waf_stage_id: str + """ + ID of the WAF stage to delete. + """ + + +@dataclass +class GetBackendStageRequest: + backend_stage_id: str + """ + ID of the requested backend stage. + """ + + +@dataclass +class GetBillingRequest: + project_id: Optional[str] + + +@dataclass +class GetBillingResponse: + current_plan: Optional[PlanDetails] + """ + Information on the currently-selected, active Edge Services subscription plan. + """ + + pipeline_number: int + """ + Total number of pipelines currently configured. + """ + + current_plan_cache_usage: int + """ + Total amount of data egressed from the cache in gigabytes from the beginning of the month, for the active subscription plan. + """ + + extra_cache_usage: int + """ + Total amount of extra data egressed from cache in gigabytes from the beginning of the month, not included in the subscription plans. + """ + + current_plan_waf_usage: int + """ + Total number of requests processed by the WAF since the beginning of the current month, for the active subscription plan. + """ + + extra_waf_usage: int + """ + Total number of extra requests processed by the WAF from the beginning of the month, not included in the subscription plans. + """ + + plan_cost: Optional[Money] + """ + Cost to date (this month) for Edge Service subscription plans. This comprises the pro-rata cost of the current subscription plan, and any previous subscription plans that were active earlier in the month. + """ + + extra_pipelines_cost: Optional[Money] + """ + Cost to date (this month) of pipelines not included in the subscription plans. + """ + + plans_usage_details: Dict[str, PlanUsageDetails] + """ + Detailed costs and usage for all Edge Services subscription plans that were activated during the month. + """ + + extra_cache_cost: Optional[Money] + """ + Cost to date (this month) of the data egressed from the cache that is not included in the subscription plans. + """ + + extra_waf_cost: Optional[Money] + """ + Cost to date (this month) of the extra requests processed by the WAF that were not included in the subscription plans. + """ + + waf_add_on: Optional[Money] + """ + Cost of activating WAF add-on (where subscription plan does not include WAF). + """ + + total_cost: Optional[Money] + """ + Total cost to date (this month) of all Edge Services resources including active subscription plan, previously active plans, extra pipelines and extra egress cache data. + """ + + +@dataclass +class GetCacheStageRequest: + cache_stage_id: str + """ + ID of the requested cache stage. + """ + + +@dataclass +class GetCurrentPlanRequest: + project_id: Optional[str] + + +@dataclass +class GetDNSStageRequest: + dns_stage_id: str + """ + ID of the requested DNS stage. + """ + + +@dataclass +class GetPipelineRequest: + pipeline_id: str + """ + ID of the requested pipeline. + """ + + +@dataclass +class GetPurgeRequestRequest: + purge_request_id: str + """ + ID of the requested purge request. + """ + + +@dataclass +class GetRouteStageRequest: + route_stage_id: str + """ + ID of the requested route stage. + """ + + +@dataclass +class GetTLSStageRequest: + tls_stage_id: str + """ + ID of the requested TLS stage. + """ + + +@dataclass +class GetWafStageRequest: + waf_stage_id: str + """ + ID of the requested WAF stage. + """ + + +@dataclass +class HeadStageResponse: + head_stage: Optional[HeadStageResponseHeadStage] + """ + Modified or created head stage. + """ + + +@dataclass +class ListBackendStagesRequest: + order_by: Optional[ListBackendStagesRequestOrderBy] + """ + Sort order of backend stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of backend stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only backend stages from this pipeline will be returned. + """ + + bucket_name: Optional[str] + """ + Bucket name to filter for. Only backend stages from this Bucket will be returned. + """ + + bucket_region: Optional[str] + """ + Bucket region to filter for. Only backend stages with buckets in this region will be returned. + """ + + lb_id: Optional[str] + """ + Load Balancer ID to filter for. Only backend stages with this Load Balancer will be returned. + """ + + +@dataclass +class ListBackendStagesResponse: + stages: List[BackendStage] + """ + Paginated list of backend stages. + """ + + total_count: int + """ + Count of all backend stages matching the requested criteria. + """ + + +@dataclass +class ListCacheStagesRequest: + order_by: Optional[ListCacheStagesRequestOrderBy] + """ + Sort order of cache stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of cache stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only cache stages from this pipeline will be returned. + """ + + +@dataclass +class ListCacheStagesResponse: + stages: List[CacheStage] + """ + Paginated list of cache stages. + """ + + total_count: int + """ + Count of all cache stages matching the requested criteria. + """ + + +@dataclass +class ListDNSStagesRequest: + order_by: Optional[ListDNSStagesRequestOrderBy] + """ + Sort order of DNS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of DNS stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only DNS stages from this pipeline will be returned. + """ + + fqdn: Optional[str] + """ + Fully Qualified Domain Name to filter for (in the format subdomain.example.com). Only DNS stages with this FQDN will be returned. + """ + + +@dataclass +class ListDNSStagesResponse: + stages: List[DNSStage] + """ + Paginated list of DNS stages. + """ + + total_count: int + """ + Count of all DNS stages matching the requested criteria. + """ + + +@dataclass +class ListHeadStagesRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of head stages to return per page. + """ + + +@dataclass +class ListHeadStagesResponse: + head_stages: List[ListHeadStagesResponseHeadStage] + """ + Number of head stages to return per page. + """ + + total_count: int + """ + Count of all head stages matching the requested pipeline_id. + """ + + +@dataclass +class ListPipelinesRequest: + order_by: Optional[ListPipelinesRequestOrderBy] + """ + Sort order of pipelines in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of pipelines to return per page. + """ + + name: Optional[str] + """ + Pipeline name to filter for. Only pipelines with this string within their name will be returned. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. Only pipelines from this Organization will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for. Only pipelines from this Project will be returned. + """ + + has_backend_stage_lb: Optional[bool] + """ + Filter on backend stage. Only pipelines with a Load Balancer origin will be returned. + """ + + +@dataclass +class ListPipelinesResponse: + pipelines: List[Pipeline] + """ + Paginated list of pipelines. + """ + + total_count: int + """ + Count of all pipelines matching the requested criteria. + """ + + +@dataclass +class ListPipelinesWithStagesRequest: + order_by: Optional[ListPipelinesWithStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + name: Optional[str] + + organization_id: Optional[str] + + project_id: Optional[str] + + +@dataclass +class ListPipelinesWithStagesResponse: + pipelines: List[PipelineStages] + + total_count: int + + +@dataclass +class ListPlansResponse: + total_count: int + + plans: List[PlanDetails] + + +@dataclass +class ListPurgeRequestsRequest: + order_by: Optional[ListPurgeRequestsRequestOrderBy] + """ + Sort order of purge requests in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of purge requests to return per page. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. Only purge requests from this Project will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for. Only purge requests from this Project will be returned. + """ + + pipeline_id: Optional[str] + """ + Pipeline ID to filter for. Only purge requests from this pipeline will be returned. + """ + + +@dataclass +class ListPurgeRequestsResponse: + purge_requests: List[PurgeRequest] + """ + Paginated list of purge requests. + """ + + total_count: int + """ + Count of all purge requests matching the requested criteria. + """ + + +@dataclass +class ListRouteRulesRequest: + route_stage_id: str + """ + Route stage ID to filter for. Only route rules from this route stage will be returned. + """ + + +@dataclass +class ListRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class ListRouteStagesRequest: + order_by: Optional[ListRouteStagesRequestOrderBy] + """ + Sort order of route stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of route stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only route stages from this pipeline will be returned. + """ + + +@dataclass +class ListRouteStagesResponse: + stages: List[RouteStage] + """ + Paginated list of summarized route stages. + """ + + total_count: int + """ + Count of all route stages matching the requested criteria. + """ + + +@dataclass +class ListTLSStagesRequest: + order_by: Optional[ListTLSStagesRequestOrderBy] + """ + Sort order of TLS stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of TLS stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only TLS stages from this pipeline will be returned. + """ + + secret_id: Optional[str] + """ + Secret ID to filter for. Only TLS stages with this Secret ID will be returned. + """ + + secret_region: Optional[str] + """ + Secret region to filter for. Only TLS stages with a Secret in this region will be returned. + """ + + +@dataclass +class ListTLSStagesResponse: + stages: List[TLSStage] + """ + Paginated list of TLS stages. + """ + + total_count: int + """ + Count of all TLS stages matching the requested criteria. + """ + + +@dataclass +class ListWafStagesRequest: + order_by: Optional[ListWafStagesRequestOrderBy] + """ + Sort order of WAF stages in the response. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Number of WAF stages to return per page. + """ + + pipeline_id: str + """ + Pipeline ID to filter for. Only WAF stages from this pipeline will be returned. + """ + + +@dataclass +class ListWafStagesResponse: + stages: List[WafStage] + """ + Paginated list of WAF stages. + """ + + total_count: int + """ + Count of all WAF stages matching the requested criteria. + """ + + +@dataclass +class Plan: + plan_name: PlanName + + +@dataclass +class SearchBackendStagesRequest: + order_by: Optional[SearchBackendStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + project_id: Optional[str] + + bucket_name: Optional[str] + + bucket_region: Optional[str] + + lb_id: Optional[str] + + +@dataclass +class SearchWafStagesRequest: + order_by: Optional[SearchWafStagesRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + project_id: Optional[str] + + +@dataclass +class SelectPlanRequest: + project_id: Optional[str] + + plan_name: Optional[PlanName] + + +@dataclass +class SetHeadStageRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + add_new_head_stage: Optional[SetHeadStageRequestAddNewHeadStage] + + remove_head_stage: Optional[SetHeadStageRequestRemoveHeadStage] + + swap_head_stage: Optional[SetHeadStageRequestSwapHeadStage] + + +@dataclass +class SetRouteRulesRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + route_rules: Optional[List[SetRouteRulesRequestRouteRule]] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class SetRouteRulesResponse: + route_rules: List[RouteRule] + """ + List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + """ + + +@dataclass +class UpdateBackendStageRequest: + backend_stage_id: str + """ + ID of the backend stage to update. + """ + + pipeline_id: str + """ + Pipeline ID the Backend stage belongs to. + """ + + scaleway_s3: Optional[ScalewayS3BackendConfig] + + scaleway_lb: Optional[ScalewayLbBackendConfig] + + +@dataclass +class UpdateCacheStageRequest: + cache_stage_id: str + """ + ID of the cache stage to update. + """ + + fallback_ttl: Optional[str] + """ + Time To Live (TTL) in seconds. Defines how long content is cached. + """ + + backend_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + route_stage_id: Optional[str] + + +@dataclass +class UpdateDNSStageRequest: + dns_stage_id: str + """ + ID of the DNS stage to update. + """ + + fqdns: Optional[List[str]] + """ + Fully Qualified Domain Name (in the format subdomain.example.com) attached to the stage. + """ + + tls_stage_id: Optional[str] + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + +@dataclass +class UpdatePipelineRequest: + pipeline_id: str + """ + ID of the pipeline to update. + """ + + name: Optional[str] + """ + Name of the pipeline. + """ + + description: Optional[str] + """ + Description of the pipeline. + """ + + +@dataclass +class UpdateRouteStageRequest: + route_stage_id: str + """ + ID of the route stage to update. + """ + + waf_stage_id: Optional[str] + + +@dataclass +class UpdateTLSStageRequest: + tls_stage_id: str + """ + ID of the TLS stage to update. + """ + + tls_secrets_config: Optional[TLSSecretsConfig] + """ + Secret (from Scaleway Secret-Manager) containing your custom certificate. + """ + + managed_certificate: Optional[bool] + """ + True when Scaleway generates and manages a Let's Encrypt certificate for the TLS stage/custom endpoint. + """ + + cache_stage_id: Optional[str] + + backend_stage_id: Optional[str] + + route_stage_id: Optional[str] + + waf_stage_id: Optional[str] + + +@dataclass +class UpdateWafStageRequest: + waf_stage_id: str + """ + ID of the WAF stage to update. + """ + + mode: Optional[WafStageMode] + """ + Mode defining WAF behavior (`disable`/`log_only`/`enable`). + """ + + paranoia_level: Optional[int] + """ + Sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. + """ + + backend_stage_id: Optional[str] diff --git a/scaleway/scaleway/file/__init__.py b/scaleway/scaleway/file/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway/scaleway/file/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/file/v1alpha1/__init__.py b/scaleway/scaleway/file/v1alpha1/__init__.py new file mode 100644 index 00000000..05c3dbdf --- /dev/null +++ b/scaleway/scaleway/file/v1alpha1/__init__.py @@ -0,0 +1,35 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import AttachmentResourceType +from .types import FileSystemStatus +from .content import FILE_SYSTEM_TRANSIENT_STATUSES +from .types import ListFileSystemsRequestOrderBy +from .types import Attachment +from .types import FileSystem +from .types import CreateFileSystemRequest +from .types import DeleteFileSystemRequest +from .types import GetFileSystemRequest +from .types import ListAttachmentsRequest +from .types import ListAttachmentsResponse +from .types import ListFileSystemsRequest +from .types import ListFileSystemsResponse +from .types import UpdateFileSystemRequest +from .api import FileV1Alpha1API + +__all__ = [ + "AttachmentResourceType", + "FileSystemStatus", + "FILE_SYSTEM_TRANSIENT_STATUSES", + "ListFileSystemsRequestOrderBy", + "Attachment", + "FileSystem", + "CreateFileSystemRequest", + "DeleteFileSystemRequest", + "GetFileSystemRequest", + "ListAttachmentsRequest", + "ListAttachmentsResponse", + "ListFileSystemsRequest", + "ListFileSystemsResponse", + "UpdateFileSystemRequest", + "FileV1Alpha1API", +] diff --git a/scaleway/scaleway/file/v1alpha1/api.py b/scaleway/scaleway/file/v1alpha1/api.py new file mode 100644 index 00000000..98c4af9a --- /dev/null +++ b/scaleway/scaleway/file/v1alpha1/api.py @@ -0,0 +1,434 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + AttachmentResourceType, + ListFileSystemsRequestOrderBy, + Attachment, + CreateFileSystemRequest, + FileSystem, + ListAttachmentsResponse, + ListFileSystemsResponse, + UpdateFileSystemRequest, +) +from .content import ( + FILE_SYSTEM_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_FileSystem, + unmarshal_ListAttachmentsResponse, + unmarshal_ListFileSystemsResponse, + marshal_CreateFileSystemRequest, + marshal_UpdateFileSystemRequest, +) + + +class FileV1Alpha1API(API): + """ + This API allows you to manage your File Storage resources. + """ + + def get_file_system( + self, + *, + filesystem_id: str, + region: Optional[ScwRegion] = None, + ) -> FileSystem: + """ + Get filesystem details. + Retrieve all properties and current status of a specific filesystem identified by its ID. + :param filesystem_id: UUID of the filesystem. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`FileSystem ` + + Usage: + :: + + result = api.get_file_system( + filesystem_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_filesystem_id = validate_path_param("filesystem_id", filesystem_id) + + res = self._request( + "GET", + f"/file/v1alpha1/regions/{param_region}/filesystems/{param_filesystem_id}", + ) + + self._throw_on_error(res) + return unmarshal_FileSystem(res.json()) + + def wait_for_file_system( + self, + *, + filesystem_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[FileSystem, bool]] = None, + ) -> FileSystem: + """ + Get filesystem details. + Retrieve all properties and current status of a specific filesystem identified by its ID. + :param filesystem_id: UUID of the filesystem. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`FileSystem ` + + Usage: + :: + + result = api.get_file_system( + filesystem_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in FILE_SYSTEM_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_file_system, + options=options, + args={ + "filesystem_id": filesystem_id, + "region": region, + }, + ) + + def list_file_systems( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListFileSystemsRequestOrderBy] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListFileSystemsResponse: + """ + List all filesystems. + Retrieve all filesystems in the specified region. By default, the filesystems listed are ordered by creation date in ascending order. This can be modified using the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by project ID. + :param page: Page number (starting at 1). + :param page_size: Number of entries per page (default: 20, max: 100). + :param name: Filter the returned filesystems by their names. + :param tags: Filter by tags. Only filesystems with one or more matching tags will be returned. + :return: :class:`ListFileSystemsResponse ` + + Usage: + :: + + result = api.list_file_systems() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/file/v1alpha1/regions/{param_region}/filesystems", + params={ + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListFileSystemsResponse(res.json()) + + def list_file_systems_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListFileSystemsRequestOrderBy] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[FileSystem]: + """ + List all filesystems. + Retrieve all filesystems in the specified region. By default, the filesystems listed are ordered by creation date in ascending order. This can be modified using the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Criteria to use when ordering the list. + :param project_id: Filter by project ID. + :param page: Page number (starting at 1). + :param page_size: Number of entries per page (default: 20, max: 100). + :param name: Filter the returned filesystems by their names. + :param tags: Filter by tags. Only filesystems with one or more matching tags will be returned. + :return: :class:`List[FileSystem] ` + + Usage: + :: + + result = api.list_file_systems_all() + """ + + return fetch_all_pages( + type=ListFileSystemsResponse, + key="filesystems", + fetcher=self.list_file_systems, + args={ + "region": region, + "order_by": order_by, + "project_id": project_id, + "page": page, + "page_size": page_size, + "name": name, + "tags": tags, + }, + ) + + def list_attachments( + self, + *, + region: Optional[ScwRegion] = None, + filesystem_id: Optional[str] = None, + resource_id: Optional[str] = None, + resource_type: Optional[AttachmentResourceType] = None, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListAttachmentsResponse: + """ + List filesystems attachments. + List all existing attachments in a specified region. + By default, the attachments listed are ordered by creation date in ascending order. This can be modified using the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param filesystem_id: UUID of the File Storage volume. + :param resource_id: Filter by resource ID. + :param resource_type: Filter by resource type. + :param zone: Filter by resource zone. + :param page: Page number (starting at 1). + :param page_size: Number of entries per page (default: 20, max: 100). + :return: :class:`ListAttachmentsResponse ` + + Usage: + :: + + result = api.list_attachments() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/file/v1alpha1/regions/{param_region}/attachments", + params={ + "filesystem_id": filesystem_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "resource_id": resource_id, + "resource_type": resource_type, + "zone": zone or self.client.default_zone, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListAttachmentsResponse(res.json()) + + def list_attachments_all( + self, + *, + region: Optional[ScwRegion] = None, + filesystem_id: Optional[str] = None, + resource_id: Optional[str] = None, + resource_type: Optional[AttachmentResourceType] = None, + zone: Optional[ScwZone] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[Attachment]: + """ + List filesystems attachments. + List all existing attachments in a specified region. + By default, the attachments listed are ordered by creation date in ascending order. This can be modified using the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param filesystem_id: UUID of the File Storage volume. + :param resource_id: Filter by resource ID. + :param resource_type: Filter by resource type. + :param zone: Filter by resource zone. + :param page: Page number (starting at 1). + :param page_size: Number of entries per page (default: 20, max: 100). + :return: :class:`List[Attachment] ` + + Usage: + :: + + result = api.list_attachments_all() + """ + + return fetch_all_pages( + type=ListAttachmentsResponse, + key="attachments", + fetcher=self.list_attachments, + args={ + "region": region, + "filesystem_id": filesystem_id, + "resource_id": resource_id, + "resource_type": resource_type, + "zone": zone, + "page": page, + "page_size": page_size, + }, + ) + + def create_file_system( + self, + *, + name: str, + size: int, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> FileSystem: + """ + Create a new filesystem. + To create a new filesystem, you must specify a name, a size, and a project ID. + :param name: Name of the filesystem. + :param size: Must be compliant with the minimum (100 GB) and maximum (10 TB) allowed size. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: UUID of the project the filesystem belongs to. + :param tags: List of tags assigned to the filesystem. + :return: :class:`FileSystem ` + + Usage: + :: + + result = api.create_file_system( + name="example", + size=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/file/v1alpha1/regions/{param_region}/filesystems", + body=marshal_CreateFileSystemRequest( + CreateFileSystemRequest( + name=name, + size=size, + region=region, + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_FileSystem(res.json()) + + def delete_file_system( + self, + *, + filesystem_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a detached filesystem. + You must specify the `filesystem_id` of the filesystem you want to delete. + :param filesystem_id: UUID of the filesystem. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_file_system( + filesystem_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_filesystem_id = validate_path_param("filesystem_id", filesystem_id) + + res = self._request( + "DELETE", + f"/file/v1alpha1/regions/{param_region}/filesystems/{param_filesystem_id}", + ) + + self._throw_on_error(res) + + def update_file_system( + self, + *, + filesystem_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + size: Optional[int] = None, + tags: Optional[List[str]] = None, + ) -> FileSystem: + """ + Update filesystem properties. + Update the technical details of a filesystem, such as its name, tags or its new size. + :param filesystem_id: UUID of the filesystem. + :param region: Region to target. If none is passed will use default region from the config. + :param name: When defined, is the new name of the filesystem. + :param size: Size in bytes, with a granularity of 100 GB (10^11 bytes). + Must be compliant with the minimum (100 GB) and maximum (10 TB) allowed size. + :param tags: List of tags assigned to the filesystem. + :return: :class:`FileSystem ` + + Usage: + :: + + result = api.update_file_system( + filesystem_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_filesystem_id = validate_path_param("filesystem_id", filesystem_id) + + res = self._request( + "PATCH", + f"/file/v1alpha1/regions/{param_region}/filesystems/{param_filesystem_id}", + body=marshal_UpdateFileSystemRequest( + UpdateFileSystemRequest( + filesystem_id=filesystem_id, + region=region, + name=name, + size=size, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_FileSystem(res.json()) diff --git a/scaleway/scaleway/file/v1alpha1/content.py b/scaleway/scaleway/file/v1alpha1/content.py new file mode 100644 index 00000000..c6a422b4 --- /dev/null +++ b/scaleway/scaleway/file/v1alpha1/content.py @@ -0,0 +1,15 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + FileSystemStatus, +) + +FILE_SYSTEM_TRANSIENT_STATUSES: List[FileSystemStatus] = [ + FileSystemStatus.CREATING, + FileSystemStatus.UPDATING, +] +""" +Lists transient statutes of the enum :class:`FileSystemStatus `. +""" diff --git a/scaleway/scaleway/file/v1alpha1/marshalling.py b/scaleway/scaleway/file/v1alpha1/marshalling.py new file mode 100644 index 00000000..e9b6d39d --- /dev/null +++ b/scaleway/scaleway/file/v1alpha1/marshalling.py @@ -0,0 +1,188 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from .types import ( + FileSystem, + Attachment, + ListAttachmentsResponse, + ListFileSystemsResponse, + CreateFileSystemRequest, + UpdateFileSystemRequest, +) + + +def unmarshal_FileSystem(data: Any) -> FileSystem: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'FileSystem' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("number_of_attachments", None) + if field is not None: + args["number_of_attachments"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return FileSystem(**args) + + +def unmarshal_Attachment(data: Any) -> Attachment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Attachment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("filesystem_id", None) + if field is not None: + args["filesystem_id"] = field + + field = data.get("resource_id", None) + if field is not None: + args["resource_id"] = field + + field = data.get("resource_type", None) + if field is not None: + args["resource_type"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + return Attachment(**args) + + +def unmarshal_ListAttachmentsResponse(data: Any) -> ListAttachmentsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListAttachmentsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("attachments", None) + if field is not None: + args["attachments"] = ( + [unmarshal_Attachment(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListAttachmentsResponse(**args) + + +def unmarshal_ListFileSystemsResponse(data: Any) -> ListFileSystemsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListFileSystemsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("filesystems", None) + if field is not None: + args["filesystems"] = ( + [unmarshal_FileSystem(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListFileSystemsResponse(**args) + + +def marshal_CreateFileSystemRequest( + request: CreateFileSystemRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.size is not None: + output["size"] = request.size + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_UpdateFileSystemRequest( + request: UpdateFileSystemRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.size is not None: + output["size"] = request.size + + if request.tags is not None: + output["tags"] = request.tags + + return output diff --git a/scaleway/scaleway/file/v1alpha1/types.py b/scaleway/scaleway/file/v1alpha1/types.py new file mode 100644 index 00000000..04f5973a --- /dev/null +++ b/scaleway/scaleway/file/v1alpha1/types.py @@ -0,0 +1,356 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class AttachmentResourceType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_RESOURCE_TYPE = "unknown_resource_type" + INSTANCE_SERVER = "instance_server" + + def __str__(self) -> str: + return str(self.value) + + +class FileSystemStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + AVAILABLE = "available" + ERROR = "error" + CREATING = "creating" + UPDATING = "updating" + + def __str__(self) -> str: + return str(self.value) + + +class ListFileSystemsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class Attachment: + """ + Represents an attachment between a filesystem and a resource. + """ + + id: str + """ + UUID of the attachment. + """ + + filesystem_id: str + """ + UUID of the filesystem. + """ + + resource_id: str + """ + UUID of the attached resource. + """ + + resource_type: AttachmentResourceType + """ + The type of the attached resource. + """ + + zone: Optional[ScwZone] + """ + The zone where the resource is located. + """ + + +@dataclass +class FileSystem: + """ + Represents a filesystem resource and its properties. + """ + + id: str + """ + UUID of the filesystem. + """ + + name: str + """ + Name of the filesystem. + """ + + size: int + """ + Filesystem size in bytes. + """ + + status: FileSystemStatus + """ + Current status of the filesystem (e.g. creating, available, ...). + """ + + project_id: str + """ + UUID of the project to which the filesystem belongs. + """ + + organization_id: str + """ + UUID of the organization to which the filesystem belongs. + """ + + tags: List[str] + """ + List of tags assigned to the filesystem. + """ + + number_of_attachments: int + """ + The current number of attachments (mounts) that the filesystem has. + """ + + region: ScwRegion + """ + Region where the filesystem is located. + """ + + created_at: Optional[datetime] + """ + Creation date of the filesystem. + """ + + updated_at: Optional[datetime] + """ + Last update date of the properties of the filesystem. + """ + + +@dataclass +class CreateFileSystemRequest: + """ + Request to create a new filesystem. + """ + + name: str + """ + Name of the filesystem. + """ + + size: int + """ + Must be compliant with the minimum (100 GB) and maximum (10 TB) allowed size. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + UUID of the project the filesystem belongs to. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the filesystem. + """ + + +@dataclass +class DeleteFileSystemRequest: + """ + Request to delete a specific filesystem. + """ + + filesystem_id: str + """ + UUID of the filesystem. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetFileSystemRequest: + """ + Request to retrieve a specific filesystem. + """ + + filesystem_id: str + """ + UUID of the filesystem. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListAttachmentsRequest: + """ + Request to list filesystem attachments with filtering and pagination options. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + filesystem_id: Optional[str] + """ + UUID of the File Storage volume. + """ + + resource_id: Optional[str] + """ + Filter by resource ID. + """ + + resource_type: Optional[AttachmentResourceType] + """ + Filter by resource type. + """ + + zone: Optional[ScwZone] + """ + Filter by resource zone. + """ + + page: Optional[int] + """ + Page number (starting at 1). + """ + + page_size: Optional[int] + """ + Number of entries per page (default: 20, max: 100). + """ + + +@dataclass +class ListAttachmentsResponse: + """ + Response containing a list of filesystem attachments and total count. + """ + + attachments: List[Attachment] + """ + List of filesystem attachments matching the request criteria. + """ + + total_count: int + """ + Total number of filesystem attachments matching the criteria. + """ + + +@dataclass +class ListFileSystemsRequest: + """ + Request to list filesystems with filtering and pagination options. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListFileSystemsRequestOrderBy] + """ + Criteria to use when ordering the list. + """ + + project_id: Optional[str] + """ + Filter by project ID. + """ + + page: Optional[int] + """ + Page number (starting at 1). + """ + + page_size: Optional[int] + """ + Number of entries per page (default: 20, max: 100). + """ + + name: Optional[str] + """ + Filter the returned filesystems by their names. + """ + + tags: Optional[List[str]] + """ + Filter by tags. Only filesystems with one or more matching tags will be returned. + """ + + +@dataclass +class ListFileSystemsResponse: + """ + Response containing a list of filesystems and total count. + """ + + filesystems: List[FileSystem] + """ + List of filesystems matching the request criteria. + """ + + total_count: int + """ + Total number of filesystems matching the criteria. + """ + + +@dataclass +class UpdateFileSystemRequest: + """ + Request to update a specific filesystem. + """ + + filesystem_id: str + """ + UUID of the filesystem. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + When defined, is the new name of the filesystem. + """ + + size: Optional[int] + """ + Size in bytes, with a granularity of 100 GB (10^11 bytes). +Must be compliant with the minimum (100 GB) and maximum (10 TB) allowed size. + """ + + tags: Optional[List[str]] + """ + List of tags assigned to the filesystem. + """ diff --git a/scaleway/scaleway/flexibleip/v1alpha1/api.py b/scaleway/scaleway/flexibleip/v1alpha1/api.py index 3cdcce04..2e298c1c 100644 --- a/scaleway/scaleway/flexibleip/v1alpha1/api.py +++ b/scaleway/scaleway/flexibleip/v1alpha1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, @@ -49,7 +49,7 @@ class FlexibleipV1Alpha1API(API): """ - Elastic Metal - Flexible IP API. + This API allows you to manage your Elastic Metal servers' flexible public IP addresses. """ def create_flexible_ip( @@ -57,7 +57,7 @@ def create_flexible_ip( *, description: str, is_ipv6: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, server_id: Optional[str] = None, @@ -110,7 +110,7 @@ def get_flexible_ip( self, *, fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> FlexibleIP: """ Get an existing flexible IP. @@ -142,7 +142,7 @@ def wait_for_flexible_ip( self, *, fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[FlexibleIP, bool]] = None, ) -> FlexibleIP: """ @@ -178,7 +178,7 @@ def wait_for_flexible_ip( def list_flexible_i_ps( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListFlexibleIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -232,7 +232,7 @@ def list_flexible_i_ps( def list_flexible_i_ps_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListFlexibleIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -283,7 +283,7 @@ def update_flexible_ip( self, *, fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, reverse: Optional[str] = None, @@ -331,7 +331,7 @@ def delete_flexible_ip( self, *, fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an existing flexible IP. @@ -362,7 +362,7 @@ def attach_flexible_ip( *, fips_ids: List[str], server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> AttachFlexibleIPsResponse: """ Attach an existing flexible IP to a server. @@ -403,7 +403,7 @@ def detach_flexible_ip( self, *, fips_ids: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> DetachFlexibleIPsResponse: """ Detach an existing flexible IP from a server. @@ -442,7 +442,7 @@ def generate_mac_addr( *, fip_id: str, mac_type: MACAddressType, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> FlexibleIP: """ Generate a virtual MAC address on an existing flexible IP. @@ -485,7 +485,7 @@ def duplicate_mac_addr( *, fip_id: str, duplicate_from_fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> FlexibleIP: """ Duplicate a virtual MAC address to another flexible IP. @@ -528,7 +528,7 @@ def move_mac_addr( *, fip_id: str, dst_fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> FlexibleIP: """ Relocate an existing virtual MAC address to a different flexible IP. @@ -570,7 +570,7 @@ def delete_mac_addr( self, *, fip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Detach a given virtual MAC address from an existing flexible IP. diff --git a/scaleway/scaleway/flexibleip/v1alpha1/marshalling.py b/scaleway/scaleway/flexibleip/v1alpha1/marshalling.py index 5f44ed7d..6f754d00 100644 --- a/scaleway/scaleway/flexibleip/v1alpha1/marshalling.py +++ b/scaleway/scaleway/flexibleip/v1alpha1/marshalling.py @@ -52,10 +52,14 @@ def unmarshal_MACAddress(data: Any) -> MACAddress: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return MACAddress(**args) @@ -99,6 +103,8 @@ def unmarshal_FlexibleIP(data: Any) -> FlexibleIP: field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("reverse", None) if field is not None: @@ -111,14 +117,20 @@ def unmarshal_FlexibleIP(data: Any) -> FlexibleIP: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("mac_address", None) if field is not None: args["mac_address"] = unmarshal_MACAddress(field) + else: + args["mac_address"] = None field = data.get("server_id", None) if field is not None: args["server_id"] = field + else: + args["server_id"] = None return FlexibleIP(**args) diff --git a/scaleway/scaleway/flexibleip/v1alpha1/types.py b/scaleway/scaleway/flexibleip/v1alpha1/types.py index 36ce0fce..623c8c4e 100644 --- a/scaleway/scaleway/flexibleip/v1alpha1/types.py +++ b/scaleway/scaleway/flexibleip/v1alpha1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -80,7 +80,7 @@ class MACAddress: Status of virtual MAC. """ - zone: Zone + zone: ScwZone """ MAC address IP Availability Zone. """ @@ -148,7 +148,7 @@ class FlexibleIP: Reverse DNS value. """ - zone: Zone + zone: ScwZone """ Availability Zone of the flexible IP. """ @@ -181,7 +181,7 @@ class AttachFlexibleIPRequest: ID of the server on which to attach the flexible IPs. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -212,7 +212,7 @@ class CreateFlexibleIPRequest: Defines whether the flexible IP has an IPv6 address. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -245,7 +245,7 @@ class DeleteFlexibleIPRequest: ID of the flexible IP to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -258,7 +258,7 @@ class DeleteMACAddrRequest: If the flexible IP belongs to a MAC group, the MAC will be removed from both the MAC group and flexible IP. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -271,7 +271,7 @@ class DetachFlexibleIPRequest: List of flexible IP IDs to detach from a server. Multiple IDs can be provided. Note that flexible IPs must belong to the same MAC group. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -302,7 +302,7 @@ class DuplicateMACAddrRequest: Note that flexible IPs need to be attached to the same server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -320,7 +320,7 @@ class GenerateMACAddrRequest: TODO. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -333,7 +333,7 @@ class GetFlexibleIPRequest: ID of the flexible IP. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -341,7 +341,7 @@ class GetFlexibleIPRequest: @dataclass class ListFlexibleIPsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -406,7 +406,7 @@ class MoveMACAddrRequest: dst_fip_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -419,7 +419,7 @@ class UpdateFlexibleIPRequest: ID of the flexible IP to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway/scaleway/function/v1beta1/__init__.py b/scaleway/scaleway/function/v1beta1/__init__.py index b6e5acf9..2b9481aa 100644 --- a/scaleway/scaleway/function/v1beta1/__init__.py +++ b/scaleway/scaleway/function/v1beta1/__init__.py @@ -7,6 +7,7 @@ from .types import FunctionHttpOption from .types import FunctionPrivacy from .types import FunctionRuntime +from .types import FunctionSandbox from .types import FunctionStatus from .content import FUNCTION_TRANSIENT_STATUSES from .types import ListCronsRequestOrderBy @@ -61,7 +62,6 @@ from .types import GetNamespaceRequest from .types import GetTokenRequest from .types import GetTriggerRequest -from .types import IssueJWTRequest from .types import ListCronsRequest from .types import ListCronsResponse from .types import ListDomainsRequest @@ -91,6 +91,7 @@ "FunctionHttpOption", "FunctionPrivacy", "FunctionRuntime", + "FunctionSandbox", "FunctionStatus", "FUNCTION_TRANSIENT_STATUSES", "ListCronsRequestOrderBy", @@ -145,7 +146,6 @@ "GetNamespaceRequest", "GetTokenRequest", "GetTriggerRequest", - "IssueJWTRequest", "ListCronsRequest", "ListCronsResponse", "ListDomainsRequest", diff --git a/scaleway/scaleway/function/v1beta1/api.py b/scaleway/scaleway/function/v1beta1/api.py index ef47b00b..63826d8c 100644 --- a/scaleway/scaleway/function/v1beta1/api.py +++ b/scaleway/scaleway/function/v1beta1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( OneOfPossibility, @@ -21,6 +21,7 @@ FunctionHttpOption, FunctionPrivacy, FunctionRuntime, + FunctionSandbox, ListCronsRequestOrderBy, ListDomainsRequestOrderBy, ListFunctionsRequestOrderBy, @@ -96,12 +97,14 @@ class FunctionV1Beta1API(API): - """ """ + """ + This API allows you to manage your Serverless Functions. + """ def list_namespaces( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -151,7 +154,7 @@ def list_namespaces( def list_namespaces_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -196,7 +199,7 @@ def get_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Get a namespace. @@ -230,7 +233,7 @@ def wait_for_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Namespace, bool]] = None, ) -> Namespace: """ @@ -266,12 +269,13 @@ def wait_for_namespace( def create_namespace( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, environment_variables: Optional[Dict[str, str]] = None, project_id: Optional[str] = None, description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, + tags: Optional[List[str]] = None, ) -> Namespace: """ Create a new namespace. @@ -282,6 +286,7 @@ def create_namespace( :param project_id: UUID of the project in which the namespace will be created. :param description: Description of the namespace. :param secret_environment_variables: Secret environment variables of the namespace. + :param tags: Tags of the Serverless Function Namespace. :return: :class:`Namespace ` Usage: @@ -305,6 +310,7 @@ def create_namespace( project_id=project_id, description=description, secret_environment_variables=secret_environment_variables, + tags=tags, ), self.client, ), @@ -317,10 +323,11 @@ def update_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, environment_variables: Optional[Dict[str, str]] = None, description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, + tags: Optional[List[str]] = None, ) -> Namespace: """ Update an existing namespace. @@ -330,6 +337,7 @@ def update_namespace( :param environment_variables: Environment variables of the namespace. :param description: Description of the namespace. :param secret_environment_variables: Secret environment variables of the namespace. + :param tags: Tags of the Serverless Function Namespace. :return: :class:`Namespace ` Usage: @@ -355,6 +363,7 @@ def update_namespace( environment_variables=environment_variables, description=description, secret_environment_variables=secret_environment_variables, + tags=tags, ), self.client, ), @@ -367,7 +376,7 @@ def delete_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Delete an existing namespace. @@ -401,7 +410,7 @@ def list_functions( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListFunctionsRequestOrderBy] = None, @@ -417,7 +426,7 @@ def list_functions( :param page_size: Number of functions per page. :param order_by: Order of the functions. :param name: Name of the function. - :param organization_id: UUID of the Organziation the function belongs to. + :param organization_id: UUID of the Organization the function belongs to. :param project_id: UUID of the Project the function belongs to. :return: :class:`ListFunctionsResponse ` @@ -455,7 +464,7 @@ def list_functions_all( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListFunctionsRequestOrderBy] = None, @@ -471,7 +480,7 @@ def list_functions_all( :param page_size: Number of functions per page. :param order_by: Order of the functions. :param name: Name of the function. - :param organization_id: UUID of the Organziation the function belongs to. + :param organization_id: UUID of the Organization the function belongs to. :param project_id: UUID of the Project the function belongs to. :return: :class:`List[Function] ` @@ -503,7 +512,7 @@ def get_function( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Function: """ Get a function. @@ -537,7 +546,7 @@ def wait_for_function( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Function, bool]] = None, ) -> Function: """ @@ -574,7 +583,7 @@ def create_function( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, environment_variables: Optional[Dict[str, str]] = None, min_scale: Optional[int] = None, @@ -587,6 +596,8 @@ def create_function( description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, http_option: Optional[FunctionHttpOption] = None, + sandbox: Optional[FunctionSandbox] = None, + tags: Optional[List[str]] = None, ) -> Function: """ Create a new function. @@ -595,7 +606,7 @@ def create_function( :param region: Region to target. If none is passed will use default region from the config. :param name: Name of the function to create. :param environment_variables: Environment variables of the function. - :param min_scale: Minumum number of instances to scale the function to. + :param min_scale: Minimum number of instances to scale the function to. :param max_scale: Maximum number of instances to scale the function to. :param runtime: Runtime to use with the function. :param memory_limit: Memory limit of the function in MB. @@ -607,6 +618,8 @@ def create_function( :param http_option: Possible values: - redirected: Responds to HTTP request with a 301 redirect to ask the clients to use HTTPS. - enabled: Serve both HTTP and HTTPS traffic. + :param sandbox: Execution environment of the function. + :param tags: Tags of the Serverless Function. :return: :class:`Function ` Usage: @@ -640,6 +653,8 @@ def create_function( description=description, secret_environment_variables=secret_environment_variables, http_option=http_option, + sandbox=sandbox, + tags=tags, ), self.client, ), @@ -652,7 +667,7 @@ def update_function( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, environment_variables: Optional[Dict[str, str]] = None, min_scale: Optional[int] = None, max_scale: Optional[int] = None, @@ -665,6 +680,8 @@ def update_function( description: Optional[str] = None, secret_environment_variables: Optional[List[Secret]] = None, http_option: Optional[FunctionHttpOption] = None, + sandbox: Optional[FunctionSandbox] = None, + tags: Optional[List[str]] = None, ) -> Function: """ Update an existing function. @@ -672,7 +689,7 @@ def update_function( :param function_id: UUID of the function to update. :param region: Region to target. If none is passed will use default region from the config. :param environment_variables: Environment variables of the function to update. - :param min_scale: Minumum number of instances to scale the function to. + :param min_scale: Minimum number of instances to scale the function to. :param max_scale: Maximum number of instances to scale the function to. :param runtime: Runtime to use with the function. :param memory_limit: Memory limit of the function in MB. @@ -685,6 +702,8 @@ def update_function( :param http_option: Possible values: - redirected: Responds to HTTP request with a 301 redirect to ask the clients to use HTTPS. - enabled: Serve both HTTP and HTTPS traffic. + :param sandbox: Execution environment of the function. + :param tags: Tags of the Serverless Function. :return: :class:`Function ` Usage: @@ -719,6 +738,8 @@ def update_function( description=description, secret_environment_variables=secret_environment_variables, http_option=http_option, + sandbox=sandbox, + tags=tags, ), self.client, ), @@ -731,7 +752,7 @@ def delete_function( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Function: """ Delete a function. @@ -765,7 +786,7 @@ def deploy_function( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Function: """ Deploy a function. @@ -799,7 +820,7 @@ def deploy_function( def list_function_runtimes( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListFunctionRuntimesResponse: """ List function runtimes. @@ -830,7 +851,7 @@ def get_function_upload_url( *, function_id: str, content_length: int, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> UploadURL: """ Get an upload URL of a function. @@ -869,12 +890,12 @@ def get_function_download_url( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DownloadURL: """ Get a download URL of a function. Get a download URL for a function associated with the specified ID. - :param function_id: UUID of the function to get the the download URL for. + :param function_id: UUID of the function to get the download URL for. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`DownloadURL ` @@ -903,7 +924,7 @@ def list_crons( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListCronsRequestOrderBy] = None, @@ -948,7 +969,7 @@ def list_crons_all( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListCronsRequestOrderBy] = None, @@ -988,7 +1009,7 @@ def get_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cron: """ Get a cron. @@ -1022,7 +1043,7 @@ def wait_for_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Cron, bool]] = None, ) -> Cron: """ @@ -1060,7 +1081,7 @@ def create_cron( *, function_id: str, schedule: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, args: Optional[Dict[str, Any]] = None, name: Optional[str] = None, ) -> Cron: @@ -1109,7 +1130,7 @@ def update_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, function_id: Optional[str] = None, schedule: Optional[str] = None, args: Optional[Dict[str, Any]] = None, @@ -1162,7 +1183,7 @@ def delete_cron( self, *, cron_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cron: """ Delete an existing cron. @@ -1196,7 +1217,7 @@ def list_domains( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDomainsRequestOrderBy] = None, @@ -1204,7 +1225,7 @@ def list_domains( """ List all domain name bindings. List all domain name bindings in a specified region. - :param function_id: UUID of the function the domain is assoicated with. + :param function_id: UUID of the function the domain is associated with. :param region: Region to target. If none is passed will use default region from the config. :param page: Page number. :param page_size: Number of domains per page. @@ -1241,7 +1262,7 @@ def list_domains_all( self, *, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDomainsRequestOrderBy] = None, @@ -1249,7 +1270,7 @@ def list_domains_all( """ List all domain name bindings. List all domain name bindings in a specified region. - :param function_id: UUID of the function the domain is assoicated with. + :param function_id: UUID of the function the domain is associated with. :param region: Region to target. If none is passed will use default region from the config. :param page: Page number. :param page_size: Number of domains per page. @@ -1281,7 +1302,7 @@ def get_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Get a domain name binding. @@ -1315,7 +1336,7 @@ def wait_for_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Domain, bool]] = None, ) -> Domain: """ @@ -1353,7 +1374,7 @@ def create_domain( *, hostname: str, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Create a domain name binding. @@ -1396,7 +1417,7 @@ def delete_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Delete a domain name binding. @@ -1426,57 +1447,10 @@ def delete_domain( self._throw_on_error(res) return unmarshal_Domain(res.json()) - def issue_jwt( - self, - *, - region: Optional[Region] = None, - function_id: Optional[str] = None, - namespace_id: Optional[str] = None, - expires_at: Optional[datetime] = None, - ) -> Token: - """ - Create a JWT token. - Deprecated in favor of CreateToken. - :param region: Region to target. If none is passed will use default region from the config. - :param function_id: - One-Of ('scope'): at most one of 'function_id', 'namespace_id' could be set. - :param namespace_id: - One-Of ('scope'): at most one of 'function_id', 'namespace_id' could be set. - :param expires_at: - :return: :class:`Token ` - :deprecated - - Usage: - :: - - result = api.issue_jwt() - """ - - param_region = validate_path_param( - "region", region or self.client.default_region - ) - - res = self._request( - "GET", - f"/functions/v1beta1/regions/{param_region}/issue-jwt", - params={ - "expires_at": expires_at, - **resolve_one_of( - [ - OneOfPossibility("function_id", function_id), - OneOfPossibility("namespace_id", namespace_id), - ] - ), - }, - ) - - self._throw_on_error(res) - return unmarshal_Token(res.json()) - def create_token( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, function_id: Optional[str] = None, namespace_id: Optional[str] = None, description: Optional[str] = None, @@ -1525,7 +1499,7 @@ def get_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Token: """ Get a token. @@ -1558,7 +1532,7 @@ def wait_for_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Token, bool]] = None, ) -> Token: """ @@ -1593,7 +1567,7 @@ def wait_for_token( def list_tokens( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTokensRequestOrderBy] = None, @@ -1606,7 +1580,7 @@ def list_tokens( :param page: Page number. :param page_size: Number of tokens per page. :param order_by: Sort order for the tokens. - :param function_id: UUID of the function the token is assoicated with. + :param function_id: UUID of the function the token is associated with. :param namespace_id: UUID of the namespace the token is associated with. :return: :class:`ListTokensResponse ` @@ -1638,7 +1612,7 @@ def list_tokens( def list_tokens_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTokensRequestOrderBy] = None, @@ -1651,7 +1625,7 @@ def list_tokens_all( :param page: Page number. :param page_size: Number of tokens per page. :param order_by: Sort order for the tokens. - :param function_id: UUID of the function the token is assoicated with. + :param function_id: UUID of the function the token is associated with. :param namespace_id: UUID of the namespace the token is associated with. :return: :class:`List[Token] ` @@ -1679,7 +1653,7 @@ def delete_token( self, *, token_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Token: """ Delete a token. @@ -1713,7 +1687,7 @@ def create_trigger( *, name: str, function_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, scw_sqs_config: Optional[CreateTriggerRequestMnqSqsClientConfig] = None, scw_nats_config: Optional[CreateTriggerRequestMnqNatsClientConfig] = None, @@ -1771,7 +1745,7 @@ def get_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Trigger: """ Get a trigger. @@ -1805,7 +1779,7 @@ def wait_for_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Trigger, bool]] = None, ) -> Trigger: """ @@ -1841,7 +1815,7 @@ def wait_for_trigger( def list_triggers( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTriggersRequestOrderBy] = None, @@ -1897,7 +1871,7 @@ def list_triggers( def list_triggers_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTriggersRequestOrderBy] = None, @@ -1945,7 +1919,7 @@ def update_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, description: Optional[str] = None, sqs_config: Optional[UpdateTriggerRequestSqsClientConfig] = None, @@ -1996,7 +1970,7 @@ def delete_trigger( self, *, trigger_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Trigger: """ Delete a trigger. diff --git a/scaleway/scaleway/function/v1beta1/marshalling.py b/scaleway/scaleway/function/v1beta1/marshalling.py index 34ff2d4d..d3cb71cd 100644 --- a/scaleway/scaleway/function/v1beta1/marshalling.py +++ b/scaleway/scaleway/function/v1beta1/marshalling.py @@ -79,6 +79,8 @@ def unmarshal_Cron(data: Any) -> Cron: field = data.get("args", None) if field is not None: args["args"] = field + else: + args["args"] = None return Cron(**args) @@ -114,6 +116,8 @@ def unmarshal_Domain(data: Any) -> Domain: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None return Domain(**args) @@ -205,6 +209,30 @@ def unmarshal_Function(data: Any) -> Function: else None ) + field = data.get("timeout", None) + if field is not None: + args["timeout"] = field + else: + args["timeout"] = None + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + else: + args["error_message"] = None + + field = data.get("build_message", None) + if field is not None: + args["build_message"] = field + else: + args["build_message"] = None + + field = data.get("description", None) + if field is not None: + args["description"] = field + else: + args["description"] = None + field = data.get("region", None) if field is not None: args["region"] = field @@ -217,21 +245,31 @@ def unmarshal_Function(data: Any) -> Function: if field is not None: args["runtime_message"] = field - field = data.get("timeout", None) + field = data.get("sandbox", None) if field is not None: - args["timeout"] = field + args["sandbox"] = field - field = data.get("error_message", None) + field = data.get("tags", None) if field is not None: - args["error_message"] = field + args["tags"] = field - field = data.get("build_message", None) + field = data.get("created_at", None) if field is not None: - args["build_message"] = field + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None - field = data.get("description", None) + field = data.get("updated_at", None) if field is not None: - args["description"] = field + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("ready_at", None) + if field is not None: + args["ready_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["ready_at"] = None return Function(**args) @@ -288,13 +326,33 @@ def unmarshal_Namespace(data: Any) -> Namespace: if field is not None: args["region"] = field + field = data.get("tags", None) + if field is not None: + args["tags"] = field + field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Namespace(**args) @@ -322,22 +380,32 @@ def unmarshal_Token(data: Any) -> Token: field = data.get("function_id", None) if field is not None: args["function_id"] = field + else: + args["function_id"] = None field = data.get("namespace_id", None) if field is not None: args["namespace_id"] = field + else: + args["namespace_id"] = None field = data.get("public_key", None) if field is not None: args["public_key"] = field + else: + args["public_key"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None return Token(**args) @@ -369,6 +437,8 @@ def unmarshal_TriggerMnqNatsClientConfig(data: Any) -> TriggerMnqNatsClientConfi field = data.get("mnq_credential_id", None) if field is not None: args["mnq_credential_id"] = field + else: + args["mnq_credential_id"] = None return TriggerMnqNatsClientConfig(**args) @@ -396,6 +466,8 @@ def unmarshal_TriggerMnqSqsClientConfig(data: Any) -> TriggerMnqSqsClientConfig: field = data.get("mnq_credential_id", None) if field is not None: args["mnq_credential_id"] = field + else: + args["mnq_credential_id"] = None return TriggerMnqSqsClientConfig(**args) @@ -462,18 +534,26 @@ def unmarshal_Trigger(data: Any) -> Trigger: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("scw_sqs_config", None) if field is not None: args["scw_sqs_config"] = unmarshal_TriggerMnqSqsClientConfig(field) + else: + args["scw_sqs_config"] = None field = data.get("scw_nats_config", None) if field is not None: args["scw_nats_config"] = unmarshal_TriggerMnqNatsClientConfig(field) + else: + args["scw_nats_config"] = None field = data.get("sqs_config", None) if field is not None: args["sqs_config"] = unmarshal_TriggerSqsClientConfig(field) + else: + args["sqs_config"] = None return Trigger(**args) @@ -813,6 +893,12 @@ def marshal_CreateFunctionRequest( if request.http_option is not None: output["http_option"] = str(request.http_option) + if request.sandbox is not None: + output["sandbox"] = str(request.sandbox) + + if request.tags is not None: + output["tags"] = request.tags + return output @@ -840,6 +926,9 @@ def marshal_CreateNamespaceRequest( for item in request.secret_environment_variables ] + if request.tags is not None: + output["tags"] = request.tags + return output @@ -861,7 +950,7 @@ def marshal_CreateTokenRequest( output["description"] = request.description if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -1019,6 +1108,12 @@ def marshal_UpdateFunctionRequest( if request.http_option is not None: output["http_option"] = str(request.http_option) + if request.sandbox is not None: + output["sandbox"] = str(request.sandbox) + + if request.tags is not None: + output["tags"] = request.tags + return output @@ -1040,6 +1135,9 @@ def marshal_UpdateNamespaceRequest( for item in request.secret_environment_variables ] + if request.tags is not None: + output["tags"] = request.tags + return output diff --git a/scaleway/scaleway/function/v1beta1/types.py b/scaleway/scaleway/function/v1beta1/types.py index 9da2784b..1e3b8220 100644 --- a/scaleway/scaleway/function/v1beta1/types.py +++ b/scaleway/scaleway/function/v1beta1/types.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -84,6 +84,25 @@ class FunctionRuntime(str, Enum, metaclass=StrEnumMeta): GO120 = "go120" NODE20 = "node20" GO121 = "go121" + NODE22 = "node22" + PYTHON312 = "python312" + PHP83 = "php83" + GO122 = "go122" + RUST179 = "rust179" + GO123 = "go123" + GO124 = "go124" + PYTHON313 = "python313" + RUST185 = "rust185" + PHP84 = "php84" + + def __str__(self) -> str: + return str(self.value) + + +class FunctionSandbox(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SANDBOX = "unknown_sandbox" + V1 = "v1" + V2 = "v2" def __str__(self) -> str: return str(self.value) @@ -505,7 +524,27 @@ class Function: Secret environment variables of the function. """ - region: Region + timeout: Optional[str] + """ + Request processing time limit for the function. + """ + + error_message: Optional[str] + """ + Error message if the function is in "error" state. + """ + + build_message: Optional[str] + """ + Description of the current build step. + """ + + description: Optional[str] + """ + Description of the function. + """ + + region: ScwRegion """ Region in which the function is deployed. """ @@ -519,24 +558,29 @@ class Function: runtime_message: str - timeout: Optional[str] + sandbox: FunctionSandbox """ - Request processing time limit for the function. + Execution environment of the function. """ - error_message: Optional[str] + tags: List[str] """ - Error message if the function is in "error" state. + List of tags applied to the Serverless Function. """ - build_message: Optional[str] + created_at: Optional[datetime] """ - Description of the current build step. + Creation date of the function. """ - description: Optional[str] + updated_at: Optional[datetime] """ - Description of the function. + Last update date of the function. + """ + + ready_at: Optional[datetime] + """ + Last date when the function was successfully deployed and set to ready. """ @@ -587,11 +631,16 @@ class Namespace: Secret environment variables of the namespace. """ - region: Region + region: ScwRegion """ Region in which the namespace is located. """ + tags: List[str] + """ + List of tags applied to the Serverless Function Namespace. + """ + error_message: Optional[str] """ Error message if the namespace is in "error" state. @@ -602,6 +651,16 @@ class Namespace: Description of the namespace. """ + created_at: Optional[datetime] + """ + Creation date of the namespace. + """ + + updated_at: Optional[datetime] + """ + Last update date of the namespace. + """ + @dataclass class Token: @@ -703,7 +762,7 @@ class CreateCronRequest: Schedule of the cron in UNIX cron format. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -731,7 +790,7 @@ class CreateDomainRequest: UUID of the function to associate the domain with. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -744,7 +803,7 @@ class CreateFunctionRequest: UUID of the namespace the function will be created in. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -761,7 +820,7 @@ class CreateFunctionRequest: min_scale: Optional[int] """ - Minumum number of instances to scale the function to. + Minimum number of instances to scale the function to. """ max_scale: Optional[int] @@ -808,10 +867,20 @@ class CreateFunctionRequest: - enabled: Serve both HTTP and HTTPS traffic. """ + sandbox: Optional[FunctionSandbox] + """ + Execution environment of the function. + """ + + tags: Optional[List[str]] + """ + Tags of the Serverless Function. + """ + @dataclass class CreateNamespaceRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -838,10 +907,15 @@ class CreateNamespaceRequest: Secret environment variables of the namespace. """ + tags: Optional[List[str]] + """ + Tags of the Serverless Function Namespace. + """ + @dataclass class CreateTokenRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -873,7 +947,7 @@ class CreateTriggerRequest: ID of the function to trigger. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -897,7 +971,7 @@ class DeleteCronRequest: UUID of the cron to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -910,7 +984,7 @@ class DeleteDomainRequest: UUID of the domain to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -923,7 +997,7 @@ class DeleteFunctionRequest: UUID of the function to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -936,7 +1010,7 @@ class DeleteNamespaceRequest: UUID of the namespace. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -949,7 +1023,7 @@ class DeleteTokenRequest: UUID of the token to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -962,7 +1036,7 @@ class DeleteTriggerRequest: ID of the trigger to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -975,7 +1049,7 @@ class DeployFunctionRequest: UUID of the function to deploy. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -995,7 +1069,7 @@ class GetCronRequest: UUID of the cron to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1008,7 +1082,7 @@ class GetDomainRequest: UUID of the domain to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1018,10 +1092,10 @@ class GetDomainRequest: class GetFunctionDownloadURLRequest: function_id: str """ - UUID of the function to get the the download URL for. + UUID of the function to get the download URL for. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1034,7 +1108,7 @@ class GetFunctionRequest: UUID of the function. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1052,7 +1126,7 @@ class GetFunctionUploadURLRequest: Size of the archive to upload in bytes. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1065,7 +1139,7 @@ class GetNamespaceRequest: UUID of the namespace. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1078,7 +1152,7 @@ class GetTokenRequest: UUID of the token to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1091,26 +1165,12 @@ class GetTriggerRequest: ID of the trigger to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ -@dataclass -class IssueJWTRequest: - region: Optional[Region] - """ - Region to target. If none is passed will use default region from the config. - """ - - expires_at: Optional[datetime] - - function_id: Optional[str] - - namespace_id: Optional[str] - - @dataclass class ListCronsRequest: function_id: str @@ -1118,7 +1178,7 @@ class ListCronsRequest: UUID of the function. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1156,10 +1216,10 @@ class ListCronsResponse: class ListDomainsRequest: function_id: str """ - UUID of the function the domain is assoicated with. + UUID of the function the domain is associated with. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1195,7 +1255,7 @@ class ListDomainsResponse: @dataclass class ListFunctionRuntimesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1221,7 +1281,7 @@ class ListFunctionsRequest: UUID of the namespace the function belongs to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1248,7 +1308,7 @@ class ListFunctionsRequest: organization_id: Optional[str] """ - UUID of the Organziation the function belongs to. + UUID of the Organization the function belongs to. """ project_id: Optional[str] @@ -1272,7 +1332,7 @@ class ListFunctionsResponse: @dataclass class ListNamespacesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1320,7 +1380,7 @@ class ListNamespacesResponse: @dataclass class ListTokensRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1342,7 +1402,7 @@ class ListTokensRequest: function_id: Optional[str] """ - UUID of the function the token is assoicated with. + UUID of the function the token is associated with. """ namespace_id: Optional[str] @@ -1360,7 +1420,7 @@ class ListTokensResponse: @dataclass class ListTriggersRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1407,7 +1467,7 @@ class UpdateCronRequest: UUID of the cron to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1440,7 +1500,7 @@ class UpdateFunctionRequest: UUID of the function to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1452,7 +1512,7 @@ class UpdateFunctionRequest: min_scale: Optional[int] """ - Minumum number of instances to scale the function to. + Minimum number of instances to scale the function to. """ max_scale: Optional[int] @@ -1507,6 +1567,16 @@ class UpdateFunctionRequest: - enabled: Serve both HTTP and HTTPS traffic. """ + sandbox: Optional[FunctionSandbox] + """ + Execution environment of the function. + """ + + tags: Optional[List[str]] + """ + Tags of the Serverless Function. + """ + @dataclass class UpdateNamespaceRequest: @@ -1515,7 +1585,7 @@ class UpdateNamespaceRequest: UUID of the namespapce. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1535,6 +1605,11 @@ class UpdateNamespaceRequest: Secret environment variables of the namespace. """ + tags: Optional[List[str]] + """ + Tags of the Serverless Function Namespace. + """ + @dataclass class UpdateTriggerRequest: @@ -1543,7 +1618,7 @@ class UpdateTriggerRequest: ID of the trigger to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/scaleway/iam/v1alpha1/__init__.py b/scaleway/scaleway/iam/v1alpha1/__init__.py index cc30cf04..a2f0c4b1 100644 --- a/scaleway/scaleway/iam/v1alpha1/__init__.py +++ b/scaleway/scaleway/iam/v1alpha1/__init__.py @@ -1,6 +1,7 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. from .types import BearerType +from .types import GracePeriodType from .types import ListAPIKeysRequestOrderBy from .types import ListApplicationsRequestOrderBy from .types import ListGroupsRequestOrderBy @@ -11,15 +12,22 @@ from .types import ListQuotaRequestOrderBy from .types import ListSSHKeysRequestOrderBy from .types import ListUsersRequestOrderBy +from .types import LocalityType from .types import LogAction from .types import LogResourceType from .types import PermissionSetScopeType from .types import UserStatus from .types import UserType -from .types import RuleSpecs +from .types import ConnectionConnectedOrganization +from .types import ConnectionConnectedUser +from .types import QuotumLimit from .types import JWT +from .types import RuleSpecs +from .types import CreateUserRequestMember +from .types import Connection from .types import APIKey from .types import Application +from .types import GracePeriod from .types import Group from .types import Log from .types import PermissionSet @@ -37,6 +45,7 @@ from .types import CreateJWTRequest from .types import CreatePolicyRequest from .types import CreateSSHKeyRequest +from .types import CreateUserMFAOTPRequest from .types import CreateUserRequest from .types import DeleteAPIKeyRequest from .types import DeleteApplicationRequest @@ -44,6 +53,7 @@ from .types import DeleteJWTRequest from .types import DeletePolicyRequest from .types import DeleteSSHKeyRequest +from .types import DeleteUserMFAOTPRequest from .types import DeleteUserRequest from .types import EncodedJWT from .types import GetAPIKeyRequest @@ -51,14 +61,19 @@ from .types import GetGroupRequest from .types import GetJWTRequest from .types import GetLogRequest +from .types import GetOrganizationSecuritySettingsRequest from .types import GetPolicyRequest from .types import GetQuotumRequest from .types import GetSSHKeyRequest +from .types import GetUserConnectionsRequest +from .types import GetUserConnectionsResponse from .types import GetUserRequest from .types import ListAPIKeysRequest from .types import ListAPIKeysResponse from .types import ListApplicationsRequest from .types import ListApplicationsResponse +from .types import ListGracePeriodsRequest +from .types import ListGracePeriodsResponse from .types import ListGroupsRequest from .types import ListGroupsResponse from .types import ListJWTsRequest @@ -77,20 +92,31 @@ from .types import ListSSHKeysResponse from .types import ListUsersRequest from .types import ListUsersResponse +from .types import LockUserRequest +from .types import MFAOTP +from .types import MigrateOrganizationGuestsRequest +from .types import OrganizationSecuritySettings from .types import RemoveGroupMemberRequest from .types import SetGroupMembersRequest from .types import SetRulesRequest from .types import SetRulesResponse +from .types import UnlockUserRequest from .types import UpdateAPIKeyRequest from .types import UpdateApplicationRequest from .types import UpdateGroupRequest +from .types import UpdateOrganizationSecuritySettingsRequest from .types import UpdatePolicyRequest from .types import UpdateSSHKeyRequest +from .types import UpdateUserPasswordRequest from .types import UpdateUserRequest +from .types import UpdateUserUsernameRequest +from .types import ValidateUserMFAOTPRequest +from .types import ValidateUserMFAOTPResponse from .api import IamV1Alpha1API __all__ = [ "BearerType", + "GracePeriodType", "ListAPIKeysRequestOrderBy", "ListApplicationsRequestOrderBy", "ListGroupsRequestOrderBy", @@ -101,15 +127,22 @@ "ListQuotaRequestOrderBy", "ListSSHKeysRequestOrderBy", "ListUsersRequestOrderBy", + "LocalityType", "LogAction", "LogResourceType", "PermissionSetScopeType", "UserStatus", "UserType", - "RuleSpecs", + "ConnectionConnectedOrganization", + "ConnectionConnectedUser", + "QuotumLimit", "JWT", + "RuleSpecs", + "CreateUserRequestMember", + "Connection", "APIKey", "Application", + "GracePeriod", "Group", "Log", "PermissionSet", @@ -127,6 +160,7 @@ "CreateJWTRequest", "CreatePolicyRequest", "CreateSSHKeyRequest", + "CreateUserMFAOTPRequest", "CreateUserRequest", "DeleteAPIKeyRequest", "DeleteApplicationRequest", @@ -134,6 +168,7 @@ "DeleteJWTRequest", "DeletePolicyRequest", "DeleteSSHKeyRequest", + "DeleteUserMFAOTPRequest", "DeleteUserRequest", "EncodedJWT", "GetAPIKeyRequest", @@ -141,14 +176,19 @@ "GetGroupRequest", "GetJWTRequest", "GetLogRequest", + "GetOrganizationSecuritySettingsRequest", "GetPolicyRequest", "GetQuotumRequest", "GetSSHKeyRequest", + "GetUserConnectionsRequest", + "GetUserConnectionsResponse", "GetUserRequest", "ListAPIKeysRequest", "ListAPIKeysResponse", "ListApplicationsRequest", "ListApplicationsResponse", + "ListGracePeriodsRequest", + "ListGracePeriodsResponse", "ListGroupsRequest", "ListGroupsResponse", "ListJWTsRequest", @@ -167,15 +207,25 @@ "ListSSHKeysResponse", "ListUsersRequest", "ListUsersResponse", + "LockUserRequest", + "MFAOTP", + "MigrateOrganizationGuestsRequest", + "OrganizationSecuritySettings", "RemoveGroupMemberRequest", "SetGroupMembersRequest", "SetRulesRequest", "SetRulesResponse", + "UnlockUserRequest", "UpdateAPIKeyRequest", "UpdateApplicationRequest", "UpdateGroupRequest", + "UpdateOrganizationSecuritySettingsRequest", "UpdatePolicyRequest", "UpdateSSHKeyRequest", + "UpdateUserPasswordRequest", "UpdateUserRequest", + "UpdateUserUsernameRequest", + "ValidateUserMFAOTPRequest", + "ValidateUserMFAOTPResponse", "IamV1Alpha1API", ] diff --git a/scaleway/scaleway/iam/v1alpha1/api.py b/scaleway/scaleway/iam/v1alpha1/api.py index b67f7a3f..8a88b1dd 100644 --- a/scaleway/scaleway/iam/v1alpha1/api.py +++ b/scaleway/scaleway/iam/v1alpha1/api.py @@ -26,6 +26,7 @@ ListUsersRequestOrderBy, LogAction, LogResourceType, + UserType, APIKey, AddGroupMemberRequest, AddGroupMembersRequest, @@ -37,11 +38,14 @@ CreatePolicyRequest, CreateSSHKeyRequest, CreateUserRequest, + CreateUserRequestMember, EncodedJWT, + GetUserConnectionsResponse, Group, JWT, ListAPIKeysResponse, ListApplicationsResponse, + ListGracePeriodsResponse, ListGroupsResponse, ListJWTsResponse, ListLogsResponse, @@ -52,6 +56,8 @@ ListSSHKeysResponse, ListUsersResponse, Log, + MFAOTP, + OrganizationSecuritySettings, PermissionSet, Policy, Quotum, @@ -65,10 +71,15 @@ UpdateAPIKeyRequest, UpdateApplicationRequest, UpdateGroupRequest, + UpdateOrganizationSecuritySettingsRequest, UpdatePolicyRequest, UpdateSSHKeyRequest, + UpdateUserPasswordRequest, UpdateUserRequest, + UpdateUserUsernameRequest, User, + ValidateUserMFAOTPRequest, + ValidateUserMFAOTPResponse, ) from .marshalling import ( unmarshal_JWT, @@ -81,8 +92,10 @@ unmarshal_SSHKey, unmarshal_User, unmarshal_EncodedJWT, + unmarshal_GetUserConnectionsResponse, unmarshal_ListAPIKeysResponse, unmarshal_ListApplicationsResponse, + unmarshal_ListGracePeriodsResponse, unmarshal_ListGroupsResponse, unmarshal_ListJWTsResponse, unmarshal_ListLogsResponse, @@ -92,7 +105,10 @@ unmarshal_ListRulesResponse, unmarshal_ListSSHKeysResponse, unmarshal_ListUsersResponse, + unmarshal_MFAOTP, + unmarshal_OrganizationSecuritySettings, unmarshal_SetRulesResponse, + unmarshal_ValidateUserMFAOTPResponse, marshal_AddGroupMemberRequest, marshal_AddGroupMembersRequest, marshal_CreateAPIKeyRequest, @@ -108,15 +124,19 @@ marshal_UpdateAPIKeyRequest, marshal_UpdateApplicationRequest, marshal_UpdateGroupRequest, + marshal_UpdateOrganizationSecuritySettingsRequest, marshal_UpdatePolicyRequest, marshal_UpdateSSHKeyRequest, + marshal_UpdateUserPasswordRequest, marshal_UpdateUserRequest, + marshal_UpdateUserUsernameRequest, + marshal_ValidateUserMFAOTPRequest, ) class IamV1Alpha1API(API): """ - IAM API. + This API allows you to manage Identity and Access Management (IAM) across your Scaleway Organizations, Projects and resources. """ def list_ssh_keys( @@ -356,6 +376,7 @@ def list_users( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, + type_: Optional[UserType] = None, ) -> ListUsersResponse: """ List users of an Organization. @@ -367,6 +388,7 @@ def list_users( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. + :param type_: Filter by user type. :return: :class:`ListUsersResponse ` Usage: @@ -386,6 +408,7 @@ def list_users( "page": page, "page_size": page_size or self.client.default_page_size, "tag": tag, + "type": type_, "user_ids": user_ids, }, ) @@ -403,6 +426,7 @@ def list_users_all( user_ids: Optional[List[str]] = None, mfa: Optional[bool] = None, tag: Optional[str] = None, + type_: Optional[UserType] = None, ) -> List[User]: """ List users of an Organization. @@ -414,6 +438,7 @@ def list_users_all( :param user_ids: Filter by list of IDs. :param mfa: Filter by MFA status. :param tag: Filter by tags containing a given string. + :param type_: Filter by user type. :return: :class:`List[User] ` Usage: @@ -434,6 +459,7 @@ def list_users_all( "user_ids": user_ids, "mfa": mfa, "tag": tag, + "type_": type_, }, ) @@ -471,12 +497,22 @@ def update_user( *, user_id: str, tags: Optional[List[str]] = None, + email: Optional[str] = None, + first_name: Optional[str] = None, + last_name: Optional[str] = None, + phone_number: Optional[str] = None, + locale: Optional[str] = None, ) -> User: """ Update a user. Update the parameters of a user, including `tags`. :param user_id: ID of the user to update. :param tags: New tags for the user (maximum of 10 tags). + :param email: IAM member email. + :param first_name: IAM member first name. + :param last_name: IAM member last name. + :param phone_number: IAM member phone number. + :param locale: IAM member locale. :return: :class:`User ` Usage: @@ -496,6 +532,11 @@ def update_user( UpdateUserRequest( user_id=user_id, tags=tags, + email=email, + first_name=first_name, + last_name=last_name, + phone_number=phone_number, + locale=locale, ), self.client, ), @@ -534,24 +575,26 @@ def delete_user( def create_user( self, *, - email: str, organization_id: Optional[str] = None, + email: Optional[str] = None, tags: Optional[List[str]] = None, + member: Optional[CreateUserRequestMember] = None, ) -> User: """ Create a new user. - Create a new user. You must define the `organization_id` and the `email` in your request. - :param email: Email of the user. + Create a new user. You must define the `organization_id` in your request. If you are adding a member, enter the member's details. If you are adding a guest, you must define the `email` and not add the member attribute. :param organization_id: ID of the Organization. + :param email: Email of the user. + One-Of ('type'): at most one of 'email', 'member' could be set. :param tags: Tags associated with the user. + :param member: Details of IAM member. + One-Of ('type'): at most one of 'email', 'member' could be set. :return: :class:`User ` Usage: :: - result = api.create_user( - email="example", - ) + result = api.create_user() """ res = self._request( @@ -559,9 +602,86 @@ def create_user( "/iam/v1alpha1/users", body=marshal_CreateUserRequest( CreateUserRequest( - email=email, organization_id=organization_id, tags=tags, + email=email, + member=member, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + def update_user_username( + self, + *, + user_id: str, + username: str, + ) -> User: + """ + Update an user's username. + :param user_id: ID of the user to update. + :param username: The new username. + :return: :class:`User ` + + Usage: + :: + + result = api.update_user_username( + user_id="example", + username="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/update-username", + body=marshal_UpdateUserUsernameRequest( + UpdateUserUsernameRequest( + user_id=user_id, + username=username, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + def update_user_password( + self, + *, + user_id: str, + password: str, + ) -> User: + """ + Update an user's password. + :param user_id: ID of the user to update. + :param password: The new password. + :return: :class:`User ` + + Usage: + :: + + result = api.update_user_password( + user_id="example", + password="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/update-password", + body=marshal_UpdateUserPasswordRequest( + UpdateUserPasswordRequest( + user_id=user_id, + password=password, ), self.client, ), @@ -570,6 +690,214 @@ def create_user( self._throw_on_error(res) return unmarshal_User(res.json()) + def create_user_mfaotp( + self, + *, + user_id: str, + ) -> MFAOTP: + """ + Create a MFA OTP. + :param user_id: User ID of the MFA OTP. + :return: :class:`MFAOTP ` + + Usage: + :: + + result = api.create_user_mfaotp( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/mfa-otp", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_MFAOTP(res.json()) + + def validate_user_mfaotp( + self, + *, + user_id: str, + one_time_password: str, + ) -> ValidateUserMFAOTPResponse: + """ + Validate a MFA OTP. + :param user_id: User ID of the MFA OTP. + :param one_time_password: A password generated using the OTP. + :return: :class:`ValidateUserMFAOTPResponse ` + + Usage: + :: + + result = api.validate_user_mfaotp( + user_id="example", + one_time_password="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/validate-mfa-otp", + body=marshal_ValidateUserMFAOTPRequest( + ValidateUserMFAOTPRequest( + user_id=user_id, + one_time_password=one_time_password, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ValidateUserMFAOTPResponse(res.json()) + + def delete_user_mfaotp( + self, + *, + user_id: str, + ) -> None: + """ + Delete a MFA OTP. + :param user_id: User ID of the MFA OTP. + + Usage: + :: + + result = api.delete_user_mfaotp( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "DELETE", + f"/iam/v1alpha1/users/{param_user_id}/mfa-otp", + body={}, + ) + + self._throw_on_error(res) + + def lock_user( + self, + *, + user_id: str, + ) -> User: + """ + Lock a member. + Lock a member. A locked member cannot log in or use API keys until the locked status is removed. + :param user_id: ID of the user to lock. + :return: :class:`User ` + + Usage: + :: + + result = api.lock_user( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/lock", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + def unlock_user( + self, + *, + user_id: str, + ) -> User: + """ + Unlock a member. + :param user_id: ID of the user to unlock. + :return: :class:`User ` + + Usage: + :: + + result = api.unlock_user( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "POST", + f"/iam/v1alpha1/users/{param_user_id}/unlock", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + def list_grace_periods( + self, + *, + user_id: Optional[str] = None, + ) -> ListGracePeriodsResponse: + """ + List grace periods of a member. + List the grace periods of a member. + :param user_id: ID of the user to list grace periods for. + :return: :class:`ListGracePeriodsResponse ` + + Usage: + :: + + result = api.list_grace_periods() + """ + + res = self._request( + "GET", + "/iam/v1alpha1/grace-periods", + params={ + "user_id": user_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListGracePeriodsResponse(res.json()) + + def get_user_connections( + self, + *, + user_id: str, + ) -> GetUserConnectionsResponse: + """ + :param user_id: ID of the user to list connections for. + :return: :class:`GetUserConnectionsResponse ` + + Usage: + :: + + result = api.get_user_connections( + user_id="example", + ) + """ + + param_user_id = validate_path_param("user_id", user_id) + + res = self._request( + "GET", + f"/iam/v1alpha1/users/{param_user_id}/connections", + ) + + self._throw_on_error(res) + return unmarshal_GetUserConnectionsResponse(res.json()) + def list_applications( self, *, @@ -961,7 +1289,7 @@ def get_group( ) -> Group: """ Get a group. - Retrive information about a given group, specified by the `group_id` parameter. The group's full details, including `user_ids` and `application_ids` are returned in the response. + Retrieve information about a given group, specified by the `group_id` parameter. The group's full details, including `user_ids` and `application_ids` are returned in the response. :param group_id: ID of the group. :return: :class:`Group ` @@ -1079,7 +1407,7 @@ def add_group_member( ) -> Group: """ Add a user or an application to a group. - Add a user or an application to a group. You can specify a `user_id` and and `application_id` in the body of your request. Note that you can only add one of each per request. + Add a user or an application to a group. You can specify a `user_id` and `application_id` in the body of your request. Note that you can only add one of each per request. :param group_id: ID of the group. :param user_id: ID of the user to add. One-Of ('member'): at most one of 'user_id', 'application_id' could be set. @@ -1163,7 +1491,7 @@ def remove_group_member( ) -> Group: """ Remove a user or an application from a group. - Remove a user or an application from a group. You can specify a `user_id` and and `application_id` in the body of your request. Note that you can only remove one of each per request. Removing a user from a group means that any permissions given to them via the group (i.e. from an attached policy) will no longer apply. Be sure you want to remove these permissions from the user before proceeding. + Remove a user or an application from a group. You can specify a `user_id` and `application_id` in the body of your request. Note that you can only remove one of each per request. Removing a user from a group means that any permissions given to them via the group (i.e. from an attached policy) will no longer apply. Be sure you want to remove these permissions from the user before proceeding. :param group_id: ID of the group. :param user_id: ID of the user to remove. One-Of ('member'): at most one of 'user_id', 'application_id' could be set. @@ -1878,7 +2206,7 @@ def create_api_key( ) -> APIKey: """ Create an API key. - Create an API key. You must specify the `application_id` or the `user_id` and the description. You can also specify the `default_project_id` which is the Project ID of your preferred Project, to use with Object Storage. The `access_key` and `secret_key` values are returned in the response. Note that he secret key is only showed once. Make sure that you copy and store both keys somewhere safe. + Create an API key. You must specify the `application_id` or the `user_id` and the description. You can also specify the `default_project_id`, which is the Project ID of your preferred Project, to use with Object Storage. The `access_key` and `secret_key` values are returned in the response. Note that the secret key is only shown once. Make sure that you copy and store both keys somewhere safe. :param description: Description of the API key (max length is 200 characters). :param application_id: ID of the application. One-Of ('bearer'): at most one of 'application_id', 'user_id' could be set. @@ -1921,7 +2249,7 @@ def get_api_key( ) -> APIKey: """ Get an API key. - Retrive information about an API key, specified by the `access_key` parameter. The API key's details, including either the `user_id` or `application_id` of its bearer are returned in the response. Note that the string value for the `secret_key` is nullable, and therefore is not displayed in the response. The `secret_key` value is only displayed upon API key creation. + Retrieve information about an API key, specified by the `access_key` parameter. The API key's details, including either the `user_id` or `application_id` of its bearer are returned in the response. Note that the string value for the `secret_key` is nullable, and therefore is not displayed in the response. The `secret_key` value is only displayed upon API key creation. :param access_key: Access key to search for. :return: :class:`APIKey ` @@ -2018,6 +2346,7 @@ def list_quota( page_size: Optional[int] = None, page: Optional[int] = None, organization_id: Optional[str] = None, + quotum_names: Optional[List[str]] = None, ) -> ListQuotaResponse: """ List all quotas in the Organization. @@ -2026,6 +2355,7 @@ def list_quota( :param page_size: Number of results per page. Value must be between 1 and 100. :param page: Page number. Value must be greater than 1. :param organization_id: Filter by Organization ID. + :param quotum_names: List of quotum names to filter from. :return: :class:`ListQuotaResponse ` Usage: @@ -2043,6 +2373,7 @@ def list_quota( or self.client.default_organization_id, "page": page, "page_size": page_size or self.client.default_page_size, + "quotum_names": quotum_names, }, ) @@ -2056,6 +2387,7 @@ def list_quota_all( page_size: Optional[int] = None, page: Optional[int] = None, organization_id: Optional[str] = None, + quotum_names: Optional[List[str]] = None, ) -> List[Quotum]: """ List all quotas in the Organization. @@ -2064,6 +2396,7 @@ def list_quota_all( :param page_size: Number of results per page. Value must be between 1 and 100. :param page: Page number. Value must be greater than 1. :param organization_id: Filter by Organization ID. + :param quotum_names: List of quotum names to filter from. :return: :class:`List[Quotum] ` Usage: @@ -2081,6 +2414,7 @@ def list_quota_all( "page_size": page_size, "page": page, "organization_id": organization_id, + "quotum_names": quotum_names, }, ) @@ -2122,16 +2456,16 @@ def get_quotum( def list_jw_ts( self, *, + audience_id: str, order_by: Optional[ListJWTsRequestOrderBy] = None, - audience_id: Optional[str] = None, page_size: Optional[int] = None, page: Optional[int] = None, expired: Optional[bool] = None, ) -> ListJWTsResponse: """ List JWTs. - :param order_by: Criteria for sorting results. :param audience_id: ID of the user to search. + :param order_by: Criteria for sorting results. :param page_size: Number of results per page. Value must be between 1 and 100. :param page: Page number. Value must be greater to 1. :param expired: Filter out expired JWTs or not. @@ -2140,7 +2474,9 @@ def list_jw_ts( Usage: :: - result = api.list_jw_ts() + result = api.list_jw_ts( + audience_id="example", + ) """ res = self._request( @@ -2161,16 +2497,16 @@ def list_jw_ts( def list_jw_ts_all( self, *, + audience_id: str, order_by: Optional[ListJWTsRequestOrderBy] = None, - audience_id: Optional[str] = None, page_size: Optional[int] = None, page: Optional[int] = None, expired: Optional[bool] = None, ) -> List[JWT]: """ List JWTs. - :param order_by: Criteria for sorting results. :param audience_id: ID of the user to search. + :param order_by: Criteria for sorting results. :param page_size: Number of results per page. Value must be between 1 and 100. :param page: Page number. Value must be greater to 1. :param expired: Filter out expired JWTs or not. @@ -2179,7 +2515,9 @@ def list_jw_ts_all( Usage: :: - result = api.list_jw_ts_all() + result = api.list_jw_ts_all( + audience_id="example", + ) """ return fetch_all_pages( @@ -2187,8 +2525,8 @@ def list_jw_ts_all( key="jwts", fetcher=self.list_jw_ts, args={ - "order_by": order_by, "audience_id": audience_id, + "order_by": order_by, "page_size": page_size, "page": page, "expired": expired, @@ -2416,3 +2754,101 @@ def get_log( self._throw_on_error(res) return unmarshal_Log(res.json()) + + def get_organization_security_settings( + self, + *, + organization_id: Optional[str] = None, + ) -> OrganizationSecuritySettings: + """ + Get security settings of an Organization. + Retrieve information about the security settings of an Organization, specified by the `organization_id` parameter. + :param organization_id: ID of the Organization. + :return: :class:`OrganizationSecuritySettings ` + + Usage: + :: + + result = api.get_organization_security_settings() + """ + + param_organization_id = validate_path_param( + "organization_id", organization_id or self.client.default_organization_id + ) + + res = self._request( + "GET", + f"/iam/v1alpha1/organizations/{param_organization_id}/security-settings", + ) + + self._throw_on_error(res) + return unmarshal_OrganizationSecuritySettings(res.json()) + + def update_organization_security_settings( + self, + *, + organization_id: Optional[str] = None, + enforce_password_renewal: Optional[bool] = None, + grace_period_duration: Optional[str] = None, + login_attempts_before_locked: Optional[int] = None, + ) -> OrganizationSecuritySettings: + """ + Update the security settings of an Organization. + :param organization_id: ID of the Organization. + :param enforce_password_renewal: Defines whether password renewal is enforced during first login. + :param grace_period_duration: Duration of the grace period to renew password or enable MFA. + :param login_attempts_before_locked: Number of login attempts before the account is locked. + :return: :class:`OrganizationSecuritySettings ` + + Usage: + :: + + result = api.update_organization_security_settings() + """ + + param_organization_id = validate_path_param( + "organization_id", organization_id or self.client.default_organization_id + ) + + res = self._request( + "PATCH", + f"/iam/v1alpha1/organizations/{param_organization_id}/security-settings", + body=marshal_UpdateOrganizationSecuritySettingsRequest( + UpdateOrganizationSecuritySettingsRequest( + organization_id=organization_id, + enforce_password_renewal=enforce_password_renewal, + grace_period_duration=grace_period_duration, + login_attempts_before_locked=login_attempts_before_locked, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_OrganizationSecuritySettings(res.json()) + + def migrate_organization_guests( + self, + *, + organization_id: Optional[str] = None, + ) -> None: + """ + Migrate the organization's guests to IAM members. + :param organization_id: ID of the Organization. + + Usage: + :: + + result = api.migrate_organization_guests() + """ + + param_organization_id = validate_path_param( + "organization_id", organization_id or self.client.default_organization_id + ) + + res = self._request( + "POST", + f"/iam/v1alpha1/organizations/{param_organization_id}/migrate-guests", + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/iam/v1alpha1/marshalling.py b/scaleway/scaleway/iam/v1alpha1/marshalling.py index 83f6650e..3bdb9e46 100644 --- a/scaleway/scaleway/iam/v1alpha1/marshalling.py +++ b/scaleway/scaleway/iam/v1alpha1/marshalling.py @@ -16,12 +16,19 @@ Group, Log, Policy, + QuotumLimit, Quotum, SSHKey, User, EncodedJWT, + ConnectionConnectedOrganization, + ConnectionConnectedUser, + Connection, + GetUserConnectionsResponse, ListAPIKeysResponse, ListApplicationsResponse, + GracePeriod, + ListGracePeriodsResponse, ListGroupsResponse, ListJWTsResponse, ListLogsResponse, @@ -33,7 +40,10 @@ ListRulesResponse, ListSSHKeysResponse, ListUsersResponse, + MFAOTP, + OrganizationSecuritySettings, SetRulesResponse, + ValidateUserMFAOTPResponse, AddGroupMemberRequest, AddGroupMembersRequest, CreateAPIKeyRequest, @@ -43,6 +53,7 @@ RuleSpecs, CreatePolicyRequest, CreateSSHKeyRequest, + CreateUserRequestMember, CreateUserRequest, RemoveGroupMemberRequest, SetGroupMembersRequest, @@ -50,9 +61,13 @@ UpdateAPIKeyRequest, UpdateApplicationRequest, UpdateGroupRequest, + UpdateOrganizationSecuritySettingsRequest, UpdatePolicyRequest, UpdateSSHKeyRequest, + UpdateUserPasswordRequest, UpdateUserRequest, + UpdateUserUsernameRequest, + ValidateUserMFAOTPRequest, ) @@ -87,14 +102,20 @@ def unmarshal_JWT(data: Any) -> JWT: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None return JWT(**args) @@ -119,37 +140,57 @@ def unmarshal_APIKey(data: Any) -> APIKey: if field is not None: args["default_project_id"] = field + field = data.get("secret_key", None) + if field is not None: + args["secret_key"] = field + else: + args["secret_key"] = None + + field = data.get("application_id", None) + if field is not None: + args["application_id"] = field + else: + args["application_id"] = None + field = data.get("editable", None) if field is not None: args["editable"] = field - field = data.get("creation_ip", None) + field = data.get("deletable", None) if field is not None: - args["creation_ip"] = field + args["deletable"] = field - field = data.get("secret_key", None) + field = data.get("managed", None) if field is not None: - args["secret_key"] = field + args["managed"] = field - field = data.get("application_id", None) + field = data.get("creation_ip", None) if field is not None: - args["application_id"] = field + args["creation_ip"] = field field = data.get("user_id", None) if field is not None: args["user_id"] = field + else: + args["user_id"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None return APIKey(**args) @@ -182,6 +223,14 @@ def unmarshal_Application(data: Any) -> Application: if field is not None: args["editable"] = field + field = data.get("deletable", None) + if field is not None: + args["deletable"] = field + + field = data.get("managed", None) + if field is not None: + args["managed"] = field + field = data.get("nb_api_keys", None) if field is not None: args["nb_api_keys"] = field @@ -193,10 +242,14 @@ def unmarshal_Application(data: Any) -> Application: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Application(**args) @@ -237,13 +290,29 @@ def unmarshal_Group(data: Any) -> Group: if field is not None: args["tags"] = field + field = data.get("editable", None) + if field is not None: + args["editable"] = field + + field = data.get("deletable", None) + if field is not None: + args["deletable"] = field + + field = data.get("managed", None) + if field is not None: + args["managed"] = field + field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Group(**args) @@ -291,6 +360,8 @@ def unmarshal_Log(data: Any) -> Log: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return Log(**args) @@ -319,17 +390,17 @@ def unmarshal_Policy(data: Any) -> Policy: if field is not None: args["organization_id"] = field - field = data.get("created_at", None) + field = data.get("editable", None) if field is not None: - args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + args["editable"] = field - field = data.get("updated_at", None) + field = data.get("deletable", None) if field is not None: - args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + args["deletable"] = field - field = data.get("editable", None) + field = data.get("managed", None) if field is not None: - args["editable"] = field + args["managed"] = field field = data.get("nb_rules", None) if field is not None: @@ -343,6 +414,18 @@ def unmarshal_Policy(data: Any) -> Policy: if field is not None: args["nb_permission_sets"] = field + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + field = data.get("tags", None) if field is not None: args["tags"] = field @@ -350,22 +433,71 @@ def unmarshal_Policy(data: Any) -> Policy: field = data.get("user_id", None) if field is not None: args["user_id"] = field + else: + args["user_id"] = None field = data.get("group_id", None) if field is not None: args["group_id"] = field + else: + args["group_id"] = None field = data.get("application_id", None) if field is not None: args["application_id"] = field + else: + args["application_id"] = None field = data.get("no_principal", None) if field is not None: args["no_principal"] = field + else: + args["no_principal"] = None return Policy(**args) +def unmarshal_QuotumLimit(data: Any) -> QuotumLimit: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'QuotumLimit' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("global", None) + if field is not None: + args["global_"] = field + else: + args["global_"] = None + + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("limit", None) + if field is not None: + args["limit"] = field + else: + args["limit"] = None + + field = data.get("unlimited", None) + if field is not None: + args["unlimited"] = field + else: + args["unlimited"] = None + + return QuotumLimit(**args) + + def unmarshal_Quotum(data: Any) -> Quotum: if not isinstance(data, dict): raise TypeError( @@ -378,13 +510,39 @@ def unmarshal_Quotum(data: Any) -> Quotum: if field is not None: args["name"] = field + field = data.get("pretty_name", None) + if field is not None: + args["pretty_name"] = field + + field = data.get("unit", None) + if field is not None: + args["unit"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("locality_type", None) + if field is not None: + args["locality_type"] = field + + field = data.get("limits", None) + if field is not None: + args["limits"] = ( + [unmarshal_QuotumLimit(v) for v in field] if field is not None else None + ) + field = data.get("limit", None) if field is not None: args["limit"] = field + else: + args["limit"] = None field = data.get("unlimited", None) if field is not None: args["unlimited"] = field + else: + args["unlimited"] = None return Quotum(**args) @@ -428,10 +586,14 @@ def unmarshal_SSHKey(data: Any) -> SSHKey: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return SSHKey(**args) @@ -452,6 +614,26 @@ def unmarshal_User(data: Any) -> User: if field is not None: args["email"] = field + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("first_name", None) + if field is not None: + args["first_name"] = field + + field = data.get("last_name", None) + if field is not None: + args["last_name"] = field + + field = data.get("phone_number", None) + if field is not None: + args["phone_number"] = field + + field = data.get("locale", None) + if field is not None: + args["locale"] = field + field = data.get("organization_id", None) if field is not None: args["organization_id"] = field @@ -460,7 +642,27 @@ def unmarshal_User(data: Any) -> User: if field is not None: args["deletable"] = field - field = data.get("type_", None) + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("last_login_at", None) + if field is not None: + args["last_login_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["last_login_at"] = None + + field = data.get("type", None) if field is not None: args["type_"] = field @@ -468,10 +670,6 @@ def unmarshal_User(data: Any) -> User: if field is not None: args["status"] = field - field = data.get("created_at", None) - if field is not None: - args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field - field = data.get("mfa", None) if field is not None: args["mfa"] = field @@ -484,19 +682,15 @@ def unmarshal_User(data: Any) -> User: if field is not None: args["tags"] = field - field = data.get("updated_at", None) - if field is not None: - args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field - - field = data.get("last_login_at", None) + field = data.get("locked", None) if field is not None: - args["last_login_at"] = ( - parser.isoparse(field) if isinstance(field, str) else field - ) + args["locked"] = field field = data.get("two_factor_enabled", None) if field is not None: args["two_factor_enabled"] = field + else: + args["two_factor_enabled"] = None return User(**args) @@ -520,10 +714,100 @@ def unmarshal_EncodedJWT(data: Any) -> EncodedJWT: field = data.get("jwt", None) if field is not None: args["jwt"] = unmarshal_JWT(field) + else: + args["jwt"] = None return EncodedJWT(**args) +def unmarshal_ConnectionConnectedOrganization( + data: Any, +) -> ConnectionConnectedOrganization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ConnectionConnectedOrganization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("locked", None) + if field is not None: + args["locked"] = field + + return ConnectionConnectedOrganization(**args) + + +def unmarshal_ConnectionConnectedUser(data: Any) -> ConnectionConnectedUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ConnectionConnectedUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return ConnectionConnectedUser(**args) + + +def unmarshal_Connection(data: Any) -> Connection: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Connection' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("organization", None) + if field is not None: + args["organization"] = unmarshal_ConnectionConnectedOrganization(field) + else: + args["organization"] = None + + field = data.get("user", None) + if field is not None: + args["user"] = unmarshal_ConnectionConnectedUser(field) + else: + args["user"] = None + + return Connection(**args) + + +def unmarshal_GetUserConnectionsResponse(data: Any) -> GetUserConnectionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetUserConnectionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("connections", None) + if field is not None: + args["connections"] = ( + [unmarshal_Connection(v) for v in field] if field is not None else None + ) + + return GetUserConnectionsResponse(**args) + + def unmarshal_ListAPIKeysResponse(data: Any) -> ListAPIKeysResponse: if not isinstance(data, dict): raise TypeError( @@ -566,6 +850,50 @@ def unmarshal_ListApplicationsResponse(data: Any) -> ListApplicationsResponse: return ListApplicationsResponse(**args) +def unmarshal_GracePeriod(data: Any) -> GracePeriod: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GracePeriod' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + return GracePeriod(**args) + + +def unmarshal_ListGracePeriodsResponse(data: Any) -> ListGracePeriodsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGracePeriodsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("grace_periods", None) + if field is not None: + args["grace_periods"] = ( + [unmarshal_GracePeriod(v) for v in field] if field is not None else None + ) + + return ListGracePeriodsResponse(**args) + + def unmarshal_ListGroupsResponse(data: Any) -> ListGroupsResponse: if not isinstance(data, dict): raise TypeError( @@ -652,6 +980,8 @@ def unmarshal_PermissionSet(data: Any) -> PermissionSet: field = data.get("categories", None) if field is not None: args["categories"] = field + else: + args["categories"] = None return PermissionSet(**args) @@ -735,21 +1065,33 @@ def unmarshal_Rule(data: Any) -> Rule: if field is not None: args["permission_sets_scope_type"] = field + field = data.get("condition", None) + if field is not None: + args["condition"] = field + field = data.get("permission_set_names", None) if field is not None: args["permission_set_names"] = field + else: + args["permission_set_names"] = None field = data.get("project_ids", None) if field is not None: args["project_ids"] = field + else: + args["project_ids"] = None field = data.get("organization_id", None) if field is not None: args["organization_id"] = field + else: + args["organization_id"] = None field = data.get("account_root_user_id", None) if field is not None: args["account_root_user_id"] = field + else: + args["account_root_user_id"] = None return Rule(**args) @@ -817,6 +1159,46 @@ def unmarshal_ListUsersResponse(data: Any) -> ListUsersResponse: return ListUsersResponse(**args) +def unmarshal_MFAOTP(data: Any) -> MFAOTP: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'MFAOTP' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secret", None) + if field is not None: + args["secret"] = field + + return MFAOTP(**args) + + +def unmarshal_OrganizationSecuritySettings(data: Any) -> OrganizationSecuritySettings: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OrganizationSecuritySettings' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enforce_password_renewal", None) + if field is not None: + args["enforce_password_renewal"] = field + + field = data.get("login_attempts_before_locked", None) + if field is not None: + args["login_attempts_before_locked"] = field + + field = data.get("grace_period_duration", None) + if field is not None: + args["grace_period_duration"] = field + else: + args["grace_period_duration"] = None + + return OrganizationSecuritySettings(**args) + + def unmarshal_SetRulesResponse(data: Any) -> SetRulesResponse: if not isinstance(data, dict): raise TypeError( @@ -834,6 +1216,21 @@ def unmarshal_SetRulesResponse(data: Any) -> SetRulesResponse: return SetRulesResponse(**args) +def unmarshal_ValidateUserMFAOTPResponse(data: Any) -> ValidateUserMFAOTPResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ValidateUserMFAOTPResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("recovery_codes", None) + if field is not None: + args["recovery_codes"] = field + + return ValidateUserMFAOTPResponse(**args) + + def marshal_AddGroupMemberRequest( request: AddGroupMemberRequest, defaults: ProfileDefaults, @@ -884,7 +1281,7 @@ def marshal_CreateAPIKeyRequest( output["description"] = request.description if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() if request.default_project_id is not None: output["default_project_id"] = request.default_project_id @@ -971,6 +1368,9 @@ def marshal_RuleSpecs( ), ) + if request.condition is not None: + output["condition"] = request.condition + if request.permission_set_names is not None: output["permission_set_names"] = request.permission_set_names @@ -1031,8 +1431,8 @@ def marshal_CreateSSHKeyRequest( return output -def marshal_CreateUserRequest( - request: CreateUserRequest, +def marshal_CreateUserRequestMember( + request: CreateUserRequestMember, defaults: ProfileDefaults, ) -> Dict[str, Any]: output: Dict[str, Any] = {} @@ -1040,6 +1440,47 @@ def marshal_CreateUserRequest( if request.email is not None: output["email"] = request.email + if request.send_password_email is not None: + output["send_password_email"] = request.send_password_email + + if request.send_welcome_email is not None: + output["send_welcome_email"] = request.send_welcome_email + + if request.username is not None: + output["username"] = request.username + + if request.password is not None: + output["password"] = request.password + + if request.first_name is not None: + output["first_name"] = request.first_name + + if request.last_name is not None: + output["last_name"] = request.last_name + + if request.phone_number is not None: + output["phone_number"] = request.phone_number + + if request.locale is not None: + output["locale"] = request.locale + + return output + + +def marshal_CreateUserRequest( + request: CreateUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("email", request.email), + OneOfPossibility("member", request.member), + ] + ), + ) + if request.organization_id is not None: output["organization_id"] = ( request.organization_id or defaults.default_organization_id @@ -1149,6 +1590,24 @@ def marshal_UpdateGroupRequest( return output +def marshal_UpdateOrganizationSecuritySettingsRequest( + request: UpdateOrganizationSecuritySettingsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.enforce_password_renewal is not None: + output["enforce_password_renewal"] = request.enforce_password_renewal + + if request.grace_period_duration is not None: + output["grace_period_duration"] = request.grace_period_duration + + if request.login_attempts_before_locked is not None: + output["login_attempts_before_locked"] = request.login_attempts_before_locked + + return output + + def marshal_UpdatePolicyRequest( request: UpdatePolicyRequest, defaults: ProfileDefaults, @@ -1192,6 +1651,18 @@ def marshal_UpdateSSHKeyRequest( return output +def marshal_UpdateUserPasswordRequest( + request: UpdateUserPasswordRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + return output + + def marshal_UpdateUserRequest( request: UpdateUserRequest, defaults: ProfileDefaults, @@ -1201,4 +1672,43 @@ def marshal_UpdateUserRequest( if request.tags is not None: output["tags"] = request.tags + if request.email is not None: + output["email"] = request.email + + if request.first_name is not None: + output["first_name"] = request.first_name + + if request.last_name is not None: + output["last_name"] = request.last_name + + if request.phone_number is not None: + output["phone_number"] = request.phone_number + + if request.locale is not None: + output["locale"] = request.locale + + return output + + +def marshal_UpdateUserUsernameRequest( + request: UpdateUserUsernameRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + return output + + +def marshal_ValidateUserMFAOTPRequest( + request: ValidateUserMFAOTPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.one_time_password is not None: + output["one_time_password"] = request.one_time_password + return output diff --git a/scaleway/scaleway/iam/v1alpha1/types.py b/scaleway/scaleway/iam/v1alpha1/types.py index 000c6d97..a3cd107d 100644 --- a/scaleway/scaleway/iam/v1alpha1/types.py +++ b/scaleway/scaleway/iam/v1alpha1/types.py @@ -7,6 +7,10 @@ from enum import Enum from typing import List, Optional +from scaleway_core.bridge import ( + Region as ScwRegion, + Zone as ScwZone, +) from scaleway_core.utils import ( StrEnumMeta, ) @@ -21,6 +25,15 @@ def __str__(self) -> str: return str(self.value) +class GracePeriodType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_GRACE_PERIOD_TYPE = "unknown_grace_period_type" + UPDATE_PASSWORD = "update_password" + SET_MFA = "set_mfa" + + def __str__(self) -> str: + return str(self.value) + + class ListAPIKeysRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -126,6 +139,17 @@ class ListUsersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): EMAIL_DESC = "email_desc" LAST_LOGIN_ASC = "last_login_asc" LAST_LOGIN_DESC = "last_login_desc" + USERNAME_ASC = "username_asc" + USERNAME_DESC = "username_desc" + + def __str__(self) -> str: + return str(self.value) + + +class LocalityType(str, Enum, metaclass=StrEnumMeta): + GLOBAL = "global" + REGION = "region" + ZONE = "zone" def __str__(self) -> str: return str(self.value) @@ -176,21 +200,41 @@ class UserType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_TYPE = "unknown_type" GUEST = "guest" OWNER = "owner" + MEMBER = "member" def __str__(self) -> str: return str(self.value) @dataclass -class RuleSpecs: - permission_set_names: Optional[List[str]] - """ - Names of permission sets bound to the rule. - """ +class ConnectionConnectedOrganization: + id: str - project_ids: Optional[List[str]] + name: str - organization_id: Optional[str] + locked: bool + + +@dataclass +class ConnectionConnectedUser: + id: str + + username: str + + type_: UserType + + +@dataclass +class QuotumLimit: + global_: Optional[bool] + + region: Optional[ScwRegion] + + zone: Optional[ScwZone] + + limit: Optional[int] + + unlimited: Optional[bool] @dataclass @@ -236,6 +280,84 @@ class JWT: """ +@dataclass +class RuleSpecs: + condition: str + """ + Condition expression to evaluate. + """ + + permission_set_names: Optional[List[str]] + """ + Names of permission sets bound to the rule. + """ + + project_ids: Optional[List[str]] + + organization_id: Optional[str] + + +@dataclass +class CreateUserRequestMember: + email: str + """ + Email of the user to create. + """ + + send_password_email: bool + """ + Whether or not to send an email containing the member's password. + """ + + send_welcome_email: bool + """ + Whether or not to send a welcome email that includes onboarding information. + """ + + username: str + """ + The member's username. + """ + + password: str + """ + The member's password. + """ + + first_name: str + """ + The member's first name. + """ + + last_name: str + """ + The member's last name. + """ + + phone_number: str + """ + The member's phone number. + """ + + locale: str + """ + The member's locale. + """ + + +@dataclass +class Connection: + organization: Optional[ConnectionConnectedOrganization] + """ + Information about the connected organization. + """ + + user: Optional[ConnectionConnectedUser] + """ + Information about the connected user. + """ + + @dataclass class APIKey: access_key: str @@ -258,6 +380,16 @@ class APIKey: Defines whether or not the API key is editable. """ + deletable: bool + """ + Defines whether or not the API key is deletable. + """ + + managed: bool + """ + Defines whether or not the API key is managed. + """ + creation_ip: str """ IP address of the device that created the API key. @@ -315,6 +447,16 @@ class Application: Defines whether or not the application is editable. """ + deletable: bool + """ + Defines whether or not the application is deletable. + """ + + managed: bool + """ + Defines whether or not the application is managed. + """ + nb_api_keys: int """ Number of API keys attributed to the application. @@ -336,6 +478,24 @@ class Application: """ +@dataclass +class GracePeriod: + type_: GracePeriodType + """ + Type of grace period. + """ + + created_at: Optional[datetime] + """ + Date and time the grace period was created. + """ + + expires_at: Optional[datetime] + """ + Date and time the grace period expires. + """ + + @dataclass class Group: id: str @@ -373,6 +533,21 @@ class Group: Tags associated to the group. """ + editable: bool + """ + Defines whether or not the group is editable. + """ + + deletable: bool + """ + Defines whether or not the group is deletable. + """ + + managed: bool + """ + Defines whether or not the group is managed. + """ + created_at: Optional[datetime] """ Date and time of group creation. @@ -482,11 +657,31 @@ class Policy: Organization ID of the policy. """ + created_at: Optional[datetime] + """ + Date and time of policy creation. + """ + + updated_at: Optional[datetime] + """ + Date and time of last policy update. + """ + editable: bool """ Defines whether or not a policy is editable. """ + deletable: bool + """ + Defines whether or not a policy is deletable. + """ + + managed: bool + """ + Defines whether or not a policy is managed. + """ + nb_rules: int """ Number of rules of the policy. @@ -507,16 +702,6 @@ class Policy: Tags associated with the policy. """ - created_at: Optional[datetime] - """ - Date and time of policy creation. - """ - - updated_at: Optional[datetime] - """ - Date and time of last policy update. - """ - user_id: Optional[str] group_id: Optional[str] @@ -533,6 +718,31 @@ class Quotum: Name of the quota. """ + pretty_name: str + """ + A human-readable name for the quota. + """ + + unit: str + """ + The unit in which the quota is expressed. + """ + + description: str + """ + Details about the quota. + """ + + locality_type: LocalityType + """ + Whether this quotum is applied on at the zone level, region level, or globally. + """ + + limits: List[QuotumLimit] + """ + Limits per locality. + """ + limit: Optional[int] unlimited: Optional[bool] @@ -550,6 +760,11 @@ class Rule: Permission_set_names have the same scope_type. """ + condition: str + """ + Condition expression to evaluate. + """ + permission_set_names: Optional[List[str]] """ Names of permission sets bound to the rule. @@ -622,6 +837,31 @@ class User: Email of user. """ + username: str + """ + User identifier unique to the Organization. + """ + + first_name: str + """ + First name of the user. + """ + + last_name: str + """ + Last name of the user. + """ + + phone_number: str + """ + Phone number of the user. + """ + + locale: str + """ + Locale of the user. + """ + organization_id: str """ ID of the Organization. @@ -632,6 +872,21 @@ class User: Deletion status of user. Owners cannot be deleted. """ + created_at: Optional[datetime] + """ + Date user was created. + """ + + updated_at: Optional[datetime] + """ + Date of last user update. + """ + + last_login_at: Optional[datetime] + """ + Date of the last login. + """ + type_: UserType """ Type of user. @@ -642,11 +897,6 @@ class User: Status of user invitation. """ - created_at: Optional[datetime] - """ - Date user was created. - """ - mfa: bool """ Defines whether MFA is enabled. @@ -662,14 +912,9 @@ class User: Tags associated with the user. """ - updated_at: Optional[datetime] - """ - Date of last user update. - """ - - last_login_at: Optional[datetime] + locked: bool """ - Date of the last login. + Defines whether the user is locked. """ two_factor_enabled: Optional[bool] @@ -849,12 +1094,15 @@ class CreateSSHKeyRequest: @dataclass -class CreateUserRequest: - email: str +class CreateUserMFAOTPRequest: + user_id: str """ - Email of the user. + User ID of the MFA OTP. """ + +@dataclass +class CreateUserRequest: organization_id: Optional[str] """ ID of the Organization. @@ -865,6 +1113,10 @@ class CreateUserRequest: Tags associated with the user. """ + email: Optional[str] + + member: Optional[CreateUserRequestMember] + @dataclass class DeleteAPIKeyRequest: @@ -911,6 +1163,14 @@ class DeleteSSHKeyRequest: ssh_key_id: str +@dataclass +class DeleteUserMFAOTPRequest: + user_id: str + """ + User ID of the MFA OTP. + """ + + @dataclass class DeleteUserRequest: user_id: str @@ -977,6 +1237,14 @@ class GetLogRequest: """ +@dataclass +class GetOrganizationSecuritySettingsRequest: + organization_id: Optional[str] + """ + ID of the Organization. + """ + + @dataclass class GetPolicyRequest: policy_id: str @@ -1006,6 +1274,22 @@ class GetSSHKeyRequest: """ +@dataclass +class GetUserConnectionsRequest: + user_id: str + """ + ID of the user to list connections for. + """ + + +@dataclass +class GetUserConnectionsResponse: + connections: List[Connection] + """ + List of connections. + """ + + @dataclass class GetUserRequest: user_id: str @@ -1145,6 +1429,22 @@ class ListApplicationsResponse: """ +@dataclass +class ListGracePeriodsRequest: + user_id: Optional[str] + """ + ID of the user to list grace periods for. + """ + + +@dataclass +class ListGracePeriodsResponse: + grace_periods: List[GracePeriod] + """ + List of grace periods. + """ + + @dataclass class ListGroupsRequest: order_by: Optional[ListGroupsRequestOrderBy] @@ -1208,14 +1508,14 @@ class ListGroupsResponse: @dataclass class ListJWTsRequest: - order_by: Optional[ListJWTsRequestOrderBy] + audience_id: str """ - Criteria for sorting results. + ID of the user to search. """ - audience_id: Optional[str] + order_by: Optional[ListJWTsRequestOrderBy] """ - ID of the user to search. + Criteria for sorting results. """ page_size: Optional[int] @@ -1436,6 +1736,11 @@ class ListQuotaRequest: Filter by Organization ID. """ + quotum_names: Optional[List[str]] + """ + List of quotum names to filter from. + """ + @dataclass class ListQuotaResponse: @@ -1569,6 +1874,11 @@ class ListUsersRequest: Filter by tags containing a given string. """ + type_: Optional[UserType] + """ + Filter by user type. + """ + @dataclass class ListUsersResponse: @@ -1583,6 +1893,45 @@ class ListUsersResponse: """ +@dataclass +class LockUserRequest: + user_id: str + """ + ID of the user to lock. + """ + + +@dataclass +class MFAOTP: + secret: str + + +@dataclass +class MigrateOrganizationGuestsRequest: + organization_id: Optional[str] + """ + ID of the Organization. + """ + + +@dataclass +class OrganizationSecuritySettings: + enforce_password_renewal: bool + """ + Defines whether password renewal is enforced during first login. + """ + + login_attempts_before_locked: int + """ + Number of login attempts before the account is locked. + """ + + grace_period_duration: Optional[str] + """ + Duration of the grace period to renew password or enable MFA. + """ + + @dataclass class RemoveGroupMemberRequest: group_id: str @@ -1625,6 +1974,14 @@ class SetRulesResponse: """ +@dataclass +class UnlockUserRequest: + user_id: str + """ + ID of the user to unlock. + """ + + @dataclass class UpdateAPIKeyRequest: access_key: str @@ -1689,6 +2046,29 @@ class UpdateGroupRequest: """ +@dataclass +class UpdateOrganizationSecuritySettingsRequest: + organization_id: Optional[str] + """ + ID of the Organization. + """ + + enforce_password_renewal: Optional[bool] + """ + Defines whether password renewal is enforced during first login. + """ + + grace_period_duration: Optional[str] + """ + Duration of the grace period to renew password or enable MFA. + """ + + login_attempts_before_locked: Optional[int] + """ + Number of login attempts before the account is locked. + """ + + @dataclass class UpdatePolicyRequest: policy_id: str @@ -1735,6 +2115,19 @@ class UpdateSSHKeyRequest: """ +@dataclass +class UpdateUserPasswordRequest: + user_id: str + """ + ID of the user to update. + """ + + password: str + """ + The new password. + """ + + @dataclass class UpdateUserRequest: user_id: str @@ -1746,3 +2139,62 @@ class UpdateUserRequest: """ New tags for the user (maximum of 10 tags). """ + + email: Optional[str] + """ + IAM member email. + """ + + first_name: Optional[str] + """ + IAM member first name. + """ + + last_name: Optional[str] + """ + IAM member last name. + """ + + phone_number: Optional[str] + """ + IAM member phone number. + """ + + locale: Optional[str] + """ + IAM member locale. + """ + + +@dataclass +class UpdateUserUsernameRequest: + user_id: str + """ + ID of the user to update. + """ + + username: str + """ + The new username. + """ + + +@dataclass +class ValidateUserMFAOTPRequest: + user_id: str + """ + User ID of the MFA OTP. + """ + + one_time_password: str + """ + A password generated using the OTP. + """ + + +@dataclass +class ValidateUserMFAOTPResponse: + recovery_codes: List[str] + """ + List of recovery codes usable for this OTP method. + """ diff --git a/scaleway/scaleway/inference/__init__.py b/scaleway/scaleway/inference/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway/scaleway/inference/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/inference/v1/__init__.py b/scaleway/scaleway/inference/v1/__init__.py new file mode 100644 index 00000000..526e0c63 --- /dev/null +++ b/scaleway/scaleway/inference/v1/__init__.py @@ -0,0 +1,79 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DeploymentStatus +from .content import DEPLOYMENT_TRANSIENT_STATUSES +from .types import ListDeploymentsRequestOrderBy +from .types import ListModelsRequestOrderBy +from .types import ModelStatus +from .content import MODEL_TRANSIENT_STATUSES +from .types import NodeTypeStock +from .types import ModelSupportedQuantization +from .types import EndpointPrivateNetworkDetails +from .types import EndpointPublicNetworkDetails +from .types import ModelSupportedNode +from .types import DeploymentQuantization +from .types import Endpoint +from .types import ModelSupportInfo +from .types import EndpointSpec +from .types import ModelSource +from .types import Deployment +from .types import Model +from .types import NodeType +from .types import CreateDeploymentRequest +from .types import CreateEndpointRequest +from .types import CreateModelRequest +from .types import DeleteDeploymentRequest +from .types import DeleteEndpointRequest +from .types import DeleteModelRequest +from .types import GetDeploymentCertificateRequest +from .types import GetDeploymentRequest +from .types import GetModelRequest +from .types import ListDeploymentsRequest +from .types import ListDeploymentsResponse +from .types import ListModelsRequest +from .types import ListModelsResponse +from .types import ListNodeTypesRequest +from .types import ListNodeTypesResponse +from .types import UpdateDeploymentRequest +from .types import UpdateEndpointRequest +from .api import InferenceV1API + +__all__ = [ + "DeploymentStatus", + "DEPLOYMENT_TRANSIENT_STATUSES", + "ListDeploymentsRequestOrderBy", + "ListModelsRequestOrderBy", + "ModelStatus", + "MODEL_TRANSIENT_STATUSES", + "NodeTypeStock", + "ModelSupportedQuantization", + "EndpointPrivateNetworkDetails", + "EndpointPublicNetworkDetails", + "ModelSupportedNode", + "DeploymentQuantization", + "Endpoint", + "ModelSupportInfo", + "EndpointSpec", + "ModelSource", + "Deployment", + "Model", + "NodeType", + "CreateDeploymentRequest", + "CreateEndpointRequest", + "CreateModelRequest", + "DeleteDeploymentRequest", + "DeleteEndpointRequest", + "DeleteModelRequest", + "GetDeploymentCertificateRequest", + "GetDeploymentRequest", + "GetModelRequest", + "ListDeploymentsRequest", + "ListDeploymentsResponse", + "ListModelsRequest", + "ListModelsResponse", + "ListNodeTypesRequest", + "ListNodeTypesResponse", + "UpdateDeploymentRequest", + "UpdateEndpointRequest", + "InferenceV1API", +] diff --git a/scaleway/scaleway/inference/v1/api.py b/scaleway/scaleway/inference/v1/api.py new file mode 100644 index 00000000..9088a783 --- /dev/null +++ b/scaleway/scaleway/inference/v1/api.py @@ -0,0 +1,871 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, + ScwFile, + unmarshal_ScwFile, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + ListDeploymentsRequestOrderBy, + ListModelsRequestOrderBy, + CreateDeploymentRequest, + CreateEndpointRequest, + CreateModelRequest, + Deployment, + DeploymentQuantization, + Endpoint, + EndpointSpec, + ListDeploymentsResponse, + ListModelsResponse, + ListNodeTypesResponse, + Model, + ModelSource, + NodeType, + UpdateDeploymentRequest, + UpdateEndpointRequest, +) +from .content import ( + DEPLOYMENT_TRANSIENT_STATUSES, + MODEL_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_Endpoint, + unmarshal_Deployment, + unmarshal_Model, + unmarshal_ListDeploymentsResponse, + unmarshal_ListModelsResponse, + unmarshal_ListNodeTypesResponse, + marshal_CreateDeploymentRequest, + marshal_CreateEndpointRequest, + marshal_CreateModelRequest, + marshal_UpdateDeploymentRequest, + marshal_UpdateEndpointRequest, +) + + +class InferenceV1API(API): + """ + This API allows you to handle your Managed Inference services. + """ + + def list_deployments( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDeploymentsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListDeploymentsResponse: + """ + List inference deployments. + List all your inference deployments. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of deployments to return per page. + :param order_by: Order in which to return results. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param name: Filter by deployment name. + :param tags: Filter by tags. + :return: :class:`ListDeploymentsResponse ` + + Usage: + :: + + result = api.list_deployments() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDeploymentsResponse(res.json()) + + def list_deployments_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDeploymentsRequestOrderBy] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Deployment]: + """ + List inference deployments. + List all your inference deployments. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of deployments to return per page. + :param order_by: Order in which to return results. + :param project_id: Filter by Project ID. + :param organization_id: Filter by Organization ID. + :param name: Filter by deployment name. + :param tags: Filter by tags. + :return: :class:`List[Deployment] ` + + Usage: + :: + + result = api.list_deployments_all() + """ + + return fetch_all_pages( + type=ListDeploymentsResponse, + key="deployments", + fetcher=self.list_deployments, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "project_id": project_id, + "organization_id": organization_id, + "name": name, + "tags": tags, + }, + ) + + def get_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> Deployment: + """ + Get a deployment. + Get the deployment for the given ID. + :param deployment_id: ID of the deployment to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = api.get_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + def wait_for_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Deployment, bool]] = None, + ) -> Deployment: + """ + Get a deployment. + Get the deployment for the given ID. + :param deployment_id: ID of the deployment to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = api.get_deployment( + deployment_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in DEPLOYMENT_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_deployment, + options=options, + args={ + "deployment_id": deployment_id, + "region": region, + }, + ) + + def create_deployment( + self, + *, + model_id: str, + node_type_name: str, + endpoints: List[EndpointSpec], + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + accept_eula: Optional[bool] = None, + tags: Optional[List[str]] = None, + min_size: Optional[int] = None, + max_size: Optional[int] = None, + quantization: Optional[DeploymentQuantization] = None, + ) -> Deployment: + """ + Create a deployment. + Create a new inference deployment related to a specific model. + :param model_id: ID of the model to use. + :param node_type_name: Name of the node type to use. + :param endpoints: List of endpoints to create. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the deployment. + :param project_id: ID of the Project to create the deployment in. + :param accept_eula: If the model has an EULA, you must accept it before proceeding. + The terms of the EULA can be retrieved using the `GetModelEula` API call. + :param tags: List of tags to apply to the deployment. + :param min_size: Defines the minimum size of the pool. + :param max_size: Defines the maximum size of the pool. + :param quantization: Quantization settings to apply to this deployment. + :return: :class:`Deployment ` + + Usage: + :: + + result = api.create_deployment( + model_id="example", + node_type_name="example", + endpoints=[], + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/deployments", + body=marshal_CreateDeploymentRequest( + CreateDeploymentRequest( + model_id=model_id, + node_type_name=node_type_name, + endpoints=endpoints, + region=region, + name=name or random_name(prefix="inference"), + project_id=project_id, + accept_eula=accept_eula, + tags=tags, + min_size=min_size, + max_size=max_size, + quantization=quantization, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + def update_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + min_size: Optional[int] = None, + max_size: Optional[int] = None, + model_id: Optional[str] = None, + quantization: Optional[DeploymentQuantization] = None, + ) -> Deployment: + """ + Update a deployment. + Update an existing inference deployment. + :param deployment_id: ID of the deployment to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the deployment. + :param tags: List of tags to apply to the deployment. + :param min_size: Defines the new minimum size of the pool. + :param max_size: Defines the new maximum size of the pool. + :param model_id: Id of the model to set to the deployment. + :param quantization: Quantization to use to the deployment. + :return: :class:`Deployment ` + + Usage: + :: + + result = api.update_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "PATCH", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + body=marshal_UpdateDeploymentRequest( + UpdateDeploymentRequest( + deployment_id=deployment_id, + region=region, + name=name, + tags=tags, + min_size=min_size, + max_size=max_size, + model_id=model_id, + quantization=quantization, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + def delete_deployment( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> Deployment: + """ + Delete a deployment. + Delete an existing inference deployment. + :param deployment_id: ID of the deployment to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Deployment ` + + Usage: + :: + + result = api.delete_deployment( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}", + ) + + self._throw_on_error(res) + return unmarshal_Deployment(res.json()) + + def get_deployment_certificate( + self, + *, + deployment_id: str, + region: Optional[ScwRegion] = None, + ) -> ScwFile: + """ + Get the CA certificate. + Get the CA certificate used for the deployment of private endpoints. + The CA certificate will be returned as a PEM file. + :param deployment_id: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ScwFile ` + + Usage: + :: + + result = api.get_deployment_certificate( + deployment_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_deployment_id = validate_path_param("deployment_id", deployment_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/deployments/{param_deployment_id}/certificate", + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + def create_endpoint( + self, + *, + deployment_id: str, + endpoint: EndpointSpec, + region: Optional[ScwRegion] = None, + ) -> Endpoint: + """ + Create an endpoint. + Create a new Endpoint related to a specific deployment. + :param deployment_id: ID of the deployment to create the endpoint for. + :param endpoint: Specification of the endpoint. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Endpoint ` + + Usage: + :: + + result = api.create_endpoint( + deployment_id="example", + endpoint=EndpointSpec(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/endpoints", + body=marshal_CreateEndpointRequest( + CreateEndpointRequest( + deployment_id=deployment_id, + endpoint=endpoint, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Endpoint(res.json()) + + def update_endpoint( + self, + *, + endpoint_id: str, + region: Optional[ScwRegion] = None, + disable_auth: Optional[bool] = None, + ) -> Endpoint: + """ + Update an endpoint. + Update an existing Endpoint. + :param endpoint_id: ID of the endpoint to update. + :param region: Region to target. If none is passed will use default region from the config. + :param disable_auth: By default, deployments are protected by IAM authentication. + When setting this field to true, the authentication will be disabled. + :return: :class:`Endpoint ` + + Usage: + :: + + result = api.update_endpoint( + endpoint_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_endpoint_id = validate_path_param("endpoint_id", endpoint_id) + + res = self._request( + "PATCH", + f"/inference/v1/regions/{param_region}/endpoints/{param_endpoint_id}", + body=marshal_UpdateEndpointRequest( + UpdateEndpointRequest( + endpoint_id=endpoint_id, + region=region, + disable_auth=disable_auth, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Endpoint(res.json()) + + def delete_endpoint( + self, + *, + endpoint_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete an endpoint. + Delete an existing Endpoint. + :param endpoint_id: ID of the endpoint to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_endpoint( + endpoint_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_endpoint_id = validate_path_param("endpoint_id", endpoint_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/endpoints/{param_endpoint_id}", + ) + + self._throw_on_error(res) + + def list_models( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListModelsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListModelsResponse: + """ + List models. + List all available models. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of models to return per page. + :param project_id: Filter by Project ID. + :param name: Filter by model name. + :param tags: Filter by tags. + :return: :class:`ListModelsResponse ` + + Usage: + :: + + result = api.list_models() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/models", + params={ + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListModelsResponse(res.json()) + + def list_models_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListModelsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[Model]: + """ + List models. + List all available models. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of models to return per page. + :param project_id: Filter by Project ID. + :param name: Filter by model name. + :param tags: Filter by tags. + :return: :class:`List[Model] ` + + Usage: + :: + + result = api.list_models_all() + """ + + return fetch_all_pages( + type=ListModelsResponse, + key="models", + fetcher=self.list_models, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "name": name, + "tags": tags, + }, + ) + + def get_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + ) -> Model: + """ + Get a model. + Get the model for the given ID. + :param model_id: ID of the model to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Model ` + + Usage: + :: + + result = api.get_model( + model_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_model_id = validate_path_param("model_id", model_id) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/models/{param_model_id}", + ) + + self._throw_on_error(res) + return unmarshal_Model(res.json()) + + def wait_for_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Model, bool]] = None, + ) -> Model: + """ + Get a model. + Get the model for the given ID. + :param model_id: ID of the model to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Model ` + + Usage: + :: + + result = api.get_model( + model_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in MODEL_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_model, + options=options, + args={ + "model_id": model_id, + "region": region, + }, + ) + + def create_model( + self, + *, + source: ModelSource, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + project_id: Optional[str] = None, + ) -> Model: + """ + Import a model. + Import a new model to your model library. + :param source: Where to import the model from. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the model. + :param project_id: ID of the Project to import the model in. + :return: :class:`Model ` + + Usage: + :: + + result = api.create_model( + source=ModelSource(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/inference/v1/regions/{param_region}/models", + body=marshal_CreateModelRequest( + CreateModelRequest( + source=source, + region=region, + name=name or random_name(prefix="model"), + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Model(res.json()) + + def delete_model( + self, + *, + model_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a model. + Delete an existing model from your model library. + :param model_id: ID of the model to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_model( + model_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_model_id = validate_path_param("model_id", model_id) + + res = self._request( + "DELETE", + f"/inference/v1/regions/{param_region}/models/{param_model_id}", + ) + + self._throw_on_error(res) + + def list_node_types( + self, + *, + include_disabled_types: bool, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListNodeTypesResponse: + """ + List available node types. + List all available node types. By default, the node types returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param include_disabled_types: Include disabled node types in the response. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of node types to return per page. + :return: :class:`ListNodeTypesResponse ` + + Usage: + :: + + result = api.list_node_types( + include_disabled_types=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/inference/v1/regions/{param_region}/node-types", + params={ + "include_disabled_types": include_disabled_types, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListNodeTypesResponse(res.json()) + + def list_node_types_all( + self, + *, + include_disabled_types: bool, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[NodeType]: + """ + List available node types. + List all available node types. By default, the node types returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param include_disabled_types: Include disabled node types in the response. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return. + :param page_size: Maximum number of node types to return per page. + :return: :class:`List[NodeType] ` + + Usage: + :: + + result = api.list_node_types_all( + include_disabled_types=False, + ) + """ + + return fetch_all_pages( + type=ListNodeTypesResponse, + key="node_types", + fetcher=self.list_node_types, + args={ + "include_disabled_types": include_disabled_types, + "region": region, + "page": page, + "page_size": page_size, + }, + ) diff --git a/scaleway/scaleway/inference/v1/content.py b/scaleway/scaleway/inference/v1/content.py new file mode 100644 index 00000000..887e0b7e --- /dev/null +++ b/scaleway/scaleway/inference/v1/content.py @@ -0,0 +1,24 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + DeploymentStatus, + ModelStatus, +) + +DEPLOYMENT_TRANSIENT_STATUSES: List[DeploymentStatus] = [ + DeploymentStatus.CREATING, + DeploymentStatus.DEPLOYING, + DeploymentStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`DeploymentStatus `. +""" +MODEL_TRANSIENT_STATUSES: List[ModelStatus] = [ + ModelStatus.PREPARING, + ModelStatus.DOWNLOADING, +] +""" +Lists transient statutes of the enum :class:`ModelStatus `. +""" diff --git a/scaleway/scaleway/inference/v1/marshalling.py b/scaleway/scaleway/inference/v1/marshalling.py new file mode 100644 index 00000000..59057723 --- /dev/null +++ b/scaleway/scaleway/inference/v1/marshalling.py @@ -0,0 +1,655 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + EndpointPrivateNetworkDetails, + EndpointPublicNetworkDetails, + Endpoint, + ModelSupportedQuantization, + ModelSupportedNode, + ModelSupportInfo, + DeploymentQuantization, + Deployment, + Model, + ListDeploymentsResponse, + ListModelsResponse, + NodeType, + ListNodeTypesResponse, + EndpointSpec, + CreateDeploymentRequest, + CreateEndpointRequest, + ModelSource, + CreateModelRequest, + UpdateDeploymentRequest, + UpdateEndpointRequest, +) + + +def unmarshal_EndpointPrivateNetworkDetails(data: Any) -> EndpointPrivateNetworkDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPrivateNetworkDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + return EndpointPrivateNetworkDetails(**args) + + +def unmarshal_EndpointPublicNetworkDetails(data: Any) -> EndpointPublicNetworkDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPublicNetworkDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return EndpointPublicNetworkDetails(**args) + + +def unmarshal_Endpoint(data: Any) -> Endpoint: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Endpoint' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("url", None) + if field is not None: + args["url"] = field + + field = data.get("disable_auth", None) + if field is not None: + args["disable_auth"] = field + + field = data.get("public_network", None) + if field is not None: + args["public_network"] = unmarshal_EndpointPublicNetworkDetails(field) + else: + args["public_network"] = None + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None + + return Endpoint(**args) + + +def unmarshal_ModelSupportedQuantization(data: Any) -> ModelSupportedQuantization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportedQuantization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("quantization_bits", None) + if field is not None: + args["quantization_bits"] = field + + field = data.get("allowed", None) + if field is not None: + args["allowed"] = field + + field = data.get("max_context_size", None) + if field is not None: + args["max_context_size"] = field + + return ModelSupportedQuantization(**args) + + +def unmarshal_ModelSupportedNode(data: Any) -> ModelSupportedNode: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportedNode' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_type_name", None) + if field is not None: + args["node_type_name"] = field + + field = data.get("quantizations", None) + if field is not None: + args["quantizations"] = ( + [unmarshal_ModelSupportedQuantization(v) for v in field] + if field is not None + else None + ) + + return ModelSupportedNode(**args) + + +def unmarshal_ModelSupportInfo(data: Any) -> ModelSupportInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ModelSupportInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("nodes", None) + if field is not None: + args["nodes"] = ( + [unmarshal_ModelSupportedNode(v) for v in field] + if field is not None + else None + ) + + return ModelSupportInfo(**args) + + +def unmarshal_DeploymentQuantization(data: Any) -> DeploymentQuantization: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DeploymentQuantization' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("bits", None) + if field is not None: + args["bits"] = field + + return DeploymentQuantization(**args) + + +def unmarshal_Deployment(data: Any) -> Deployment: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Deployment' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("node_type_name", None) + if field is not None: + args["node_type_name"] = field + + field = data.get("endpoints", None) + if field is not None: + args["endpoints"] = ( + [unmarshal_Endpoint(v) for v in field] if field is not None else None + ) + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("min_size", None) + if field is not None: + args["min_size"] = field + + field = data.get("max_size", None) + if field is not None: + args["max_size"] = field + + field = data.get("model_id", None) + if field is not None: + args["model_id"] = field + + field = data.get("model_name", None) + if field is not None: + args["model_name"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + else: + args["error_message"] = None + + field = data.get("quantization", None) + if field is not None: + args["quantization"] = unmarshal_DeploymentQuantization(field) + else: + args["quantization"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Deployment(**args) + + +def unmarshal_Model(data: Any) -> Model: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Model' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("has_eula", None) + if field is not None: + args["has_eula"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("nodes_support", None) + if field is not None: + args["nodes_support"] = ( + [unmarshal_ModelSupportInfo(v) for v in field] + if field is not None + else None + ) + + field = data.get("parameter_size_bits", None) + if field is not None: + args["parameter_size_bits"] = field + + field = data.get("size_bytes", None) + if field is not None: + args["size_bytes"] = field + + field = data.get("error_message", None) + if field is not None: + args["error_message"] = field + else: + args["error_message"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Model(**args) + + +def unmarshal_ListDeploymentsResponse(data: Any) -> ListDeploymentsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDeploymentsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("deployments", None) + if field is not None: + args["deployments"] = ( + [unmarshal_Deployment(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDeploymentsResponse(**args) + + +def unmarshal_ListModelsResponse(data: Any) -> ListModelsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListModelsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("models", None) + if field is not None: + args["models"] = ( + [unmarshal_Model(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListModelsResponse(**args) + + +def unmarshal_NodeType(data: Any) -> NodeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("stock_status", None) + if field is not None: + args["stock_status"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("vcpus", None) + if field is not None: + args["vcpus"] = field + + field = data.get("memory", None) + if field is not None: + args["memory"] = field + + field = data.get("vram", None) + if field is not None: + args["vram"] = field + + field = data.get("disabled", None) + if field is not None: + args["disabled"] = field + + field = data.get("beta", None) + if field is not None: + args["beta"] = field + + field = data.get("gpus", None) + if field is not None: + args["gpus"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return NodeType(**args) + + +def unmarshal_ListNodeTypesResponse(data: Any) -> ListNodeTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListNodeTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_types", None) + if field is not None: + args["node_types"] = ( + [unmarshal_NodeType(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListNodeTypesResponse(**args) + + +def marshal_EndpointPrivateNetworkDetails( + request: EndpointPrivateNetworkDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + return output + + +def marshal_EndpointPublicNetworkDetails( + request: EndpointPublicNetworkDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_DeploymentQuantization( + request: DeploymentQuantization, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.bits is not None: + output["bits"] = request.bits + + return output + + +def marshal_EndpointSpec( + request: EndpointSpec, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("public_network", request.public_network), + OneOfPossibility("private_network", request.private_network), + ] + ), + ) + + if request.disable_auth is not None: + output["disable_auth"] = request.disable_auth + + return output + + +def marshal_CreateDeploymentRequest( + request: CreateDeploymentRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.model_id is not None: + output["model_id"] = request.model_id + + if request.node_type_name is not None: + output["node_type_name"] = request.node_type_name + + if request.endpoints is not None: + output["endpoints"] = [ + marshal_EndpointSpec(item, defaults) for item in request.endpoints + ] + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.accept_eula is not None: + output["accept_eula"] = request.accept_eula + + if request.tags is not None: + output["tags"] = request.tags + + if request.min_size is not None: + output["min_size"] = request.min_size + + if request.max_size is not None: + output["max_size"] = request.max_size + + if request.quantization is not None: + output["quantization"] = marshal_DeploymentQuantization( + request.quantization, defaults + ) + + return output + + +def marshal_CreateEndpointRequest( + request: CreateEndpointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.deployment_id is not None: + output["deployment_id"] = request.deployment_id + + if request.endpoint is not None: + output["endpoint"] = marshal_EndpointSpec(request.endpoint, defaults) + + return output + + +def marshal_ModelSource( + request: ModelSource, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("secret", request.secret), + ] + ), + ) + + if request.url is not None: + output["url"] = request.url + + return output + + +def marshal_CreateModelRequest( + request: CreateModelRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.source is not None: + output["source"] = marshal_ModelSource(request.source, defaults) + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_UpdateDeploymentRequest( + request: UpdateDeploymentRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.min_size is not None: + output["min_size"] = request.min_size + + if request.max_size is not None: + output["max_size"] = request.max_size + + if request.model_id is not None: + output["model_id"] = request.model_id + + if request.quantization is not None: + output["quantization"] = marshal_DeploymentQuantization( + request.quantization, defaults + ) + + return output + + +def marshal_UpdateEndpointRequest( + request: UpdateEndpointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.disable_auth is not None: + output["disable_auth"] = request.disable_auth + + return output diff --git a/scaleway/scaleway/inference/v1/types.py b/scaleway/scaleway/inference/v1/types.py new file mode 100644 index 00000000..a4246cb0 --- /dev/null +++ b/scaleway/scaleway/inference/v1/types.py @@ -0,0 +1,775 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DeploymentStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + DEPLOYING = "deploying" + READY = "ready" + ERROR = "error" + DELETING = "deleting" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class ListDeploymentsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListModelsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + DISPLAY_RANK_ASC = "display_rank_asc" + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ModelStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + PREPARING = "preparing" + DOWNLOADING = "downloading" + READY = "ready" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class NodeTypeStock(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STOCK = "unknown_stock" + LOW_STOCK = "low_stock" + OUT_OF_STOCK = "out_of_stock" + AVAILABLE = "available" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class ModelSupportedQuantization: + quantization_bits: int + """ + Number of bits for this supported quantization. + """ + + allowed: bool + """ + Tells whether this quantization is allowed for this node type. + """ + + max_context_size: int + """ + Maximum inference context size available for this node type and quantization. + """ + + +@dataclass +class EndpointPrivateNetworkDetails: + private_network_id: str + + +@dataclass +class EndpointPublicNetworkDetails: + pass + + +@dataclass +class ModelSupportedNode: + node_type_name: str + """ + Supported node type. + """ + + quantizations: List[ModelSupportedQuantization] + """ + Supported quantizations. + """ + + +@dataclass +class DeploymentQuantization: + bits: int + """ + The number of bits each model parameter should be quantized to. The quantization method is chosen based on this value. + """ + + +@dataclass +class Endpoint: + id: str + """ + Unique identifier. + """ + + url: str + """ + For private endpoints, the URL will be accessible only from the Private Network. +In addition, private endpoints will expose a CA certificate that can be used to verify the server's identity. +This CA certificate can be retrieved using the `GetDeploymentCertificate` API call. + """ + + disable_auth: bool + """ + Defines whether the authentication is disabled. + """ + + public_network: Optional[EndpointPublicNetworkDetails] + + private_network: Optional[EndpointPrivateNetworkDetails] + + +@dataclass +class ModelSupportInfo: + nodes: List[ModelSupportedNode] + """ + List of supported node types. + """ + + +@dataclass +class EndpointSpec: + disable_auth: bool + """ + By default, deployments are protected by IAM authentication. +When setting this field to true, the authentication will be disabled. + """ + + public_network: Optional[EndpointPublicNetworkDetails] + + private_network: Optional[EndpointPrivateNetworkDetails] + + +@dataclass +class ModelSource: + url: str + + secret: Optional[str] + + +@dataclass +class Deployment: + id: str + """ + Unique identifier. + """ + + name: str + """ + Name of the deployment. + """ + + project_id: str + """ + Project ID. + """ + + status: DeploymentStatus + """ + Status of the deployment. + """ + + tags: List[str] + """ + List of tags applied to the deployment. + """ + + node_type_name: str + """ + Node type of the deployment. + """ + + endpoints: List[Endpoint] + """ + List of endpoints. + """ + + size: int + """ + Current size of the pool. + """ + + min_size: int + """ + Defines the minimum size of the pool. + """ + + max_size: int + """ + Defines the maximum size of the pool. + """ + + model_id: str + """ + ID of the model used for the deployment. + """ + + model_name: str + """ + Name of the deployed model. + """ + + region: ScwRegion + """ + Region of the deployment. + """ + + error_message: Optional[str] + """ + Displays information if your deployment is in error state. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization parameters for this deployment. + """ + + created_at: Optional[datetime] + """ + Creation date of the deployment. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the deployment. + """ + + +@dataclass +class Model: + id: str + """ + Unique identifier. + """ + + name: str + """ + Unique Name identifier. + """ + + project_id: str + """ + Project ID. + """ + + tags: List[str] + """ + List of tags applied to the model. + """ + + status: ModelStatus + """ + Status of the model. + """ + + description: str + """ + Purpose of the model. + """ + + has_eula: bool + """ + Defines whether the model has an end user license agreement. + """ + + region: ScwRegion + """ + Region of the model. + """ + + nodes_support: List[ModelSupportInfo] + """ + Supported nodes types with quantization options and context lengths. + """ + + parameter_size_bits: int + """ + Size, in bits, of the model parameters. + """ + + size_bytes: int + """ + Total size, in bytes, of the model files. + """ + + error_message: Optional[str] + """ + Displays information if your model is in error state. + """ + + created_at: Optional[datetime] + """ + Creation date of the model. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the model. + """ + + +@dataclass +class NodeType: + name: str + """ + Name of the node type. + """ + + stock_status: NodeTypeStock + """ + Current stock status for the node type. + """ + + description: str + """ + Current specs of the offer. + """ + + vcpus: int + """ + Number of virtual CPUs. + """ + + memory: int + """ + Quantity of RAM. + """ + + vram: int + """ + Quantity of GPU RAM. + """ + + disabled: bool + """ + The node type is currently disabled. + """ + + beta: bool + """ + The node type is currently in beta. + """ + + gpus: int + """ + Number of GPUs. + """ + + region: ScwRegion + """ + Region of the node type. + """ + + created_at: Optional[datetime] + """ + Creation date of the node type. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the node type. + """ + + +@dataclass +class CreateDeploymentRequest: + model_id: str + """ + ID of the model to use. + """ + + node_type_name: str + """ + Name of the node type to use. + """ + + endpoints: List[EndpointSpec] + """ + List of endpoints to create. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the deployment. + """ + + project_id: Optional[str] + """ + ID of the Project to create the deployment in. + """ + + accept_eula: Optional[bool] + """ + If the model has an EULA, you must accept it before proceeding. +The terms of the EULA can be retrieved using the `GetModelEula` API call. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the deployment. + """ + + min_size: Optional[int] + """ + Defines the minimum size of the pool. + """ + + max_size: Optional[int] + """ + Defines the maximum size of the pool. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization settings to apply to this deployment. + """ + + +@dataclass +class CreateEndpointRequest: + deployment_id: str + """ + ID of the deployment to create the endpoint for. + """ + + endpoint: EndpointSpec + """ + Specification of the endpoint. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateModelRequest: + source: ModelSource + """ + Where to import the model from. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the model. + """ + + project_id: Optional[str] + """ + ID of the Project to import the model in. + """ + + +@dataclass +class DeleteDeploymentRequest: + deployment_id: str + """ + ID of the deployment to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteEndpointRequest: + endpoint_id: str + """ + ID of the endpoint to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteModelRequest: + model_id: str + """ + ID of the model to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDeploymentCertificateRequest: + deployment_id: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDeploymentRequest: + deployment_id: str + """ + ID of the deployment to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetModelRequest: + model_id: str + """ + ID of the model to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListDeploymentsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of deployments to return per page. + """ + + order_by: Optional[ListDeploymentsRequestOrderBy] + """ + Order in which to return results. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + organization_id: Optional[str] + """ + Filter by Organization ID. + """ + + name: Optional[str] + """ + Filter by deployment name. + """ + + tags: Optional[List[str]] + """ + Filter by tags. + """ + + +@dataclass +class ListDeploymentsResponse: + deployments: List[Deployment] + """ + List of deployments on the current page. + """ + + total_count: int + """ + Total number of deployments. + """ + + +@dataclass +class ListModelsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListModelsRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of models to return per page. + """ + + project_id: Optional[str] + """ + Filter by Project ID. + """ + + name: Optional[str] + """ + Filter by model name. + """ + + tags: Optional[List[str]] + """ + Filter by tags. + """ + + +@dataclass +class ListModelsResponse: + models: List[Model] + """ + List of models on the current page. + """ + + total_count: int + """ + Total number of models. + """ + + +@dataclass +class ListNodeTypesRequest: + include_disabled_types: bool + """ + Include disabled node types in the response. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of node types to return per page. + """ + + +@dataclass +class ListNodeTypesResponse: + node_types: List[NodeType] + """ + List of node types. + """ + + total_count: int + """ + Total number of node types. + """ + + +@dataclass +class UpdateDeploymentRequest: + deployment_id: str + """ + ID of the deployment to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the deployment. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the deployment. + """ + + min_size: Optional[int] + """ + Defines the new minimum size of the pool. + """ + + max_size: Optional[int] + """ + Defines the new maximum size of the pool. + """ + + model_id: Optional[str] + """ + Id of the model to set to the deployment. + """ + + quantization: Optional[DeploymentQuantization] + """ + Quantization to use to the deployment. + """ + + +@dataclass +class UpdateEndpointRequest: + endpoint_id: str + """ + ID of the endpoint to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + disable_auth: Optional[bool] + """ + By default, deployments are protected by IAM authentication. +When setting this field to true, the authentication will be disabled. + """ diff --git a/scaleway/scaleway/llm_inference/v1beta1/__init__.py b/scaleway/scaleway/inference/v1beta1/__init__.py similarity index 97% rename from scaleway/scaleway/llm_inference/v1beta1/__init__.py rename to scaleway/scaleway/inference/v1beta1/__init__.py index e78f7a95..b542f359 100644 --- a/scaleway/scaleway/llm_inference/v1beta1/__init__.py +++ b/scaleway/scaleway/inference/v1beta1/__init__.py @@ -41,7 +41,7 @@ from .types import SetDeploymentACLRulesResponse from .types import UpdateDeploymentRequest from .types import UpdateEndpointRequest -from .api import LlmInferenceV1Beta1API +from .api import InferenceV1Beta1API __all__ = [ "DeploymentStatus", @@ -85,5 +85,5 @@ "SetDeploymentACLRulesResponse", "UpdateDeploymentRequest", "UpdateEndpointRequest", - "LlmInferenceV1Beta1API", + "InferenceV1Beta1API", ] diff --git a/scaleway/scaleway/llm_inference/v1beta1/api.py b/scaleway/scaleway/inference/v1beta1/api.py similarity index 91% rename from scaleway/scaleway/llm_inference/v1beta1/api.py rename to scaleway/scaleway/inference/v1beta1/api.py index d842f72d..df3e67d8 100644 --- a/scaleway/scaleway/llm_inference/v1beta1/api.py +++ b/scaleway/scaleway/inference/v1beta1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ScwFile, unmarshal_ScwFile, ) @@ -63,13 +63,15 @@ ) -class LlmInferenceV1Beta1API(API): - """ """ +class InferenceV1Beta1API(API): + """ + This API allows you to manage your Inference services. + """ def list_deployments( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDeploymentsRequestOrderBy] = None, @@ -103,7 +105,7 @@ def list_deployments( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/deployments", + f"/inference/v1beta1/regions/{param_region}/deployments", params={ "name": name, "order_by": order_by, @@ -122,7 +124,7 @@ def list_deployments( def list_deployments_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDeploymentsRequestOrderBy] = None, @@ -170,7 +172,7 @@ def get_deployment( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Deployment: """ Get a deployment. @@ -194,7 +196,7 @@ def get_deployment( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", ) self._throw_on_error(res) @@ -204,7 +206,7 @@ def wait_for_deployment( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Deployment, bool]] = None, ) -> Deployment: """ @@ -243,7 +245,7 @@ def create_deployment( model_name: str, node_type: str, endpoints: List[EndpointSpec], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, project_id: Optional[str] = None, accept_eula: Optional[bool] = None, @@ -283,14 +285,14 @@ def create_deployment( res = self._request( "POST", - f"/llm-inference/v1beta1/regions/{param_region}/deployments", + f"/inference/v1beta1/regions/{param_region}/deployments", body=marshal_CreateDeploymentRequest( CreateDeploymentRequest( model_name=model_name, node_type=node_type, endpoints=endpoints, region=region, - name=name or random_name(prefix="llm"), + name=name or random_name(prefix="inference"), project_id=project_id, accept_eula=accept_eula, tags=tags, @@ -308,7 +310,7 @@ def update_deployment( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, min_size: Optional[int] = None, @@ -340,7 +342,7 @@ def update_deployment( res = self._request( "PATCH", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", body=marshal_UpdateDeploymentRequest( UpdateDeploymentRequest( deployment_id=deployment_id, @@ -361,7 +363,7 @@ def delete_deployment( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Deployment: """ Delete a deployment. @@ -385,7 +387,7 @@ def delete_deployment( res = self._request( "DELETE", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}", ) self._throw_on_error(res) @@ -395,7 +397,7 @@ def get_deployment_certificate( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ScwFile: """ Get the CA certificate. @@ -420,7 +422,7 @@ def get_deployment_certificate( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/certificate", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/certificate", ) self._throw_on_error(res) @@ -431,7 +433,7 @@ def create_endpoint( *, deployment_id: str, endpoint: EndpointSpec, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Endpoint: """ Create an endpoint. @@ -456,7 +458,7 @@ def create_endpoint( res = self._request( "POST", - f"/llm-inference/v1beta1/regions/{param_region}/endpoints", + f"/inference/v1beta1/regions/{param_region}/endpoints", body=marshal_CreateEndpointRequest( CreateEndpointRequest( deployment_id=deployment_id, @@ -474,7 +476,7 @@ def update_endpoint( self, *, endpoint_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, disable_auth: Optional[bool] = None, ) -> Endpoint: """ @@ -482,7 +484,7 @@ def update_endpoint( Update an existing Endpoint. :param endpoint_id: ID of the endpoint to update. :param region: Region to target. If none is passed will use default region from the config. - :param disable_auth: By default, LLM deployments are protected by IAM authentication. + :param disable_auth: By default, deployments are protected by IAM authentication. When setting this field to true, the authentication will be disabled. :return: :class:`Endpoint ` @@ -501,7 +503,7 @@ def update_endpoint( res = self._request( "PATCH", - f"/llm-inference/v1beta1/regions/{param_region}/endpoints/{param_endpoint_id}", + f"/inference/v1beta1/regions/{param_region}/endpoints/{param_endpoint_id}", body=marshal_UpdateEndpointRequest( UpdateEndpointRequest( endpoint_id=endpoint_id, @@ -519,7 +521,7 @@ def delete_endpoint( self, *, endpoint_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete an endpoint. @@ -542,7 +544,7 @@ def delete_endpoint( res = self._request( "DELETE", - f"/llm-inference/v1beta1/regions/{param_region}/endpoints/{param_endpoint_id}", + f"/inference/v1beta1/regions/{param_region}/endpoints/{param_endpoint_id}", ) self._throw_on_error(res) @@ -551,7 +553,7 @@ def list_deployment_acl_rules( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListDeploymentACLRulesResponse: @@ -579,7 +581,7 @@ def list_deployment_acl_rules( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", params={ "page": page, "page_size": page_size or self.client.default_page_size, @@ -593,7 +595,7 @@ def list_deployment_acl_rules_all( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[ACLRule]: @@ -630,7 +632,7 @@ def add_deployment_acl_rules( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, acls: Optional[List[ACLRuleRequest]] = None, ) -> AddDeploymentACLRulesResponse: """ @@ -656,7 +658,7 @@ def add_deployment_acl_rules( res = self._request( "POST", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", body=marshal_AddDeploymentACLRulesRequest( AddDeploymentACLRulesRequest( deployment_id=deployment_id, @@ -674,7 +676,7 @@ def set_deployment_acl_rules( self, *, deployment_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, acls: Optional[List[ACLRuleRequest]] = None, ) -> SetDeploymentACLRulesResponse: """ @@ -700,7 +702,7 @@ def set_deployment_acl_rules( res = self._request( "PUT", - f"/llm-inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", + f"/inference/v1beta1/regions/{param_region}/deployments/{param_deployment_id}/acls", body=marshal_SetDeploymentACLRulesRequest( SetDeploymentACLRulesRequest( deployment_id=deployment_id, @@ -718,10 +720,10 @@ def delete_deployment_acl_rule( self, *, acl_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ - Delete an exising ACL. + Delete an existing ACL. :param acl_id: ID of the ACL rule to delete. :param region: Region to target. If none is passed will use default region from the config. @@ -740,7 +742,7 @@ def delete_deployment_acl_rule( res = self._request( "DELETE", - f"/llm-inference/v1beta1/regions/{param_region}/acls/{param_acl_id}", + f"/inference/v1beta1/regions/{param_region}/acls/{param_acl_id}", ) self._throw_on_error(res) @@ -748,7 +750,7 @@ def delete_deployment_acl_rule( def list_models( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListModelsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -758,7 +760,7 @@ def list_models( ) -> ListModelsResponse: """ List models. - List all available LLM models. + List all available models. :param region: Region to target. If none is passed will use default region from the config. :param order_by: Order in which to return results. :param page: Page number to return. @@ -780,7 +782,7 @@ def list_models( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/models", + f"/inference/v1beta1/regions/{param_region}/models", params={ "name": name, "order_by": order_by, @@ -797,7 +799,7 @@ def list_models( def list_models_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListModelsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -807,7 +809,7 @@ def list_models_all( ) -> List[Model]: """ List models. - List all available LLM models. + List all available models. :param region: Region to target. If none is passed will use default region from the config. :param order_by: Order in which to return results. :param page: Page number to return. @@ -842,7 +844,7 @@ def get_model( self, *, model_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Model: """ Get a model. @@ -866,7 +868,7 @@ def get_model( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/models/{param_model_id}", + f"/inference/v1beta1/regions/{param_region}/models/{param_model_id}", ) self._throw_on_error(res) @@ -876,7 +878,7 @@ def get_model_eula( self, *, model_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Eula: """ :param model_id: @@ -898,7 +900,7 @@ def get_model_eula( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/models/{param_model_id}/eula", + f"/inference/v1beta1/regions/{param_region}/models/{param_model_id}/eula", ) self._throw_on_error(res) @@ -908,7 +910,7 @@ def list_node_types( self, *, include_disabled_types: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListNodeTypesResponse: @@ -935,7 +937,7 @@ def list_node_types( res = self._request( "GET", - f"/llm-inference/v1beta1/regions/{param_region}/node-types", + f"/inference/v1beta1/regions/{param_region}/node-types", params={ "include_disabled_types": include_disabled_types, "page": page, @@ -950,7 +952,7 @@ def list_node_types_all( self, *, include_disabled_types: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[NodeType]: diff --git a/scaleway/scaleway/llm_inference/v1beta1/content.py b/scaleway/scaleway/inference/v1beta1/content.py similarity index 100% rename from scaleway/scaleway/llm_inference/v1beta1/content.py rename to scaleway/scaleway/inference/v1beta1/content.py diff --git a/scaleway/scaleway/llm_inference/v1beta1/marshalling.py b/scaleway/scaleway/inference/v1beta1/marshalling.py similarity index 95% rename from scaleway/scaleway/llm_inference/v1beta1/marshalling.py rename to scaleway/scaleway/inference/v1beta1/marshalling.py index e8146598..413ff779 100644 --- a/scaleway/scaleway/llm_inference/v1beta1/marshalling.py +++ b/scaleway/scaleway/inference/v1beta1/marshalling.py @@ -87,10 +87,14 @@ def unmarshal_Endpoint(data: Any) -> Endpoint: field = data.get("public_access", None) if field is not None: args["public_access"] = unmarshal_EndpointPublicAccessDetails(field) + else: + args["public_access"] = None field = data.get("private_network", None) if field is not None: args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None return Endpoint(**args) @@ -149,6 +153,10 @@ def unmarshal_Deployment(data: Any) -> Deployment: if field is not None: args["model_name"] = field + field = data.get("model_id", None) + if field is not None: + args["model_id"] = field + field = data.get("region", None) if field is not None: args["region"] = field @@ -156,14 +164,20 @@ def unmarshal_Deployment(data: Any) -> Deployment: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Deployment(**args) @@ -187,10 +201,14 @@ def unmarshal_ModelS3Model(data: Any) -> ModelS3Model: field = data.get("node_type", None) if field is not None: args["node_type"] = field + else: + args["node_type"] = None field = data.get("triton_server_version", None) if field is not None: args["triton_server_version"] = field + else: + args["triton_server_version"] = None return ModelS3Model(**args) @@ -250,14 +268,20 @@ def unmarshal_Model(data: Any) -> Model: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("s3_model", None) if field is not None: args["s3_model"] = unmarshal_ModelS3Model(field) + else: + args["s3_model"] = None return Model(**args) @@ -433,10 +457,14 @@ def unmarshal_NodeType(data: Any) -> NodeType: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return NodeType(**args) @@ -597,7 +625,7 @@ def marshal_CreateEndpointRequest( output["deployment_id"] = request.deployment_id if request.endpoint is not None: - output["endpoint"] = (marshal_EndpointSpec(request.endpoint, defaults),) + output["endpoint"] = marshal_EndpointSpec(request.endpoint, defaults) return output diff --git a/scaleway-async/scaleway_async/llm_inference/v1beta1/types.py b/scaleway/scaleway/inference/v1beta1/types.py similarity index 93% rename from scaleway-async/scaleway_async/llm_inference/v1beta1/types.py rename to scaleway/scaleway/inference/v1beta1/types.py index eedd3d8b..c93b59bc 100644 --- a/scaleway-async/scaleway_async/llm_inference/v1beta1/types.py +++ b/scaleway/scaleway/inference/v1beta1/types.py @@ -8,7 +8,7 @@ from typing import Dict, List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -39,6 +39,7 @@ def __str__(self) -> str: class ListModelsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + DISPLAY_RANK_ASC = "display_rank_asc" CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" NAME_ASC = "name_asc" @@ -154,7 +155,7 @@ class ACLRule: class EndpointSpec: disable_auth: bool """ - By default, LLM deployments are protected by IAM authentication. + By default, deployments are protected by IAM authentication. When setting this field to true, the authentication will be disabled. """ @@ -220,7 +221,12 @@ class Deployment: The inference model used for the deployment. """ - region: Region + model_id: str + """ + ID of the model used for the deployment. + """ + + region: ScwRegion """ Region of the deployment. """ @@ -275,10 +281,10 @@ class Model: has_eula: bool """ - Defines whether the model has an end user licence agreement. + Defines whether the model has an end user license agreement. """ - region: Region + region: ScwRegion """ Region of the model. """ @@ -358,7 +364,7 @@ class NodeType: Number of GPUs. """ - region: Region + region: ScwRegion """ Region of the node type. """ @@ -381,7 +387,7 @@ class AddDeploymentACLRulesRequest: ID of the deployment to add ACL rules to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -417,7 +423,7 @@ class CreateDeploymentRequest: List of endpoints to create. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -466,7 +472,7 @@ class CreateEndpointRequest: Specification of the endpoint. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -479,7 +485,7 @@ class DeleteDeploymentACLRuleRequest: ID of the ACL rule to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -492,7 +498,7 @@ class DeleteDeploymentRequest: ID of the deployment to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -505,7 +511,7 @@ class DeleteEndpointRequest: ID of the endpoint to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -515,7 +521,7 @@ class DeleteEndpointRequest: class Eula: content: str """ - Content of the end user licence agreement. + Content of the end user license agreement. """ @@ -523,7 +529,7 @@ class Eula: class GetDeploymentCertificateRequest: deployment_id: str - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -536,7 +542,7 @@ class GetDeploymentRequest: ID of the deployment to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -546,7 +552,7 @@ class GetDeploymentRequest: class GetModelEulaRequest: model_id: str - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -559,7 +565,7 @@ class GetModelRequest: ID of the model to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -572,7 +578,7 @@ class ListDeploymentACLRulesRequest: ID of the deployment to list ACL rules for. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -603,7 +609,7 @@ class ListDeploymentACLRulesResponse: @dataclass class ListDeploymentsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -659,7 +665,7 @@ class ListDeploymentsResponse: @dataclass class ListModelsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -715,7 +721,7 @@ class ListNodeTypesRequest: Include disabled node types in the response. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -751,7 +757,7 @@ class SetDeploymentACLRulesRequest: ID of the deployment to set ACL rules for. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -777,7 +783,7 @@ class UpdateDeploymentRequest: ID of the deployment to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -810,13 +816,13 @@ class UpdateEndpointRequest: ID of the endpoint to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ disable_auth: Optional[bool] """ - By default, LLM deployments are protected by IAM authentication. + By default, deployments are protected by IAM authentication. When setting this field to true, the authentication will be disabled. """ diff --git a/scaleway/scaleway/instance/v1/__init__.py b/scaleway/scaleway/instance/v1/__init__.py index 8f2320f2..05aba600 100644 --- a/scaleway/scaleway/instance/v1/__init__.py +++ b/scaleway/scaleway/instance/v1/__init__.py @@ -55,6 +55,7 @@ from .types import VolumeServer from .types import SnapshotBaseVolume from .types import ServerTypeCapabilities +from .types import ServerTypeGPUInfo from .types import ServerTypeNetwork from .types import ServerTypeVolumeConstraintsByType from .types import VolumeTypeCapabilities @@ -77,8 +78,11 @@ from .types import VolumeImageUpdateTemplate from .types import SecurityGroupTemplate from .types import ApplyBlockMigrationRequest +from .types import AttachServerFileSystemRequest +from .types import AttachServerFileSystemResponse from .types import AttachServerVolumeRequest from .types import AttachServerVolumeResponse +from .types import CheckBlockMigrationOrganizationQuotasRequest from .types import CreateImageRequest from .types import CreateImageResponse from .types import CreateIpRequest @@ -107,12 +111,12 @@ from .types import DeleteServerUserDataRequest from .types import DeleteSnapshotRequest from .types import DeleteVolumeRequest +from .types import DetachServerFileSystemRequest +from .types import DetachServerFileSystemResponse from .types import DetachServerVolumeRequest from .types import DetachServerVolumeResponse from .types import ExportSnapshotRequest from .types import ExportSnapshotResponse -from .types import GetBootscriptRequest -from .types import GetBootscriptResponse from .types import GetDashboardRequest from .types import GetDashboardResponse from .types import GetImageRequest @@ -129,6 +133,7 @@ from .types import GetSecurityGroupResponse from .types import GetSecurityGroupRuleRequest from .types import GetSecurityGroupRuleResponse +from .types import GetServerCompatibleTypesRequest from .types import GetServerRequest from .types import GetServerResponse from .types import GetServerTypesAvailabilityRequest @@ -137,8 +142,6 @@ from .types import GetSnapshotResponse from .types import GetVolumeRequest from .types import GetVolumeResponse -from .types import ListBootscriptsRequest -from .types import ListBootscriptsResponse from .types import ListDefaultSecurityGroupRulesRequest from .types import ListImagesRequest from .types import ListImagesResponse @@ -170,6 +173,7 @@ from .types import PlanBlockMigrationRequest from .types import ServerActionRequest from .types import ServerActionResponse +from .types import ServerCompatibleTypes from .types import SetImageRequest from .types import SetPlacementGroupRequest from .types import SetPlacementGroupResponse @@ -254,6 +258,7 @@ "VolumeServer", "SnapshotBaseVolume", "ServerTypeCapabilities", + "ServerTypeGPUInfo", "ServerTypeNetwork", "ServerTypeVolumeConstraintsByType", "VolumeTypeCapabilities", @@ -276,8 +281,11 @@ "VolumeImageUpdateTemplate", "SecurityGroupTemplate", "ApplyBlockMigrationRequest", + "AttachServerFileSystemRequest", + "AttachServerFileSystemResponse", "AttachServerVolumeRequest", "AttachServerVolumeResponse", + "CheckBlockMigrationOrganizationQuotasRequest", "CreateImageRequest", "CreateImageResponse", "CreateIpRequest", @@ -306,12 +314,12 @@ "DeleteServerUserDataRequest", "DeleteSnapshotRequest", "DeleteVolumeRequest", + "DetachServerFileSystemRequest", + "DetachServerFileSystemResponse", "DetachServerVolumeRequest", "DetachServerVolumeResponse", "ExportSnapshotRequest", "ExportSnapshotResponse", - "GetBootscriptRequest", - "GetBootscriptResponse", "GetDashboardRequest", "GetDashboardResponse", "GetImageRequest", @@ -328,6 +336,7 @@ "GetSecurityGroupResponse", "GetSecurityGroupRuleRequest", "GetSecurityGroupRuleResponse", + "GetServerCompatibleTypesRequest", "GetServerRequest", "GetServerResponse", "GetServerTypesAvailabilityRequest", @@ -336,8 +345,6 @@ "GetSnapshotResponse", "GetVolumeRequest", "GetVolumeResponse", - "ListBootscriptsRequest", - "ListBootscriptsResponse", "ListDefaultSecurityGroupRulesRequest", "ListImagesRequest", "ListImagesResponse", @@ -369,6 +376,7 @@ "PlanBlockMigrationRequest", "ServerActionRequest", "ServerActionResponse", + "ServerCompatibleTypes", "SetImageRequest", "SetPlacementGroupRequest", "SetPlacementGroupResponse", diff --git a/scaleway/scaleway/instance/v1/api.py b/scaleway/scaleway/instance/v1/api.py index 0400e08b..f0c8ca3d 100644 --- a/scaleway/scaleway/instance/v1/api.py +++ b/scaleway/scaleway/instance/v1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( random_name, @@ -43,9 +43,12 @@ SnapshotVolumeType, VolumeVolumeType, ApplyBlockMigrationRequest, + AttachServerFileSystemRequest, + AttachServerFileSystemResponse, AttachServerVolumeRequest, AttachServerVolumeResponse, Bootscript, + CheckBlockMigrationOrganizationQuotasRequest, CreateImageRequest, CreateImageResponse, CreateIpRequest, @@ -64,11 +67,12 @@ CreateSnapshotResponse, CreateVolumeRequest, CreateVolumeResponse, + DetachServerFileSystemRequest, + DetachServerFileSystemResponse, DetachServerVolumeRequest, DetachServerVolumeResponse, ExportSnapshotRequest, ExportSnapshotResponse, - GetBootscriptResponse, GetDashboardResponse, GetImageResponse, GetIpResponse, @@ -83,7 +87,6 @@ GetVolumeResponse, Image, Ip, - ListBootscriptsResponse, ListImagesResponse, ListIpsResponse, ListPlacementGroupsResponse, @@ -109,6 +112,7 @@ ServerActionRequest, ServerActionRequestVolumeBackupTemplate, ServerActionResponse, + ServerCompatibleTypes, ServerIp, ServerIpv6, ServerLocation, @@ -151,6 +155,7 @@ ) from .marshalling import ( unmarshal_PrivateNIC, + unmarshal_AttachServerFileSystemResponse, unmarshal_AttachServerVolumeResponse, unmarshal_CreateImageResponse, unmarshal_CreateIpResponse, @@ -161,9 +166,9 @@ unmarshal_CreateServerResponse, unmarshal_CreateSnapshotResponse, unmarshal_CreateVolumeResponse, + unmarshal_DetachServerFileSystemResponse, unmarshal_DetachServerVolumeResponse, unmarshal_ExportSnapshotResponse, - unmarshal_GetBootscriptResponse, unmarshal_GetDashboardResponse, unmarshal_GetImageResponse, unmarshal_GetIpResponse, @@ -176,7 +181,6 @@ unmarshal_GetServerTypesAvailabilityResponse, unmarshal_GetSnapshotResponse, unmarshal_GetVolumeResponse, - unmarshal_ListBootscriptsResponse, unmarshal_ListImagesResponse, unmarshal_ListIpsResponse, unmarshal_ListPlacementGroupsResponse, @@ -192,6 +196,7 @@ unmarshal_ListVolumesTypesResponse, unmarshal_MigrationPlan, unmarshal_ServerActionResponse, + unmarshal_ServerCompatibleTypes, unmarshal_SetPlacementGroupResponse, unmarshal_SetPlacementGroupServersResponse, unmarshal_SetSecurityGroupRulesResponse, @@ -210,7 +215,9 @@ unmarshal__SetServerResponse, unmarshal__SetSnapshotResponse, marshal_ApplyBlockMigrationRequest, + marshal_AttachServerFileSystemRequest, marshal_AttachServerVolumeRequest, + marshal_CheckBlockMigrationOrganizationQuotasRequest, marshal_CreateImageRequest, marshal_CreateIpRequest, marshal_CreatePlacementGroupRequest, @@ -220,6 +227,7 @@ marshal_CreateServerRequest, marshal_CreateSnapshotRequest, marshal_CreateVolumeRequest, + marshal_DetachServerFileSystemRequest, marshal_DetachServerVolumeRequest, marshal_ExportSnapshotRequest, marshal_PlanBlockMigrationRequest, @@ -247,13 +255,13 @@ class InstanceV1API(API): """ - Instance API. + This API allows you to manage your CPU and GPU Instances. """ def get_server_types_availability( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, ) -> GetServerTypesAvailabilityResponse: @@ -288,7 +296,7 @@ def get_server_types_availability( def list_servers_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, ) -> ListServersTypesResponse: @@ -323,7 +331,7 @@ def list_servers_types( def list_volumes_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, ) -> ListVolumesTypesResponse: @@ -358,7 +366,7 @@ def list_volumes_types( def list_servers( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, organization: Optional[str] = None, @@ -366,6 +374,7 @@ def list_servers( name: Optional[str] = None, private_ip: Optional[str] = None, without_ip: Optional[bool] = None, + with_ip: Optional[str] = None, commercial_type: Optional[str] = None, state: Optional[ServerState] = None, tags: Optional[List[str]] = None, @@ -386,6 +395,7 @@ def list_servers( :param name: Filter Instances by name (eg. "server1" will return "server100" and "server1" but not "foo"). :param private_ip: List Instances by private_ip. :param without_ip: List Instances that are not attached to a public IP. + :param with_ip: List Instances by IP (both private_ip and public_ip are supported). :param commercial_type: List Instances of this commercial type. :param state: List Instances in this state. :param tags: List Instances with these exact tags (to filter with several tags, use commas to separate them). @@ -424,6 +434,7 @@ def list_servers( "servers": ",".join(servers) if servers and len(servers) > 0 else None, "state": state, "tags": ",".join(tags) if tags and len(tags) > 0 else None, + "with_ip": with_ip, "without_ip": without_ip, }, ) @@ -434,7 +445,7 @@ def list_servers( def list_servers_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, organization: Optional[str] = None, @@ -442,6 +453,7 @@ def list_servers_all( name: Optional[str] = None, private_ip: Optional[str] = None, without_ip: Optional[bool] = None, + with_ip: Optional[str] = None, commercial_type: Optional[str] = None, state: Optional[ServerState] = None, tags: Optional[List[str]] = None, @@ -462,6 +474,7 @@ def list_servers_all( :param name: Filter Instances by name (eg. "server1" will return "server100" and "server1" but not "foo"). :param private_ip: List Instances by private_ip. :param without_ip: List Instances that are not attached to a public IP. + :param with_ip: List Instances by IP (both private_ip and public_ip are supported). :param commercial_type: List Instances of this commercial type. :param state: List Instances in this state. :param tags: List Instances with these exact tags (to filter with several tags, use commas to separate them). @@ -491,6 +504,7 @@ def list_servers_all( "name": name, "private_ip": private_ip, "without_ip": without_ip, + "with_ip": with_ip, "commercial_type": commercial_type, "state": state, "tags": tags, @@ -505,40 +519,41 @@ def list_servers_all( def _create_server( self, *, + zone: Optional[ScwZone] = None, commercial_type: str, - image: str, - enable_ipv6: bool, - zone: Optional[Zone] = None, name: Optional[str] = None, dynamic_ip_required: Optional[bool] = None, routed_ip_enabled: Optional[bool] = None, + image: Optional[str] = None, volumes: Optional[Dict[str, VolumeServerTemplate]] = None, + enable_ipv6: Optional[bool] = None, + protected: bool, public_ip: Optional[str] = None, public_ips: Optional[List[str]] = None, boot_type: Optional[BootType] = None, - bootscript: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, tags: Optional[List[str]] = None, security_group: Optional[str] = None, placement_group: Optional[str] = None, + admin_password_encryption_ssh_key_id: Optional[str] = None, ) -> CreateServerResponse: """ Create an Instance. Create a new Instance of the specified commercial type in the specified zone. Pay attention to the volumes parameter, which takes an object which can be used in different ways to achieve different behaviors. Get more information in the [Technical Information](#technical-information) section of the introduction. - :param commercial_type: Define the Instance commercial type (i.e. GP1-S). - :param image: Instance image ID or label. - :param enable_ipv6: True if IPv6 is enabled on the server. :param zone: Zone to target. If none is passed will use default zone from the config. + :param commercial_type: Define the Instance commercial type (i.e. GP1-S). :param name: Instance name. :param dynamic_ip_required: Define if a dynamic IPv4 is required for the Instance. :param routed_ip_enabled: If true, configure the Instance so it uses the new routed IP mode. + :param image: Instance image ID or label. :param volumes: Volumes attached to the server. + :param enable_ipv6: True if IPv6 is enabled on the server (deprecated and always `False` when `routed_ip_enabled` is `True`). + :param protected: True to activate server protection option. :param public_ip: ID of the reserved IP to attach to the Instance. :param public_ips: A list of reserved IP IDs to attach to the Instance. :param boot_type: Boot type to use. - :param bootscript: Bootscript ID to use when `boot_type` is set to `bootscript`. :param organization: Instance Organization ID. One-Of ('project_identifier'): at most one of 'project', 'organization' could be set. :param project: Instance Project ID. @@ -546,6 +561,7 @@ def _create_server( :param tags: Instance tags. :param security_group: Security group ID. :param placement_group: Placement group ID if Instance must be part of a placement group. + :param admin_password_encryption_ssh_key_id: The public_key value of this key is used to encrypt the admin password. :return: :class:`CreateServerResponse ` Usage: @@ -553,8 +569,7 @@ def _create_server( result = api._create_server( commercial_type="example", - image="example", - enable_ipv6=False, + protected=False, ) """ @@ -567,19 +582,20 @@ def _create_server( CreateServerRequest( zone=zone, commercial_type=commercial_type, - image=image, name=name or random_name(prefix="srv"), dynamic_ip_required=dynamic_ip_required, routed_ip_enabled=routed_ip_enabled, - enable_ipv6=enable_ipv6, + image=image, volumes=volumes, + enable_ipv6=enable_ipv6, + protected=protected, public_ip=public_ip, public_ips=public_ips, boot_type=boot_type, - bootscript=bootscript, tags=tags, security_group=security_group, placement_group=placement_group, + admin_password_encryption_ssh_key_id=admin_password_encryption_ssh_key_id, project=project, organization=organization, ), @@ -594,7 +610,7 @@ def delete_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an Instance. @@ -624,7 +640,7 @@ def get_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetServerResponse: """ Get an Instance. @@ -655,12 +671,11 @@ def get_server( def _set_server( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, id: str, name: str, commercial_type: str, dynamic_ip_required: bool, - enable_ipv6: bool, hostname: str, organization: Optional[str] = None, project: Optional[str] = None, @@ -668,24 +683,25 @@ def _set_server( tags: Optional[List[str]] = None, creation_date: Optional[datetime] = None, routed_ip_enabled: Optional[bool] = None, + enable_ipv6: Optional[bool] = None, image: Optional[Image] = None, protected: bool, private_ip: Optional[str] = None, public_ip: Optional[ServerIp] = None, public_ips: Optional[List[ServerIp]] = None, modification_date: Optional[datetime] = None, - state_detail: str, state: Optional[ServerState] = None, location: Optional[ServerLocation] = None, ipv6: Optional[ServerIpv6] = None, - bootscript: Optional[Bootscript] = None, boot_type: Optional[BootType] = None, + state_detail: str, volumes: Optional[Dict[str, Volume]] = None, security_group: Optional[SecurityGroupSummary] = None, maintenances: Optional[List[ServerMaintenance]] = None, arch: Optional[Arch] = None, placement_group: Optional[PlacementGroup] = None, private_nics: Optional[List[PrivateNIC]] = None, + admin_password_encryption_ssh_key_id: Optional[str] = None, ) -> _SetServerResponse: """ :param zone: Zone to target. If none is passed will use default zone from the config. @@ -693,7 +709,6 @@ def _set_server( :param name: Instance name. :param commercial_type: Instance commercial type (eg. GP1-M). :param dynamic_ip_required: True if a dynamic IPv4 is required. - :param enable_ipv6: True if IPv6 is enabled. :param hostname: Instance host name. :param organization: Instance Organization ID. :param project: Instance Project ID. @@ -701,24 +716,25 @@ def _set_server( :param tags: Tags associated with the Instance. :param creation_date: Instance creation date. :param routed_ip_enabled: True to configure the instance so it uses the new routed IP mode (once this is set to True you cannot set it back to False). + :param enable_ipv6: True if IPv6 is enabled (deprecated and always `False` when `routed_ip_enabled` is `True`). :param image: Provide information on the Instance image. :param protected: Instance protection option is activated. - :param private_ip: Instance private IP address. - :param public_ip: Information about the public IP. + :param private_ip: Instance private IP address (deprecated and always `null` when `routed_ip_enabled` is `True`). + :param public_ip: Information about the public IP (deprecated in favor of `public_ips`). :param public_ips: Information about all the public IPs attached to the server. :param modification_date: Instance modification date. - :param state_detail: Instance state_detail. :param state: Instance state. :param location: Instance location. - :param ipv6: Instance IPv6 address. - :param bootscript: Instance bootscript. + :param ipv6: Instance IPv6 address (deprecated when `routed_ip_enabled` is `True`). :param boot_type: Instance boot type. + :param state_detail: Instance state_detail. :param volumes: Instance volumes. :param security_group: Instance security group. :param maintenances: Instance planned maintenances. :param arch: Instance architecture (refers to the CPU architecture used for the Instance, e.g. x86_64, arm64). :param placement_group: Instance placement group. :param private_nics: Instance private NICs. + :param admin_password_encryption_ssh_key_id: The public_key value of this key is used to encrypt the admin password. When set to an empty string, reset this value and admin_password_encrypted_value to an empty string so a new password may be generated. :return: :class:`_SetServerResponse <_SetServerResponse>` Usage: @@ -729,7 +745,6 @@ def _set_server( name="example", commercial_type="example", dynamic_ip_required=False, - enable_ipv6=False, hostname="example", protected=False, state_detail="example", @@ -748,26 +763,25 @@ def _set_server( id=id, name=name, commercial_type=commercial_type, + organization=organization, dynamic_ip_required=dynamic_ip_required, - enable_ipv6=enable_ipv6, hostname=hostname, - organization=organization, + protected=protected, + state_detail=state_detail, project=project, allowed_actions=allowed_actions, tags=tags, creation_date=creation_date, routed_ip_enabled=routed_ip_enabled, + enable_ipv6=enable_ipv6, image=image, - protected=protected, private_ip=private_ip, public_ip=public_ip, public_ips=public_ips, modification_date=modification_date, - state_detail=state_detail, state=state, location=location, ipv6=ipv6, - bootscript=bootscript, boot_type=boot_type, volumes=volumes, security_group=security_group, @@ -775,6 +789,7 @@ def _set_server( arch=arch, placement_group=placement_group, private_nics=private_nics, + admin_password_encryption_ssh_key_id=admin_password_encryption_ssh_key_id, ), self.client, ), @@ -787,12 +802,11 @@ def _update_server( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, boot_type: Optional[BootType] = None, tags: Optional[List[str]] = None, volumes: Optional[Dict[str, VolumeServerTemplate]] = None, - bootscript: Optional[str] = None, dynamic_ip_required: Optional[bool] = None, routed_ip_enabled: Optional[bool] = None, public_ips: Optional[List[str]] = None, @@ -802,6 +816,7 @@ def _update_server( placement_group: Optional[str] = None, private_nics: Optional[List[str]] = None, commercial_type: Optional[str] = None, + admin_password_encryption_ssh_key_id: Optional[str] = None, ) -> UpdateServerResponse: """ Update an Instance. @@ -812,19 +827,20 @@ def _update_server( :param boot_type: :param tags: Tags of the Instance. :param volumes: - :param bootscript: :param dynamic_ip_required: :param routed_ip_enabled: True to configure the instance so it uses the new routed IP mode (once this is set to True you cannot set it back to False). :param public_ips: A list of reserved IP IDs to attach to the Instance. :param enable_ipv6: - :param protected: + :param protected: True to activate server protection option. :param security_group: :param placement_group: Placement group ID if Instance must be part of a placement group. :param private_nics: Instance private NICs. :param commercial_type: Warning: This field has some restrictions: - Cannot be changed if the Instance is not in `stopped` state. - Cannot be changed if the Instance is in a placement group. + - Cannot be changed from/to a Windows offer to/from a Linux offer. - Local storage requirements of the target commercial_types must be fulfilled (i.e. if an Instance has 80GB of local storage, it can be changed into a GP1-XS, which has a maximum of 150GB, but it cannot be changed into a DEV1-S, which has only 20GB). + :param admin_password_encryption_ssh_key_id: The public_key value of this key is used to encrypt the admin password. When set to an empty string, reset this value and admin_password_encrypted_value to an empty string so a new password may be generated. :return: :class:`UpdateServerResponse ` Usage: @@ -849,7 +865,6 @@ def _update_server( boot_type=boot_type, tags=tags, volumes=volumes, - bootscript=bootscript, dynamic_ip_required=dynamic_ip_required, routed_ip_enabled=routed_ip_enabled, public_ips=public_ips, @@ -859,6 +874,7 @@ def _update_server( placement_group=placement_group, private_nics=private_nics, commercial_type=commercial_type, + admin_password_encryption_ssh_key_id=admin_password_encryption_ssh_key_id, ), self.client, ), @@ -871,7 +887,7 @@ def list_server_actions( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ListServerActionsResponse: """ List Instance actions. @@ -903,10 +919,11 @@ def server_action( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, action: Optional[ServerAction] = None, name: Optional[str] = None, volumes: Optional[Dict[str, ServerActionRequestVolumeBackupTemplate]] = None, + disable_ipv6: Optional[bool] = None, ) -> ServerActionResponse: """ Perform action. @@ -917,12 +934,15 @@ def server_action( * `stop_in_place`: Stop the Instance, but keep the slot on the hypervisor. * `reboot`: Stop the instance and restart it. * `backup`: Create an image with all the volumes of an Instance. - * `terminate`: Delete the Instance along with all attached volumes. + * `terminate`: Delete the Instance along with its attached volumes, except for SBS volumes. * `enable_routed_ip`: Migrate the Instance to the new network stack. - Keep in mind that terminating an Instance will result in the deletion of all attached volumes, including local and block storage. - If you want to preserve your local volumes, you should use the `archive` action instead of `terminate`. Similarly, if you want to keep your block storage volumes, you must first detach them before issuing the `terminate` command. - For more information, read the [Volumes](#path-volumes-list-volumes) documentation. + The `terminate` action will result in the deletion of `l_ssd`, `b_ssd` and `scratch` volumes types, `sbs_volume` volumes type will only be detached. + If you want to preserve your volumes, you should detach them before the Instance deletion or `terminate` action. + + The `backup` action can be done with: + * No `volumes` key in the body: an image is created with snapshots of all the server volumes, except for the `scratch` volumes types. + * `volumes` key in the body with a dictionary as value, in this dictionary volumes UUID as keys and empty dictionaries as values : an image is created with the snapshots of the volumes in `volumes` key. `scratch` volumes types can't be shapshotted. :param server_id: UUID of the Instance. :param zone: Zone to target. If none is passed will use default zone from the config. :param action: Action to perform on the Instance. @@ -930,6 +950,8 @@ def server_action( This field should only be specified when performing a backup action. :param volumes: For each volume UUID, the snapshot parameters of the volume. This field should only be specified when performing a backup action. + :param disable_ipv6: Disable IPv6 on the Instance while performing migration to routed IPs. + This field should only be specified when performing a enable_routed_ip action. :return: :class:`ServerActionResponse ` Usage: @@ -953,6 +975,7 @@ def server_action( action=action, name=name, volumes=volumes, + disable_ipv6=disable_ipv6, ), self.client, ), @@ -965,7 +988,7 @@ def list_server_user_data( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ListServerUserDataResponse: """ List user data. @@ -998,7 +1021,7 @@ def delete_server_user_data( *, server_id: str, key: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete user data. @@ -1027,12 +1050,49 @@ def delete_server_user_data( self._throw_on_error(res) + def get_server_compatible_types( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> ServerCompatibleTypes: + """ + Get Instance compatible types. + Get compatible commercial types that can be used to update the Instance. The compatibility of an Instance offer is based on: + * the CPU architecture + * the OS type + * the required l_ssd storage size + * the required scratch storage size + If the specified Instance offer is flagged as end of service, the best compatible offer is the first returned. + :param server_id: UUID of the Instance you want to get. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ServerCompatibleTypes ` + + Usage: + :: + + result = api.get_server_compatible_types( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/instance/v1/zones/{param_zone}/servers/{param_server_id}/compatible-types", + ) + + self._throw_on_error(res) + return unmarshal_ServerCompatibleTypes(res.json()) + def attach_server_volume( self, *, server_id: str, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, volume_type: Optional[AttachServerVolumeRequestVolumeType] = None, boot: Optional[bool] = None, ) -> AttachServerVolumeResponse: @@ -1079,7 +1139,7 @@ def detach_server_volume( *, server_id: str, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> DetachServerVolumeResponse: """ :param server_id: @@ -1115,10 +1175,94 @@ def detach_server_volume( self._throw_on_error(res) return unmarshal_DetachServerVolumeResponse(res.json()) + def attach_server_file_system( + self, + *, + server_id: str, + filesystem_id: str, + zone: Optional[ScwZone] = None, + ) -> AttachServerFileSystemResponse: + """ + Attach a filesystem volume to an Instance. + :param server_id: + :param filesystem_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`AttachServerFileSystemResponse ` + + Usage: + :: + + result = api.attach_server_file_system( + server_id="example", + filesystem_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/instance/v1/zones/{param_zone}/servers/{param_server_id}/attach-filesystem", + body=marshal_AttachServerFileSystemRequest( + AttachServerFileSystemRequest( + server_id=server_id, + filesystem_id=filesystem_id, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AttachServerFileSystemResponse(res.json()) + + def detach_server_file_system( + self, + *, + server_id: str, + filesystem_id: str, + zone: Optional[ScwZone] = None, + ) -> DetachServerFileSystemResponse: + """ + Detach a filesystem volume to an Instance. + :param server_id: + :param filesystem_id: + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`DetachServerFileSystemResponse ` + + Usage: + :: + + result = api.detach_server_file_system( + server_id="example", + filesystem_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/instance/v1/zones/{param_zone}/servers/{param_server_id}/detach-filesystem", + body=marshal_DetachServerFileSystemRequest( + DetachServerFileSystemRequest( + server_id=server_id, + filesystem_id=filesystem_id, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DetachServerFileSystemResponse(res.json()) + def list_images( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -1171,7 +1315,7 @@ def list_images( def list_images_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -1222,7 +1366,7 @@ def get_image( self, *, image_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetImageResponse: """ Get an Instance image. @@ -1255,9 +1399,8 @@ def create_image( *, root_volume: str, arch: Arch, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, - default_bootscript: Optional[str] = None, extra_volumes: Optional[Dict[str, VolumeTemplate]] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -1271,7 +1414,6 @@ def create_image( :param arch: Architecture of the image. :param zone: Zone to target. If none is passed will use default zone from the config. :param name: Name of the image. - :param default_bootscript: Default bootscript of the image. :param extra_volumes: Additional volumes of the image. :param organization: Organization ID of the image. One-Of ('project_identifier'): at most one of 'project', 'organization' could be set. @@ -1301,7 +1443,6 @@ def create_image( arch=arch, zone=zone, name=name or random_name(prefix="img"), - default_bootscript=default_bootscript, extra_volumes=extra_volumes, tags=tags, public=public, @@ -1318,7 +1459,7 @@ def create_image( def _set_image( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, id: str, name: str, arch: Optional[Arch] = None, @@ -1400,7 +1541,7 @@ def update_image( self, *, image_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, arch: Optional[Arch] = None, extra_volumes: Optional[Dict[str, VolumeImageUpdateTemplate]] = None, @@ -1454,7 +1595,7 @@ def delete_image( self, *, image_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an Instance image. @@ -1483,7 +1624,7 @@ def delete_image( def list_snapshots( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, project: Optional[str] = None, per_page: Optional[int] = None, @@ -1533,7 +1674,7 @@ def list_snapshots( def list_snapshots_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, project: Optional[str] = None, per_page: Optional[int] = None, @@ -1580,7 +1721,7 @@ def list_snapshots_all( def create_snapshot( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, volume_id: Optional[str] = None, tags: Optional[List[str]] = None, @@ -1644,7 +1785,7 @@ def get_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetSnapshotResponse: """ Get a snapshot. @@ -1677,7 +1818,7 @@ def _set_snapshot( *, id: str, name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, volume_type: Optional[VolumeVolumeType] = None, size: int, @@ -1751,7 +1892,7 @@ def update_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, ) -> UpdateSnapshotResponse: @@ -1796,7 +1937,7 @@ def delete_snapshot( self, *, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a snapshot. @@ -1828,13 +1969,13 @@ def export_snapshot( bucket: str, key: str, snapshot_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ExportSnapshotResponse: """ Export a snapshot. - Export a snapshot to a specified S3 bucket in the same region. - :param bucket: S3 bucket name. - :param key: S3 object key. + Export a snapshot to a specified Object Storage bucket in the same region. + :param bucket: Object Storage bucket name. + :param key: Object key. :param snapshot_id: Snapshot ID. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`ExportSnapshotResponse ` @@ -1872,7 +2013,7 @@ def export_snapshot( def list_volumes( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, volume_type: Optional[VolumeVolumeType] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -1922,7 +2063,7 @@ def list_volumes( def list_volumes_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, volume_type: Optional[VolumeVolumeType] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -1969,7 +2110,7 @@ def list_volumes_all( def create_volume( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -2028,7 +2169,7 @@ def get_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetVolumeResponse: """ Get a volume. @@ -2060,7 +2201,7 @@ def update_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, size: Optional[int] = None, @@ -2108,7 +2249,7 @@ def delete_volume( self, *, volume_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a volume. @@ -2137,7 +2278,7 @@ def delete_volume( def list_security_groups( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -2187,7 +2328,7 @@ def list_security_groups( def list_security_groups_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -2236,7 +2377,7 @@ def create_security_group( *, description: str, stateful: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -2308,7 +2449,7 @@ def get_security_group( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetSecurityGroupResponse: """ Get a security group. @@ -2342,7 +2483,7 @@ def delete_security_group( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a security group. @@ -2373,7 +2514,7 @@ def delete_security_group( def _set_security_group( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, id: str, name: str, description: str, @@ -2460,7 +2601,7 @@ def update_security_group( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, description: Optional[str] = None, enable_default_security: Optional[bool] = None, @@ -2527,7 +2668,7 @@ def update_security_group( def list_default_security_group_rules( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ListSecurityGroupRulesResponse: """ Get default rules. @@ -2555,7 +2696,7 @@ def list_security_group_rules( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, ) -> ListSecurityGroupRulesResponse: @@ -2597,7 +2738,7 @@ def list_security_group_rules_all( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, ) -> List[SecurityGroupRule]: @@ -2640,7 +2781,7 @@ def create_security_group_rule( ip_range: str, position: int, editable: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, dest_port_from: Optional[int] = None, dest_port_to: Optional[int] = None, ) -> CreateSecurityGroupRuleResponse: @@ -2705,7 +2846,7 @@ def set_security_group_rules( self, *, security_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, rules: Optional[List[SetSecurityGroupRulesRequestRule]] = None, ) -> SetSecurityGroupRulesResponse: """ @@ -2750,7 +2891,7 @@ def delete_security_group_rule( *, security_group_id: str, security_group_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete rule. @@ -2788,7 +2929,7 @@ def get_security_group_rule( *, security_group_id: str, security_group_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetSecurityGroupRuleResponse: """ Get rule. @@ -2832,7 +2973,7 @@ def _set_security_group_rule( ip_range: str, position: int, editable: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, protocol: Optional[SecurityGroupRuleProtocol] = None, direction: Optional[SecurityGroupRuleDirection] = None, action: Optional[SecurityGroupRuleAction] = None, @@ -2907,7 +3048,7 @@ def update_security_group_rule( *, security_group_id: str, security_group_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, protocol: Optional[SecurityGroupRuleProtocol] = None, direction: Optional[SecurityGroupRuleDirection] = None, action: Optional[SecurityGroupRuleAction] = None, @@ -2974,7 +3115,7 @@ def update_security_group_rule( def list_placement_groups( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, organization: Optional[str] = None, @@ -3021,7 +3162,7 @@ def list_placement_groups( def list_placement_groups_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, per_page: Optional[int] = None, page: Optional[int] = None, organization: Optional[str] = None, @@ -3065,7 +3206,7 @@ def list_placement_groups_all( def create_placement_group( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, organization: Optional[str] = None, project: Optional[str] = None, @@ -3119,7 +3260,7 @@ def get_placement_group( self, *, placement_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetPlacementGroupResponse: """ Get a placement group. @@ -3154,7 +3295,7 @@ def set_placement_group( *, placement_group_id: str, name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, policy_mode: Optional[PlacementGroupPolicyMode] = None, policy_type: Optional[PlacementGroupPolicyType] = None, @@ -3213,7 +3354,7 @@ def update_placement_group( self, *, placement_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, policy_mode: Optional[PlacementGroupPolicyMode] = None, @@ -3266,7 +3407,7 @@ def delete_placement_group( self, *, placement_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete the specified placement group. @@ -3297,7 +3438,7 @@ def get_placement_group_servers( self, *, placement_group_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetPlacementGroupServersResponse: """ Get placement group servers. @@ -3332,7 +3473,7 @@ def set_placement_group_servers( *, placement_group_id: str, servers: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetPlacementGroupServersResponse: """ Set placement group servers. @@ -3377,7 +3518,7 @@ def update_placement_group_servers( *, placement_group_id: str, servers: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> UpdatePlacementGroupServersResponse: """ Update placement group servers. @@ -3420,7 +3561,7 @@ def update_placement_group_servers( def list_ips( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project: Optional[str] = None, organization: Optional[str] = None, tags: Optional[List[str]] = None, @@ -3439,7 +3580,7 @@ def list_ips( :param name: Filter on the IP address (Works as a LIKE operation on the IP address). :param per_page: A positive integer lower or equal to 100 to select the number of items to return. :param page: A positive integer to choose the page to return. - :param type_: Filter on the IP Mobility IP type (whose value should be either 'nat', 'routed_ipv4' or 'routed_ipv6'). + :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`ListIpsResponse ` Usage: @@ -3470,7 +3611,7 @@ def list_ips( def list_ips_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project: Optional[str] = None, organization: Optional[str] = None, tags: Optional[List[str]] = None, @@ -3489,7 +3630,7 @@ def list_ips_all( :param name: Filter on the IP address (Works as a LIKE operation on the IP address). :param per_page: A positive integer lower or equal to 100 to select the number of items to return. :param page: A positive integer to choose the page to return. - :param type_: Filter on the IP Mobility IP type (whose value should be either 'nat', 'routed_ipv4' or 'routed_ipv6'). + :param type_: Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`List[Ip] ` Usage: @@ -3517,7 +3658,7 @@ def list_ips_all( def create_ip( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, project: Optional[str] = None, tags: Optional[List[str]] = None, @@ -3534,7 +3675,7 @@ def create_ip( One-Of ('project_identifier'): at most one of 'project', 'organization' could be set. :param tags: Tags of the IP. :param server: UUID of the Instance you want to attach the IP to. - :param type_: IP type to reserve (either 'nat', 'routed_ipv4' or 'routed_ipv6'). + :param type_: IP type to reserve (either 'routed_ipv4' or 'routed_ipv6'). :return: :class:`CreateIpResponse ` Usage: @@ -3568,7 +3709,7 @@ def get_ip( self, *, ip: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetIpResponse: """ Get a flexible IP. @@ -3600,7 +3741,7 @@ def update_ip( self, *, ip: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, reverse: Optional[str] = None, type_: Optional[IpType] = None, tags: Optional[List[str]] = None, @@ -3612,7 +3753,7 @@ def update_ip( :param ip: IP ID or IP address. :param zone: Zone to target. If none is passed will use default zone from the config. :param reverse: Reverse domain name. - :param type_: Convert a 'nat' IP to a 'routed_ipv4'. + :param type_: Should have no effect. :param tags: An array of keywords you want to tag this IP with. :param server: :return: :class:`UpdateIpResponse ` @@ -3651,7 +3792,7 @@ def delete_ip( self, *, ip: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a flexible IP. @@ -3681,7 +3822,7 @@ def list_private_ni_cs( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -3724,7 +3865,7 @@ def list_private_ni_cs_all( self, *, server_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, per_page: Optional[int] = None, page: Optional[int] = None, @@ -3765,9 +3906,10 @@ def create_private_nic( *, server_id: str, private_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, ip_ids: Optional[List[str]] = None, + ipam_ip_ids: Optional[List[str]] = None, ) -> CreatePrivateNICResponse: """ Create a private NIC connecting an Instance to a Private Network. @@ -3776,6 +3918,7 @@ def create_private_nic( :param zone: Zone to target. If none is passed will use default zone from the config. :param tags: Private NIC tags. :param ip_ids: Ip_ids defined from IPAM. + :param ipam_ip_ids: UUID of IPAM ips, to be attached to the instance in the requested private network. :return: :class:`CreatePrivateNICResponse ` Usage: @@ -3800,6 +3943,7 @@ def create_private_nic( zone=zone, tags=tags, ip_ids=ip_ids, + ipam_ip_ids=ipam_ip_ids, ), self.client, ), @@ -3813,7 +3957,7 @@ def get_private_nic( *, server_id: str, private_nic_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GetPrivateNICResponse: """ Get a private NIC. @@ -3849,7 +3993,7 @@ def update_private_nic( *, server_id: str, private_nic_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, ) -> PrivateNIC: """ @@ -3896,7 +4040,7 @@ def delete_private_nic( *, server_id: str, private_nic_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a private NIC. @@ -3924,134 +4068,10 @@ def delete_private_nic( self._throw_on_error(res) - def list_bootscripts( - self, - *, - zone: Optional[Zone] = None, - arch: Optional[str] = None, - title: Optional[str] = None, - default: Optional[bool] = None, - public: Optional[bool] = None, - per_page: Optional[int] = None, - page: Optional[int] = None, - ) -> ListBootscriptsResponse: - """ - List bootscripts. - :param zone: Zone to target. If none is passed will use default zone from the config. - :param arch: - :param title: - :param default: - :param public: - :param per_page: - :param page: - :return: :class:`ListBootscriptsResponse ` - :deprecated - - Usage: - :: - - result = api.list_bootscripts() - """ - - param_zone = validate_path_param("zone", zone or self.client.default_zone) - - res = self._request( - "GET", - f"/instance/v1/zones/{param_zone}/bootscripts", - params={ - "arch": arch, - "default": default, - "page": page, - "per_page": per_page or self.client.default_page_size, - "public": public, - "title": title, - }, - ) - - self._throw_on_error(res) - return unmarshal_ListBootscriptsResponse(res.json()) - - def list_bootscripts_all( - self, - *, - zone: Optional[Zone] = None, - arch: Optional[str] = None, - title: Optional[str] = None, - default: Optional[bool] = None, - public: Optional[bool] = None, - per_page: Optional[int] = None, - page: Optional[int] = None, - ) -> List[Bootscript]: - """ - List bootscripts. - :param zone: Zone to target. If none is passed will use default zone from the config. - :param arch: - :param title: - :param default: - :param public: - :param per_page: - :param page: - :return: :class:`List[Bootscript] ` - :deprecated - - Usage: - :: - - result = api.list_bootscripts_all() - """ - - return fetch_all_pages( - type=ListBootscriptsResponse, - key="bootscripts", - fetcher=self.list_bootscripts, - args={ - "zone": zone, - "arch": arch, - "title": title, - "default": default, - "public": public, - "per_page": per_page, - "page": page, - }, - ) - - def get_bootscript( - self, - *, - bootscript_id: str, - zone: Optional[Zone] = None, - ) -> GetBootscriptResponse: - """ - Get bootscripts. - Get details of a bootscript with the specified ID. - :param bootscript_id: - :param zone: Zone to target. If none is passed will use default zone from the config. - :return: :class:`GetBootscriptResponse ` - :deprecated - - Usage: - :: - - result = api.get_bootscript( - bootscript_id="example", - ) - """ - - param_zone = validate_path_param("zone", zone or self.client.default_zone) - param_bootscript_id = validate_path_param("bootscript_id", bootscript_id) - - res = self._request( - "GET", - f"/instance/v1/zones/{param_zone}/bootscripts/{param_bootscript_id}", - ) - - self._throw_on_error(res) - return unmarshal_GetBootscriptResponse(res.json()) - def get_dashboard( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization: Optional[str] = None, project: Optional[str] = None, ) -> GetDashboardResponse: @@ -4084,13 +4104,17 @@ def get_dashboard( def plan_block_migration( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, volume_id: Optional[str] = None, snapshot_id: Optional[str] = None, ) -> MigrationPlan: """ Get a volume or snapshot's migration plan. - Given a volume or snapshot, returns the migration plan for a call to the RPC ApplyBlockMigration. This plan will include zero or one volume, and zero or more snapshots, which will need to be migrated together. This RPC does not perform the actual migration itself, ApplyBlockMigration must be used. The validation_key value returned by this call must be provided to the ApplyBlockMigration call to confirm that all resources listed in the plan should be migrated. + Given a volume or snapshot, returns the migration plan but does not perform the actual migration. To perform the migration, you have to call the [Migrate a volume and/or snapshots to SBS](#path-volumes-migrate-a-volume-andor-snapshots-to-sbs-scaleway-block-storage) endpoint afterward. + The endpoint returns the resources that should be migrated together: + - the volume and any snapshots created from the volume, if the call was made to plan a volume migration. + - the base volume of the snapshot (if the volume is not deleted) and its related snapshots, if the call was made to plan a snapshot migration. + The endpoint also returns the validation_key, which must be provided to the [Migrate a volume and/or snapshots to SBS](#path-volumes-migrate-a-volume-andor-snapshots-to-sbs-scaleway-block-storage) endpoint to confirm that all resources listed in the plan should be migrated. :param zone: Zone to target. If none is passed will use default zone from the config. :param volume_id: The volume for which the migration plan will be generated. One-Of ('resource'): at most one of 'volume_id', 'snapshot_id' could be set. @@ -4126,18 +4150,18 @@ def apply_block_migration( self, *, validation_key: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, volume_id: Optional[str] = None, snapshot_id: Optional[str] = None, ) -> None: """ Migrate a volume and/or snapshots to SBS (Scaleway Block Storage). - To be used, this RPC must be preceded by a call to PlanBlockMigration. To migrate all resources mentioned in the MigrationPlan, the validation_key returned in the MigrationPlan must be provided. - :param validation_key: A value to be retrieved from a call to PlanBlockMigration, to confirm that the volume and/or snapshots specified in said plan should be migrated. + To be used, the call to this endpoint must be preceded by a call to the [Get a volume or snapshot's migration plan](#path-volumes-get-a-volume-or-snapshots-migration-plan) endpoint. To migrate all resources mentioned in the migration plan, the validation_key returned in the plan must be provided. + :param validation_key: A value to be retrieved from a call to the [Get a volume or snapshot's migration plan](#path-volumes-get-a-volume-or-snapshots-migration-plan) endpoint, to confirm that the volume and/or snapshots specified in said plan should be migrated. :param zone: Zone to target. If none is passed will use default zone from the config. - :param volume_id: The volume to migrate, along with potentially other resources, according to the migration plan generated with a call to PlanBlockMigration. + :param volume_id: The volume to migrate, along with potentially other resources, according to the migration plan generated with a call to the [Get a volume or snapshot's migration plan](#path-volumes-get-a-volume-or-snapshots-migration-plan) endpoint. One-Of ('resource'): at most one of 'volume_id', 'snapshot_id' could be set. - :param snapshot_id: The snapshot to migrate, along with potentially other resources, according to the migration plan generated with a call to PlanBlockMigration. + :param snapshot_id: The snapshot to migrate, along with potentially other resources, according to the migration plan generated with a call to the [Get a volume or snapshot's migration plan](#path-volumes-get-a-volume-or-snapshots-migration-plan) endpoint. One-Of ('resource'): at most one of 'volume_id', 'snapshot_id' could be set. Usage: @@ -4165,3 +4189,35 @@ def apply_block_migration( ) self._throw_on_error(res) + + def check_block_migration_organization_quotas( + self, + *, + zone: Optional[ScwZone] = None, + organization: Optional[str] = None, + ) -> None: + """ + :param zone: Zone to target. If none is passed will use default zone from the config. + :param organization: + + Usage: + :: + + result = api.check_block_migration_organization_quotas() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/instance/v1/zones/{param_zone}/block-migration/check-organization-quotas", + body=marshal_CheckBlockMigrationOrganizationQuotasRequest( + CheckBlockMigrationOrganizationQuotasRequest( + zone=zone, + organization=organization, + ), + self.client, + ), + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/instance/v1/custom_api.py b/scaleway/scaleway/instance/v1/custom_api.py new file mode 100644 index 00000000..1892caf8 --- /dev/null +++ b/scaleway/scaleway/instance/v1/custom_api.py @@ -0,0 +1,130 @@ +from typing import Optional, Dict + +from requests import Response + +from scaleway_core.bridge import Zone as ScwZone +from scaleway_core.utils import validate_path_param +from .api import InstanceV1API +from .custom_marshalling import marshal_GetServerUserDataRequest +from .custom_types import GetServerUserDataRequest, GetAllServerUserDataResponse + + +class InstanceUtilsV1API(InstanceV1API): + """ + This API extends InstanceV1API by adding utility methods for managing Instance resources, + such as getting and setting server user data, while inheriting all methods of InstanceV1API. + """ + + def get_server_user_data( + self, server_id: str, key: str, zone: Optional[ScwZone] = None + ) -> Response: + """ + GetServerUserData gets the content of a user data on a server for the given key. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param server_id: + :param key: + :return: A plain text response with data user information + + Usage: + :: + + result = api.get_server_user_data( + server_id="example", + key="example", + ) + """ + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "GET", + f"/instance/v1/zones/{param_zone}/servers/{param_server_id}/user_data/{key}", + body=marshal_GetServerUserDataRequest( + GetServerUserDataRequest( + zone=zone, + server_id=server_id, + key=key, + ), + self.client, + ), + ) + self._throw_on_error(res) + return res + + def set_server_user_data( + self, server_id: str, key: str, content: bytes, zone: Optional[ScwZone] = None + ) -> Response: + """ + Sets the content of a user data on a server for the given key. + :param zone: Zone to target. If none is passed, it will use the default zone from the config. + :param server_id: The ID of the server. + :param key: The user data key. + :param content: The content to set as user data in bytes. + :return: A plain text response confirming the operation. + """ + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + headers = { + "Content-Type": "text/plain", + } + res = self._request( + "PATCH", + f"/instance/v1/zones/{param_zone}/servers/{param_server_id}/user_data/{key}", + body=content, + headers=headers, + ) + + self._throw_on_error(res) + return res + + def get_all_server_user_data( + self, server_id: str, zone: Optional[ScwZone] = None + ) -> GetAllServerUserDataResponse: + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + all_user_data_res = InstanceUtilsV1API.list_server_user_data( + self, server_id=param_server_id, zone=param_zone + ) + + user_data: Dict[str, bytes] = {} + for key in all_user_data_res.user_data: + value = InstanceUtilsV1API.get_server_user_data( + self, server_id=param_server_id, key=key + ) + print("value: ", value) + user_data[key] = value.content + + res = GetAllServerUserDataResponse(user_data=user_data) + + return res + + def set_all_server_user_data( + self, + server_id: str, + user_data: Dict[str, bytes], + zone: Optional[ScwZone] = None, + ) -> Optional[None]: + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + all_user_data_res = InstanceUtilsV1API.list_server_user_data( + self, server_id=param_server_id, zone=param_zone + ) + for key in all_user_data_res.user_data: + if user_data.get(key) is not None: + continue + InstanceUtilsV1API.delete_server_user_data( + self, server_id=param_server_id, key=key + ) + + for key in user_data: + InstanceUtilsV1API.set_server_user_data( + self, + server_id=param_server_id, + zone=param_zone, + key=key, + content=user_data[key], + ) + + return None diff --git a/scaleway/scaleway/instance/v1/custom_marshalling.py b/scaleway/scaleway/instance/v1/custom_marshalling.py new file mode 100644 index 00000000..a4f3c840 --- /dev/null +++ b/scaleway/scaleway/instance/v1/custom_marshalling.py @@ -0,0 +1,35 @@ +from typing import Dict, Any + +from scaleway.instance.v1.custom_types import ( + GetServerUserDataRequest, + GetAllServerUserDataRequest, +) +from scaleway_core.profile import ProfileDefaults + + +def marshal_GetServerUserDataRequest( + request: GetServerUserDataRequest, defaults: ProfileDefaults +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.server_id is not None: + output["server_id"] = request.server_id + if request.key is not None: + output["key"] = request.key + if request.zone is not None: + output["zone"] = request.zone + + return output + + +def marshal_ListServerUserDataRequest( + request: GetAllServerUserDataRequest, defaults: ProfileDefaults +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.server_id is not None: + output["server_id"] = request.server_id + if request.zone is not None: + output["zone"] = request.zone + + return output diff --git a/scaleway/scaleway/instance/v1/custom_types.py b/scaleway/scaleway/instance/v1/custom_types.py new file mode 100644 index 00000000..043e9b3e --- /dev/null +++ b/scaleway/scaleway/instance/v1/custom_types.py @@ -0,0 +1,46 @@ +from dataclasses import dataclass +from typing import Optional, Dict + +from scaleway_core.bridge import Zone as ScwZone + + +@dataclass +class GetServerUserDataRequest: + server_id: str + + """ + Key defines the user data key to get + """ + key: str + + """ + Zone of the user data to get + """ + zone: Optional[ScwZone] + + +@dataclass +class GetAllServerUserDataRequest: + server_id: str + + """ + Zone of the user data to get + """ + zone: Optional[ScwZone] + + +@dataclass +class GetAllServerUserDataResponse: + user_data: Dict[str, bytes] + + +@dataclass +class SetAllServerUserDataRequest: + server_id: str + + user_data: Dict[str, bytes] + + """ + Zone of the user data to set + """ + zone: Optional[ScwZone] diff --git a/scaleway/scaleway/instance/v1/marshalling.py b/scaleway/scaleway/instance/v1/marshalling.py index 0d7765d5..86c38fc2 100644 --- a/scaleway/scaleway/instance/v1/marshalling.py +++ b/scaleway/scaleway/instance/v1/marshalling.py @@ -37,6 +37,7 @@ ServerMaintenance, VolumeServer, Server, + AttachServerFileSystemResponse, AttachServerVolumeResponse, CreateImageResponse, Ip, @@ -53,9 +54,9 @@ Task, CreateSnapshotResponse, CreateVolumeResponse, + DetachServerFileSystemResponse, DetachServerVolumeResponse, ExportSnapshotResponse, - GetBootscriptResponse, Dashboard, GetDashboardResponse, GetImageResponse, @@ -71,7 +72,6 @@ GetServerTypesAvailabilityResponse, GetSnapshotResponse, GetVolumeResponse, - ListBootscriptsResponse, ListImagesResponse, ListIpsResponse, ListPlacementGroupsResponse, @@ -84,6 +84,7 @@ ServerTypeNetworkInterface, ServerTypeVolumeConstraintSizes, ServerTypeCapabilities, + ServerTypeGPUInfo, ServerTypeNetwork, ServerTypeVolumeConstraintsByType, ServerType, @@ -96,6 +97,7 @@ ListVolumesTypesResponse, MigrationPlan, ServerActionResponse, + ServerCompatibleTypes, SetPlacementGroupResponse, SetPlacementGroupServersResponse, SetSecurityGroupRulesResponse, @@ -109,7 +111,9 @@ UpdateSnapshotResponse, UpdateVolumeResponse, ApplyBlockMigrationRequest, + AttachServerFileSystemRequest, AttachServerVolumeRequest, + CheckBlockMigrationOrganizationQuotasRequest, VolumeTemplate, CreateImageRequest, CreateIpRequest, @@ -121,6 +125,7 @@ CreateServerRequest, CreateSnapshotRequest, CreateVolumeRequest, + DetachServerFileSystemRequest, DetachServerVolumeRequest, ExportSnapshotRequest, PlanBlockMigrationRequest, @@ -208,6 +213,10 @@ def unmarshal_Bootscript(data: Any) -> Bootscript: args: Dict[str, Any] = {} + field = data.get("architecture", None) + if field is not None: + args["architecture"] = field + field = data.get("bootcmdargs", None) if field is not None: args["bootcmdargs"] = field @@ -236,10 +245,6 @@ def unmarshal_Bootscript(data: Any) -> Bootscript: if field is not None: args["organization"] = field - field = data.get("project", None) - if field is not None: - args["project"] = field - field = data.get("public", None) if field is not None: args["public"] = field @@ -248,9 +253,9 @@ def unmarshal_Bootscript(data: Any) -> Bootscript: if field is not None: args["title"] = field - field = data.get("arch", None) + field = data.get("project", None) if field is not None: - args["arch"] = field + args["project"] = field field = data.get("zone", None) if field is not None: @@ -294,18 +299,24 @@ def unmarshal_Volume(data: Any) -> Volume: field = data.get("export_uri", None) if field is not None: args["export_uri"] = field + else: + args["export_uri"] = None field = data.get("creation_date", None) if field is not None: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None field = data.get("tags", None) if field is not None: @@ -322,6 +333,8 @@ def unmarshal_Volume(data: Any) -> Volume: field = data.get("server", None) if field is not None: args["server"] = unmarshal_ServerSummary(field) + else: + args["server"] = None return Volume(**args) @@ -394,16 +407,22 @@ def unmarshal_Image(data: Any) -> Image: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None field = data.get("default_bootscript", None) if field is not None: args["default_bootscript"] = unmarshal_Bootscript(field) + else: + args["default_bootscript"] = None field = data.get("public", None) if field is not None: @@ -428,6 +447,8 @@ def unmarshal_Image(data: Any) -> Image: field = data.get("root_volume", None) if field is not None: args["root_volume"] = unmarshal_VolumeSummary(field) + else: + args["root_volume"] = None return Image(**args) @@ -618,6 +639,8 @@ def unmarshal_ServerMaintenance(data: Any) -> ServerMaintenance: field = data.get("start_date", None) if field is not None: args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None return ServerMaintenance(**args) @@ -637,34 +660,36 @@ def unmarshal_VolumeServer(data: Any) -> VolumeServer: field = data.get("name", None) if field is not None: args["name"] = field + else: + args["name"] = None field = data.get("export_uri", None) if field is not None: args["export_uri"] = field + else: + args["export_uri"] = None field = data.get("organization", None) if field is not None: args["organization"] = field - - field = data.get("size", None) - if field is not None: - args["size"] = field + else: + args["organization"] = None field = data.get("server", None) if field is not None: args["server"] = unmarshal_ServerSummary(field) + else: + args["server"] = None - field = data.get("volume_type", None) - if field is not None: - args["volume_type"] = field - - field = data.get("state", None) + field = data.get("size", None) if field is not None: - args["state"] = field + args["size"] = field + else: + args["size"] = None - field = data.get("project", None) + field = data.get("volume_type", None) if field is not None: - args["project"] = field + args["volume_type"] = field field = data.get("boot", None) if field is not None: @@ -679,12 +704,28 @@ def unmarshal_VolumeServer(data: Any) -> VolumeServer: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None + + field = data.get("state", None) + if field is not None: + args["state"] = field + else: + args["state"] = None + + field = data.get("project", None) + if field is not None: + args["project"] = field + else: + args["project"] = None return VolumeServer(**args) @@ -732,19 +773,13 @@ def unmarshal_Server(data: Any) -> Server: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("dynamic_ip_required", None) if field is not None: args["dynamic_ip_required"] = field - field = data.get("routed_ip_enabled", None) - if field is not None: - args["routed_ip_enabled"] = field - - field = data.get("enable_ipv6", None) - if field is not None: - args["enable_ipv6"] = field - field = data.get("hostname", None) if field is not None: args["hostname"] = field @@ -753,17 +788,35 @@ def unmarshal_Server(data: Any) -> Server: if field is not None: args["protected"] = field + field = data.get("routed_ip_enabled", None) + if field is not None: + args["routed_ip_enabled"] = field + else: + args["routed_ip_enabled"] = None + + field = data.get("enable_ipv6", None) + if field is not None: + args["enable_ipv6"] = field + else: + args["enable_ipv6"] = None + field = data.get("image", None) if field is not None: args["image"] = unmarshal_Image(field) + else: + args["image"] = None field = data.get("private_ip", None) if field is not None: args["private_ip"] = field + else: + args["private_ip"] = None field = data.get("public_ip", None) if field is not None: args["public_ip"] = unmarshal_ServerIp(field) + else: + args["public_ip"] = None field = data.get("public_ips", None) if field is not None: @@ -791,43 +844,53 @@ def unmarshal_Server(data: Any) -> Server: else None ) + field = data.get("maintenances", None) + if field is not None: + args["maintenances"] = ( + [unmarshal_ServerMaintenance(v) for v in field] + if field is not None + else None + ) + + field = data.get("state_detail", None) + if field is not None: + args["state_detail"] = field + + field = data.get("arch", None) + if field is not None: + args["arch"] = field + field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None field = data.get("location", None) if field is not None: args["location"] = unmarshal_ServerLocation(field) + else: + args["location"] = None field = data.get("ipv6", None) if field is not None: args["ipv6"] = unmarshal_ServerIpv6(field) - - field = data.get("bootscript", None) - if field is not None: - args["bootscript"] = unmarshal_Bootscript(field) + else: + args["ipv6"] = None field = data.get("security_group", None) if field is not None: args["security_group"] = unmarshal_SecurityGroupSummary(field) + else: + args["security_group"] = None - field = data.get("maintenances", None) - if field is not None: - args["maintenances"] = ( - [unmarshal_ServerMaintenance(v) for v in field] - if field is not None - else None - ) - - field = data.get("state_detail", None) - if field is not None: - args["state_detail"] = field - - field = data.get("arch", None) + field = data.get("placement_group", None) if field is not None: - args["arch"] = field + args["placement_group"] = unmarshal_PlacementGroup(field) + else: + args["placement_group"] = None field = data.get("private_nics", None) if field is not None: @@ -839,13 +902,44 @@ def unmarshal_Server(data: Any) -> Server: if field is not None: args["zone"] = field - field = data.get("placement_group", None) + field = data.get("end_of_service", None) if field is not None: - args["placement_group"] = unmarshal_PlacementGroup(field) + args["end_of_service"] = field + + field = data.get("admin_password_encryption_ssh_key_id", None) + if field is not None: + args["admin_password_encryption_ssh_key_id"] = field + else: + args["admin_password_encryption_ssh_key_id"] = None + + field = data.get("admin_password_encrypted_value", None) + if field is not None: + args["admin_password_encrypted_value"] = field + else: + args["admin_password_encrypted_value"] = None return Server(**args) +def unmarshal_AttachServerFileSystemResponse( + data: Any, +) -> AttachServerFileSystemResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AttachServerFileSystemResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("server", None) + if field is not None: + args["server"] = unmarshal_Server(field) + else: + args["server"] = None + + return AttachServerFileSystemResponse(**args) + + def unmarshal_AttachServerVolumeResponse(data: Any) -> AttachServerVolumeResponse: if not isinstance(data, dict): raise TypeError( @@ -857,6 +951,8 @@ def unmarshal_AttachServerVolumeResponse(data: Any) -> AttachServerVolumeRespons field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None return AttachServerVolumeResponse(**args) @@ -872,6 +968,8 @@ def unmarshal_CreateImageResponse(data: Any) -> CreateImageResponse: field = data.get("image", None) if field is not None: args["image"] = unmarshal_Image(field) + else: + args["image"] = None return CreateImageResponse(**args) @@ -904,7 +1002,7 @@ def unmarshal_Ip(data: Any) -> Ip: if field is not None: args["project"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -927,10 +1025,14 @@ def unmarshal_Ip(data: Any) -> Ip: field = data.get("reverse", None) if field is not None: args["reverse"] = field + else: + args["reverse"] = None field = data.get("server", None) if field is not None: args["server"] = unmarshal_ServerSummary(field) + else: + args["server"] = None return Ip(**args) @@ -946,6 +1048,8 @@ def unmarshal_CreateIpResponse(data: Any) -> CreateIpResponse: field = data.get("ip", None) if field is not None: args["ip"] = unmarshal_Ip(field) + else: + args["ip"] = None return CreateIpResponse(**args) @@ -961,6 +1065,8 @@ def unmarshal_CreatePlacementGroupResponse(data: Any) -> CreatePlacementGroupRes field = data.get("placement_group", None) if field is not None: args["placement_group"] = unmarshal_PlacementGroup(field) + else: + args["placement_group"] = None return CreatePlacementGroupResponse(**args) @@ -976,6 +1082,8 @@ def unmarshal_CreatePrivateNICResponse(data: Any) -> CreatePrivateNICResponse: field = data.get("private_nic", None) if field is not None: args["private_nic"] = unmarshal_PrivateNIC(field) + else: + args["private_nic"] = None return CreatePrivateNICResponse(**args) @@ -1049,18 +1157,24 @@ def unmarshal_SecurityGroup(data: Any) -> SecurityGroup: field = data.get("organization_default", None) if field is not None: args["organization_default"] = field + else: + args["organization_default"] = None field = data.get("creation_date", None) if field is not None: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None return SecurityGroup(**args) @@ -1076,6 +1190,8 @@ def unmarshal_CreateSecurityGroupResponse(data: Any) -> CreateSecurityGroupRespo field = data.get("security_group", None) if field is not None: args["security_group"] = unmarshal_SecurityGroup(field) + else: + args["security_group"] = None return CreateSecurityGroupResponse(**args) @@ -1123,10 +1239,14 @@ def unmarshal_SecurityGroupRule(data: Any) -> SecurityGroupRule: field = data.get("dest_port_from", None) if field is not None: args["dest_port_from"] = field + else: + args["dest_port_from"] = None field = data.get("dest_port_to", None) if field is not None: args["dest_port_to"] = field + else: + args["dest_port_to"] = None return SecurityGroupRule(**args) @@ -1144,6 +1264,8 @@ def unmarshal_CreateSecurityGroupRuleResponse( field = data.get("rule", None) if field is not None: args["rule"] = unmarshal_SecurityGroupRule(field) + else: + args["rule"] = None return CreateSecurityGroupRuleResponse(**args) @@ -1159,6 +1281,8 @@ def unmarshal_CreateServerResponse(data: Any) -> CreateServerResponse: field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None return CreateServerResponse(**args) @@ -1229,22 +1353,30 @@ def unmarshal_Snapshot(data: Any) -> Snapshot: field = data.get("base_volume", None) if field is not None: args["base_volume"] = unmarshal_SnapshotBaseVolume(field) + else: + args["base_volume"] = None field = data.get("creation_date", None) if field is not None: args["creation_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["creation_date"] = None field = data.get("modification_date", None) if field is not None: args["modification_date"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["modification_date"] = None field = data.get("error_reason", None) if field is not None: args["error_reason"] = field + else: + args["error_reason"] = None return Snapshot(**args) @@ -1288,12 +1420,16 @@ def unmarshal_Task(data: Any) -> Task: field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None field = data.get("terminated_at", None) if field is not None: args["terminated_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["terminated_at"] = None return Task(**args) @@ -1309,10 +1445,14 @@ def unmarshal_CreateSnapshotResponse(data: Any) -> CreateSnapshotResponse: field = data.get("snapshot", None) if field is not None: args["snapshot"] = unmarshal_Snapshot(field) + else: + args["snapshot"] = None field = data.get("task", None) if field is not None: args["task"] = unmarshal_Task(field) + else: + args["task"] = None return CreateSnapshotResponse(**args) @@ -1328,14 +1468,18 @@ def unmarshal_CreateVolumeResponse(data: Any) -> CreateVolumeResponse: field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None return CreateVolumeResponse(**args) -def unmarshal_DetachServerVolumeResponse(data: Any) -> DetachServerVolumeResponse: +def unmarshal_DetachServerFileSystemResponse( + data: Any, +) -> DetachServerFileSystemResponse: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'DetachServerVolumeResponse' failed as data isn't a dictionary." + "Unmarshalling the type 'DetachServerFileSystemResponse' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} @@ -1343,38 +1487,44 @@ def unmarshal_DetachServerVolumeResponse(data: Any) -> DetachServerVolumeRespons field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None - return DetachServerVolumeResponse(**args) + return DetachServerFileSystemResponse(**args) -def unmarshal_ExportSnapshotResponse(data: Any) -> ExportSnapshotResponse: +def unmarshal_DetachServerVolumeResponse(data: Any) -> DetachServerVolumeResponse: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'ExportSnapshotResponse' failed as data isn't a dictionary." + "Unmarshalling the type 'DetachServerVolumeResponse' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} - field = data.get("task", None) + field = data.get("server", None) if field is not None: - args["task"] = unmarshal_Task(field) + args["server"] = unmarshal_Server(field) + else: + args["server"] = None - return ExportSnapshotResponse(**args) + return DetachServerVolumeResponse(**args) -def unmarshal_GetBootscriptResponse(data: Any) -> GetBootscriptResponse: +def unmarshal_ExportSnapshotResponse(data: Any) -> ExportSnapshotResponse: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'GetBootscriptResponse' failed as data isn't a dictionary." + "Unmarshalling the type 'ExportSnapshotResponse' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} - field = data.get("bootscript", None) + field = data.get("task", None) if field is not None: - args["bootscript"] = unmarshal_Bootscript(field) + args["task"] = unmarshal_Task(field) + else: + args["task"] = None - return GetBootscriptResponse(**args) + return ExportSnapshotResponse(**args) def unmarshal_Dashboard(data: Any) -> Dashboard: @@ -1425,18 +1575,10 @@ def unmarshal_Dashboard(data: Any) -> Dashboard: if field is not None: args["volumes_l_ssd_count"] = field - field = data.get("volumes_b_ssd_count", None) - if field is not None: - args["volumes_b_ssd_count"] = field - field = data.get("volumes_l_ssd_total_size", None) if field is not None: args["volumes_l_ssd_total_size"] = field - field = data.get("volumes_b_ssd_total_size", None) - if field is not None: - args["volumes_b_ssd_total_size"] = field - field = data.get("private_nics_count", None) if field is not None: args["private_nics_count"] = field @@ -1445,6 +1587,18 @@ def unmarshal_Dashboard(data: Any) -> Dashboard: if field is not None: args["placement_groups_count"] = field + field = data.get("volumes_b_ssd_count", None) + if field is not None: + args["volumes_b_ssd_count"] = field + else: + args["volumes_b_ssd_count"] = None + + field = data.get("volumes_b_ssd_total_size", None) + if field is not None: + args["volumes_b_ssd_total_size"] = field + else: + args["volumes_b_ssd_total_size"] = None + return Dashboard(**args) @@ -1459,6 +1613,8 @@ def unmarshal_GetDashboardResponse(data: Any) -> GetDashboardResponse: field = data.get("dashboard", None) if field is not None: args["dashboard"] = unmarshal_Dashboard(field) + else: + args["dashboard"] = None return GetDashboardResponse(**args) @@ -1474,6 +1630,8 @@ def unmarshal_GetImageResponse(data: Any) -> GetImageResponse: field = data.get("image", None) if field is not None: args["image"] = unmarshal_Image(field) + else: + args["image"] = None return GetImageResponse(**args) @@ -1489,6 +1647,8 @@ def unmarshal_GetIpResponse(data: Any) -> GetIpResponse: field = data.get("ip", None) if field is not None: args["ip"] = unmarshal_Ip(field) + else: + args["ip"] = None return GetIpResponse(**args) @@ -1504,6 +1664,8 @@ def unmarshal_GetPlacementGroupResponse(data: Any) -> GetPlacementGroupResponse: field = data.get("placement_group", None) if field is not None: args["placement_group"] = unmarshal_PlacementGroup(field) + else: + args["placement_group"] = None return GetPlacementGroupResponse(**args) @@ -1563,6 +1725,8 @@ def unmarshal_GetPrivateNICResponse(data: Any) -> GetPrivateNICResponse: field = data.get("private_nic", None) if field is not None: args["private_nic"] = unmarshal_PrivateNIC(field) + else: + args["private_nic"] = None return GetPrivateNICResponse(**args) @@ -1578,6 +1742,8 @@ def unmarshal_GetSecurityGroupResponse(data: Any) -> GetSecurityGroupResponse: field = data.get("security_group", None) if field is not None: args["security_group"] = unmarshal_SecurityGroup(field) + else: + args["security_group"] = None return GetSecurityGroupResponse(**args) @@ -1593,6 +1759,8 @@ def unmarshal_GetSecurityGroupRuleResponse(data: Any) -> GetSecurityGroupRuleRes field = data.get("rule", None) if field is not None: args["rule"] = unmarshal_SecurityGroupRule(field) + else: + args["rule"] = None return GetSecurityGroupRuleResponse(**args) @@ -1608,6 +1776,8 @@ def unmarshal_GetServerResponse(data: Any) -> GetServerResponse: field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None return GetServerResponse(**args) @@ -1668,6 +1838,8 @@ def unmarshal_GetSnapshotResponse(data: Any) -> GetSnapshotResponse: field = data.get("snapshot", None) if field is not None: args["snapshot"] = unmarshal_Snapshot(field) + else: + args["snapshot"] = None return GetSnapshotResponse(**args) @@ -1683,31 +1855,12 @@ def unmarshal_GetVolumeResponse(data: Any) -> GetVolumeResponse: field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None return GetVolumeResponse(**args) -def unmarshal_ListBootscriptsResponse(data: Any) -> ListBootscriptsResponse: - if not isinstance(data, dict): - raise TypeError( - "Unmarshalling the type 'ListBootscriptsResponse' failed as data isn't a dictionary." - ) - - args: Dict[str, Any] = {} - - field = data.get("total_count", None) - if field is not None: - args["total_count"] = field - - field = data.get("bootscripts", None) - if field is not None: - args["bootscripts"] = ( - [unmarshal_Bootscript(v) for v in field] if field is not None else None - ) - - return ListBootscriptsResponse(**args) - - def unmarshal_ListImagesResponse(data: Any) -> ListImagesResponse: if not isinstance(data, dict): raise TypeError( @@ -1900,10 +2053,14 @@ def unmarshal_ServerTypeNetworkInterface(data: Any) -> ServerTypeNetworkInterfac field = data.get("internal_bandwidth", None) if field is not None: args["internal_bandwidth"] = field + else: + args["internal_bandwidth"] = None field = data.get("internet_bandwidth", None) if field is not None: args["internet_bandwidth"] = field + else: + args["internet_bandwidth"] = None return ServerTypeNetworkInterface(**args) @@ -1941,13 +2098,42 @@ def unmarshal_ServerTypeCapabilities(data: Any) -> ServerTypeCapabilities: if field is not None: args["boot_types"] = [BootType(v) for v in field] if field is not None else None + field = data.get("max_file_systems", None) + if field is not None: + args["max_file_systems"] = field + field = data.get("block_storage", None) if field is not None: args["block_storage"] = field + else: + args["block_storage"] = None return ServerTypeCapabilities(**args) +def unmarshal_ServerTypeGPUInfo(data: Any) -> ServerTypeGPUInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerTypeGPUInfo' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("gpu_manufacturer", None) + if field is not None: + args["gpu_manufacturer"] = field + + field = data.get("gpu_name", None) + if field is not None: + args["gpu_name"] = field + + field = data.get("gpu_memory", None) + if field is not None: + args["gpu_memory"] = field + + return ServerTypeGPUInfo(**args) + + def unmarshal_ServerTypeNetwork(data: Any) -> ServerTypeNetwork: if not isinstance(data, dict): raise TypeError( @@ -1971,10 +2157,14 @@ def unmarshal_ServerTypeNetwork(data: Any) -> ServerTypeNetwork: field = data.get("sum_internal_bandwidth", None) if field is not None: args["sum_internal_bandwidth"] = field + else: + args["sum_internal_bandwidth"] = None field = data.get("sum_internet_bandwidth", None) if field is not None: args["sum_internet_bandwidth"] = field + else: + args["sum_internet_bandwidth"] = None return ServerTypeNetwork(**args) @@ -1992,6 +2182,8 @@ def unmarshal_ServerTypeVolumeConstraintsByType( field = data.get("l_ssd", None) if field is not None: args["l_ssd"] = unmarshal_ServerTypeVolumeConstraintSizes(field) + else: + args["l_ssd"] = None return ServerTypeVolumeConstraintsByType(**args) @@ -2007,6 +2199,8 @@ def unmarshal_ServerType(data: Any) -> ServerType: field = data.get("monthly_price", None) if field is not None: args["monthly_price"] = field + else: + args["monthly_price"] = None field = data.get("hourly_price", None) if field is not None: @@ -2028,35 +2222,59 @@ def unmarshal_ServerType(data: Any) -> ServerType: if field is not None: args["arch"] = field - field = data.get("baremetal", None) + field = data.get("end_of_service", None) if field is not None: - args["baremetal"] = field + args["end_of_service"] = field field = data.get("per_volume_constraint", None) if field is not None: args["per_volume_constraint"] = unmarshal_ServerTypeVolumeConstraintsByType( field ) + else: + args["per_volume_constraint"] = None field = data.get("volumes_constraint", None) if field is not None: args["volumes_constraint"] = unmarshal_ServerTypeVolumeConstraintSizes(field) + else: + args["volumes_constraint"] = None field = data.get("gpu", None) if field is not None: args["gpu"] = field + else: + args["gpu"] = None + + field = data.get("gpu_info", None) + if field is not None: + args["gpu_info"] = unmarshal_ServerTypeGPUInfo(field) + else: + args["gpu_info"] = None field = data.get("network", None) if field is not None: args["network"] = unmarshal_ServerTypeNetwork(field) + else: + args["network"] = None field = data.get("capabilities", None) if field is not None: args["capabilities"] = unmarshal_ServerTypeCapabilities(field) + else: + args["capabilities"] = None field = data.get("scratch_storage_max_size", None) if field is not None: args["scratch_storage_max_size"] = field + else: + args["scratch_storage_max_size"] = None + + field = data.get("block_bandwidth", None) + if field is not None: + args["block_bandwidth"] = field + else: + args["block_bandwidth"] = None return ServerType(**args) @@ -2175,10 +2393,14 @@ def unmarshal_VolumeType(data: Any) -> VolumeType: field = data.get("capabilities", None) if field is not None: args["capabilities"] = unmarshal_VolumeTypeCapabilities(field) + else: + args["capabilities"] = None field = data.get("constraints", None) if field is not None: args["constraints"] = unmarshal_VolumeTypeConstraints(field) + else: + args["constraints"] = None return VolumeType(**args) @@ -2227,6 +2449,8 @@ def unmarshal_MigrationPlan(data: Any) -> MigrationPlan: field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None return MigrationPlan(**args) @@ -2242,10 +2466,27 @@ def unmarshal_ServerActionResponse(data: Any) -> ServerActionResponse: field = data.get("task", None) if field is not None: args["task"] = unmarshal_Task(field) + else: + args["task"] = None return ServerActionResponse(**args) +def unmarshal_ServerCompatibleTypes(data: Any) -> ServerCompatibleTypes: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerCompatibleTypes' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("compatible_types", None) + if field is not None: + args["compatible_types"] = field + + return ServerCompatibleTypes(**args) + + def unmarshal_SetPlacementGroupResponse(data: Any) -> SetPlacementGroupResponse: if not isinstance(data, dict): raise TypeError( @@ -2257,6 +2498,8 @@ def unmarshal_SetPlacementGroupResponse(data: Any) -> SetPlacementGroupResponse: field = data.get("placement_group", None) if field is not None: args["placement_group"] = unmarshal_PlacementGroup(field) + else: + args["placement_group"] = None return SetPlacementGroupResponse(**args) @@ -2312,6 +2555,8 @@ def unmarshal_UpdateImageResponse(data: Any) -> UpdateImageResponse: field = data.get("image", None) if field is not None: args["image"] = unmarshal_Image(field) + else: + args["image"] = None return UpdateImageResponse(**args) @@ -2327,6 +2572,8 @@ def unmarshal_UpdateIpResponse(data: Any) -> UpdateIpResponse: field = data.get("ip", None) if field is not None: args["ip"] = unmarshal_Ip(field) + else: + args["ip"] = None return UpdateIpResponse(**args) @@ -2342,6 +2589,8 @@ def unmarshal_UpdatePlacementGroupResponse(data: Any) -> UpdatePlacementGroupRes field = data.get("placement_group", None) if field is not None: args["placement_group"] = unmarshal_PlacementGroup(field) + else: + args["placement_group"] = None return UpdatePlacementGroupResponse(**args) @@ -2378,6 +2627,8 @@ def unmarshal_UpdateSecurityGroupResponse(data: Any) -> UpdateSecurityGroupRespo field = data.get("security_group", None) if field is not None: args["security_group"] = unmarshal_SecurityGroup(field) + else: + args["security_group"] = None return UpdateSecurityGroupResponse(**args) @@ -2395,6 +2646,8 @@ def unmarshal_UpdateSecurityGroupRuleResponse( field = data.get("rule", None) if field is not None: args["rule"] = unmarshal_SecurityGroupRule(field) + else: + args["rule"] = None return UpdateSecurityGroupRuleResponse(**args) @@ -2410,6 +2663,8 @@ def unmarshal_UpdateServerResponse(data: Any) -> UpdateServerResponse: field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None return UpdateServerResponse(**args) @@ -2425,6 +2680,8 @@ def unmarshal_UpdateSnapshotResponse(data: Any) -> UpdateSnapshotResponse: field = data.get("snapshot", None) if field is not None: args["snapshot"] = unmarshal_Snapshot(field) + else: + args["snapshot"] = None return UpdateSnapshotResponse(**args) @@ -2440,6 +2697,8 @@ def unmarshal_UpdateVolumeResponse(data: Any) -> UpdateVolumeResponse: field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None return UpdateVolumeResponse(**args) @@ -2455,6 +2714,8 @@ def unmarshal__SetImageResponse(data: Any) -> _SetImageResponse: field = data.get("image", None) if field is not None: args["image"] = unmarshal_Image(field) + else: + args["image"] = None return _SetImageResponse(**args) @@ -2470,6 +2731,8 @@ def unmarshal__SetSecurityGroupResponse(data: Any) -> _SetSecurityGroupResponse: field = data.get("security_group", None) if field is not None: args["security_group"] = unmarshal_SecurityGroup(field) + else: + args["security_group"] = None return _SetSecurityGroupResponse(**args) @@ -2485,6 +2748,8 @@ def unmarshal__SetSecurityGroupRuleResponse(data: Any) -> _SetSecurityGroupRuleR field = data.get("rule", None) if field is not None: args["rule"] = unmarshal_SecurityGroupRule(field) + else: + args["rule"] = None return _SetSecurityGroupRuleResponse(**args) @@ -2500,6 +2765,8 @@ def unmarshal__SetServerResponse(data: Any) -> _SetServerResponse: field = data.get("server", None) if field is not None: args["server"] = unmarshal_Server(field) + else: + args["server"] = None return _SetServerResponse(**args) @@ -2515,6 +2782,8 @@ def unmarshal__SetSnapshotResponse(data: Any) -> _SetSnapshotResponse: field = data.get("snapshot", None) if field is not None: args["snapshot"] = unmarshal_Snapshot(field) + else: + args["snapshot"] = None return _SetSnapshotResponse(**args) @@ -2539,6 +2808,18 @@ def marshal_ApplyBlockMigrationRequest( return output +def marshal_AttachServerFileSystemRequest( + request: AttachServerFileSystemRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.filesystem_id is not None: + output["filesystem_id"] = request.filesystem_id + + return output + + def marshal_AttachServerVolumeRequest( request: AttachServerVolumeRequest, defaults: ProfileDefaults, @@ -2557,6 +2838,20 @@ def marshal_AttachServerVolumeRequest( return output +def marshal_CheckBlockMigrationOrganizationQuotasRequest( + request: CheckBlockMigrationOrganizationQuotasRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.organization is not None: + output["organization"] = ( + request.organization or defaults.default_organization_id + ) + + return output + + def marshal_VolumeTemplate( request: VolumeTemplate, defaults: ProfileDefaults, @@ -2621,9 +2916,6 @@ def marshal_CreateImageRequest( if request.name is not None: output["name"] = request.name - if request.default_bootscript is not None: - output["default_bootscript"] = request.default_bootscript - if request.extra_volumes is not None: output["extra_volumes"] = { key: marshal_VolumeTemplate(value, defaults) @@ -2721,6 +3013,9 @@ def marshal_CreatePrivateNICRequest( if request.ip_ids is not None: output["ip_ids"] = request.ip_ids + if request.ipam_ip_ids is not None: + output["ipam_ip_ids"] = request.ipam_ip_ids + return output @@ -2865,9 +3160,6 @@ def marshal_CreateServerRequest( if request.commercial_type is not None: output["commercial_type"] = request.commercial_type - if request.image is not None: - output["image"] = request.image - if request.name is not None: output["name"] = request.name @@ -2877,8 +3169,8 @@ def marshal_CreateServerRequest( if request.routed_ip_enabled is not None: output["routed_ip_enabled"] = request.routed_ip_enabled - if request.enable_ipv6 is not None: - output["enable_ipv6"] = request.enable_ipv6 + if request.image is not None: + output["image"] = request.image if request.volumes is not None: output["volumes"] = { @@ -2886,6 +3178,12 @@ def marshal_CreateServerRequest( for key, value in request.volumes.items() } + if request.enable_ipv6 is not None: + output["enable_ipv6"] = request.enable_ipv6 + + if request.protected is not None: + output["protected"] = request.protected + if request.public_ip is not None: output["public_ip"] = request.public_ip @@ -2895,9 +3193,6 @@ def marshal_CreateServerRequest( if request.boot_type is not None: output["boot_type"] = str(request.boot_type) - if request.bootscript is not None: - output["bootscript"] = request.bootscript - if request.tags is not None: output["tags"] = request.tags @@ -2907,6 +3202,11 @@ def marshal_CreateServerRequest( if request.placement_group is not None: output["placement_group"] = request.placement_group + if request.admin_password_encryption_ssh_key_id is not None: + output["admin_password_encryption_ssh_key_id"] = ( + request.admin_password_encryption_ssh_key_id + ) + return output @@ -2994,6 +3294,18 @@ def marshal_CreateVolumeRequest( return output +def marshal_DetachServerFileSystemRequest( + request: DetachServerFileSystemRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.filesystem_id is not None: + output["filesystem_id"] = request.filesystem_id + + return output + + def marshal_DetachServerVolumeRequest( request: DetachServerVolumeRequest, defaults: ProfileDefaults, @@ -3068,6 +3380,9 @@ def marshal_ServerActionRequest( for key, value in request.volumes.items() } + if request.disable_ipv6 is not None: + output["disable_ipv6"] = request.disable_ipv6 + return output @@ -3092,6 +3407,9 @@ def marshal_Bootscript( ) -> Dict[str, Any]: output: Dict[str, Any] = {} + if request.architecture is not None: + output["architecture"] = str(request.architecture) + if request.bootcmdargs is not None: output["bootcmdargs"] = request.bootcmdargs @@ -3115,17 +3433,14 @@ def marshal_Bootscript( request.organization or defaults.default_organization_id ) - if request.project is not None: - output["project"] = request.project or defaults.default_project_id - if request.public is not None: output["public"] = request.public if request.title is not None: output["title"] = request.title - if request.arch is not None: - output["arch"] = str(request.arch) + if request.project is not None: + output["project"] = request.project or defaults.default_project_id if request.zone is not None: output["zone"] = request.zone or defaults.default_zone @@ -3163,10 +3478,10 @@ def marshal_Volume( output["export_uri"] = request.export_uri if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.modification_date is not None: - output["modification_date"] = request.modification_date + output["modification_date"] = request.modification_date.isoformat() if request.tags is not None: output["tags"] = request.tags @@ -3178,7 +3493,7 @@ def marshal_Volume( output["zone"] = request.zone or defaults.default_zone if request.server is not None: - output["server"] = (marshal_ServerSummary(request.server, defaults),) + output["server"] = marshal_ServerSummary(request.server, defaults) return output @@ -3217,10 +3532,10 @@ def marshal_SetImageRequest( output["arch"] = str(request.arch) if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.modification_date is not None: - output["modification_date"] = request.modification_date + output["modification_date"] = request.modification_date.isoformat() if request.from_server is not None: output["from_server"] = request.from_server @@ -3229,8 +3544,8 @@ def marshal_SetImageRequest( output["public"] = request.public if request.default_bootscript is not None: - output["default_bootscript"] = ( - marshal_Bootscript(request.default_bootscript, defaults), + output["default_bootscript"] = marshal_Bootscript( + request.default_bootscript, defaults ) if request.extra_volumes is not None: @@ -3245,7 +3560,7 @@ def marshal_SetImageRequest( ) if request.root_volume is not None: - output["root_volume"] = (marshal_VolumeSummary(request.root_volume, defaults),) + output["root_volume"] = marshal_VolumeSummary(request.root_volume, defaults) if request.state is not None: output["state"] = str(request.state) @@ -3561,9 +3876,6 @@ def marshal_UpdateServerRequest( for key, value in request.volumes.items() } - if request.bootscript is not None: - output["bootscript"] = request.bootscript - if request.dynamic_ip_required is not None: output["dynamic_ip_required"] = request.dynamic_ip_required @@ -3580,8 +3892,8 @@ def marshal_UpdateServerRequest( output["protected"] = request.protected if request.security_group is not None: - output["security_group"] = ( - marshal_SecurityGroupTemplate(request.security_group, defaults), + output["security_group"] = marshal_SecurityGroupTemplate( + request.security_group, defaults ) if request.placement_group is not None: @@ -3593,6 +3905,11 @@ def marshal_UpdateServerRequest( if request.commercial_type is not None: output["commercial_type"] = request.commercial_type + if request.admin_password_encryption_ssh_key_id is not None: + output["admin_password_encryption_ssh_key_id"] = ( + request.admin_password_encryption_ssh_key_id + ) + return output @@ -3648,10 +3965,10 @@ def marshal__SetSecurityGroupRequest( output["tags"] = request.tags if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.modification_date is not None: - output["modification_date"] = request.modification_date + output["modification_date"] = request.modification_date.isoformat() if request.project_default is not None: output["project_default"] = request.project_default @@ -3750,14 +4067,14 @@ def marshal_Image( ) if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.modification_date is not None: - output["modification_date"] = request.modification_date + output["modification_date"] = request.modification_date.isoformat() if request.default_bootscript is not None: - output["default_bootscript"] = ( - marshal_Bootscript(request.default_bootscript, defaults), + output["default_bootscript"] = marshal_Bootscript( + request.default_bootscript, defaults ) if request.public is not None: @@ -3776,7 +4093,7 @@ def marshal_Image( output["zone"] = request.zone or defaults.default_zone if request.root_volume is not None: - output["root_volume"] = (marshal_VolumeSummary(request.root_volume, defaults),) + output["root_volume"] = marshal_VolumeSummary(request.root_volume, defaults) return output @@ -3952,7 +4269,7 @@ def marshal_ServerMaintenance( output["reason"] = request.reason if request.start_date is not None: - output["start_date"] = request.start_date + output["start_date"] = request.start_date.isoformat() return output @@ -3969,19 +4286,22 @@ def marshal__SetServerRequest( if request.commercial_type is not None: output["commercial_type"] = request.commercial_type + if request.organization is not None: + output["organization"] = ( + request.organization or defaults.default_organization_id + ) + if request.dynamic_ip_required is not None: output["dynamic_ip_required"] = request.dynamic_ip_required - if request.enable_ipv6 is not None: - output["enable_ipv6"] = request.enable_ipv6 - if request.hostname is not None: output["hostname"] = request.hostname - if request.organization is not None: - output["organization"] = ( - request.organization or defaults.default_organization_id - ) + if request.protected is not None: + output["protected"] = request.protected + + if request.state_detail is not None: + output["state_detail"] = request.state_detail if request.project is not None: output["project"] = request.project or defaults.default_project_id @@ -3993,22 +4313,22 @@ def marshal__SetServerRequest( output["tags"] = request.tags if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.routed_ip_enabled is not None: output["routed_ip_enabled"] = request.routed_ip_enabled - if request.image is not None: - output["image"] = (marshal_Image(request.image, defaults),) + if request.enable_ipv6 is not None: + output["enable_ipv6"] = request.enable_ipv6 - if request.protected is not None: - output["protected"] = request.protected + if request.image is not None: + output["image"] = marshal_Image(request.image, defaults) if request.private_ip is not None: output["private_ip"] = request.private_ip if request.public_ip is not None: - output["public_ip"] = (marshal_ServerIp(request.public_ip, defaults),) + output["public_ip"] = marshal_ServerIp(request.public_ip, defaults) if request.public_ips is not None: output["public_ips"] = [ @@ -4016,22 +4336,16 @@ def marshal__SetServerRequest( ] if request.modification_date is not None: - output["modification_date"] = request.modification_date - - if request.state_detail is not None: - output["state_detail"] = request.state_detail + output["modification_date"] = request.modification_date.isoformat() if request.state is not None: output["state"] = str(request.state) if request.location is not None: - output["location"] = (marshal_ServerLocation(request.location, defaults),) + output["location"] = marshal_ServerLocation(request.location, defaults) if request.ipv6 is not None: - output["ipv6"] = (marshal_ServerIpv6(request.ipv6, defaults),) - - if request.bootscript is not None: - output["bootscript"] = (marshal_Bootscript(request.bootscript, defaults),) + output["ipv6"] = marshal_ServerIpv6(request.ipv6, defaults) if request.boot_type is not None: output["boot_type"] = str(request.boot_type) @@ -4043,8 +4357,8 @@ def marshal__SetServerRequest( } if request.security_group is not None: - output["security_group"] = ( - marshal_SecurityGroupSummary(request.security_group, defaults), + output["security_group"] = marshal_SecurityGroupSummary( + request.security_group, defaults ) if request.maintenances is not None: @@ -4056,8 +4370,8 @@ def marshal__SetServerRequest( output["arch"] = str(request.arch) if request.placement_group is not None: - output["placement_group"] = ( - marshal_PlacementGroup(request.placement_group, defaults), + output["placement_group"] = marshal_PlacementGroup( + request.placement_group, defaults ) if request.private_nics is not None: @@ -4065,6 +4379,11 @@ def marshal__SetServerRequest( marshal_PrivateNIC(item, defaults) for item in request.private_nics ] + if request.admin_password_encryption_ssh_key_id is not None: + output["admin_password_encryption_ssh_key_id"] = ( + request.admin_password_encryption_ssh_key_id + ) + return output @@ -4110,15 +4429,15 @@ def marshal__SetSnapshotRequest( output["state"] = str(request.state) if request.base_volume is not None: - output["base_volume"] = ( - marshal_SnapshotBaseVolume(request.base_volume, defaults), + output["base_volume"] = marshal_SnapshotBaseVolume( + request.base_volume, defaults ) if request.creation_date is not None: - output["creation_date"] = request.creation_date + output["creation_date"] = request.creation_date.isoformat() if request.modification_date is not None: - output["modification_date"] = request.modification_date + output["modification_date"] = request.modification_date.isoformat() if request.project is not None: output["project"] = request.project or defaults.default_project_id diff --git a/scaleway/scaleway/instance/v1/test_user_data.py b/scaleway/scaleway/instance/v1/test_user_data.py new file mode 100644 index 00000000..3cb26427 --- /dev/null +++ b/scaleway/scaleway/instance/v1/test_user_data.py @@ -0,0 +1,64 @@ +import sys +import unittest +import logging +from typing import Dict + +from scaleway_core.client import Client +from .custom_api import InstanceUtilsV1API + +logger = logging.getLogger() +logger.level = logging.DEBUG +stream_handler = logging.StreamHandler(sys.stdout) +logger.addHandler(stream_handler) + + +class TestServerUserData(unittest.TestCase): + def setUp(self) -> None: + self.client = Client() + self.instance_api = InstanceUtilsV1API(self.client, bypass_validation=True) + self.server = self.instance_api._create_server( + commercial_type="DEV1-S", + zone="fr-par-1", + image="ubuntu_jammy", + name="my-server-web", + volumes={}, + protected=False, + ) + + @unittest.skip("API Test is not up") + def test_set_and_get_server_user_data(self) -> None: + if self.server is None or self.server.server is None: + self.fail("Server setup failed.") + key = "first key" + content = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10" + self.instance_api.set_server_user_data( + server_id=self.server.server.id, key=key, content=content + ) + user_data = self.instance_api.get_server_user_data( + server_id=self.server.server.id, key=key + ) + self.assertIsNotNone(user_data) + + @unittest.skip("API Test is not up") + def test_set_and_get_all_user_data(self) -> None: + if self.server is None or self.server.server is None: + self.fail("Server setup failed.") + key = "first key" + content = b"content first key" + key_bis = "second key" + content_bis = b"test content" + another_key = "third key" + another_content = b"another content to test" + + user_data: Dict[str, bytes] = { + key_bis: content_bis, + another_key: another_content, + key: content, + } + self.instance_api.set_all_server_user_data( + server_id=self.server.server.id, user_data=user_data + ) + response = self.instance_api.get_all_server_user_data( + server_id=self.server.server.id + ) + self.assertIsNotNone(response) diff --git a/scaleway/scaleway/instance/v1/types.py b/scaleway/scaleway/instance/v1/types.py index ce054860..fb8865a7 100644 --- a/scaleway/scaleway/instance/v1/types.py +++ b/scaleway/scaleway/instance/v1/types.py @@ -8,7 +8,7 @@ from typing import Dict, List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -66,7 +66,6 @@ def __str__(self) -> str: class IpType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_IPTYPE = "unknown_iptype" - NAT = "nat" ROUTED_IPV4 = "routed_ipv4" ROUTED_IPV6 = "routed_ipv6" @@ -308,64 +307,31 @@ class ServerSummary: @dataclass class Bootscript: + architecture: Arch + bootcmdargs: str - """ - Bootscript arguments. - """ default: bool - """ - Display if the bootscript is the default bootscript (if no other boot option is configured). - """ dtb: str - """ - Provide information regarding a Device Tree Binary (DTB) for use with C1 servers. - """ id: str - """ - Bootscript ID. - """ initrd: str - """ - Initrd (initial ramdisk) configuration. - """ kernel: str - """ - Instance kernel version. - """ organization: str - """ - Bootscript Organization ID. - """ - - project: str - """ - Bootscript Project ID. - """ public: bool - """ - Provide information if the bootscript is public. - """ title: str - """ - Bootscript title. - """ - arch: Arch - """ - Bootscript architecture. - """ + project: str - zone: Zone + zone: ScwZone """ - Zone in which the bootscript is located. + Zone to target. If none is passed will use default zone from the config. """ @@ -426,7 +392,7 @@ class Volume: Volume state. """ - zone: Zone + zone: ScwZone """ Zone in which the volume is located. """ @@ -502,7 +468,7 @@ class Image: tags: List[str] - zone: Zone + zone: ScwZone """ Zone to target. If none is passed will use default zone from the config. """ @@ -549,10 +515,11 @@ class PlacementGroup: policy_respected: bool """ - Returns true if the policy is respected, false otherwise. + In the server endpoints the value is always false as it is deprecated. +In the placement group endpoints the value is correct. """ - zone: Zone + zone: ScwZone """ Zone in which the placement group is located. """ @@ -693,25 +660,21 @@ class ServerMaintenance: class VolumeServer: id: str - name: str - - export_uri: str + name: Optional[str] - organization: str + export_uri: Optional[str] - size: int + organization: Optional[str] server: Optional[ServerSummary] - volume_type: VolumeServerVolumeType - - state: VolumeServerState + size: Optional[int] - project: str + volume_type: VolumeServerVolumeType boot: bool - zone: Zone + zone: ScwZone """ Zone to target. If none is passed will use default zone from the config. """ @@ -720,6 +683,10 @@ class VolumeServer: modification_date: Optional[datetime] + state: Optional[VolumeServerState] + + project: Optional[str] + @dataclass class SnapshotBaseVolume: @@ -741,12 +708,35 @@ class ServerTypeCapabilities: List of supported boot types. """ + max_file_systems: int + """ + Max number of SFS (Scaleway File Systems) that can be attached to the Instance. + """ + block_storage: Optional[bool] """ Defines whether the Instance supports block storage. """ +@dataclass +class ServerTypeGPUInfo: + gpu_manufacturer: str + """ + GPU manufacturer. + """ + + gpu_name: str + """ + GPU model name. + """ + + gpu_memory: int + """ + RAM of a single GPU, in bytes. + """ + + @dataclass class ServerTypeNetwork: interfaces: List[ServerTypeNetworkInterface] @@ -837,114 +827,114 @@ class Server: True if a dynamic IPv4 is required. """ - routed_ip_enabled: bool + hostname: str """ - True to configure the instance so it uses the new routed IP mode. + Instance host name. """ - enable_ipv6: bool + protected: bool """ - True if IPv6 is enabled. + Defines whether the Instance protection option is activated. """ - hostname: str + public_ips: List[ServerIp] """ - Instance host name. + Information about all the public IPs attached to the server. """ - protected: bool + mac_address: str """ - Defines whether the Instance protection option is activated. + The server's MAC address. """ - image: Optional[Image] + state: ServerState """ - Information about the Instance image. + Instance state. """ - private_ip: Optional[str] + boot_type: BootType """ - Private IP address of the Instance. + Instance boot type. """ - public_ip: Optional[ServerIp] + volumes: Dict[str, VolumeServer] """ - Information about the public IP. + Instance volumes. """ - public_ips: List[ServerIp] + maintenances: List[ServerMaintenance] """ - Information about all the public IPs attached to the server. + Instance planned maintenance. """ - mac_address: str + state_detail: str """ - The server's MAC address. + Detailed information about the Instance state. """ - state: ServerState + arch: Arch """ - Instance state. + Instance architecture. """ - boot_type: BootType + private_nics: List[PrivateNIC] """ - Instance boot type. + Instance private NICs. """ - volumes: Dict[str, VolumeServer] + zone: ScwZone """ - Instance volumes. + Zone in which the Instance is located. """ - modification_date: Optional[datetime] + end_of_service: bool """ - Instance modification date. + True if the Instance type has reached end of service. """ - location: Optional[ServerLocation] + routed_ip_enabled: Optional[bool] """ - Instance location. + True to configure the instance so it uses the routed IP mode. Use of `routed_ip_enabled` as `False` is deprecated. """ - ipv6: Optional[ServerIpv6] + enable_ipv6: Optional[bool] """ - Instance IPv6 address. + True if IPv6 is enabled (deprecated and always `False` when `routed_ip_enabled` is `True`). """ - bootscript: Optional[Bootscript] + image: Optional[Image] """ - Instance bootscript. + Information about the Instance image. """ - security_group: Optional[SecurityGroupSummary] + private_ip: Optional[str] """ - Instance security group. + Private IP address of the Instance (deprecated and always `null` when `routed_ip_enabled` is `True`). """ - maintenances: List[ServerMaintenance] + public_ip: Optional[ServerIp] """ - Instance planned maintenance. + Information about the public IP (deprecated in favor of `public_ips`). """ - state_detail: str + modification_date: Optional[datetime] """ - Detailed information about the Instance state. + Instance modification date. """ - arch: Arch + location: Optional[ServerLocation] """ - Instance architecture. + Instance location. """ - private_nics: List[PrivateNIC] + ipv6: Optional[ServerIpv6] """ - Instance private NICs. + Instance IPv6 address (deprecated when `routed_ip_enabled` is `True`). """ - zone: Zone + security_group: Optional[SecurityGroupSummary] """ - Zone in which the Instance is located. + Instance security group. """ placement_group: Optional[PlacementGroup] @@ -952,6 +942,16 @@ class Server: Instance placement group. """ + admin_password_encryption_ssh_key_id: Optional[str] + """ + The public_key value of this key is used to encrypt the admin password. When set to an empty string, reset this value and admin_password_encrypted_value to an empty string so a new password may be generated. + """ + + admin_password_encrypted_value: Optional[str] + """ + This value is reset when admin_password_encryption_ssh_key_id is set to an empty string. + """ + @dataclass class VolumeTemplate: @@ -1000,7 +1000,7 @@ class Ip: ipam_id: str - zone: Zone + zone: ScwZone """ Zone to target. If none is passed will use default zone from the config. """ @@ -1077,7 +1077,7 @@ class SecurityGroup: Security group state. """ - zone: Zone + zone: ScwZone """ Zone in which the security group is located. """ @@ -1114,7 +1114,7 @@ class SecurityGroupRule: editable: bool - zone: Zone + zone: ScwZone """ Zone to target. If none is passed will use default zone from the config. """ @@ -1209,7 +1209,7 @@ class Snapshot: Snapshot state. """ - zone: Zone + zone: ScwZone """ Snapshot zone. """ @@ -1261,9 +1261,9 @@ class Task: href_result: str - zone: Zone + zone: ScwZone """ - Zone in which the task is excecuted. + Zone in which the task is executed. """ started_at: Optional[datetime] @@ -1299,16 +1299,16 @@ class Dashboard: volumes_l_ssd_count: int - volumes_b_ssd_count: int - volumes_l_ssd_total_size: int - volumes_b_ssd_total_size: int - private_nics_count: int placement_groups_count: int + volumes_b_ssd_count: Optional[int] + + volumes_b_ssd_total_size: Optional[int] + @dataclass class PlacementGroupServer: @@ -1365,9 +1365,9 @@ class ServerType: CPU architecture. """ - baremetal: bool + end_of_service: bool """ - True if it is a baremetal Instance. + True if this Instance type has reached end of service. """ per_volume_constraint: Optional[ServerTypeVolumeConstraintsByType] @@ -1385,6 +1385,11 @@ class ServerType: Number of GPU. """ + gpu_info: Optional[ServerTypeGPUInfo] + """ + GPU information. + """ + network: Optional[ServerTypeNetwork] """ Network available for the Instance. @@ -1400,6 +1405,11 @@ class ServerType: Maximum available scratch storage. """ + block_bandwidth: Optional[int] + """ + The maximum bandwidth allocated to block storage access (in bytes per second). + """ + @dataclass class VolumeType: @@ -1466,7 +1476,7 @@ class SetSecurityGroupRulesRequestRule: Indicates if this rule is editable. Rules with the value false will be ignored. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone of the rule. This field is ignored. """ @@ -1491,10 +1501,10 @@ class SecurityGroupTemplate: class ApplyBlockMigrationRequest: validation_key: str """ - A value to be retrieved from a call to PlanBlockMigration, to confirm that the volume and/or snapshots specified in said plan should be migrated. + A value to be retrieved from a call to the [Get a volume or snapshot's migration plan](#path-volumes-get-a-volume-or-snapshots-migration-plan) endpoint, to confirm that the volume and/or snapshots specified in said plan should be migrated. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1504,13 +1514,30 @@ class ApplyBlockMigrationRequest: snapshot_id: Optional[str] +@dataclass +class AttachServerFileSystemRequest: + server_id: str + + filesystem_id: str + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class AttachServerFileSystemResponse: + server: Optional[Server] + + @dataclass class AttachServerVolumeRequest: server_id: str volume_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1525,6 +1552,16 @@ class AttachServerVolumeResponse: server: Optional[Server] +@dataclass +class CheckBlockMigrationOrganizationQuotasRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + organization: Optional[str] + + @dataclass class CreateImageRequest: root_volume: str @@ -1537,7 +1574,7 @@ class CreateImageRequest: Architecture of the image. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1547,11 +1584,6 @@ class CreateImageRequest: Name of the image. """ - default_bootscript: Optional[str] - """ - Default bootscript of the image. - """ - extra_volumes: Optional[Dict[str, VolumeTemplate]] """ Additional volumes of the image. @@ -1579,7 +1611,7 @@ class CreateImageResponse: @dataclass class CreateIpRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1596,7 +1628,7 @@ class CreateIpRequest: type_: Optional[IpType] """ - IP type to reserve (either 'nat', 'routed_ipv4' or 'routed_ipv6'). + IP type to reserve (either 'routed_ipv4' or 'routed_ipv6'). """ project: Optional[str] @@ -1611,7 +1643,7 @@ class CreateIpResponse: @dataclass class CreatePlacementGroupRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1658,7 +1690,7 @@ class CreatePrivateNICRequest: UUID of the private network where the private NIC will be attached. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1673,6 +1705,11 @@ class CreatePrivateNICRequest: Ip_ids defined from IPAM. """ + ipam_ip_ids: Optional[List[str]] + """ + UUID of IPAM ips, to be attached to the instance in the requested private network. + """ + @dataclass class CreatePrivateNICResponse: @@ -1691,7 +1728,7 @@ class CreateSecurityGroupRequest: Whether the security group is stateful or not. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1760,7 +1797,7 @@ class CreateSecurityGroupRuleRequest: Indicates if this rule is editable (will be ignored). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1783,7 +1820,7 @@ class CreateSecurityGroupRuleResponse: @dataclass class CreateServerRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1793,11 +1830,6 @@ class CreateServerRequest: Define the Instance commercial type (i.e. GP1-S). """ - image: str - """ - Instance image ID or label. - """ - name: Optional[str] """ Instance name. @@ -1813,9 +1845,9 @@ class CreateServerRequest: If true, configure the Instance so it uses the new routed IP mode. """ - enable_ipv6: bool + image: Optional[str] """ - True if IPv6 is enabled on the server. + Instance image ID or label. """ volumes: Optional[Dict[str, VolumeServerTemplate]] @@ -1823,6 +1855,16 @@ class CreateServerRequest: Volumes attached to the server. """ + enable_ipv6: Optional[bool] + """ + True if IPv6 is enabled on the server (deprecated and always `False` when `routed_ip_enabled` is `True`). + """ + + protected: bool + """ + True to activate server protection option. + """ + public_ip: Optional[str] """ ID of the reserved IP to attach to the Instance. @@ -1838,11 +1880,6 @@ class CreateServerRequest: Boot type to use. """ - bootscript: Optional[str] - """ - Bootscript ID to use when `boot_type` is set to `bootscript`. - """ - tags: Optional[List[str]] """ Instance tags. @@ -1858,6 +1895,11 @@ class CreateServerRequest: Placement group ID if Instance must be part of a placement group. """ + admin_password_encryption_ssh_key_id: Optional[str] + """ + The public_key value of this key is used to encrypt the admin password. + """ + project: Optional[str] organization: Optional[str] @@ -1870,7 +1912,7 @@ class CreateServerResponse: @dataclass class CreateSnapshotRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1925,7 +1967,7 @@ class CreateSnapshotResponse: @dataclass class CreateVolumeRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1966,7 +2008,7 @@ class DeleteImageRequest: UUID of the image you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1979,7 +2021,7 @@ class DeleteIpRequest: ID or address of the IP to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1992,7 +2034,7 @@ class DeletePlacementGroupRequest: UUID of the placement group you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2010,7 +2052,7 @@ class DeletePrivateNICRequest: Private NIC unique ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2023,7 +2065,7 @@ class DeleteSecurityGroupRequest: UUID of the security group you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2035,7 +2077,7 @@ class DeleteSecurityGroupRuleRequest: security_group_rule_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2045,7 +2087,7 @@ class DeleteSecurityGroupRuleRequest: class DeleteServerRequest: server_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2063,7 +2105,7 @@ class DeleteServerUserDataRequest: Key of the user data to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2076,7 +2118,7 @@ class DeleteSnapshotRequest: UUID of the snapshot you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2089,19 +2131,36 @@ class DeleteVolumeRequest: UUID of the volume you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DetachServerFileSystemRequest: + server_id: str + + filesystem_id: str + + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ +@dataclass +class DetachServerFileSystemResponse: + server: Optional[Server] + + @dataclass class DetachServerVolumeRequest: server_id: str volume_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2116,12 +2175,12 @@ class DetachServerVolumeResponse: class ExportSnapshotRequest: bucket: str """ - S3 bucket name. + Object Storage bucket name. """ key: str """ - S3 object key. + Object key. """ snapshot_id: str @@ -2129,7 +2188,7 @@ class ExportSnapshotRequest: Snapshot ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2140,24 +2199,9 @@ class ExportSnapshotResponse: task: Optional[Task] -@dataclass -class GetBootscriptRequest: - bootscript_id: str - - zone: Optional[Zone] - """ - Zone to target. If none is passed will use default zone from the config. - """ - - -@dataclass -class GetBootscriptResponse: - bootscript: Optional[Bootscript] - - @dataclass class GetDashboardRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2179,7 +2223,7 @@ class GetImageRequest: UUID of the image you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2197,7 +2241,7 @@ class GetIpRequest: IP ID or address to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2215,7 +2259,7 @@ class GetPlacementGroupRequest: UUID of the placement group you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2233,7 +2277,7 @@ class GetPlacementGroupServersRequest: UUID of the placement group you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2259,7 +2303,7 @@ class GetPrivateNICRequest: Private NIC unique ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2277,7 +2321,7 @@ class GetSecurityGroupRequest: UUID of the security group you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2294,7 +2338,7 @@ class GetSecurityGroupRuleRequest: security_group_rule_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2305,6 +2349,19 @@ class GetSecurityGroupRuleResponse: rule: Optional[SecurityGroupRule] +@dataclass +class GetServerCompatibleTypesRequest: + server_id: str + """ + UUID of the Instance you want to get. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class GetServerRequest: server_id: str @@ -2312,7 +2369,7 @@ class GetServerRequest: UUID of the Instance you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2325,7 +2382,7 @@ class GetServerResponse: @dataclass class GetServerTypesAvailabilityRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2358,7 +2415,7 @@ class GetSnapshotRequest: UUID of the snapshot you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2376,7 +2433,7 @@ class GetVolumeRequest: UUID of the volume you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2387,42 +2444,9 @@ class GetVolumeResponse: volume: Optional[Volume] -@dataclass -class ListBootscriptsRequest: - zone: Optional[Zone] - """ - Zone to target. If none is passed will use default zone from the config. - """ - - arch: Optional[str] - - title: Optional[str] - - default: Optional[bool] - - public: Optional[bool] - - per_page: Optional[int] - - page: Optional[int] - - -@dataclass -class ListBootscriptsResponse: - total_count: int - """ - Total number of bootscripts. - """ - - bootscripts: List[Bootscript] - """ - List of bootscripts. - """ - - @dataclass class ListDefaultSecurityGroupRulesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2430,7 +2454,7 @@ class ListDefaultSecurityGroupRulesRequest: @dataclass class ListImagesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2467,7 +2491,7 @@ class ListImagesResponse: @dataclass class ListIpsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2504,7 +2528,7 @@ class ListIpsRequest: type_: Optional[str] """ - Filter on the IP Mobility IP type (whose value should be either 'nat', 'routed_ipv4' or 'routed_ipv6'). + Filter on the IP Mobility IP type (whose value should be either 'routed_ipv4' or 'routed_ipv6'). """ @@ -2523,7 +2547,7 @@ class ListIpsResponse: @dataclass class ListPlacementGroupsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2579,7 +2603,7 @@ class ListPrivateNICsRequest: Instance to which the private NIC is attached. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2614,7 +2638,7 @@ class ListSecurityGroupRulesRequest: UUID of the security group. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2645,7 +2669,7 @@ class ListSecurityGroupRulesResponse: @dataclass class ListSecurityGroupsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2703,7 +2727,7 @@ class ListSecurityGroupsResponse: class ListServerActionsRequest: server_id: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2721,7 +2745,7 @@ class ListServerUserDataRequest: UUID of the Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2734,7 +2758,7 @@ class ListServerUserDataResponse: @dataclass class ListServersRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2774,6 +2798,11 @@ class ListServersRequest: List Instances that are not attached to a public IP. """ + with_ip: Optional[str] + """ + List Instances by IP (both private_ip and public_ip are supported). + """ + commercial_type: Optional[str] """ List Instances of this commercial type. @@ -2830,7 +2859,7 @@ class ListServersResponse: @dataclass class ListServersTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2855,7 +2884,7 @@ class ListServersTypesResponse: @dataclass class ListSnapshotsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2911,7 +2940,7 @@ class ListSnapshotsResponse: @dataclass class ListVolumesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2967,7 +2996,7 @@ class ListVolumesResponse: @dataclass class ListVolumesTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2999,7 +3028,7 @@ class MigrationPlan: validation_key: str """ - A value to be passed to ApplyBlockMigrationRequest, to confirm that the execution of the plan is being requested. + A value to be passed to the call to the [Migrate a volume and/or snapshots to SBS](#path-volumes-migrate-a-volume-andor-snapshots-to-sbs-scaleway-block-storage) endpoint, to confirm that the execution of the plan is being requested. """ volume: Optional[Volume] @@ -3010,7 +3039,7 @@ class MigrationPlan: @dataclass class PlanBlockMigrationRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3027,7 +3056,7 @@ class ServerActionRequest: UUID of the Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3049,15 +3078,29 @@ class ServerActionRequest: This field should only be specified when performing a backup action. """ + disable_ipv6: Optional[bool] + """ + Disable IPv6 on the Instance while performing migration to routed IPs. +This field should only be specified when performing a enable_routed_ip action. + """ + @dataclass class ServerActionResponse: task: Optional[Task] +@dataclass +class ServerCompatibleTypes: + compatible_types: List[str] + """ + Instance compatible types. + """ + + @dataclass class SetImageRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3097,7 +3140,7 @@ class SetPlacementGroupRequest: name: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3130,7 +3173,7 @@ class SetPlacementGroupServersRequest: An array of the Instances' UUIDs you want to configure. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3151,7 +3194,7 @@ class SetSecurityGroupRulesRequest: UUID of the security group to update the rules on. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3174,7 +3217,7 @@ class UpdateImageRequest: UUID of the image. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3217,7 +3260,7 @@ class UpdateIpRequest: IP ID or IP address. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3229,7 +3272,7 @@ class UpdateIpRequest: type_: Optional[IpType] """ - Convert a 'nat' IP to a 'routed_ipv4'. + Should have no effect. """ tags: Optional[List[str]] @@ -3252,7 +3295,7 @@ class UpdatePlacementGroupRequest: UUID of the placement group. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3295,7 +3338,7 @@ class UpdatePlacementGroupServersRequest: An array of the Instances' UUIDs you want to configure. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3321,7 +3364,7 @@ class UpdatePrivateNICRequest: Private NIC unique ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3339,7 +3382,7 @@ class UpdateSecurityGroupRequest: UUID of the security group. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3407,7 +3450,7 @@ class UpdateSecurityGroupRuleRequest: UUID of the rule. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3460,7 +3503,7 @@ class UpdateServerRequest: UUID of the Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3479,8 +3522,6 @@ class UpdateServerRequest: volumes: Optional[Dict[str, VolumeServerTemplate]] - bootscript: Optional[str] - dynamic_ip_required: Optional[bool] routed_ip_enabled: Optional[bool] @@ -3496,6 +3537,9 @@ class UpdateServerRequest: enable_ipv6: Optional[bool] protected: Optional[bool] + """ + True to activate server protection option. + """ security_group: Optional[SecurityGroupTemplate] @@ -3514,9 +3558,15 @@ class UpdateServerRequest: Warning: This field has some restrictions: - Cannot be changed if the Instance is not in `stopped` state. - Cannot be changed if the Instance is in a placement group. +- Cannot be changed from/to a Windows offer to/from a Linux offer. - Local storage requirements of the target commercial_types must be fulfilled (i.e. if an Instance has 80GB of local storage, it can be changed into a GP1-XS, which has a maximum of 150GB, but it cannot be changed into a DEV1-S, which has only 20GB). """ + admin_password_encryption_ssh_key_id: Optional[str] + """ + The public_key value of this key is used to encrypt the admin password. When set to an empty string, reset this value and admin_password_encrypted_value to an empty string so a new password may be generated. + """ + @dataclass class UpdateServerResponse: @@ -3530,7 +3580,7 @@ class UpdateSnapshotRequest: UUID of the snapshot. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3558,7 +3608,7 @@ class UpdateVolumeRequest: UUID of the volume. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway/scaleway/instance/v1/types_private.py b/scaleway/scaleway/instance/v1/types_private.py index 9acfb25e..38526ba0 100644 --- a/scaleway/scaleway/instance/v1/types_private.py +++ b/scaleway/scaleway/instance/v1/types_private.py @@ -7,7 +7,7 @@ from typing import Dict, List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from .types import ( @@ -22,7 +22,6 @@ SnapshotState, VolumeVolumeType, ServerSummary, - Bootscript, Volume, Image, PlacementGroup, @@ -47,7 +46,7 @@ class _SetImageResponse: @dataclass class _SetSecurityGroupRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -126,7 +125,7 @@ class _SetSecurityGroupRuleRequest: ip_range: str position: int editable: bool - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -144,7 +143,7 @@ class _SetSecurityGroupRuleResponse: @dataclass class _SetServerRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -160,21 +159,25 @@ class _SetServerRequest: """ Instance commercial type (eg. GP1-M). """ - dynamic_ip_required: bool + organization: Optional[str] """ - True if a dynamic IPv4 is required. + Instance Organization ID. """ - enable_ipv6: bool + dynamic_ip_required: bool """ - True if IPv6 is enabled. + True if a dynamic IPv4 is required. """ hostname: str """ Instance host name. """ - organization: Optional[str] + protected: bool """ - Instance Organization ID. + Instance protection option is activated. + """ + state_detail: str + """ + Instance state_detail. """ project: Optional[str] """ @@ -196,21 +199,21 @@ class _SetServerRequest: """ True to configure the instance so it uses the new routed IP mode (once this is set to True you cannot set it back to False). """ - image: Optional[Image] + enable_ipv6: Optional[bool] """ - Provide information on the Instance image. + True if IPv6 is enabled (deprecated and always `False` when `routed_ip_enabled` is `True`). """ - protected: bool + image: Optional[Image] """ - Instance protection option is activated. + Provide information on the Instance image. """ private_ip: Optional[str] """ - Instance private IP address. + Instance private IP address (deprecated and always `null` when `routed_ip_enabled` is `True`). """ public_ip: Optional[ServerIp] """ - Information about the public IP. + Information about the public IP (deprecated in favor of `public_ips`). """ public_ips: Optional[List[ServerIp]] """ @@ -220,10 +223,6 @@ class _SetServerRequest: """ Instance modification date. """ - state_detail: str - """ - Instance state_detail. - """ state: Optional[ServerState] """ Instance state. @@ -234,11 +233,7 @@ class _SetServerRequest: """ ipv6: Optional[ServerIpv6] """ - Instance IPv6 address. - """ - bootscript: Optional[Bootscript] - """ - Instance bootscript. + Instance IPv6 address (deprecated when `routed_ip_enabled` is `True`). """ boot_type: Optional[BootType] """ @@ -268,6 +263,10 @@ class _SetServerRequest: """ Instance private NICs. """ + admin_password_encryption_ssh_key_id: Optional[str] + """ + The public_key value of this key is used to encrypt the admin password. When set to an empty string, reset this value and admin_password_encrypted_value to an empty string so a new password may be generated. + """ @dataclass @@ -279,7 +278,7 @@ class _SetServerResponse: class _SetSnapshotRequest: id: str name: str - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway/scaleway/interlink/__init__.py b/scaleway/scaleway/interlink/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway/scaleway/interlink/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/interlink/v1beta1/__init__.py b/scaleway/scaleway/interlink/v1beta1/__init__.py new file mode 100644 index 00000000..66cc0eab --- /dev/null +++ b/scaleway/scaleway/interlink/v1beta1/__init__.py @@ -0,0 +1,99 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import BgpStatus +from .types import DedicatedConnectionStatus +from .content import DEDICATED_CONNECTION_TRANSIENT_STATUSES +from .types import LinkKind +from .types import LinkStatus +from .content import LINK_TRANSIENT_STATUSES +from .types import ListDedicatedConnectionsRequestOrderBy +from .types import ListLinksRequestOrderBy +from .types import ListPartnersRequestOrderBy +from .types import ListPopsRequestOrderBy +from .types import ListRoutingPoliciesRequestOrderBy +from .types import BgpConfig +from .types import PartnerHost +from .types import SelfHost +from .types import DedicatedConnection +from .types import Link +from .types import Partner +from .types import Pop +from .types import RoutingPolicy +from .types import AttachRoutingPolicyRequest +from .types import AttachVpcRequest +from .types import CreateLinkRequest +from .types import CreateRoutingPolicyRequest +from .types import DeleteLinkRequest +from .types import DeleteRoutingPolicyRequest +from .types import DetachRoutingPolicyRequest +from .types import DetachVpcRequest +from .types import DisableRoutePropagationRequest +from .types import EnableRoutePropagationRequest +from .types import GetDedicatedConnectionRequest +from .types import GetLinkRequest +from .types import GetPartnerRequest +from .types import GetPopRequest +from .types import GetRoutingPolicyRequest +from .types import ListDedicatedConnectionsRequest +from .types import ListDedicatedConnectionsResponse +from .types import ListLinksRequest +from .types import ListLinksResponse +from .types import ListPartnersRequest +from .types import ListPartnersResponse +from .types import ListPopsRequest +from .types import ListPopsResponse +from .types import ListRoutingPoliciesRequest +from .types import ListRoutingPoliciesResponse +from .types import UpdateLinkRequest +from .types import UpdateRoutingPolicyRequest +from .api import InterlinkV1Beta1API + +__all__ = [ + "BgpStatus", + "DedicatedConnectionStatus", + "DEDICATED_CONNECTION_TRANSIENT_STATUSES", + "LinkKind", + "LinkStatus", + "LINK_TRANSIENT_STATUSES", + "ListDedicatedConnectionsRequestOrderBy", + "ListLinksRequestOrderBy", + "ListPartnersRequestOrderBy", + "ListPopsRequestOrderBy", + "ListRoutingPoliciesRequestOrderBy", + "BgpConfig", + "PartnerHost", + "SelfHost", + "DedicatedConnection", + "Link", + "Partner", + "Pop", + "RoutingPolicy", + "AttachRoutingPolicyRequest", + "AttachVpcRequest", + "CreateLinkRequest", + "CreateRoutingPolicyRequest", + "DeleteLinkRequest", + "DeleteRoutingPolicyRequest", + "DetachRoutingPolicyRequest", + "DetachVpcRequest", + "DisableRoutePropagationRequest", + "EnableRoutePropagationRequest", + "GetDedicatedConnectionRequest", + "GetLinkRequest", + "GetPartnerRequest", + "GetPopRequest", + "GetRoutingPolicyRequest", + "ListDedicatedConnectionsRequest", + "ListDedicatedConnectionsResponse", + "ListLinksRequest", + "ListLinksResponse", + "ListPartnersRequest", + "ListPartnersResponse", + "ListPopsRequest", + "ListPopsResponse", + "ListRoutingPoliciesRequest", + "ListRoutingPoliciesResponse", + "UpdateLinkRequest", + "UpdateRoutingPolicyRequest", + "InterlinkV1Beta1API", +] diff --git a/scaleway/scaleway/interlink/v1beta1/api.py b/scaleway/scaleway/interlink/v1beta1/api.py new file mode 100644 index 00000000..ed7fd366 --- /dev/null +++ b/scaleway/scaleway/interlink/v1beta1/api.py @@ -0,0 +1,1408 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + BgpStatus, + DedicatedConnectionStatus, + LinkKind, + LinkStatus, + ListDedicatedConnectionsRequestOrderBy, + ListLinksRequestOrderBy, + ListPartnersRequestOrderBy, + ListPopsRequestOrderBy, + ListRoutingPoliciesRequestOrderBy, + AttachRoutingPolicyRequest, + AttachVpcRequest, + CreateLinkRequest, + CreateRoutingPolicyRequest, + DedicatedConnection, + Link, + ListDedicatedConnectionsResponse, + ListLinksResponse, + ListPartnersResponse, + ListPopsResponse, + ListRoutingPoliciesResponse, + Partner, + Pop, + RoutingPolicy, + UpdateLinkRequest, + UpdateRoutingPolicyRequest, +) +from .content import ( + DEDICATED_CONNECTION_TRANSIENT_STATUSES, + LINK_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_DedicatedConnection, + unmarshal_Link, + unmarshal_Partner, + unmarshal_Pop, + unmarshal_RoutingPolicy, + unmarshal_ListDedicatedConnectionsResponse, + unmarshal_ListLinksResponse, + unmarshal_ListPartnersResponse, + unmarshal_ListPopsResponse, + unmarshal_ListRoutingPoliciesResponse, + marshal_AttachRoutingPolicyRequest, + marshal_AttachVpcRequest, + marshal_CreateLinkRequest, + marshal_CreateRoutingPolicyRequest, + marshal_UpdateLinkRequest, + marshal_UpdateRoutingPolicyRequest, +) + + +class InterlinkV1Beta1API(API): + """ + This API allows you to manage your Scaleway InterLink, to connect your on-premises infrastructure with your Scaleway VPC. + """ + + def list_dedicated_connections( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListDedicatedConnectionsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + status: Optional[DedicatedConnectionStatus] = None, + bandwidth_mbps: Optional[int] = None, + pop_id: Optional[str] = None, + ) -> ListDedicatedConnectionsResponse: + """ + List dedicated connections. + For self-hosted users, list their dedicated physical connections in a given region. By default, the connections returned in the list are ordered by name in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of connections to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Link name to filter for. + :param tags: Tags to filter for. + :param status: Connection status to filter for. + :param bandwidth_mbps: Filter for dedicated connections with this bandwidth size. + :param pop_id: Filter for dedicated connections present in this PoP. + :return: :class:`ListDedicatedConnectionsResponse ` + + Usage: + :: + + result = api.list_dedicated_connections() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/dedicated-connections", + params={ + "bandwidth_mbps": bandwidth_mbps, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pop_id": pop_id, + "project_id": project_id or self.client.default_project_id, + "status": status, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDedicatedConnectionsResponse(res.json()) + + def list_dedicated_connections_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListDedicatedConnectionsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + status: Optional[DedicatedConnectionStatus] = None, + bandwidth_mbps: Optional[int] = None, + pop_id: Optional[str] = None, + ) -> List[DedicatedConnection]: + """ + List dedicated connections. + For self-hosted users, list their dedicated physical connections in a given region. By default, the connections returned in the list are ordered by name in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of connections to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Link name to filter for. + :param tags: Tags to filter for. + :param status: Connection status to filter for. + :param bandwidth_mbps: Filter for dedicated connections with this bandwidth size. + :param pop_id: Filter for dedicated connections present in this PoP. + :return: :class:`List[DedicatedConnection] ` + + Usage: + :: + + result = api.list_dedicated_connections_all() + """ + + return fetch_all_pages( + type=ListDedicatedConnectionsResponse, + key="connections", + fetcher=self.list_dedicated_connections, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "organization_id": organization_id, + "name": name, + "tags": tags, + "status": status, + "bandwidth_mbps": bandwidth_mbps, + "pop_id": pop_id, + }, + ) + + def get_dedicated_connection( + self, + *, + connection_id: str, + region: Optional[ScwRegion] = None, + ) -> DedicatedConnection: + """ + Get a dedicated connection. + For self-hosted users, get a dedicated physical connection corresponding to the given ID. The response object includes information such as the connection's name, status and total bandwidth. + :param connection_id: ID of connection to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DedicatedConnection ` + + Usage: + :: + + result = api.get_dedicated_connection( + connection_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_connection_id = validate_path_param("connection_id", connection_id) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/dedicated-connections/{param_connection_id}", + ) + + self._throw_on_error(res) + return unmarshal_DedicatedConnection(res.json()) + + def wait_for_dedicated_connection( + self, + *, + connection_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[DedicatedConnection, bool]] = None, + ) -> DedicatedConnection: + """ + Get a dedicated connection. + For self-hosted users, get a dedicated physical connection corresponding to the given ID. The response object includes information such as the connection's name, status and total bandwidth. + :param connection_id: ID of connection to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DedicatedConnection ` + + Usage: + :: + + result = api.get_dedicated_connection( + connection_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in DEDICATED_CONNECTION_TRANSIENT_STATUSES + ) + + return wait_for_resource( + fetcher=self.get_dedicated_connection, + options=options, + args={ + "connection_id": connection_id, + "region": region, + }, + ) + + def list_partners( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListPartnersRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pop_ids: Optional[List[str]] = None, + ) -> ListPartnersResponse: + """ + List available partners. + List all available partners. By default, the partners returned in the list are ordered by name in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of partners to return per page. + :param pop_ids: Filter for partners present (offering a connection) in one of these PoPs. + :return: :class:`ListPartnersResponse ` + + Usage: + :: + + result = api.list_partners() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/partners", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pop_ids": pop_ids, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPartnersResponse(res.json()) + + def list_partners_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListPartnersRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + pop_ids: Optional[List[str]] = None, + ) -> List[Partner]: + """ + List available partners. + List all available partners. By default, the partners returned in the list are ordered by name in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of partners to return per page. + :param pop_ids: Filter for partners present (offering a connection) in one of these PoPs. + :return: :class:`List[Partner] ` + + Usage: + :: + + result = api.list_partners_all() + """ + + return fetch_all_pages( + type=ListPartnersResponse, + key="partners", + fetcher=self.list_partners, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "pop_ids": pop_ids, + }, + ) + + def get_partner( + self, + *, + partner_id: str, + region: Optional[ScwRegion] = None, + ) -> Partner: + """ + Get a partner. + Get a partner for the given partner IP. The response object includes information such as the partner's name, email address and portal URL. + :param partner_id: ID of partner to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Partner ` + + Usage: + :: + + result = api.get_partner( + partner_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_partner_id = validate_path_param("partner_id", partner_id) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/partners/{param_partner_id}", + ) + + self._throw_on_error(res) + return unmarshal_Partner(res.json()) + + def list_pops( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListPopsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + hosting_provider_name: Optional[str] = None, + partner_id: Optional[str] = None, + link_bandwidth_mbps: Optional[int] = None, + dedicated_available: Optional[bool] = None, + ) -> ListPopsResponse: + """ + List PoPs. + List all available PoPs (locations) for a given region. By default, the results are returned in ascending alphabetical order by name. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of PoPs to return per page. + :param name: PoP name to filter for. + :param hosting_provider_name: Hosting provider name to filter for. + :param partner_id: Filter for PoPs hosting an available shared connection from this partner. + :param link_bandwidth_mbps: Filter for PoPs with a shared connection allowing this bandwidth size. Note that we cannot guarantee that PoPs returned will have available capacity. + :param dedicated_available: Filter for PoPs with a dedicated connection available for self-hosted links. + :return: :class:`ListPopsResponse ` + + Usage: + :: + + result = api.list_pops() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/pops", + params={ + "dedicated_available": dedicated_available, + "hosting_provider_name": hosting_provider_name, + "link_bandwidth_mbps": link_bandwidth_mbps, + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "partner_id": partner_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPopsResponse(res.json()) + + def list_pops_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListPopsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + name: Optional[str] = None, + hosting_provider_name: Optional[str] = None, + partner_id: Optional[str] = None, + link_bandwidth_mbps: Optional[int] = None, + dedicated_available: Optional[bool] = None, + ) -> List[Pop]: + """ + List PoPs. + List all available PoPs (locations) for a given region. By default, the results are returned in ascending alphabetical order by name. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of PoPs to return per page. + :param name: PoP name to filter for. + :param hosting_provider_name: Hosting provider name to filter for. + :param partner_id: Filter for PoPs hosting an available shared connection from this partner. + :param link_bandwidth_mbps: Filter for PoPs with a shared connection allowing this bandwidth size. Note that we cannot guarantee that PoPs returned will have available capacity. + :param dedicated_available: Filter for PoPs with a dedicated connection available for self-hosted links. + :return: :class:`List[Pop] ` + + Usage: + :: + + result = api.list_pops_all() + """ + + return fetch_all_pages( + type=ListPopsResponse, + key="pops", + fetcher=self.list_pops, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "name": name, + "hosting_provider_name": hosting_provider_name, + "partner_id": partner_id, + "link_bandwidth_mbps": link_bandwidth_mbps, + "dedicated_available": dedicated_available, + }, + ) + + def get_pop( + self, + *, + pop_id: str, + region: Optional[ScwRegion] = None, + ) -> Pop: + """ + Get a PoP. + Get a PoP for the given PoP ID. The response object includes the PoP's name and information about its physical location. + :param pop_id: ID of PoP to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Pop ` + + Usage: + :: + + result = api.get_pop( + pop_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_pop_id = validate_path_param("pop_id", pop_id) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/pops/{param_pop_id}", + ) + + self._throw_on_error(res) + return unmarshal_Pop(res.json()) + + def list_links( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListLinksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + status: Optional[LinkStatus] = None, + bgp_v4_status: Optional[BgpStatus] = None, + bgp_v6_status: Optional[BgpStatus] = None, + pop_id: Optional[str] = None, + bandwidth_mbps: Optional[int] = None, + partner_id: Optional[str] = None, + vpc_id: Optional[str] = None, + routing_policy_id: Optional[str] = None, + pairing_key: Optional[str] = None, + kind: Optional[LinkKind] = None, + connection_id: Optional[str] = None, + ) -> ListLinksResponse: + """ + List links. + List all your links (InterLink connections). A number of filters are available, including Project ID, name, tags and status. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of links to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Link name to filter for. + :param tags: Tags to filter for. + :param status: Link status to filter for. + :param bgp_v4_status: BGP IPv4 status to filter for. + :param bgp_v6_status: BGP IPv6 status to filter for. + :param pop_id: Filter for links attached to this PoP (via connections). + :param bandwidth_mbps: Filter for link bandwidth (in Mbps). + :param partner_id: Filter for links hosted by this partner. + :param vpc_id: Filter for links attached to this VPC. + :param routing_policy_id: Filter for links using this routing policy. + :param pairing_key: Filter for the link with this pairing_key. + :param kind: Filter for hosted or self-hosted links. + :param connection_id: Filter for links self-hosted on this connection. + :return: :class:`ListLinksResponse ` + + Usage: + :: + + result = api.list_links() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/links", + params={ + "bandwidth_mbps": bandwidth_mbps, + "bgp_v4_status": bgp_v4_status, + "bgp_v6_status": bgp_v6_status, + "connection_id": connection_id, + "kind": kind, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "pairing_key": pairing_key, + "partner_id": partner_id, + "pop_id": pop_id, + "project_id": project_id or self.client.default_project_id, + "routing_policy_id": routing_policy_id, + "status": status, + "tags": tags, + "vpc_id": vpc_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListLinksResponse(res.json()) + + def list_links_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListLinksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + status: Optional[LinkStatus] = None, + bgp_v4_status: Optional[BgpStatus] = None, + bgp_v6_status: Optional[BgpStatus] = None, + pop_id: Optional[str] = None, + bandwidth_mbps: Optional[int] = None, + partner_id: Optional[str] = None, + vpc_id: Optional[str] = None, + routing_policy_id: Optional[str] = None, + pairing_key: Optional[str] = None, + kind: Optional[LinkKind] = None, + connection_id: Optional[str] = None, + ) -> List[Link]: + """ + List links. + List all your links (InterLink connections). A number of filters are available, including Project ID, name, tags and status. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of links to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Link name to filter for. + :param tags: Tags to filter for. + :param status: Link status to filter for. + :param bgp_v4_status: BGP IPv4 status to filter for. + :param bgp_v6_status: BGP IPv6 status to filter for. + :param pop_id: Filter for links attached to this PoP (via connections). + :param bandwidth_mbps: Filter for link bandwidth (in Mbps). + :param partner_id: Filter for links hosted by this partner. + :param vpc_id: Filter for links attached to this VPC. + :param routing_policy_id: Filter for links using this routing policy. + :param pairing_key: Filter for the link with this pairing_key. + :param kind: Filter for hosted or self-hosted links. + :param connection_id: Filter for links self-hosted on this connection. + :return: :class:`List[Link] ` + + Usage: + :: + + result = api.list_links_all() + """ + + return fetch_all_pages( + type=ListLinksResponse, + key="links", + fetcher=self.list_links, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "organization_id": organization_id, + "name": name, + "tags": tags, + "status": status, + "bgp_v4_status": bgp_v4_status, + "bgp_v6_status": bgp_v6_status, + "pop_id": pop_id, + "bandwidth_mbps": bandwidth_mbps, + "partner_id": partner_id, + "vpc_id": vpc_id, + "routing_policy_id": routing_policy_id, + "pairing_key": pairing_key, + "kind": kind, + "connection_id": connection_id, + }, + ) + + def get_link( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Get a link. + Get a link (InterLink session / logical InterLink resource) for the given link ID. The response object includes information about the link's various configuration details. + :param link_id: ID of the link to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = api.get_link( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}", + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + def wait_for_link( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Link, bool]] = None, + ) -> Link: + """ + Get a link. + Get a link (InterLink session / logical InterLink resource) for the given link ID. The response object includes information about the link's various configuration details. + :param link_id: ID of the link to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = api.get_link( + link_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in LINK_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_link, + options=options, + args={ + "link_id": link_id, + "region": region, + }, + ) + + def create_link( + self, + *, + name: str, + pop_id: str, + bandwidth_mbps: int, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + connection_id: Optional[str] = None, + partner_id: Optional[str] = None, + peer_asn: Optional[int] = None, + ) -> Link: + """ + Create a link. + Create a link (InterLink session / logical InterLink resource) in a given PoP, specifying its various configuration details. Links can either be hosted (facilitated by partners' shared physical connections) or self-hosted (for users who have purchased a dedicated physical connection). + :param name: Name of the link. + :param pop_id: PoP (location) where the link will be created. + :param bandwidth_mbps: Desired bandwidth for the link. Must be compatible with available link bandwidths and remaining bandwidth capacity of the connection. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to create the link in. + :param tags: List of tags to apply to the link. + :param connection_id: If set, creates a self-hosted link using this dedicated physical connection. As the customer, specify the ID of the physical connection you already have for this link. + One-Of ('host'): at most one of 'connection_id', 'partner_id' could be set. + :param partner_id: If set, creates a hosted link on a partner's connection. Specify the ID of the chosen partner, who already has a shared connection with available bandwidth. + One-Of ('host'): at most one of 'connection_id', 'partner_id' could be set. + :param peer_asn: For self-hosted links we need the peer AS Number to establish BGP session. If not given, a default one will be assigned. + :return: :class:`Link ` + + Usage: + :: + + result = api.create_link( + name="example", + pop_id="example", + bandwidth_mbps=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links", + body=marshal_CreateLinkRequest( + CreateLinkRequest( + name=name, + pop_id=pop_id, + bandwidth_mbps=bandwidth_mbps, + region=region, + project_id=project_id, + tags=tags, + peer_asn=peer_asn, + connection_id=connection_id, + partner_id=partner_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + def update_link( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + peer_asn: Optional[int] = None, + ) -> Link: + """ + Update a link. + Update an existing link, specified by its link ID. Only its name and tags can be updated. + :param link_id: ID of the link to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the link. + :param tags: List of tags to apply to the link. + :param peer_asn: For self-hosted links, AS Number to establish BGP session. + :return: :class:`Link ` + + Usage: + :: + + result = api.update_link( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "PATCH", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}", + body=marshal_UpdateLinkRequest( + UpdateLinkRequest( + link_id=link_id, + region=region, + name=name, + tags=tags, + peer_asn=peer_asn, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + def delete_link( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Delete a link. + Delete an existing link, specified by its link ID. Note that as well as deleting the link here on the Scaleway side, it is also necessary to request deletion from the partner on their side. Only when this action has been carried out on both sides will the resource be completely deleted. + :param link_id: ID of the link to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = api.delete_link( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "DELETE", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}", + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + def attach_vpc( + self, + *, + link_id: str, + vpc_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Attach a VPC. + Attach a VPC to an existing link. This facilitates communication between the resources in your Scaleway VPC, and your on-premises infrastructure. + :param link_id: ID of the link to attach VPC to. + :param vpc_id: ID of the VPC to attach. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = api.attach_vpc( + link_id="example", + vpc_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/attach-vpc", + body=marshal_AttachVpcRequest( + AttachVpcRequest( + link_id=link_id, + vpc_id=vpc_id, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + def detach_vpc( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Detach a VPC. + Detach a VPC from an existing link. + :param link_id: ID of the link to detach the VPC from. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = api.detach_vpc( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/detach-vpc", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + def attach_routing_policy( + self, + *, + link_id: str, + routing_policy_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Attach a routing policy. + Attach a routing policy to an existing link. As all routes across the link are blocked by default, you must attach a routing policy to set IP prefix filters for allowed routes, facilitating traffic flow. + :param link_id: ID of the link to attach a routing policy to. + :param routing_policy_id: ID of the routing policy to be attached. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = api.attach_routing_policy( + link_id="example", + routing_policy_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/attach-routing-policy", + body=marshal_AttachRoutingPolicyRequest( + AttachRoutingPolicyRequest( + link_id=link_id, + routing_policy_id=routing_policy_id, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + def detach_routing_policy( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Detach a routing policy. + Detach a routing policy from an existing link. Without a routing policy, all routes across the link are blocked by default. + :param link_id: ID of the link to detach a routing policy from. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = api.detach_routing_policy( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/detach-routing-policy", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + def enable_route_propagation( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Enable route propagation. + Enable all allowed prefixes (defined in a routing policy) to be announced in the BGP session. This allows traffic to flow between the attached VPC and the on-premises infrastructure along the announced routes. Note that by default, even when route propagation is enabled, all routes are blocked. It is essential to attach a routing policy to define the ranges of routes to announce. + :param link_id: ID of the link on which to enable route propagation. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = api.enable_route_propagation( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/enable-route-propagation", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + def disable_route_propagation( + self, + *, + link_id: str, + region: Optional[ScwRegion] = None, + ) -> Link: + """ + Disable route propagation. + Prevent any prefixes from being announced in the BGP session. Traffic will not be able to flow over the InterLink until route propagation is re-enabled. + :param link_id: ID of the link on which to disable route propagation. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Link ` + + Usage: + :: + + result = api.disable_route_propagation( + link_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_link_id = validate_path_param("link_id", link_id) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/links/{param_link_id}/disable-route-propagation", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Link(res.json()) + + def list_routing_policies( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListRoutingPoliciesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> ListRoutingPoliciesResponse: + """ + List routing policies. + List all routing policies in a given region. A routing policy can be attached to one or multiple links (InterLink connections). + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of routing policies to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Routing policy name to filter for. + :param tags: Tags to filter for. + :return: :class:`ListRoutingPoliciesResponse ` + + Usage: + :: + + result = api.list_routing_policies() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/routing-policies", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListRoutingPoliciesResponse(res.json()) + + def list_routing_policies_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListRoutingPoliciesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> List[RoutingPolicy]: + """ + List routing policies. + List all routing policies in a given region. A routing policy can be attached to one or multiple links (InterLink connections). + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Maximum number of routing policies to return per page. + :param project_id: Project ID to filter for. + :param organization_id: Organization ID to filter for. + :param name: Routing policy name to filter for. + :param tags: Tags to filter for. + :return: :class:`List[RoutingPolicy] ` + + Usage: + :: + + result = api.list_routing_policies_all() + """ + + return fetch_all_pages( + type=ListRoutingPoliciesResponse, + key="routing_policies", + fetcher=self.list_routing_policies, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "organization_id": organization_id, + "name": name, + "tags": tags, + }, + ) + + def get_routing_policy( + self, + *, + routing_policy_id: str, + region: Optional[ScwRegion] = None, + ) -> RoutingPolicy: + """ + Get routing policy. + Get a routing policy for the given routing policy ID. The response object gives information including the policy's name, tags and prefix filters. + :param routing_policy_id: ID of the routing policy to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`RoutingPolicy ` + + Usage: + :: + + result = api.get_routing_policy( + routing_policy_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_routing_policy_id = validate_path_param( + "routing_policy_id", routing_policy_id + ) + + res = self._request( + "GET", + f"/interlink/v1beta1/regions/{param_region}/routing-policies/{param_routing_policy_id}", + ) + + self._throw_on_error(res) + return unmarshal_RoutingPolicy(res.json()) + + def create_routing_policy( + self, + *, + name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + prefix_filter_in: Optional[List[str]] = None, + prefix_filter_out: Optional[List[str]] = None, + ) -> RoutingPolicy: + """ + Create a routing policy. + Create a routing policy. Routing policies allow you to set IP prefix filters to define the incoming route announcements to accept from the peer, and the outgoing routes to announce to the peer. + :param name: Name of the routing policy. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to create the routing policy in. + :param tags: List of tags to apply to the routing policy. + :param prefix_filter_in: IP prefixes to accept from the peer (ranges of route announcements to accept). + :param prefix_filter_out: IP prefix filters to advertise to the peer (ranges of routes to advertise). + :return: :class:`RoutingPolicy ` + + Usage: + :: + + result = api.create_routing_policy( + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/interlink/v1beta1/regions/{param_region}/routing-policies", + body=marshal_CreateRoutingPolicyRequest( + CreateRoutingPolicyRequest( + name=name, + region=region, + project_id=project_id, + tags=tags, + prefix_filter_in=prefix_filter_in, + prefix_filter_out=prefix_filter_out, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RoutingPolicy(res.json()) + + def update_routing_policy( + self, + *, + routing_policy_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + prefix_filter_in: Optional[List[str]] = None, + prefix_filter_out: Optional[List[str]] = None, + ) -> RoutingPolicy: + """ + Update a routing policy. + Update an existing routing policy, specified by its routing policy ID. Its name, tags and incoming/outgoing prefix filters can be updated. + :param routing_policy_id: ID of the routing policy to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the routing policy. + :param tags: List of tags to apply to the routing policy. + :param prefix_filter_in: IP prefixes to accept from the peer (ranges of route announcements to accept). + :param prefix_filter_out: IP prefix filters for routes to advertise to the peer (ranges of routes to advertise). + :return: :class:`RoutingPolicy ` + + Usage: + :: + + result = api.update_routing_policy( + routing_policy_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_routing_policy_id = validate_path_param( + "routing_policy_id", routing_policy_id + ) + + res = self._request( + "PATCH", + f"/interlink/v1beta1/regions/{param_region}/routing-policies/{param_routing_policy_id}", + body=marshal_UpdateRoutingPolicyRequest( + UpdateRoutingPolicyRequest( + routing_policy_id=routing_policy_id, + region=region, + name=name, + tags=tags, + prefix_filter_in=prefix_filter_in, + prefix_filter_out=prefix_filter_out, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_RoutingPolicy(res.json()) + + def delete_routing_policy( + self, + *, + routing_policy_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a routing policy. + Delete an existing routing policy, specified by its routing policy ID. + :param routing_policy_id: ID of the routing policy to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_routing_policy( + routing_policy_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_routing_policy_id = validate_path_param( + "routing_policy_id", routing_policy_id + ) + + res = self._request( + "DELETE", + f"/interlink/v1beta1/regions/{param_region}/routing-policies/{param_routing_policy_id}", + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/interlink/v1beta1/content.py b/scaleway/scaleway/interlink/v1beta1/content.py new file mode 100644 index 00000000..dea5950e --- /dev/null +++ b/scaleway/scaleway/interlink/v1beta1/content.py @@ -0,0 +1,21 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + DedicatedConnectionStatus, + LinkStatus, +) + +DEDICATED_CONNECTION_TRANSIENT_STATUSES: List[DedicatedConnectionStatus] = [ + DedicatedConnectionStatus.CONFIGURING, +] +""" +Lists transient statutes of the enum :class:`DedicatedConnectionStatus `. +""" +LINK_TRANSIENT_STATUSES: List[LinkStatus] = [ + LinkStatus.CONFIGURING, +] +""" +Lists transient statutes of the enum :class:`LinkStatus `. +""" diff --git a/scaleway/scaleway/interlink/v1beta1/marshalling.py b/scaleway/scaleway/interlink/v1beta1/marshalling.py new file mode 100644 index 00000000..0768e3db --- /dev/null +++ b/scaleway/scaleway/interlink/v1beta1/marshalling.py @@ -0,0 +1,645 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + DedicatedConnection, + BgpConfig, + PartnerHost, + SelfHost, + Link, + Partner, + Pop, + RoutingPolicy, + ListDedicatedConnectionsResponse, + ListLinksResponse, + ListPartnersResponse, + ListPopsResponse, + ListRoutingPoliciesResponse, + AttachRoutingPolicyRequest, + AttachVpcRequest, + CreateLinkRequest, + CreateRoutingPolicyRequest, + UpdateLinkRequest, + UpdateRoutingPolicyRequest, +) + + +def unmarshal_DedicatedConnection(data: Any) -> DedicatedConnection: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DedicatedConnection' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("pop_id", None) + if field is not None: + args["pop_id"] = field + + field = data.get("bandwidth_mbps", None) + if field is not None: + args["bandwidth_mbps"] = field + + field = data.get("available_link_bandwidths", None) + if field is not None: + args["available_link_bandwidths"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("demarcation_info", None) + if field is not None: + args["demarcation_info"] = field + else: + args["demarcation_info"] = None + + return DedicatedConnection(**args) + + +def unmarshal_BgpConfig(data: Any) -> BgpConfig: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BgpConfig' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("asn", None) + if field is not None: + args["asn"] = field + + field = data.get("ipv4", None) + if field is not None: + args["ipv4"] = field + + field = data.get("ipv6", None) + if field is not None: + args["ipv6"] = field + + return BgpConfig(**args) + + +def unmarshal_PartnerHost(data: Any) -> PartnerHost: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PartnerHost' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("partner_id", None) + if field is not None: + args["partner_id"] = field + + field = data.get("pairing_key", None) + if field is not None: + args["pairing_key"] = field + + field = data.get("disapproved_reason", None) + if field is not None: + args["disapproved_reason"] = field + else: + args["disapproved_reason"] = None + + return PartnerHost(**args) + + +def unmarshal_SelfHost(data: Any) -> SelfHost: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SelfHost' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("connection_id", None) + if field is not None: + args["connection_id"] = field + + return SelfHost(**args) + + +def unmarshal_Link(data: Any) -> Link: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Link' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("pop_id", None) + if field is not None: + args["pop_id"] = field + + field = data.get("bandwidth_mbps", None) + if field is not None: + args["bandwidth_mbps"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("bgp_v4_status", None) + if field is not None: + args["bgp_v4_status"] = field + + field = data.get("bgp_v6_status", None) + if field is not None: + args["bgp_v6_status"] = field + + field = data.get("enable_route_propagation", None) + if field is not None: + args["enable_route_propagation"] = field + + field = data.get("vlan", None) + if field is not None: + args["vlan"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("vpc_id", None) + if field is not None: + args["vpc_id"] = field + else: + args["vpc_id"] = None + + field = data.get("routing_policy_id", None) + if field is not None: + args["routing_policy_id"] = field + else: + args["routing_policy_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("partner", None) + if field is not None: + args["partner"] = unmarshal_PartnerHost(field) + else: + args["partner"] = None + + field = data.get("self", None) + if field is not None: + args["self_"] = unmarshal_SelfHost(field) + else: + args["self_"] = None + + field = data.get("scw_bgp_config", None) + if field is not None: + args["scw_bgp_config"] = unmarshal_BgpConfig(field) + else: + args["scw_bgp_config"] = None + + field = data.get("peer_bgp_config", None) + if field is not None: + args["peer_bgp_config"] = unmarshal_BgpConfig(field) + else: + args["peer_bgp_config"] = None + + return Link(**args) + + +def unmarshal_Partner(data: Any) -> Partner: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Partner' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("contact_email", None) + if field is not None: + args["contact_email"] = field + + field = data.get("logo_url", None) + if field is not None: + args["logo_url"] = field + + field = data.get("portal_url", None) + if field is not None: + args["portal_url"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Partner(**args) + + +def unmarshal_Pop(data: Any) -> Pop: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pop' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("hosting_provider_name", None) + if field is not None: + args["hosting_provider_name"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("city", None) + if field is not None: + args["city"] = field + + field = data.get("logo_url", None) + if field is not None: + args["logo_url"] = field + + field = data.get("available_link_bandwidths_mbps", None) + if field is not None: + args["available_link_bandwidths_mbps"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + return Pop(**args) + + +def unmarshal_RoutingPolicy(data: Any) -> RoutingPolicy: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RoutingPolicy' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("prefix_filter_in", None) + if field is not None: + args["prefix_filter_in"] = field + + field = data.get("prefix_filter_out", None) + if field is not None: + args["prefix_filter_out"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return RoutingPolicy(**args) + + +def unmarshal_ListDedicatedConnectionsResponse( + data: Any, +) -> ListDedicatedConnectionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDedicatedConnectionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("connections", None) + if field is not None: + args["connections"] = ( + [unmarshal_DedicatedConnection(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListDedicatedConnectionsResponse(**args) + + +def unmarshal_ListLinksResponse(data: Any) -> ListLinksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListLinksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("links", None) + if field is not None: + args["links"] = ( + [unmarshal_Link(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListLinksResponse(**args) + + +def unmarshal_ListPartnersResponse(data: Any) -> ListPartnersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPartnersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("partners", None) + if field is not None: + args["partners"] = ( + [unmarshal_Partner(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPartnersResponse(**args) + + +def unmarshal_ListPopsResponse(data: Any) -> ListPopsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPopsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pops", None) + if field is not None: + args["pops"] = [unmarshal_Pop(v) for v in field] if field is not None else None + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPopsResponse(**args) + + +def unmarshal_ListRoutingPoliciesResponse(data: Any) -> ListRoutingPoliciesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListRoutingPoliciesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("routing_policies", None) + if field is not None: + args["routing_policies"] = ( + [unmarshal_RoutingPolicy(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListRoutingPoliciesResponse(**args) + + +def marshal_AttachRoutingPolicyRequest( + request: AttachRoutingPolicyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.routing_policy_id is not None: + output["routing_policy_id"] = request.routing_policy_id + + return output + + +def marshal_AttachVpcRequest( + request: AttachVpcRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.vpc_id is not None: + output["vpc_id"] = request.vpc_id + + return output + + +def marshal_CreateLinkRequest( + request: CreateLinkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("connection_id", request.connection_id), + OneOfPossibility("partner_id", request.partner_id), + ] + ), + ) + + if request.name is not None: + output["name"] = request.name + + if request.pop_id is not None: + output["pop_id"] = request.pop_id + + if request.bandwidth_mbps is not None: + output["bandwidth_mbps"] = request.bandwidth_mbps + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.peer_asn is not None: + output["peer_asn"] = request.peer_asn + + return output + + +def marshal_CreateRoutingPolicyRequest( + request: CreateRoutingPolicyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.prefix_filter_in is not None: + output["prefix_filter_in"] = request.prefix_filter_in + + if request.prefix_filter_out is not None: + output["prefix_filter_out"] = request.prefix_filter_out + + return output + + +def marshal_UpdateLinkRequest( + request: UpdateLinkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.peer_asn is not None: + output["peer_asn"] = request.peer_asn + + return output + + +def marshal_UpdateRoutingPolicyRequest( + request: UpdateRoutingPolicyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.prefix_filter_in is not None: + output["prefix_filter_in"] = request.prefix_filter_in + + if request.prefix_filter_out is not None: + output["prefix_filter_out"] = request.prefix_filter_out + + return output diff --git a/scaleway/scaleway/interlink/v1beta1/types.py b/scaleway/scaleway/interlink/v1beta1/types.py new file mode 100644 index 00000000..b41c803a --- /dev/null +++ b/scaleway/scaleway/interlink/v1beta1/types.py @@ -0,0 +1,1114 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class BgpStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_BGP_STATUS = "unknown_bgp_status" + UP = "up" + DOWN = "down" + + def __str__(self) -> str: + return str(self.value) + + +class DedicatedConnectionStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATED = "created" + CONFIGURING = "configuring" + FAILED = "failed" + ACTIVE = "active" + DISABLED = "disabled" + DELETED = "deleted" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class LinkKind(str, Enum, metaclass=StrEnumMeta): + HOSTED = "hosted" + SELF_HOSTED = "self_hosted" + + def __str__(self) -> str: + return str(self.value) + + +class LinkStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_LINK_STATUS = "unknown_link_status" + CONFIGURING = "configuring" + FAILED = "failed" + REQUESTED = "requested" + REFUSED = "refused" + EXPIRED = "expired" + PROVISIONING = "provisioning" + ACTIVE = "active" + LIMITED_CONNECTIVITY = "limited_connectivity" + ALL_DOWN = "all_down" + DEPROVISIONING = "deprovisioning" + DELETED = "deleted" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class ListDedicatedConnectionsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + UPDATED_AT_ASC = "updated_at_asc" + UPDATED_AT_DESC = "updated_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListLinksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPartnersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPopsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListRoutingPoliciesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class BgpConfig: + asn: int + """ + AS Number of the BGP peer. + """ + + ipv4: str + """ + IPv4 address of the BGP peer. + """ + + ipv6: str + """ + IPv6 address of the BGP peer. + """ + + +@dataclass +class PartnerHost: + partner_id: str + """ + ID of the partner facilitating the link. + """ + + pairing_key: str + """ + Used to identify a link from a user or partner's point of view. + """ + + disapproved_reason: Optional[str] + """ + Reason given by partner to explain why they did not approve the request for a hosted link. + """ + + +@dataclass +class SelfHost: + connection_id: str + """ + Dedicated physical connection supporting the link. + """ + + +@dataclass +class DedicatedConnection: + id: str + """ + Unique identifier of the dedicated connection. + """ + + project_id: str + """ + Project ID. + """ + + organization_id: str + """ + Organization ID. + """ + + status: DedicatedConnectionStatus + """ + Status of the dedicated connection. + """ + + name: str + """ + Name of the dedicated connection. + """ + + tags: List[str] + """ + List of tags associated with the dedicated connection. + """ + + pop_id: str + """ + ID of the PoP where the dedicated connection is located. + """ + + bandwidth_mbps: int + """ + Bandwidth size of the dedicated connection. + """ + + available_link_bandwidths: List[int] + """ + Size of the links supported on this dedicated connection. + """ + + region: ScwRegion + """ + Region of the dedicated connection. + """ + + created_at: Optional[datetime] + """ + Creation date of the dedicated connection. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the dedicated connection. + """ + + demarcation_info: Optional[str] + """ + Demarcation details required by the data center to set up the supporting Cross Connect. This generally includes the physical space in the facility, the cabinet or rack the connection should land in, the patch panel to go in, the port designation, and the media type. + """ + + +@dataclass +class Link: + id: str + """ + Unique identifier of the link. + """ + + project_id: str + """ + Project ID. + """ + + organization_id: str + """ + Organization ID. + """ + + name: str + """ + Name of the link. + """ + + tags: List[str] + """ + List of tags associated with the link. + """ + + pop_id: str + """ + ID of the PoP where the link's corresponding connection is located. + """ + + bandwidth_mbps: int + """ + Rate limited bandwidth of the link. + """ + + status: LinkStatus + """ + Status of the link. + """ + + bgp_v4_status: BgpStatus + """ + Status of the link's BGP IPv4 session. + """ + + bgp_v6_status: BgpStatus + """ + Status of the link's BGP IPv6 session. + """ + + enable_route_propagation: bool + """ + Defines whether route propagation is enabled or not. To enable or disable route propagation, use the dedicated endpoint. + """ + + vlan: int + """ + VLAN of the link. + """ + + region: ScwRegion + """ + Region of the link. + """ + + vpc_id: Optional[str] + """ + ID of the Scaleway VPC attached to the link. + """ + + routing_policy_id: Optional[str] + """ + ID of the routing policy attached to the link. + """ + + created_at: Optional[datetime] + """ + Creation date of the link. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the link. + """ + + scw_bgp_config: Optional[BgpConfig] + """ + BGP configuration on Scaleway's side. + """ + + peer_bgp_config: Optional[BgpConfig] + """ + BGP configuration on peer's side (on-premises or other hosting provider). + """ + + partner: Optional[PartnerHost] + + self_: Optional[SelfHost] + + +@dataclass +class Partner: + id: str + """ + Unique identifier of the partner. + """ + + name: str + """ + Name of the partner. + """ + + contact_email: str + """ + Contact email address of partner. + """ + + logo_url: str + """ + Image URL of the partner's logo. + """ + + portal_url: str + """ + URL of the partner's portal. + """ + + created_at: Optional[datetime] + """ + Creation date of the partner. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the partner. + """ + + +@dataclass +class Pop: + id: str + """ + Unique identifier of the PoP. + """ + + name: str + """ + Name of the PoP. It is the common reference of Hosting DC (ex: TH2). + """ + + hosting_provider_name: str + """ + Name of the PoP's hosting provider, e.g. Telehouse for TH2 or OpCore for DC3. + """ + + address: str + """ + Physical address of the PoP. + """ + + city: str + """ + City where PoP is located. + """ + + logo_url: str + """ + Image URL of the PoP's logo. + """ + + available_link_bandwidths_mbps: List[int] + """ + Available bandwidth in Mbits/s for future hosted links from available connections in this PoP. + """ + + region: ScwRegion + """ + Region of the PoP. + """ + + +@dataclass +class RoutingPolicy: + id: str + """ + Unique identifier of the routing policy. + """ + + project_id: str + """ + Project ID. + """ + + organization_id: str + """ + Organization ID. + """ + + name: str + """ + Name of the routing policy. + """ + + tags: List[str] + """ + List of tags associated with the routing policy. + """ + + prefix_filter_in: List[str] + """ + IP prefixes to accept from the peer (ranges of route announcements to accept). + """ + + prefix_filter_out: List[str] + """ + IP prefix filters to advertise to the peer (ranges of routes to advertise). + """ + + region: ScwRegion + """ + Region of the routing policy. + """ + + created_at: Optional[datetime] + """ + Creation date of the routing policy. + """ + + updated_at: Optional[datetime] + """ + Last modification date of the routing policy. + """ + + +@dataclass +class AttachRoutingPolicyRequest: + link_id: str + """ + ID of the link to attach a routing policy to. + """ + + routing_policy_id: str + """ + ID of the routing policy to be attached. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class AttachVpcRequest: + link_id: str + """ + ID of the link to attach VPC to. + """ + + vpc_id: str + """ + ID of the VPC to attach. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateLinkRequest: + name: str + """ + Name of the link. + """ + + pop_id: str + """ + PoP (location) where the link will be created. + """ + + bandwidth_mbps: int + """ + Desired bandwidth for the link. Must be compatible with available link bandwidths and remaining bandwidth capacity of the connection. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to create the link in. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the link. + """ + + peer_asn: Optional[int] + """ + For self-hosted links we need the peer AS Number to establish BGP session. If not given, a default one will be assigned. + """ + + connection_id: Optional[str] + + partner_id: Optional[str] + + +@dataclass +class CreateRoutingPolicyRequest: + name: str + """ + Name of the routing policy. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to create the routing policy in. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the routing policy. + """ + + prefix_filter_in: Optional[List[str]] + """ + IP prefixes to accept from the peer (ranges of route announcements to accept). + """ + + prefix_filter_out: Optional[List[str]] + """ + IP prefix filters to advertise to the peer (ranges of routes to advertise). + """ + + +@dataclass +class DeleteLinkRequest: + link_id: str + """ + ID of the link to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteRoutingPolicyRequest: + routing_policy_id: str + """ + ID of the routing policy to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DetachRoutingPolicyRequest: + link_id: str + """ + ID of the link to detach a routing policy from. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DetachVpcRequest: + link_id: str + """ + ID of the link to detach the VPC from. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DisableRoutePropagationRequest: + link_id: str + """ + ID of the link on which to disable route propagation. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class EnableRoutePropagationRequest: + link_id: str + """ + ID of the link on which to enable route propagation. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDedicatedConnectionRequest: + connection_id: str + """ + ID of connection to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetLinkRequest: + link_id: str + """ + ID of the link to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetPartnerRequest: + partner_id: str + """ + ID of partner to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetPopRequest: + pop_id: str + """ + ID of PoP to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetRoutingPolicyRequest: + routing_policy_id: str + """ + ID of the routing policy to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListDedicatedConnectionsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListDedicatedConnectionsRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of connections to return per page. + """ + + project_id: Optional[str] + """ + Project ID to filter for. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. + """ + + name: Optional[str] + """ + Link name to filter for. + """ + + tags: Optional[List[str]] + """ + Tags to filter for. + """ + + status: Optional[DedicatedConnectionStatus] + """ + Connection status to filter for. + """ + + bandwidth_mbps: Optional[int] + """ + Filter for dedicated connections with this bandwidth size. + """ + + pop_id: Optional[str] + """ + Filter for dedicated connections present in this PoP. + """ + + +@dataclass +class ListDedicatedConnectionsResponse: + connections: List[DedicatedConnection] + """ + List of connections on current page. + """ + + total_count: int + """ + Total number of connections returned. + """ + + +@dataclass +class ListLinksRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListLinksRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of links to return per page. + """ + + project_id: Optional[str] + """ + Project ID to filter for. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. + """ + + name: Optional[str] + """ + Link name to filter for. + """ + + tags: Optional[List[str]] + """ + Tags to filter for. + """ + + status: Optional[LinkStatus] + """ + Link status to filter for. + """ + + bgp_v4_status: Optional[BgpStatus] + """ + BGP IPv4 status to filter for. + """ + + bgp_v6_status: Optional[BgpStatus] + """ + BGP IPv6 status to filter for. + """ + + pop_id: Optional[str] + """ + Filter for links attached to this PoP (via connections). + """ + + bandwidth_mbps: Optional[int] + """ + Filter for link bandwidth (in Mbps). + """ + + partner_id: Optional[str] + """ + Filter for links hosted by this partner. + """ + + vpc_id: Optional[str] + """ + Filter for links attached to this VPC. + """ + + routing_policy_id: Optional[str] + """ + Filter for links using this routing policy. + """ + + pairing_key: Optional[str] + """ + Filter for the link with this pairing_key. + """ + + kind: Optional[LinkKind] + """ + Filter for hosted or self-hosted links. + """ + + connection_id: Optional[str] + """ + Filter for links self-hosted on this connection. + """ + + +@dataclass +class ListLinksResponse: + links: List[Link] + """ + List of links on the current page. + """ + + total_count: int + """ + Total number of links. + """ + + +@dataclass +class ListPartnersRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListPartnersRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of partners to return per page. + """ + + pop_ids: Optional[List[str]] + """ + Filter for partners present (offering a connection) in one of these PoPs. + """ + + +@dataclass +class ListPartnersResponse: + partners: List[Partner] + """ + List of partners on current page. + """ + + total_count: int + """ + Total number of partners returned. + """ + + +@dataclass +class ListPopsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListPopsRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of PoPs to return per page. + """ + + name: Optional[str] + """ + PoP name to filter for. + """ + + hosting_provider_name: Optional[str] + """ + Hosting provider name to filter for. + """ + + partner_id: Optional[str] + """ + Filter for PoPs hosting an available shared connection from this partner. + """ + + link_bandwidth_mbps: Optional[int] + """ + Filter for PoPs with a shared connection allowing this bandwidth size. Note that we cannot guarantee that PoPs returned will have available capacity. + """ + + dedicated_available: Optional[bool] + """ + Filter for PoPs with a dedicated connection available for self-hosted links. + """ + + +@dataclass +class ListPopsResponse: + pops: List[Pop] + """ + List of PoPs on the current page. + """ + + total_count: int + """ + Total number of PoPs. + """ + + +@dataclass +class ListRoutingPoliciesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListRoutingPoliciesRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Maximum number of routing policies to return per page. + """ + + project_id: Optional[str] + """ + Project ID to filter for. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. + """ + + name: Optional[str] + """ + Routing policy name to filter for. + """ + + tags: Optional[List[str]] + """ + Tags to filter for. + """ + + +@dataclass +class ListRoutingPoliciesResponse: + routing_policies: List[RoutingPolicy] + + total_count: int + + +@dataclass +class UpdateLinkRequest: + link_id: str + """ + ID of the link to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the link. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the link. + """ + + peer_asn: Optional[int] + """ + For self-hosted links, AS Number to establish BGP session. + """ + + +@dataclass +class UpdateRoutingPolicyRequest: + routing_policy_id: str + """ + ID of the routing policy to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the routing policy. + """ + + tags: Optional[List[str]] + """ + List of tags to apply to the routing policy. + """ + + prefix_filter_in: Optional[List[str]] + """ + IP prefixes to accept from the peer (ranges of route announcements to accept). + """ + + prefix_filter_out: Optional[List[str]] + """ + IP prefix filters for routes to advertise to the peer (ranges of routes to advertise). + """ diff --git a/scaleway/scaleway/iot/v1/api.py b/scaleway/scaleway/iot/v1/api.py index 8d19b003..6ba11f54 100644 --- a/scaleway/scaleway/iot/v1/api.py +++ b/scaleway/scaleway/iot/v1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( WaitForOptions, @@ -100,13 +100,13 @@ class IotV1API(API): """ - This API allows you to manage IoT hubs and devices. + This API allows you to manage your IoT hubs and devices. """ def list_hubs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListHubsRequestOrderBy] = None, @@ -156,7 +156,7 @@ def list_hubs( def list_hubs_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListHubsRequestOrderBy] = None, @@ -201,7 +201,7 @@ def create_hub( self, *, product_plan: HubProductPlan, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, project_id: Optional[str] = None, disable_events: Optional[bool] = None, @@ -257,7 +257,7 @@ def get_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hub: """ Get a hub. @@ -291,7 +291,7 @@ def wait_for_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Hub, bool]] = None, ) -> Hub: """ @@ -328,7 +328,7 @@ def update_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, product_plan: Optional[HubProductPlan] = None, disable_events: Optional[bool] = None, @@ -388,7 +388,7 @@ def enable_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hub: """ Enable a hub. @@ -423,7 +423,7 @@ def disable_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hub: """ Disable a hub. @@ -458,7 +458,7 @@ def delete_hub( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, delete_devices: Optional[bool] = None, ) -> None: """ @@ -495,7 +495,7 @@ def get_hub_metrics( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, start_date: Optional[datetime] = None, ) -> GetHubMetricsResponse: """ @@ -537,7 +537,7 @@ def set_hub_ca( hub_id: str, ca_cert_pem: str, challenge_cert_pem: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hub: """ Set the certificate authority of a hub. @@ -584,7 +584,7 @@ def get_hub_ca( self, *, hub_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> GetHubCAResponse: """ Get the certificate authority of a hub. @@ -617,7 +617,7 @@ def get_hub_ca( def list_devices( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDevicesRequestOrderBy] = None, @@ -635,7 +635,7 @@ def list_devices( :param order_by: Ordering of requested devices. :param name: Name to filter for, only devices with this name will be returned. :param hub_id: Hub ID to filter for, only devices attached to this Hub will be returned. - :param allow_insecure: Defines wheter to filter the allow_insecure flag. + :param allow_insecure: Defines whether to filter the allow_insecure flag. :param status: Device status (enabled, disabled, etc.). :return: :class:`ListDevicesResponse ` @@ -669,7 +669,7 @@ def list_devices( def list_devices_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListDevicesRequestOrderBy] = None, @@ -687,7 +687,7 @@ def list_devices_all( :param order_by: Ordering of requested devices. :param name: Name to filter for, only devices with this name will be returned. :param hub_id: Hub ID to filter for, only devices attached to this Hub will be returned. - :param allow_insecure: Defines wheter to filter the allow_insecure flag. + :param allow_insecure: Defines whether to filter the allow_insecure flag. :param status: Device status (enabled, disabled, etc.). :return: :class:`List[Device] ` @@ -719,7 +719,7 @@ def create_device( hub_id: str, allow_insecure: bool, allow_multiple_connections: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, message_filters: Optional[DeviceMessageFilters] = None, description: Optional[str] = None, @@ -774,7 +774,7 @@ def get_device( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Device: """ Get a device. @@ -808,7 +808,7 @@ def update_device( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, allow_insecure: Optional[bool] = None, allow_multiple_connections: Optional[bool] = None, @@ -864,7 +864,7 @@ def enable_device( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Device: """ Enable a device. @@ -899,7 +899,7 @@ def disable_device( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Device: """ Disable a device. @@ -934,7 +934,7 @@ def renew_device_certificate( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> RenewDeviceCertificateResponse: """ Renew a device certificate. @@ -970,7 +970,7 @@ def set_device_certificate( *, device_id: str, certificate_pem: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SetDeviceCertificateResponse: """ Set a custom certificate on a device. @@ -1014,7 +1014,7 @@ def get_device_certificate( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> GetDeviceCertificateResponse: """ Get a device's certificate. @@ -1048,7 +1048,7 @@ def delete_device( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Remove a device. @@ -1080,7 +1080,7 @@ def get_device_metrics( self, *, device_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, start_date: Optional[datetime] = None, ) -> GetDeviceMetricsResponse: """ @@ -1119,7 +1119,7 @@ def get_device_metrics( def list_routes( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, @@ -1165,7 +1165,7 @@ def list_routes( def list_routes_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, @@ -1208,7 +1208,7 @@ def create_route( *, hub_id: str, topic: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, s3_config: Optional[CreateRouteRequestS3Config] = None, db_config: Optional[CreateRouteRequestDatabaseConfig] = None, @@ -1222,15 +1222,15 @@ def create_route( You need to manage the database by yourself. - REST Route. Create a route that will call a REST API on received subscribed MQTT messages. - - S3 Routes. - Create a route that will put subscribed MQTT messages into an S3 bucket. + - Amazon S3 Routes. + Create a route that will put subscribed MQTT messages into an Object Storage bucket. You need to create the bucket yourself and grant write access. Granting can be done with s3cmd (`s3cmd setacl s3:// --acl-grant=write:555c69c3-87d0-4bf8-80f1-99a2f757d031:555c69c3-87d0-4bf8-80f1-99a2f757d031`). :param hub_id: Hub ID of the route. :param topic: Topic the route subscribes to. It must be a valid MQTT topic and up to 65535 characters. :param region: Region to target. If none is passed will use default region from the config. :param name: Route name. - :param s3_config: If creating S3 Route, S3-specific configuration fields. + :param s3_config: If creating Amazon S3 Routes, Amazon S3-specific configuration fields. One-Of ('config'): at most one of 's3_config', 'db_config', 'rest_config' could be set. :param db_config: If creating Database Route, DB-specific configuration fields. One-Of ('config'): at most one of 's3_config', 'db_config', 'rest_config' could be set. @@ -1275,7 +1275,7 @@ def update_route( self, *, route_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, topic: Optional[str] = None, s3_config: Optional[UpdateRouteRequestS3Config] = None, @@ -1289,7 +1289,7 @@ def update_route( :param region: Region to target. If none is passed will use default region from the config. :param name: Route name. :param topic: Topic the route subscribes to. It must be a valid MQTT topic and up to 65535 characters. - :param s3_config: When updating S3 Route, S3-specific configuration fields. + :param s3_config: When updating Amazon S3 Route, Amazon S3-specific configuration fields. One-Of ('config'): at most one of 's3_config', 'db_config', 'rest_config' could be set. :param db_config: When updating Database Route, DB-specific configuration fields. One-Of ('config'): at most one of 's3_config', 'db_config', 'rest_config' could be set. @@ -1334,7 +1334,7 @@ def get_route( self, *, route_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Route: """ Get a route. @@ -1368,7 +1368,7 @@ def delete_route( self, *, route_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a route. @@ -1399,7 +1399,7 @@ def delete_route( def list_networks( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNetworksRequestOrderBy] = None, @@ -1447,7 +1447,7 @@ def list_networks( def list_networks_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNetworksRequestOrderBy] = None, @@ -1493,7 +1493,7 @@ def create_network( type_: NetworkNetworkType, hub_id: str, topic_prefix: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, ) -> CreateNetworkResponse: """ @@ -1542,7 +1542,7 @@ def get_network( self, *, network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Network: """ Retrieve a specific network. @@ -1576,7 +1576,7 @@ def delete_network( self, *, network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a Network. @@ -1609,7 +1609,7 @@ def get_twin_document( *, twin_id: str, document_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> TwinDocument: """ BETA - Get a Cloud Twin Document. @@ -1646,7 +1646,7 @@ def put_twin_document( *, twin_id: str, document_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, version: Optional[int] = None, data: Optional[Dict[str, Any]] = None, ) -> TwinDocument: @@ -1697,7 +1697,7 @@ def patch_twin_document( *, twin_id: str, document_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, version: Optional[int] = None, data: Optional[Dict[str, Any]] = None, ) -> TwinDocument: @@ -1753,7 +1753,7 @@ def delete_twin_document( *, twin_id: str, document_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ BETA - Delete a Cloud Twin Document. @@ -1787,7 +1787,7 @@ def list_twin_documents( self, *, twin_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListTwinDocumentsResponse: """ BETA - List the documents of a Cloud Twin. @@ -1820,7 +1820,7 @@ def delete_twin_documents( self, *, twin_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ BETA - Delete all the documents of a Cloud Twin. diff --git a/scaleway/scaleway/iot/v1/marshalling.py b/scaleway/scaleway/iot/v1/marshalling.py index 97f75d2c..518fb91e 100644 --- a/scaleway/scaleway/iot/v1/marshalling.py +++ b/scaleway/scaleway/iot/v1/marshalling.py @@ -75,6 +75,8 @@ def unmarshal_DeviceMessageFiltersRule(data: Any) -> DeviceMessageFiltersRule: field = data.get("topics", None) if field is not None: args["topics"] = field + else: + args["topics"] = None return DeviceMessageFiltersRule(**args) @@ -90,10 +92,14 @@ def unmarshal_DeviceMessageFilters(data: Any) -> DeviceMessageFilters: field = data.get("publish", None) if field is not None: args["publish"] = unmarshal_DeviceMessageFiltersRule(field) + else: + args["publish"] = None field = data.get("subscribe", None) if field is not None: args["subscribe"] = unmarshal_DeviceMessageFiltersRule(field) + else: + args["subscribe"] = None return DeviceMessageFilters(**args) @@ -131,6 +137,8 @@ def unmarshal_Device(data: Any) -> Device: args["last_activity_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_activity_at"] = None field = data.get("is_connected", None) if field is not None: @@ -151,14 +159,20 @@ def unmarshal_Device(data: Any) -> Device: field = data.get("message_filters", None) if field is not None: args["message_filters"] = unmarshal_DeviceMessageFilters(field) + else: + args["message_filters"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Device(**args) @@ -179,7 +193,7 @@ def unmarshal_Network(data: Any) -> Network: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -198,6 +212,8 @@ def unmarshal_Network(data: Any) -> Network: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return Network(**args) @@ -288,14 +304,20 @@ def unmarshal_Hub(data: Any) -> Hub: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("twins_graphite_config", None) if field is not None: args["twins_graphite_config"] = unmarshal_HubTwinsGraphiteConfig(field) + else: + args["twins_graphite_config"] = None return Hub(**args) @@ -330,10 +352,14 @@ def unmarshal_CreateDeviceResponse(data: Any) -> CreateDeviceResponse: field = data.get("device", None) if field is not None: args["device"] = unmarshal_Device(field) + else: + args["device"] = None field = data.get("certificate", None) if field is not None: args["certificate"] = unmarshal_Certificate(field) + else: + args["certificate"] = None return CreateDeviceResponse(**args) @@ -353,6 +379,8 @@ def unmarshal_CreateNetworkResponse(data: Any) -> CreateNetworkResponse: field = data.get("network", None) if field is not None: args["network"] = unmarshal_Network(field) + else: + args["network"] = None return CreateNetworkResponse(**args) @@ -372,6 +400,8 @@ def unmarshal_GetDeviceCertificateResponse(data: Any) -> GetDeviceCertificateRes field = data.get("device", None) if field is not None: args["device"] = unmarshal_Device(field) + else: + args["device"] = None return GetDeviceCertificateResponse(**args) @@ -510,17 +540,21 @@ def unmarshal_RouteSummary(data: Any) -> RouteSummary: if field is not None: args["topic"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return RouteSummary(**args) @@ -595,10 +629,14 @@ def unmarshal_RenewDeviceCertificateResponse( field = data.get("device", None) if field is not None: args["device"] = unmarshal_Device(field) + else: + args["device"] = None field = data.get("certificate", None) if field is not None: args["certificate"] = unmarshal_Certificate(field) + else: + args["certificate"] = None return RenewDeviceCertificateResponse(**args) @@ -716,29 +754,39 @@ def unmarshal_Route(data: Any) -> Route: if field is not None: args["topic"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("s3_config", None) if field is not None: args["s3_config"] = unmarshal_RouteS3Config(field) + else: + args["s3_config"] = None field = data.get("db_config", None) if field is not None: args["db_config"] = unmarshal_RouteDatabaseConfig(field) + else: + args["db_config"] = None field = data.get("rest_config", None) if field is not None: args["rest_config"] = unmarshal_RouteRestConfig(field) + else: + args["rest_config"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Route(**args) @@ -758,6 +806,8 @@ def unmarshal_SetDeviceCertificateResponse(data: Any) -> SetDeviceCertificateRes field = data.get("device", None) if field is not None: args["device"] = unmarshal_Device(field) + else: + args["device"] = None return SetDeviceCertificateResponse(**args) @@ -785,6 +835,8 @@ def unmarshal_TwinDocument(data: Any) -> TwinDocument: field = data.get("data", None) if field is not None: args["data"] = field + else: + args["data"] = None return TwinDocument(**args) @@ -811,13 +863,11 @@ def marshal_DeviceMessageFilters( output: Dict[str, Any] = {} if request.publish is not None: - output["publish"] = ( - marshal_DeviceMessageFiltersRule(request.publish, defaults), - ) + output["publish"] = marshal_DeviceMessageFiltersRule(request.publish, defaults) if request.subscribe is not None: - output["subscribe"] = ( - marshal_DeviceMessageFiltersRule(request.subscribe, defaults), + output["subscribe"] = marshal_DeviceMessageFiltersRule( + request.subscribe, defaults ) return output @@ -842,8 +892,8 @@ def marshal_CreateDeviceRequest( output["name"] = request.name if request.message_filters is not None: - output["message_filters"] = ( - marshal_DeviceMessageFilters(request.message_filters, defaults), + output["message_filters"] = marshal_DeviceMessageFilters( + request.message_filters, defaults ) if request.description is not None: @@ -1087,8 +1137,8 @@ def marshal_UpdateDeviceRequest( output["allow_multiple_connections"] = request.allow_multiple_connections if request.message_filters is not None: - output["message_filters"] = ( - marshal_DeviceMessageFilters(request.message_filters, defaults), + output["message_filters"] = marshal_DeviceMessageFilters( + request.message_filters, defaults ) if request.hub_id is not None: diff --git a/scaleway/scaleway/iot/v1/types.py b/scaleway/scaleway/iot/v1/types.py index a967258a..b6d2338a 100644 --- a/scaleway/scaleway/iot/v1/types.py +++ b/scaleway/scaleway/iot/v1/types.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, TimeSeries, ) from scaleway_core.utils import ( @@ -400,7 +400,7 @@ class Hub: Hub events topic prefix. """ - region: Region + region: ScwRegion """ Region of the Hub. """ @@ -544,12 +544,12 @@ class RouteRestConfig: class RouteS3Config: bucket_region: str """ - Region of the S3 route's destination bucket (e.g., 'fr-par'). + Region of the Amazon S3 route's destination bucket (e.g., 'fr-par'). """ bucket_name: str """ - Destination bucket name of the S3 route. + Destination bucket name of the Amazon S3 route. """ object_prefix: str @@ -559,7 +559,7 @@ class RouteS3Config: strategy: RouteS3ConfigS3Strategy """ - How the S3 route's objects will be created: one per topic or one per message. + How the Amazon S3 route's objects will be created: one per topic or one per message. """ @@ -617,7 +617,7 @@ class CreateDeviceRequest: Defines whether to allow multiple physical devices to connect with this device's credentials. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -658,7 +658,7 @@ class CreateHubRequest: Hub product plan. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -703,7 +703,7 @@ class CreateNetworkRequest: Topic prefix for the Network. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -739,7 +739,7 @@ class CreateRouteRequest: Topic the route subscribes to. It must be a valid MQTT topic and up to 65535 characters. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -763,7 +763,7 @@ class DeleteDeviceRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -776,7 +776,7 @@ class DeleteHubRequest: Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -794,7 +794,7 @@ class DeleteNetworkRequest: Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -807,7 +807,7 @@ class DeleteRouteRequest: Route ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -825,7 +825,7 @@ class DeleteTwinDocumentRequest: Name of the document. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -838,7 +838,7 @@ class DeleteTwinDocumentsRequest: Twin ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -851,7 +851,7 @@ class DisableDeviceRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -864,7 +864,7 @@ class DisableHubRequest: Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -877,7 +877,7 @@ class EnableDeviceRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -890,7 +890,7 @@ class EnableHubRequest: Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -903,7 +903,7 @@ class GetDeviceCertificateRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -929,7 +929,7 @@ class GetDeviceMetricsRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -955,7 +955,7 @@ class GetDeviceRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -965,7 +965,7 @@ class GetDeviceRequest: class GetHubCARequest: hub_id: str - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -983,7 +983,7 @@ class GetHubMetricsRequest: Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1009,7 +1009,7 @@ class GetHubRequest: Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1022,7 +1022,7 @@ class GetNetworkRequest: Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1035,7 +1035,7 @@ class GetRouteRequest: Route ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1053,7 +1053,7 @@ class GetTwinDocumentRequest: Name of the document. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1061,7 +1061,7 @@ class GetTwinDocumentRequest: @dataclass class ListDevicesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1093,7 +1093,7 @@ class ListDevicesRequest: allow_insecure: Optional[bool] """ - Defines wheter to filter the allow_insecure flag. + Defines whether to filter the allow_insecure flag. """ status: Optional[DeviceStatus] @@ -1117,7 +1117,7 @@ class ListDevicesResponse: @dataclass class ListHubsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1168,7 +1168,7 @@ class ListHubsResponse: @dataclass class ListNetworksRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1219,7 +1219,7 @@ class ListNetworksResponse: @dataclass class ListRoutesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1270,7 +1270,7 @@ class ListTwinDocumentsRequest: Twin ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1296,7 +1296,7 @@ class PatchTwinDocumentRequest: Name of the document. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1329,7 +1329,7 @@ class PutTwinDocumentRequest: Name of the document. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1352,7 +1352,7 @@ class RenewDeviceCertificateRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1427,7 +1427,7 @@ class SetDeviceCertificateRequest: PEM-encoded custom certificate. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1457,7 +1457,7 @@ class SetHubCARequest: Challenge is a PEM-encoded certificate that acts as proof of possession of the CA. It must be signed by the CA, and have a Common Name equal to the Hub ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1493,7 +1493,7 @@ class UpdateDeviceRequest: Device ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1531,7 +1531,7 @@ class UpdateHubRequest: ID of the Hub you want to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1571,7 +1571,7 @@ class UpdateRouteRequest: Route id. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/scaleway/ipam/v1/__init__.py b/scaleway/scaleway/ipam/v1/__init__.py index 78a2a03c..0cbf4d27 100644 --- a/scaleway/scaleway/ipam/v1/__init__.py +++ b/scaleway/scaleway/ipam/v1/__init__.py @@ -5,12 +5,17 @@ from .types import Resource from .types import Reverse from .types import Source +from .types import CustomResource from .types import IP +from .types import AttachIPRequest from .types import BookIPRequest +from .types import DetachIPRequest from .types import GetIPRequest from .types import ListIPsRequest from .types import ListIPsResponse +from .types import MoveIPRequest from .types import ReleaseIPRequest +from .types import ReleaseIPSetRequest from .types import UpdateIPRequest from .api import IpamV1API @@ -20,12 +25,17 @@ "Resource", "Reverse", "Source", + "CustomResource", "IP", + "AttachIPRequest", "BookIPRequest", + "DetachIPRequest", "GetIPRequest", "ListIPsRequest", "ListIPsResponse", + "MoveIPRequest", "ReleaseIPRequest", + "ReleaseIPSetRequest", "UpdateIPRequest", "IpamV1API", ] diff --git a/scaleway/scaleway/ipam/v1/api.py b/scaleway/scaleway/ipam/v1/api.py index 9453d432..e629b62e 100644 --- a/scaleway/scaleway/ipam/v1/api.py +++ b/scaleway/scaleway/ipam/v1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( OneOfPossibility, @@ -16,9 +16,14 @@ from .types import ( ListIPsRequestOrderBy, ResourceType, + AttachIPRequest, BookIPRequest, + CustomResource, + DetachIPRequest, IP, ListIPsResponse, + MoveIPRequest, + ReleaseIPSetRequest, Reverse, Source, UpdateIPRequest, @@ -26,14 +31,18 @@ from .marshalling import ( unmarshal_IP, unmarshal_ListIPsResponse, + marshal_AttachIPRequest, marshal_BookIPRequest, + marshal_DetachIPRequest, + marshal_MoveIPRequest, + marshal_ReleaseIPSetRequest, marshal_UpdateIPRequest, ) class IpamV1API(API): """ - This API allows you to manage IP addresses with Scaleway's IP Address Management tool. + This API allows you to manage your Scaleway IP addresses with our IP Address Management tool. """ def book_ip( @@ -41,20 +50,22 @@ def book_ip( *, source: Source, is_ipv6: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, address: Optional[str] = None, tags: Optional[List[str]] = None, + resource: Optional[CustomResource] = None, ) -> IP: """ - Book a new IP. - Book a new IP from the specified source. Currently IPs can only be booked from a Private Network. - :param source: Source in which to book the IP. Not all sources are available for booking. + Reserve a new IP. + Reserve a new IP from the specified source. Currently IPs can only be reserved from a Private Network. + :param source: Source in which to reserve the IP. Not all sources are available for reservation. :param is_ipv6: Request an IPv6 instead of an IPv4. :param region: Region to target. If none is passed will use default region from the config. :param project_id: When creating an IP in a Private Network, the Project must match the Private Network's Project. - :param address: Note that only the Private Network source allows you to pick a specific IP. If the requested IP is already booked, then the call will fail. + :param address: The requested address should not include the subnet mask (/suffix). Note that only the Private Network source allows you to pick a specific IP. If the requested IP is already reserved, then the call will fail. :param tags: Tags for the IP. + :param resource: Custom resource to attach to the IP being reserved. An example of a custom resource is a virtual machine hosted on an Elastic Metal server. Do not use this for attaching IP addresses to standard Scaleway resources, as it will fail - instead, see the relevant product API for an equivalent method. :return: :class:`IP ` Usage: @@ -81,6 +92,7 @@ def book_ip( project_id=project_id, address=address, tags=tags, + resource=resource, ), self.client, ), @@ -93,7 +105,7 @@ def release_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Release an IP. @@ -122,11 +134,45 @@ def release_ip( self._throw_on_error(res) + def release_ip_set( + self, + *, + region: Optional[ScwRegion] = None, + ip_ids: Optional[List[str]] = None, + ) -> None: + """ + :param region: Region to target. If none is passed will use default region from the config. + :param ip_ids: + + Usage: + :: + + result = api.release_ip_set() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/ipam/v1/regions/{param_region}/ip-sets/release", + body=marshal_ReleaseIPSetRequest( + ReleaseIPSetRequest( + region=region, + ip_ids=ip_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + def get_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> IP: """ Get an IP. @@ -160,7 +206,7 @@ def update_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, tags: Optional[List[str]] = None, reverses: Optional[List[Reverse]] = None, ) -> IP: @@ -206,21 +252,26 @@ def update_ip( def list_i_ps( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, zonal: Optional[str] = None, private_network_id: Optional[str] = None, + subnet_id: Optional[str] = None, + vpc_id: Optional[str] = None, attached: Optional[bool] = None, + resource_name: Optional[str] = None, resource_id: Optional[str] = None, + resource_ids: Optional[List[str]] = None, resource_type: Optional[ResourceType] = None, + resource_types: Optional[List[ResourceType]] = None, mac_address: Optional[str] = None, tags: Optional[List[str]] = None, organization_id: Optional[str] = None, is_ipv6: Optional[bool] = None, - resource_name: Optional[str] = None, + ip_ids: Optional[List[str]] = None, ) -> ListIPsResponse: """ List existing IPs. @@ -231,17 +282,23 @@ def list_i_ps( :param page_size: Maximum number of IPs to return per page. :param project_id: Project ID to filter for. Only IPs belonging to this Project will be returned. :param zonal: Zone to filter for. Only IPs that are zonal, and in this zone, will be returned. - One-Of ('source'): at most one of 'zonal', 'private_network_id' could be set. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. :param private_network_id: Only IPs that are private, and in this Private Network, will be returned. - One-Of ('source'): at most one of 'zonal', 'private_network_id' could be set. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. + :param subnet_id: Only IPs inside this exact subnet will be returned. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. + :param vpc_id: Only IPs owned by resources in this VPC will be returned. :param attached: Defines whether to filter only for IPs which are attached to a resource. + :param resource_name: Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. :param resource_id: Resource ID to filter for. Only IPs attached to this resource will be returned. + :param resource_ids: Resource IDs to filter for. Only IPs attached to at least one of these resources will be returned. :param resource_type: Resource type to filter for. Only IPs attached to this type of resource will be returned. + :param resource_types: Resource types to filter for. Only IPs attached to these types of resources will be returned. :param mac_address: MAC address to filter for. Only IPs attached to a resource with this MAC address will be returned. :param tags: Tags to filter for, only IPs with one or more matching tags will be returned. :param organization_id: Organization ID to filter for. Only IPs belonging to this Organization will be returned. :param is_ipv6: Defines whether to filter only for IPv4s or IPv6s. - :param resource_name: Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. + :param ip_ids: IP IDs to filter for. Only IPs with these UUIDs will be returned. :return: :class:`ListIPsResponse ` Usage: @@ -259,6 +316,7 @@ def list_i_ps( f"/ipam/v1/regions/{param_region}/ips", params={ "attached": attached, + "ip_ids": ip_ids, "is_ipv6": is_ipv6, "mac_address": mac_address, "order_by": order_by, @@ -268,12 +326,16 @@ def list_i_ps( "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, "resource_id": resource_id, + "resource_ids": resource_ids, "resource_name": resource_name, "resource_type": resource_type, + "resource_types": resource_types, "tags": tags, + "vpc_id": vpc_id, **resolve_one_of( [ OneOfPossibility("private_network_id", private_network_id), + OneOfPossibility("subnet_id", subnet_id), OneOfPossibility("zonal", zonal), ] ), @@ -286,21 +348,26 @@ def list_i_ps( def list_i_ps_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, zonal: Optional[str] = None, private_network_id: Optional[str] = None, + subnet_id: Optional[str] = None, + vpc_id: Optional[str] = None, attached: Optional[bool] = None, + resource_name: Optional[str] = None, resource_id: Optional[str] = None, + resource_ids: Optional[List[str]] = None, resource_type: Optional[ResourceType] = None, + resource_types: Optional[List[ResourceType]] = None, mac_address: Optional[str] = None, tags: Optional[List[str]] = None, organization_id: Optional[str] = None, is_ipv6: Optional[bool] = None, - resource_name: Optional[str] = None, + ip_ids: Optional[List[str]] = None, ) -> List[IP]: """ List existing IPs. @@ -311,17 +378,23 @@ def list_i_ps_all( :param page_size: Maximum number of IPs to return per page. :param project_id: Project ID to filter for. Only IPs belonging to this Project will be returned. :param zonal: Zone to filter for. Only IPs that are zonal, and in this zone, will be returned. - One-Of ('source'): at most one of 'zonal', 'private_network_id' could be set. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. :param private_network_id: Only IPs that are private, and in this Private Network, will be returned. - One-Of ('source'): at most one of 'zonal', 'private_network_id' could be set. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. + :param subnet_id: Only IPs inside this exact subnet will be returned. + One-Of ('source'): at most one of 'zonal', 'private_network_id', 'subnet_id' could be set. + :param vpc_id: Only IPs owned by resources in this VPC will be returned. :param attached: Defines whether to filter only for IPs which are attached to a resource. + :param resource_name: Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. :param resource_id: Resource ID to filter for. Only IPs attached to this resource will be returned. + :param resource_ids: Resource IDs to filter for. Only IPs attached to at least one of these resources will be returned. :param resource_type: Resource type to filter for. Only IPs attached to this type of resource will be returned. + :param resource_types: Resource types to filter for. Only IPs attached to these types of resources will be returned. :param mac_address: MAC address to filter for. Only IPs attached to a resource with this MAC address will be returned. :param tags: Tags to filter for, only IPs with one or more matching tags will be returned. :param organization_id: Organization ID to filter for. Only IPs belonging to this Organization will be returned. :param is_ipv6: Defines whether to filter only for IPv4s or IPv6s. - :param resource_name: Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. + :param ip_ids: IP IDs to filter for. Only IPs with these UUIDs will be returned. :return: :class:`List[IP] ` Usage: @@ -340,15 +413,158 @@ def list_i_ps_all( "page": page, "page_size": page_size, "project_id": project_id, + "vpc_id": vpc_id, "attached": attached, + "resource_name": resource_name, "resource_id": resource_id, + "resource_ids": resource_ids, "resource_type": resource_type, + "resource_types": resource_types, "mac_address": mac_address, "tags": tags, "organization_id": organization_id, "is_ipv6": is_ipv6, - "resource_name": resource_name, + "ip_ids": ip_ids, "zonal": zonal, "private_network_id": private_network_id, + "subnet_id": subnet_id, }, ) + + def attach_ip( + self, + *, + ip_id: str, + resource: CustomResource, + region: Optional[ScwRegion] = None, + ) -> IP: + """ + Attach IP to custom resource. + Attach an existing reserved IP from a Private Network subnet to a custom, named resource via its MAC address. An example of a custom resource is a virtual machine hosted on an Elastic Metal server. Do not use this method for attaching IP addresses to standard Scaleway resources as it will fail - see the relevant product API for an equivalent method. + :param ip_id: IP ID. + :param resource: Custom resource to be attached to the IP. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`IP ` + + Usage: + :: + + result = api.attach_ip( + ip_id="example", + resource=CustomResource(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "POST", + f"/ipam/v1/regions/{param_region}/ips/{param_ip_id}/attach", + body=marshal_AttachIPRequest( + AttachIPRequest( + ip_id=ip_id, + resource=resource, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + def detach_ip( + self, + *, + ip_id: str, + resource: CustomResource, + region: Optional[ScwRegion] = None, + ) -> IP: + """ + Detach IP from a custom resource. + Detach a private IP from a custom resource. An example of a custom resource is a virtual machine hosted on an Elastic Metal server. Do not use this method for detaching IP addresses from standard Scaleway resources (e.g. Instances, Load Balancers) as it will fail - see the relevant product API for an equivalent method. + :param ip_id: IP ID. + :param resource: Custom resource currently attached to the IP. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`IP ` + + Usage: + :: + + result = api.detach_ip( + ip_id="example", + resource=CustomResource(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "POST", + f"/ipam/v1/regions/{param_region}/ips/{param_ip_id}/detach", + body=marshal_DetachIPRequest( + DetachIPRequest( + ip_id=ip_id, + resource=resource, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + def move_ip( + self, + *, + ip_id: str, + from_resource: CustomResource, + region: Optional[ScwRegion] = None, + to_resource: Optional[CustomResource] = None, + ) -> IP: + """ + Move IP to a custom resource. + Move an existing reserved private IP from one custom resource (e.g. a virtual machine hosted on an Elastic Metal server) to another custom resource. This will detach it from the first resource, and attach it to the second. Do not use this method for moving IP addresses between standard Scaleway resources (e.g. Instances, Load Balancers) as it will fail - see the relevant product API for an equivalent method. + :param ip_id: IP ID. + :param from_resource: Custom resource currently attached to the IP. + :param region: Region to target. If none is passed will use default region from the config. + :param to_resource: Custom resource to be attached to the IP. + :return: :class:`IP ` + + Usage: + :: + + result = api.move_ip( + ip_id="example", + from_resource=CustomResource(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "POST", + f"/ipam/v1/regions/{param_region}/ips/{param_ip_id}/move", + body=marshal_MoveIPRequest( + MoveIPRequest( + ip_id=ip_id, + from_resource=from_resource, + region=region, + to_resource=to_resource, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) diff --git a/scaleway/scaleway/ipam/v1/marshalling.py b/scaleway/scaleway/ipam/v1/marshalling.py index bcd99871..dc61dff9 100644 --- a/scaleway/scaleway/ipam/v1/marshalling.py +++ b/scaleway/scaleway/ipam/v1/marshalling.py @@ -15,7 +15,12 @@ Source, IP, ListIPsResponse, + CustomResource, + AttachIPRequest, BookIPRequest, + DetachIPRequest, + MoveIPRequest, + ReleaseIPSetRequest, UpdateIPRequest, ) @@ -28,7 +33,7 @@ def unmarshal_Resource(data: Any) -> Resource: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -39,10 +44,14 @@ def unmarshal_Resource(data: Any) -> Resource: field = data.get("mac_address", None) if field is not None: args["mac_address"] = field + else: + args["mac_address"] = None field = data.get("name", None) if field is not None: args["name"] = field + else: + args["name"] = None return Resource(**args) @@ -62,6 +71,8 @@ def unmarshal_Reverse(data: Any) -> Reverse: field = data.get("address", None) if field is not None: args["address"] = field + else: + args["address"] = None return Reverse(**args) @@ -77,14 +88,20 @@ def unmarshal_Source(data: Any) -> Source: field = data.get("zonal", None) if field is not None: args["zonal"] = field + else: + args["zonal"] = None field = data.get("private_network_id", None) if field is not None: args["private_network_id"] = field + else: + args["private_network_id"] = None field = data.get("subnet_id", None) if field is not None: args["subnet_id"] = field + else: + args["subnet_id"] = None return Source(**args) @@ -113,10 +130,6 @@ def unmarshal_IP(data: Any) -> IP: if field is not None: args["is_ipv6"] = field - field = data.get("source", None) - if field is not None: - args["source"] = unmarshal_Source(field) - field = data.get("tags", None) if field is not None: args["tags"] = field @@ -134,18 +147,32 @@ def unmarshal_IP(data: Any) -> IP: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("source", None) + if field is not None: + args["source"] = unmarshal_Source(field) + else: + args["source"] = None field = data.get("resource", None) if field is not None: args["resource"] = unmarshal_Resource(field) + else: + args["resource"] = None field = data.get("zone", None) if field is not None: args["zone"] = field + else: + args["zone"] = None return IP(**args) @@ -169,6 +196,33 @@ def unmarshal_ListIPsResponse(data: Any) -> ListIPsResponse: return ListIPsResponse(**args) +def marshal_CustomResource( + request: CustomResource, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.mac_address is not None: + output["mac_address"] = request.mac_address + + if request.name is not None: + output["name"] = request.name + + return output + + +def marshal_AttachIPRequest( + request: AttachIPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.resource is not None: + output["resource"] = marshal_CustomResource(request.resource, defaults) + + return output + + def marshal_Source( request: Source, defaults: ProfileDefaults, @@ -194,7 +248,7 @@ def marshal_BookIPRequest( output: Dict[str, Any] = {} if request.source is not None: - output["source"] = (marshal_Source(request.source, defaults),) + output["source"] = marshal_Source(request.source, defaults) if request.is_ipv6 is not None: output["is_ipv6"] = request.is_ipv6 @@ -208,6 +262,50 @@ def marshal_BookIPRequest( if request.tags is not None: output["tags"] = request.tags + if request.resource is not None: + output["resource"] = marshal_CustomResource(request.resource, defaults) + + return output + + +def marshal_DetachIPRequest( + request: DetachIPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.resource is not None: + output["resource"] = marshal_CustomResource(request.resource, defaults) + + return output + + +def marshal_MoveIPRequest( + request: MoveIPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.from_resource is not None: + output["from_resource"] = marshal_CustomResource( + request.from_resource, defaults + ) + + if request.to_resource is not None: + output["to_resource"] = marshal_CustomResource(request.to_resource, defaults) + + return output + + +def marshal_ReleaseIPSetRequest( + request: ReleaseIPSetRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip_ids is not None: + output["ip_ids"] = request.ip_ids + return output diff --git a/scaleway/scaleway/ipam/v1/types.py b/scaleway/scaleway/ipam/v1/types.py index 61365126..1c7ed6fb 100644 --- a/scaleway/scaleway/ipam/v1/types.py +++ b/scaleway/scaleway/ipam/v1/types.py @@ -8,8 +8,8 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, - Zone, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -30,6 +30,7 @@ def __str__(self) -> str: class ResourceType(str, Enum, metaclass=StrEnumMeta): UNKNOWN_TYPE = "unknown_type" + CUSTOM = "custom" INSTANCE_SERVER = "instance_server" INSTANCE_IP = "instance_ip" INSTANCE_PRIVATE_NIC = "instance_private_nic" @@ -44,6 +45,13 @@ class ResourceType(str, Enum, metaclass=StrEnumMeta): BAREMETAL_SERVER = "baremetal_server" BAREMETAL_PRIVATE_NIC = "baremetal_private_nic" LLM_DEPLOYMENT = "llm_deployment" + MGDB_INSTANCE = "mgdb_instance" + APPLE_SILICON_SERVER = "apple_silicon_server" + APPLE_SILICON_PRIVATE_NIC = "apple_silicon_private_nic" + SERVERLESS_CONTAINER = "serverless_container" + SERVERLESS_FUNCTION = "serverless_function" + VPN_GATEWAY = "vpn_gateway" + DDL_DATALAB = "ddl_datalab" def __str__(self) -> str: return str(self.value) @@ -94,6 +102,19 @@ class Source: subnet_id: Optional[str] +@dataclass +class CustomResource: + mac_address: str + """ + MAC address of the custom resource. + """ + + name: Optional[str] + """ + When the resource is in a Private Network, a DNS record is available to resolve the resource name. + """ + + @dataclass class IP: id: str @@ -116,11 +137,6 @@ class IP: Defines whether the IP is an IPv6 (false = IPv4). """ - source: Source - """ - Source pool where the IP was booked in. - """ - tags: List[str] """ Tags for the IP. @@ -131,14 +147,14 @@ class IP: Array of reverses associated with the IP. """ - region: Region + region: ScwRegion """ Region of the IP. """ created_at: Optional[datetime] """ - Date the IP was booked. + Date the IP was reserved. """ updated_at: Optional[datetime] @@ -146,22 +162,45 @@ class IP: Date the IP was last modified. """ + source: Optional[Source] + """ + Source pool where the IP was reserved in. + """ + resource: Optional[Resource] """ Resource which the IP is attached to. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone of the IP, if zonal. """ +@dataclass +class AttachIPRequest: + ip_id: str + """ + IP ID. + """ + + resource: CustomResource + """ + Custom resource to be attached to the IP. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class BookIPRequest: source: Source """ - Source in which to book the IP. Not all sources are available for booking. + Source in which to reserve the IP. Not all sources are available for reservation. """ is_ipv6: bool @@ -169,7 +208,7 @@ class BookIPRequest: Request an IPv6 instead of an IPv4. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -181,7 +220,7 @@ class BookIPRequest: address: Optional[str] """ - Note that only the Private Network source allows you to pick a specific IP. If the requested IP is already booked, then the call will fail. + The requested address should not include the subnet mask (/suffix). Note that only the Private Network source allows you to pick a specific IP. If the requested IP is already reserved, then the call will fail. """ tags: Optional[List[str]] @@ -189,6 +228,29 @@ class BookIPRequest: Tags for the IP. """ + resource: Optional[CustomResource] + """ + Custom resource to attach to the IP being reserved. An example of a custom resource is a virtual machine hosted on an Elastic Metal server. Do not use this for attaching IP addresses to standard Scaleway resources, as it will fail - instead, see the relevant product API for an equivalent method. + """ + + +@dataclass +class DetachIPRequest: + ip_id: str + """ + IP ID. + """ + + resource: CustomResource + """ + Custom resource currently attached to the IP. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + @dataclass class GetIPRequest: @@ -197,7 +259,7 @@ class GetIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -205,7 +267,7 @@ class GetIPRequest: @dataclass class ListIPsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -230,21 +292,41 @@ class ListIPsRequest: Project ID to filter for. Only IPs belonging to this Project will be returned. """ + vpc_id: Optional[str] + """ + Only IPs owned by resources in this VPC will be returned. + """ + attached: Optional[bool] """ Defines whether to filter only for IPs which are attached to a resource. """ + resource_name: Optional[str] + """ + Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. + """ + resource_id: Optional[str] """ Resource ID to filter for. Only IPs attached to this resource will be returned. """ + resource_ids: Optional[List[str]] + """ + Resource IDs to filter for. Only IPs attached to at least one of these resources will be returned. + """ + resource_type: Optional[ResourceType] """ Resource type to filter for. Only IPs attached to this type of resource will be returned. """ + resource_types: Optional[List[ResourceType]] + """ + Resource types to filter for. Only IPs attached to these types of resources will be returned. + """ + mac_address: Optional[str] """ MAC address to filter for. Only IPs attached to a resource with this MAC address will be returned. @@ -265,15 +347,17 @@ class ListIPsRequest: Defines whether to filter only for IPv4s or IPv6s. """ - resource_name: Optional[str] + ip_ids: Optional[List[str]] """ - Attached resource name to filter for, only IPs attached to a resource with this string within their name will be returned. + IP IDs to filter for. Only IPs with these UUIDs will be returned. """ zonal: Optional[str] private_network_id: Optional[str] + subnet_id: Optional[str] + @dataclass class ListIPsResponse: @@ -282,6 +366,29 @@ class ListIPsResponse: ips: List[IP] +@dataclass +class MoveIPRequest: + ip_id: str + """ + IP ID. + """ + + from_resource: CustomResource + """ + Custom resource currently attached to the IP. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + to_resource: Optional[CustomResource] + """ + Custom resource to be attached to the IP. + """ + + @dataclass class ReleaseIPRequest: ip_id: str @@ -289,12 +396,22 @@ class ReleaseIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class ReleaseIPSetRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + ip_ids: Optional[List[str]] + + @dataclass class UpdateIPRequest: ip_id: str @@ -302,7 +419,7 @@ class UpdateIPRequest: IP ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/scaleway/jobs/v1alpha1/__init__.py b/scaleway/scaleway/jobs/v1alpha1/__init__.py index 5fb7578b..31880b35 100644 --- a/scaleway/scaleway/jobs/v1alpha1/__init__.py +++ b/scaleway/scaleway/jobs/v1alpha1/__init__.py @@ -4,23 +4,39 @@ from .content import JOB_RUN_TRANSIENT_STATUSES from .types import ListJobDefinitionsRequestOrderBy from .types import ListJobRunsRequestOrderBy +from .types import SecretEnvVar +from .types import SecretFile from .types import CronSchedule from .types import CreateJobDefinitionRequestCronScheduleConfig +from .types import CreateJobDefinitionSecretsRequestSecretConfig +from .types import Secret from .types import JobDefinition from .types import JobRun +from .types import Resource from .types import UpdateJobDefinitionRequestCronScheduleConfig from .types import CreateJobDefinitionRequest +from .types import CreateJobDefinitionSecretsRequest +from .types import CreateJobDefinitionSecretsResponse from .types import DeleteJobDefinitionRequest +from .types import DeleteJobDefinitionSecretRequest from .types import GetJobDefinitionRequest +from .types import GetJobDefinitionSecretRequest from .types import GetJobRunRequest +from .types import GetJobsLimitsRequest +from .types import JobsLimits +from .types import ListJobDefinitionSecretsRequest +from .types import ListJobDefinitionSecretsResponse from .types import ListJobDefinitionsRequest from .types import ListJobDefinitionsResponse from .types import ListJobRunsRequest from .types import ListJobRunsResponse +from .types import ListJobsResourcesRequest +from .types import ListJobsResourcesResponse from .types import StartJobDefinitionRequest from .types import StartJobDefinitionResponse from .types import StopJobRunRequest from .types import UpdateJobDefinitionRequest +from .types import UpdateJobDefinitionSecretRequest from .api import JobsV1Alpha1API __all__ = [ @@ -28,22 +44,38 @@ "JOB_RUN_TRANSIENT_STATUSES", "ListJobDefinitionsRequestOrderBy", "ListJobRunsRequestOrderBy", + "SecretEnvVar", + "SecretFile", "CronSchedule", "CreateJobDefinitionRequestCronScheduleConfig", + "CreateJobDefinitionSecretsRequestSecretConfig", + "Secret", "JobDefinition", "JobRun", + "Resource", "UpdateJobDefinitionRequestCronScheduleConfig", "CreateJobDefinitionRequest", + "CreateJobDefinitionSecretsRequest", + "CreateJobDefinitionSecretsResponse", "DeleteJobDefinitionRequest", + "DeleteJobDefinitionSecretRequest", "GetJobDefinitionRequest", + "GetJobDefinitionSecretRequest", "GetJobRunRequest", + "GetJobsLimitsRequest", + "JobsLimits", + "ListJobDefinitionSecretsRequest", + "ListJobDefinitionSecretsResponse", "ListJobDefinitionsRequest", "ListJobDefinitionsResponse", "ListJobRunsRequest", "ListJobRunsResponse", + "ListJobsResourcesRequest", + "ListJobsResourcesResponse", "StartJobDefinitionRequest", "StartJobDefinitionResponse", "StopJobRunRequest", "UpdateJobDefinitionRequest", + "UpdateJobDefinitionSecretRequest", "JobsV1Alpha1API", ] diff --git a/scaleway/scaleway/jobs/v1alpha1/api.py b/scaleway/scaleway/jobs/v1alpha1/api.py index 41cf1443..90d31dc8 100644 --- a/scaleway/scaleway/jobs/v1alpha1/api.py +++ b/scaleway/scaleway/jobs/v1alpha1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( random_name, @@ -13,34 +13,50 @@ fetch_all_pages, ) from .types import ( + JobRunState, ListJobDefinitionsRequestOrderBy, ListJobRunsRequestOrderBy, CreateJobDefinitionRequest, CreateJobDefinitionRequestCronScheduleConfig, + CreateJobDefinitionSecretsRequest, + CreateJobDefinitionSecretsRequestSecretConfig, + CreateJobDefinitionSecretsResponse, JobDefinition, JobRun, + JobsLimits, + ListJobDefinitionSecretsResponse, ListJobDefinitionsResponse, ListJobRunsResponse, + ListJobsResourcesResponse, + Secret, StartJobDefinitionRequest, StartJobDefinitionResponse, UpdateJobDefinitionRequest, UpdateJobDefinitionRequestCronScheduleConfig, + UpdateJobDefinitionSecretRequest, ) from .marshalling import ( + unmarshal_Secret, unmarshal_JobDefinition, unmarshal_JobRun, + unmarshal_CreateJobDefinitionSecretsResponse, + unmarshal_JobsLimits, + unmarshal_ListJobDefinitionSecretsResponse, unmarshal_ListJobDefinitionsResponse, unmarshal_ListJobRunsResponse, + unmarshal_ListJobsResourcesResponse, unmarshal_StartJobDefinitionResponse, marshal_CreateJobDefinitionRequest, + marshal_CreateJobDefinitionSecretsRequest, marshal_StartJobDefinitionRequest, marshal_UpdateJobDefinitionRequest, + marshal_UpdateJobDefinitionSecretRequest, ) class JobsV1Alpha1API(API): """ - Serverless Jobs API. + This API allows you to manage your Serverless Jobs. """ def create_job_definition( @@ -51,7 +67,7 @@ def create_job_definition( image_uri: str, command: str, description: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, local_storage_capacity: Optional[int] = None, project_id: Optional[str] = None, @@ -64,7 +80,7 @@ def create_job_definition( :param cpu_limit: CPU limit of the job. :param memory_limit: Memory limit of the job (in MiB). :param image_uri: Image to use for the job. - :param command: Startup command. + :param command: Startup command. If empty or not defined, the image's default command is used. :param description: Description of the job. :param region: Region to target. If none is passed will use default region from the config. :param name: Name of the job definition. @@ -72,7 +88,7 @@ def create_job_definition( :param project_id: UUID of the Scaleway Project containing the job. :param environment_variables: Environment variables of the job. :param job_timeout: Timeout of the job in seconds. - :param cron_schedule: + :param cron_schedule: Configure a cron for the job. :return: :class:`JobDefinition ` Usage: @@ -120,7 +136,7 @@ def get_job_definition( self, *, job_definition_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> JobDefinition: """ Get a job definition by its unique identifier. @@ -154,11 +170,12 @@ def get_job_definition( def list_job_definitions( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListJobDefinitionsRequestOrderBy] = None, project_id: Optional[str] = None, + organization_id: Optional[str] = None, ) -> ListJobDefinitionsResponse: """ List all your job definitions with filters. @@ -167,6 +184,7 @@ def list_job_definitions( :param page_size: :param order_by: :param project_id: + :param organization_id: :return: :class:`ListJobDefinitionsResponse ` Usage: @@ -184,6 +202,8 @@ def list_job_definitions( f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions", params={ "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, @@ -196,11 +216,12 @@ def list_job_definitions( def list_job_definitions_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListJobDefinitionsRequestOrderBy] = None, project_id: Optional[str] = None, + organization_id: Optional[str] = None, ) -> List[JobDefinition]: """ List all your job definitions with filters. @@ -209,6 +230,7 @@ def list_job_definitions_all( :param page_size: :param order_by: :param project_id: + :param organization_id: :return: :class:`List[JobDefinition] ` Usage: @@ -227,6 +249,7 @@ def list_job_definitions_all( "page_size": page_size, "order_by": order_by, "project_id": project_id, + "organization_id": organization_id, }, ) @@ -234,7 +257,7 @@ def update_job_definition( self, *, job_definition_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, cpu_limit: Optional[int] = None, memory_limit: Optional[int] = None, @@ -306,7 +329,7 @@ def delete_job_definition( self, *, job_definition_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete an exsisting job definition by its unique identifier. @@ -339,7 +362,7 @@ def start_job_definition( self, *, job_definition_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, command: Optional[str] = None, environment_variables: Optional[Dict[str, str]] = None, replicas: Optional[int] = None, @@ -386,11 +409,226 @@ def start_job_definition( self._throw_on_error(res) return unmarshal_StartJobDefinitionResponse(res.json()) + def create_job_definition_secrets( + self, + *, + job_definition_id: str, + secrets: List[CreateJobDefinitionSecretsRequestSecretConfig], + region: Optional[ScwRegion] = None, + ) -> CreateJobDefinitionSecretsResponse: + """ + Create a secret reference within a job definition. + :param job_definition_id: UUID of the job definition. + :param secrets: List of secrets to inject into the job. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`CreateJobDefinitionSecretsResponse ` + + Usage: + :: + + result = api.create_job_definition_secrets( + job_definition_id="example", + secrets=[], + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_job_definition_id = validate_path_param( + "job_definition_id", job_definition_id + ) + + res = self._request( + "POST", + f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions/{param_job_definition_id}/secrets", + body=marshal_CreateJobDefinitionSecretsRequest( + CreateJobDefinitionSecretsRequest( + job_definition_id=job_definition_id, + secrets=secrets, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CreateJobDefinitionSecretsResponse(res.json()) + + def get_job_definition_secret( + self, + *, + job_definition_id: str, + secret_id: str, + region: Optional[ScwRegion] = None, + ) -> Secret: + """ + Get a secret references within a job definition. + :param job_definition_id: UUID of the job definition. + :param secret_id: UUID of the secret reference within the job. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Secret ` + + Usage: + :: + + result = api.get_job_definition_secret( + job_definition_id="example", + secret_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_job_definition_id = validate_path_param( + "job_definition_id", job_definition_id + ) + param_secret_id = validate_path_param("secret_id", secret_id) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions/{param_job_definition_id}/secrets/{param_secret_id}", + ) + + self._throw_on_error(res) + return unmarshal_Secret(res.json()) + + def list_job_definition_secrets( + self, + *, + job_definition_id: str, + region: Optional[ScwRegion] = None, + ) -> ListJobDefinitionSecretsResponse: + """ + List secrets references within a job definition. + :param job_definition_id: UUID of the job definition. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ListJobDefinitionSecretsResponse ` + + Usage: + :: + + result = api.list_job_definition_secrets( + job_definition_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_job_definition_id = validate_path_param( + "job_definition_id", job_definition_id + ) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions/{param_job_definition_id}/secrets", + ) + + self._throw_on_error(res) + return unmarshal_ListJobDefinitionSecretsResponse(res.json()) + + def update_job_definition_secret( + self, + *, + job_definition_id: str, + secret_id: str, + region: Optional[ScwRegion] = None, + secret_manager_version: Optional[str] = None, + path: Optional[str] = None, + env_var_name: Optional[str] = None, + ) -> Secret: + """ + Update a secret reference within a job definition. + :param job_definition_id: UUID of the job definition. + :param secret_id: UUID of the secret reference within the job. + :param region: Region to target. If none is passed will use default region from the config. + :param secret_manager_version: Version of the secret in Secret Manager. + :param path: Path of the secret to mount inside the job (either `path` or `env_var_name` must be set). + One-Of ('secret_config'): at most one of 'path', 'env_var_name' could be set. + :param env_var_name: Environment variable name used to expose the secret inside the job (either `path` or `env_var_name` must be set). + One-Of ('secret_config'): at most one of 'path', 'env_var_name' could be set. + :return: :class:`Secret ` + + Usage: + :: + + result = api.update_job_definition_secret( + job_definition_id="example", + secret_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_job_definition_id = validate_path_param( + "job_definition_id", job_definition_id + ) + param_secret_id = validate_path_param("secret_id", secret_id) + + res = self._request( + "PATCH", + f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions/{param_job_definition_id}/secrets/{param_secret_id}", + body=marshal_UpdateJobDefinitionSecretRequest( + UpdateJobDefinitionSecretRequest( + job_definition_id=job_definition_id, + secret_id=secret_id, + region=region, + secret_manager_version=secret_manager_version, + path=path, + env_var_name=env_var_name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Secret(res.json()) + + def delete_job_definition_secret( + self, + *, + job_definition_id: str, + secret_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a secret reference within a job definition. + :param job_definition_id: UUID of the job definition. + :param secret_id: UUID of the secret reference within the job. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_job_definition_secret( + job_definition_id="example", + secret_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_job_definition_id = validate_path_param( + "job_definition_id", job_definition_id + ) + param_secret_id = validate_path_param("secret_id", secret_id) + + res = self._request( + "DELETE", + f"/serverless-jobs/v1alpha1/regions/{param_region}/job-definitions/{param_job_definition_id}/secrets/{param_secret_id}", + ) + + self._throw_on_error(res) + def get_job_run( self, *, job_run_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> JobRun: """ Get a job run by its unique identifier. @@ -423,7 +661,7 @@ def stop_job_run( self, *, job_run_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> JobRun: """ Stop a job run by its unique identifier. @@ -456,12 +694,14 @@ def stop_job_run( def list_job_runs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListJobRunsRequestOrderBy] = None, job_definition_id: Optional[str] = None, project_id: Optional[str] = None, + organization_id: Optional[str] = None, + state: Optional[JobRunState] = None, ) -> ListJobRunsResponse: """ List all job runs with filters. @@ -471,6 +711,8 @@ def list_job_runs( :param order_by: :param job_definition_id: :param project_id: + :param organization_id: + :param state: :return: :class:`ListJobRunsResponse ` Usage: @@ -489,9 +731,12 @@ def list_job_runs( params={ "job_definition_id": job_definition_id, "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, + "state": state, }, ) @@ -501,12 +746,14 @@ def list_job_runs( def list_job_runs_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListJobRunsRequestOrderBy] = None, job_definition_id: Optional[str] = None, project_id: Optional[str] = None, + organization_id: Optional[str] = None, + state: Optional[JobRunState] = None, ) -> List[JobRun]: """ List all job runs with filters. @@ -516,6 +763,8 @@ def list_job_runs_all( :param order_by: :param job_definition_id: :param project_id: + :param organization_id: + :param state: :return: :class:`List[JobRun] ` Usage: @@ -535,5 +784,63 @@ def list_job_runs_all( "order_by": order_by, "job_definition_id": job_definition_id, "project_id": project_id, + "organization_id": organization_id, + "state": state, }, ) + + def list_jobs_resources( + self, + *, + region: Optional[ScwRegion] = None, + ) -> ListJobsResourcesResponse: + """ + List jobs resources for the console. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ListJobsResourcesResponse ` + + Usage: + :: + + result = api.list_jobs_resources() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha1/regions/{param_region}/jobs-resources", + ) + + self._throw_on_error(res) + return unmarshal_ListJobsResourcesResponse(res.json()) + + def get_jobs_limits( + self, + *, + region: Optional[ScwRegion] = None, + ) -> JobsLimits: + """ + Get jobs limits for the console. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`JobsLimits ` + + Usage: + :: + + result = api.get_jobs_limits() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/serverless-jobs/v1alpha1/regions/{param_region}/jobs-limits", + ) + + self._throw_on_error(res) + return unmarshal_JobsLimits(res.json()) diff --git a/scaleway/scaleway/jobs/v1alpha1/marshalling.py b/scaleway/scaleway/jobs/v1alpha1/marshalling.py index ecb70454..17cb1e1d 100644 --- a/scaleway/scaleway/jobs/v1alpha1/marshalling.py +++ b/scaleway/scaleway/jobs/v1alpha1/marshalling.py @@ -5,21 +5,101 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) from .types import ( + SecretEnvVar, + SecretFile, + Secret, CronSchedule, JobDefinition, JobRun, + CreateJobDefinitionSecretsResponse, + JobsLimits, + ListJobDefinitionSecretsResponse, ListJobDefinitionsResponse, ListJobRunsResponse, + Resource, + ListJobsResourcesResponse, StartJobDefinitionResponse, CreateJobDefinitionRequestCronScheduleConfig, CreateJobDefinitionRequest, + CreateJobDefinitionSecretsRequestSecretConfig, + CreateJobDefinitionSecretsRequest, StartJobDefinitionRequest, UpdateJobDefinitionRequestCronScheduleConfig, UpdateJobDefinitionRequest, + UpdateJobDefinitionSecretRequest, ) +def unmarshal_SecretEnvVar(data: Any) -> SecretEnvVar: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SecretEnvVar' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + return SecretEnvVar(**args) + + +def unmarshal_SecretFile(data: Any) -> SecretFile: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SecretFile' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("path", None) + if field is not None: + args["path"] = field + + return SecretFile(**args) + + +def unmarshal_Secret(data: Any) -> Secret: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Secret' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secret_id", None) + if field is not None: + args["secret_id"] = field + + field = data.get("secret_manager_id", None) + if field is not None: + args["secret_manager_id"] = field + + field = data.get("secret_manager_version", None) + if field is not None: + args["secret_manager_version"] = field + + field = data.get("file", None) + if field is not None: + args["file"] = unmarshal_SecretFile(field) + else: + args["file"] = None + + field = data.get("env_var", None) + if field is not None: + args["env_var"] = unmarshal_SecretEnvVar(field) + else: + args["env_var"] = None + + return Secret(**args) + + def unmarshal_CronSchedule(data: Any) -> CronSchedule: if not isinstance(data, dict): raise TypeError( @@ -78,10 +158,14 @@ def unmarshal_JobDefinition(data: Any) -> JobDefinition: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("environment_variables", None) if field is not None: @@ -102,10 +186,14 @@ def unmarshal_JobDefinition(data: Any) -> JobDefinition: field = data.get("job_timeout", None) if field is not None: args["job_timeout"] = field + else: + args["job_timeout"] = None field = data.get("cron_schedule", None) if field is not None: args["cron_schedule"] = unmarshal_CronSchedule(field) + else: + args["cron_schedule"] = None return JobDefinition(**args) @@ -149,24 +237,34 @@ def unmarshal_JobRun(data: Any) -> JobRun: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("terminated_at", None) if field is not None: args["terminated_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["terminated_at"] = None field = data.get("exit_code", None) if field is not None: args["exit_code"] = field + else: + args["exit_code"] = None field = data.get("run_duration", None) if field is not None: args["run_duration"] = field + else: + args["run_duration"] = None field = data.get("environment_variables", None) if field is not None: @@ -183,10 +281,69 @@ def unmarshal_JobRun(data: Any) -> JobRun: field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None return JobRun(**args) +def unmarshal_CreateJobDefinitionSecretsResponse( + data: Any, +) -> CreateJobDefinitionSecretsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CreateJobDefinitionSecretsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secrets", None) + if field is not None: + args["secrets"] = ( + [unmarshal_Secret(v) for v in field] if field is not None else None + ) + + return CreateJobDefinitionSecretsResponse(**args) + + +def unmarshal_JobsLimits(data: Any) -> JobsLimits: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'JobsLimits' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secrets_per_job_definition", None) + if field is not None: + args["secrets_per_job_definition"] = field + + return JobsLimits(**args) + + +def unmarshal_ListJobDefinitionSecretsResponse( + data: Any, +) -> ListJobDefinitionSecretsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListJobDefinitionSecretsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("secrets", None) + if field is not None: + args["secrets"] = ( + [unmarshal_Secret(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListJobDefinitionSecretsResponse(**args) + + def unmarshal_ListJobDefinitionsResponse(data: Any) -> ListJobDefinitionsResponse: if not isinstance(data, dict): raise TypeError( @@ -229,6 +386,42 @@ def unmarshal_ListJobRunsResponse(data: Any) -> ListJobRunsResponse: return ListJobRunsResponse(**args) +def unmarshal_Resource(data: Any) -> Resource: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Resource' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("cpu_limit", None) + if field is not None: + args["cpu_limit"] = field + + field = data.get("memory_limit", None) + if field is not None: + args["memory_limit"] = field + + return Resource(**args) + + +def unmarshal_ListJobsResourcesResponse(data: Any) -> ListJobsResourcesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListJobsResourcesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("resources", None) + if field is not None: + args["resources"] = ( + [unmarshal_Resource(v) for v in field] if field is not None else None + ) + + return ListJobsResourcesResponse(**args) + + def unmarshal_StartJobDefinitionResponse(data: Any) -> StartJobDefinitionResponse: if not isinstance(data, dict): raise TypeError( @@ -300,15 +493,51 @@ def marshal_CreateJobDefinitionRequest( output["job_timeout"] = request.job_timeout if request.cron_schedule is not None: - output["cron_schedule"] = ( - marshal_CreateJobDefinitionRequestCronScheduleConfig( - request.cron_schedule, defaults - ), + output["cron_schedule"] = marshal_CreateJobDefinitionRequestCronScheduleConfig( + request.cron_schedule, defaults ) return output +def marshal_CreateJobDefinitionSecretsRequestSecretConfig( + request: CreateJobDefinitionSecretsRequestSecretConfig, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("path", request.path), + OneOfPossibility("env_var_name", request.env_var_name), + ] + ), + ) + + if request.secret_manager_id is not None: + output["secret_manager_id"] = request.secret_manager_id + + if request.secret_manager_version is not None: + output["secret_manager_version"] = request.secret_manager_version + + return output + + +def marshal_CreateJobDefinitionSecretsRequest( + request: CreateJobDefinitionSecretsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.secrets is not None: + output["secrets"] = [ + marshal_CreateJobDefinitionSecretsRequestSecretConfig(item, defaults) + for item in request.secrets + ] + + return output + + def marshal_StartJobDefinitionRequest( request: StartJobDefinitionRequest, defaults: ProfileDefaults, @@ -376,10 +605,28 @@ def marshal_UpdateJobDefinitionRequest( output["job_timeout"] = request.job_timeout if request.cron_schedule is not None: - output["cron_schedule"] = ( - marshal_UpdateJobDefinitionRequestCronScheduleConfig( - request.cron_schedule, defaults - ), + output["cron_schedule"] = marshal_UpdateJobDefinitionRequestCronScheduleConfig( + request.cron_schedule, defaults ) return output + + +def marshal_UpdateJobDefinitionSecretRequest( + request: UpdateJobDefinitionSecretRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("path", request.path), + OneOfPossibility("env_var_name", request.env_var_name), + ] + ), + ) + + if request.secret_manager_version is not None: + output["secret_manager_version"] = request.secret_manager_version + + return output diff --git a/scaleway/scaleway/jobs/v1alpha1/types.py b/scaleway/scaleway/jobs/v1alpha1/types.py index 63579d2d..edaaaf92 100644 --- a/scaleway/scaleway/jobs/v1alpha1/types.py +++ b/scaleway/scaleway/jobs/v1alpha1/types.py @@ -8,7 +8,7 @@ from typing import Dict, List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -45,11 +45,27 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class SecretEnvVar: + name: str + + +@dataclass +class SecretFile: + path: str + + @dataclass class CronSchedule: schedule: str + """ + UNIX cron schedule to run job (e.g., '* * * * *'). + """ timezone: str + """ + Timezone for the cron schedule, in tz database format (e.g., 'Europe/Paris'). + """ @dataclass @@ -59,6 +75,39 @@ class CreateJobDefinitionRequestCronScheduleConfig: timezone: str +@dataclass +class CreateJobDefinitionSecretsRequestSecretConfig: + secret_manager_id: str + + secret_manager_version: str + + path: Optional[str] + + env_var_name: Optional[str] + + +@dataclass +class Secret: + secret_id: str + """ + UUID of the secret reference within the job. + """ + + secret_manager_id: str + """ + UUID of the secret in Secret Manager. + """ + + secret_manager_version: str + """ + Version of the secret in Secret Manager. + """ + + file: Optional[SecretFile] + + env_var: Optional[SecretEnvVar] + + @dataclass class JobDefinition: id: str @@ -85,7 +134,7 @@ class JobDefinition: local_storage_capacity: int - region: Region + region: ScwRegion """ Region to target. If none is passed will use default region from the config. """ @@ -125,7 +174,7 @@ class JobRun: local_storage_capacity: int - region: Region + region: ScwRegion """ Region to target. If none is passed will use default region from the config. """ @@ -133,6 +182,13 @@ class JobRun: started_at: Optional[datetime] +@dataclass +class Resource: + cpu_limit: int + + memory_limit: int + + @dataclass class UpdateJobDefinitionRequestCronScheduleConfig: schedule: Optional[str] @@ -159,7 +215,7 @@ class CreateJobDefinitionRequest: command: str """ - Startup command. + Startup command. If empty or not defined, the image's default command is used. """ description: str @@ -167,7 +223,7 @@ class CreateJobDefinitionRequest: Description of the job. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -198,6 +254,35 @@ class CreateJobDefinitionRequest: """ cron_schedule: Optional[CreateJobDefinitionRequestCronScheduleConfig] + """ + Configure a cron for the job. + """ + + +@dataclass +class CreateJobDefinitionSecretsRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + secrets: List[CreateJobDefinitionSecretsRequestSecretConfig] + """ + List of secrets to inject into the job. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateJobDefinitionSecretsResponse: + secrets: List[Secret] + """ + List of secrets created. + """ @dataclass @@ -207,7 +292,25 @@ class DeleteJobDefinitionRequest: UUID of the job definition to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteJobDefinitionSecretRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + secret_id: str + """ + UUID of the secret reference within the job. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -220,7 +323,25 @@ class GetJobDefinitionRequest: UUID of the job definition to get. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetJobDefinitionSecretRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + secret_id: str + """ + UUID of the secret reference within the job. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -233,15 +354,54 @@ class GetJobRunRequest: UUID of the job run to get. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetJobsLimitsRequest: + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class JobsLimits: + secrets_per_job_definition: int + + +@dataclass +class ListJobDefinitionSecretsRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListJobDefinitionSecretsResponse: + secrets: List[Secret] + """ + List of secret references within a job definition. + """ + + total_count: int + """ + Total count of secret references within a job definition. + """ + + @dataclass class ListJobDefinitionsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -254,6 +414,8 @@ class ListJobDefinitionsRequest: project_id: Optional[str] + organization_id: Optional[str] + @dataclass class ListJobDefinitionsResponse: @@ -264,7 +426,7 @@ class ListJobDefinitionsResponse: @dataclass class ListJobRunsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -279,6 +441,10 @@ class ListJobRunsRequest: project_id: Optional[str] + organization_id: Optional[str] + + state: Optional[JobRunState] + @dataclass class ListJobRunsResponse: @@ -287,6 +453,19 @@ class ListJobRunsResponse: total_count: int +@dataclass +class ListJobsResourcesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListJobsResourcesResponse: + resources: List[Resource] + + @dataclass class StartJobDefinitionRequest: job_definition_id: str @@ -294,7 +473,7 @@ class StartJobDefinitionRequest: UUID of the job definition to start. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -327,7 +506,7 @@ class StopJobRunRequest: UUID of the job run to stop. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -340,7 +519,7 @@ class UpdateJobDefinitionRequest: UUID of the job definition to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -391,3 +570,30 @@ class UpdateJobDefinitionRequest: """ cron_schedule: Optional[UpdateJobDefinitionRequestCronScheduleConfig] + + +@dataclass +class UpdateJobDefinitionSecretRequest: + job_definition_id: str + """ + UUID of the job definition. + """ + + secret_id: str + """ + UUID of the secret reference within the job. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + secret_manager_version: Optional[str] + """ + Version of the secret in Secret Manager. + """ + + path: Optional[str] + + env_var_name: Optional[str] diff --git a/scaleway/scaleway/k8s/v1/__init__.py b/scaleway/scaleway/k8s/v1/__init__.py index 2eafd7b7..fcfdc43b 100644 --- a/scaleway/scaleway/k8s/v1/__init__.py +++ b/scaleway/scaleway/k8s/v1/__init__.py @@ -24,6 +24,8 @@ from .types import ClusterAutoscalerConfig from .types import ClusterOpenIDConnectConfig from .types import Pool +from .types import ACLRuleRequest +from .types import ACLRule from .types import CreateClusterRequestAutoUpgrade from .types import CreateClusterRequestAutoscalerConfig from .types import CreateClusterRequestOpenIDConnectConfig @@ -34,22 +36,31 @@ from .types import Version from .types import Cluster from .types import Node +from .types import NodeMetadataCoreV1Taint from .types import UpdateClusterRequestAutoUpgrade from .types import UpdateClusterRequestAutoscalerConfig from .types import UpdateClusterRequestOpenIDConnectConfig from .types import UpdatePoolRequestUpgradePolicy +from .types import AddClusterACLRulesRequest +from .types import AddClusterACLRulesResponse +from .types import AuthExternalNodeRequest from .types import CreateClusterRequest from .types import CreateExternalNodeRequest from .types import CreatePoolRequest +from .types import DeleteACLRuleRequest from .types import DeleteClusterRequest from .types import DeleteNodeRequest from .types import DeletePoolRequest from .types import ExternalNode +from .types import ExternalNodeAuth from .types import GetClusterKubeConfigRequest from .types import GetClusterRequest +from .types import GetNodeMetadataRequest from .types import GetNodeRequest from .types import GetPoolRequest from .types import GetVersionRequest +from .types import ListClusterACLRulesRequest +from .types import ListClusterACLRulesResponse from .types import ListClusterAvailableTypesRequest from .types import ListClusterAvailableTypesResponse from .types import ListClusterAvailableVersionsRequest @@ -64,10 +75,13 @@ from .types import ListPoolsResponse from .types import ListVersionsRequest from .types import ListVersionsResponse -from .types import MigrateToPrivateNetworkClusterRequest +from .types import MigratePoolsToNewImagesRequest +from .types import NodeMetadata from .types import RebootNodeRequest from .types import ReplaceNodeRequest from .types import ResetClusterAdminTokenRequest +from .types import SetClusterACLRulesRequest +from .types import SetClusterACLRulesResponse from .types import SetClusterTypeRequest from .types import UpdateClusterRequest from .types import UpdatePoolRequest @@ -100,6 +114,8 @@ "ClusterAutoscalerConfig", "ClusterOpenIDConnectConfig", "Pool", + "ACLRuleRequest", + "ACLRule", "CreateClusterRequestAutoUpgrade", "CreateClusterRequestAutoscalerConfig", "CreateClusterRequestOpenIDConnectConfig", @@ -110,22 +126,31 @@ "Version", "Cluster", "Node", + "NodeMetadataCoreV1Taint", "UpdateClusterRequestAutoUpgrade", "UpdateClusterRequestAutoscalerConfig", "UpdateClusterRequestOpenIDConnectConfig", "UpdatePoolRequestUpgradePolicy", + "AddClusterACLRulesRequest", + "AddClusterACLRulesResponse", + "AuthExternalNodeRequest", "CreateClusterRequest", "CreateExternalNodeRequest", "CreatePoolRequest", + "DeleteACLRuleRequest", "DeleteClusterRequest", "DeleteNodeRequest", "DeletePoolRequest", "ExternalNode", + "ExternalNodeAuth", "GetClusterKubeConfigRequest", "GetClusterRequest", + "GetNodeMetadataRequest", "GetNodeRequest", "GetPoolRequest", "GetVersionRequest", + "ListClusterACLRulesRequest", + "ListClusterACLRulesResponse", "ListClusterAvailableTypesRequest", "ListClusterAvailableTypesResponse", "ListClusterAvailableVersionsRequest", @@ -140,10 +165,13 @@ "ListPoolsResponse", "ListVersionsRequest", "ListVersionsResponse", - "MigrateToPrivateNetworkClusterRequest", + "MigratePoolsToNewImagesRequest", + "NodeMetadata", "RebootNodeRequest", "ReplaceNodeRequest", "ResetClusterAdminTokenRequest", + "SetClusterACLRulesRequest", + "SetClusterACLRulesResponse", "SetClusterTypeRequest", "UpdateClusterRequest", "UpdatePoolRequest", diff --git a/scaleway/scaleway/k8s/v1/api.py b/scaleway/scaleway/k8s/v1/api.py index a478317e..62824fcf 100644 --- a/scaleway/scaleway/k8s/v1/api.py +++ b/scaleway/scaleway/k8s/v1/api.py @@ -5,9 +5,9 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ScwFile, - Zone, + Zone as ScwZone, unmarshal_ScwFile, ) from scaleway_core.utils import ( @@ -27,6 +27,10 @@ PoolStatus, PoolVolumeType, Runtime, + ACLRule, + ACLRuleRequest, + AddClusterACLRulesRequest, + AddClusterACLRulesResponse, Cluster, ClusterType, CreateClusterRequest, @@ -37,6 +41,8 @@ CreatePoolRequest, CreatePoolRequestUpgradePolicy, ExternalNode, + ExternalNodeAuth, + ListClusterACLRulesResponse, ListClusterAvailableTypesResponse, ListClusterAvailableVersionsResponse, ListClusterTypesResponse, @@ -44,9 +50,12 @@ ListNodesResponse, ListPoolsResponse, ListVersionsResponse, - MigrateToPrivateNetworkClusterRequest, + MigratePoolsToNewImagesRequest, Node, + NodeMetadata, Pool, + SetClusterACLRulesRequest, + SetClusterACLRulesResponse, SetClusterTypeRequest, UpdateClusterRequest, UpdateClusterRequestAutoUpgrade, @@ -68,7 +77,10 @@ unmarshal_Version, unmarshal_Cluster, unmarshal_Node, + unmarshal_AddClusterACLRulesResponse, unmarshal_ExternalNode, + unmarshal_ExternalNodeAuth, + unmarshal_ListClusterACLRulesResponse, unmarshal_ListClusterAvailableTypesResponse, unmarshal_ListClusterAvailableVersionsResponse, unmarshal_ListClusterTypesResponse, @@ -76,9 +88,13 @@ unmarshal_ListNodesResponse, unmarshal_ListPoolsResponse, unmarshal_ListVersionsResponse, + unmarshal_NodeMetadata, + unmarshal_SetClusterACLRulesResponse, + marshal_AddClusterACLRulesRequest, marshal_CreateClusterRequest, marshal_CreatePoolRequest, - marshal_MigrateToPrivateNetworkClusterRequest, + marshal_MigratePoolsToNewImagesRequest, + marshal_SetClusterACLRulesRequest, marshal_SetClusterTypeRequest, marshal_UpdateClusterRequest, marshal_UpdatePoolRequest, @@ -89,13 +105,13 @@ class K8SV1API(API): """ - Kubernetes API. + This API allows you to manage Kubernetes Kapsule and Kosmos clusters. """ def list_clusters( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, order_by: Optional[ListClustersRequestOrderBy] = None, @@ -154,7 +170,7 @@ def list_clusters( def list_clusters_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, order_by: Optional[ListClustersRequestOrderBy] = None, @@ -210,7 +226,7 @@ def create_cluster( type_: str, description: str, version: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, name: Optional[str] = None, @@ -230,7 +246,7 @@ def create_cluster( """ Create a new Cluster. Create a new Kubernetes cluster in a Scaleway region. - :param type_: Type of the cluster (possible values are kapsule, multicloud, kapsule-dedicated-8, kapsule-dedicated-16). + :param type_: Type of the cluster. See [list available cluster types](#list-available-cluster-types-for-a-cluster) for a list of valid types. :param description: Cluster description. :param version: Kubernetes version of the cluster. :param region: Region to target. If none is passed will use default region from the config. @@ -300,7 +316,7 @@ def get_cluster( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cluster: """ Get a Cluster. @@ -334,7 +350,7 @@ def wait_for_cluster( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Cluster, bool]] = None, ) -> Cluster: """ @@ -371,7 +387,7 @@ def update_cluster( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, @@ -393,7 +409,7 @@ def update_cluster( :param description: New description for the cluster. :param tags: New tags associated with the cluster. :param autoscaler_config: New autoscaler config for the cluster. - :param auto_upgrade: New auto upgrade configuration for the cluster. Note that all fields need to be set. + :param auto_upgrade: New auto upgrade configuration for the cluster. Note that all fields needs to be set. :param feature_gates: List of feature gates to enable. :param admission_plugins: List of admission plugins to enable. :param open_id_connect_config: OpenID Connect configuration of the cluster. This configuration enables to update the OpenID Connect configuration of the Kubernetes API server. @@ -442,11 +458,11 @@ def delete_cluster( *, cluster_id: str, with_additional_resources: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cluster: """ Delete a Cluster. - Delete a specific Kubernetes cluster and all its associated pools and nodes. Note that this method will not delete any Load Balancer or Block Volume that are associated with the cluster. + Delete a specific Kubernetes cluster and all its associated pools and nodes, and possibly its associated Load Balancers or Block Volumes. :param cluster_id: ID of the cluster to delete. :param with_additional_resources: Defines whether all volumes (including retain volume type), empty Private Networks and Load Balancers with a name starting with the cluster ID will also be deleted. :param region: Region to target. If none is passed will use default region from the config. @@ -483,7 +499,7 @@ def upgrade_cluster( cluster_id: str, version: str, upgrade_pools: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cluster: """ Upgrade a Cluster. @@ -531,11 +547,11 @@ def set_cluster_type( *, cluster_id: str, type_: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Cluster: """ Change the Cluster type. - Change the type of a specific Kubernetes cluster. To see the possible values you can enter for the `type` field, [list available cluster types](#path-clusters-list-available-cluster-types-for-a-cluster). + Change the type of a specific Kubernetes cluster. To see the possible values you can enter for the `type` field, [list available cluster types](#list-available-cluster-types-for-a-cluster). :param cluster_id: ID of the cluster to migrate from one type to another. :param type_: Type of the cluster. Note that some migrations are not possible (please refer to product documentation). :param region: Region to target. If none is passed will use default region from the config. @@ -575,7 +591,7 @@ def list_cluster_available_versions( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListClusterAvailableVersionsResponse: """ List available versions for a Cluster. @@ -609,7 +625,7 @@ def list_cluster_available_types( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListClusterAvailableTypesResponse: """ List available cluster types for a cluster. @@ -643,7 +659,7 @@ def _get_cluster_kube_config( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, redacted: Optional[bool] = None, ) -> ScwFile: """ @@ -683,11 +699,11 @@ def reset_cluster_admin_token( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Reset the admin token of a Cluster. - Reset the admin token for a specific Kubernetes cluster. This will revoke the old admin token (which will not be usable afterwards) and create a new one. Note that you will need to download kubeconfig again to keep interacting with the cluster. + Reset the admin token for a specific Kubernetes cluster. This will revoke the old admin token (which will not be usable afterwards) and create a new one. Note that you will need to download the kubeconfig again to keep interacting with the cluster. :param cluster_id: Cluster ID on which the admin token will be renewed. :param region: Region to target. If none is passed will use default region from the config. @@ -712,27 +728,105 @@ def reset_cluster_admin_token( self._throw_on_error(res) - def migrate_to_private_network_cluster( + def list_cluster_acl_rules( self, *, cluster_id: str, - private_network_id: str, - region: Optional[Region] = None, - ) -> Cluster: + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListClusterACLRulesResponse: """ - Migrate an existing cluster to a Private Network cluster. - Migrate a cluster that was created before the release of Private Network clusters to a new one with a Private Network. - :param cluster_id: ID of the cluster to migrate. - :param private_network_id: ID of the Private Network to link to the cluster. + List ACLs. + List ACLs for a specific cluster. + :param cluster_id: ID of the cluster whose ACLs will be listed. :param region: Region to target. If none is passed will use default region from the config. - :return: :class:`Cluster ` + :param page: Page number for the returned ACLs. + :param page_size: Maximum number of ACLs per page. + :return: :class:`ListClusterACLRulesResponse ` + + Usage: + :: + + result = api.list_cluster_acl_rules( + cluster_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_cluster_id = validate_path_param("cluster_id", cluster_id) + + res = self._request( + "GET", + f"/k8s/v1/regions/{param_region}/clusters/{param_cluster_id}/acls", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListClusterACLRulesResponse(res.json()) + + def list_cluster_acl_rules_all( + self, + *, + cluster_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[ACLRule]: + """ + List ACLs. + List ACLs for a specific cluster. + :param cluster_id: ID of the cluster whose ACLs will be listed. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number for the returned ACLs. + :param page_size: Maximum number of ACLs per page. + :return: :class:`List[ACLRule] ` + + Usage: + :: + + result = api.list_cluster_acl_rules_all( + cluster_id="example", + ) + """ + + return fetch_all_pages( + type=ListClusterACLRulesResponse, + key="rules", + fetcher=self.list_cluster_acl_rules, + args={ + "cluster_id": cluster_id, + "region": region, + "page": page, + "page_size": page_size, + }, + ) + + def add_cluster_acl_rules( + self, + *, + cluster_id: str, + region: Optional[ScwRegion] = None, + acls: Optional[List[ACLRuleRequest]] = None, + ) -> AddClusterACLRulesResponse: + """ + Add new ACLs. + Add new ACL rules for a specific cluster. + :param cluster_id: ID of the cluster whose ACLs will be added. + :param region: Region to target. If none is passed will use default region from the config. + :param acls: ACLs to add. + :return: :class:`AddClusterACLRulesResponse ` Usage: :: - result = api.migrate_to_private_network_cluster( + result = api.add_cluster_acl_rules( cluster_id="example", - private_network_id="example", ) """ @@ -743,25 +837,100 @@ def migrate_to_private_network_cluster( res = self._request( "POST", - f"/k8s/v1/regions/{param_region}/clusters/{param_cluster_id}/migrate-to-private-network", - body=marshal_MigrateToPrivateNetworkClusterRequest( - MigrateToPrivateNetworkClusterRequest( + f"/k8s/v1/regions/{param_region}/clusters/{param_cluster_id}/acls", + body=marshal_AddClusterACLRulesRequest( + AddClusterACLRulesRequest( cluster_id=cluster_id, - private_network_id=private_network_id, region=region, + acls=acls, ), self.client, ), ) self._throw_on_error(res) - return unmarshal_Cluster(res.json()) + return unmarshal_AddClusterACLRulesResponse(res.json()) + + def set_cluster_acl_rules( + self, + *, + cluster_id: str, + region: Optional[ScwRegion] = None, + acls: Optional[List[ACLRuleRequest]] = None, + ) -> SetClusterACLRulesResponse: + """ + Set new ACLs. + Set new ACL rules for a specific cluster. + :param cluster_id: ID of the cluster whose ACLs will be set. + :param region: Region to target. If none is passed will use default region from the config. + :param acls: ACLs to set. + :return: :class:`SetClusterACLRulesResponse ` + + Usage: + :: + + result = api.set_cluster_acl_rules( + cluster_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_cluster_id = validate_path_param("cluster_id", cluster_id) + + res = self._request( + "PUT", + f"/k8s/v1/regions/{param_region}/clusters/{param_cluster_id}/acls", + body=marshal_SetClusterACLRulesRequest( + SetClusterACLRulesRequest( + cluster_id=cluster_id, + region=region, + acls=acls, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetClusterACLRulesResponse(res.json()) + + def delete_acl_rule( + self, + *, + acl_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete an existing ACL. + :param acl_id: ID of the ACL rule to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_acl_rule( + acl_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_acl_id = validate_path_param("acl_id", acl_id) + + res = self._request( + "DELETE", + f"/k8s/v1/regions/{param_region}/acls/{param_acl_id}", + ) + + self._throw_on_error(res) def list_pools( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPoolsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -812,7 +981,7 @@ def list_pools_all( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPoolsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -857,7 +1026,7 @@ def list_pools_all( def create_pool( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, cluster_id: str, node_type: str, autoscaling: bool, @@ -872,7 +1041,7 @@ def create_pool( tags: Optional[List[str]] = None, kubelet_args: Optional[Dict[str, str]] = None, upgrade_policy: Optional[CreatePoolRequestUpgradePolicy] = None, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, root_volume_type: Optional[PoolVolumeType] = None, root_volume_size: Optional[int] = None, ) -> Pool: @@ -885,17 +1054,20 @@ def create_pool( :param autoscaling: Defines whether the autoscaling feature is enabled for the pool. :param size: Size (number of nodes) of the pool. :param name: Pool name. - :param placement_group_id: Placement group ID in which all the nodes of the pool will be created. + :param placement_group_id: Placement group ID in which all the nodes of the pool will be created, placement groups are limited to 20 instances. :param min_size: Defines the minimum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. :param autohealing: Defines whether the autohealing feature is enabled for the pool. :param public_ip_disabled: Defines if the public IP should be removed from Nodes. To use this feature, your Cluster must have an attached Private Network set up with a Public Gateway. :param max_size: Defines the maximum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. - :param container_runtime: Customization of the container runtime is available for each pool. Note that `docker` has been deprecated since version 1.20 and will be removed by version 1.24. - :param tags: Tags associated with the pool. + :param container_runtime: Customization of the container runtime is available for each pool. + :param tags: Tags associated with the pool, see [managing tags](https://www.scaleway.com/en/docs/containers/kubernetes/api-cli/managing-tags). :param kubelet_args: Kubelet arguments to be used by this pool. Note that this feature is experimental. :param upgrade_policy: Pool upgrade policy. :param zone: Zone in which the pool's nodes will be spawned. - :param root_volume_type: Defines the system volume disk type. Two different types of volume (`volume_type`) are provided: `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. `b_ssd` is a remote block storage which means your system is stored on a centralized and resilient cluster. + :param root_volume_type: * `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. This type is not available for all node types + * `sbs-5k` is a remote block storage which means your system is stored on a centralized and resilient cluster with 5k IOPS limits + * `sbs-15k` is a faster remote block storage which means your system is stored on a centralized and resilient cluster with 15k IOPS limits + * `b_ssd` is the legacy remote block storage which means your system is stored on a centralized and resilient cluster. Consider using `sbs-5k` or `sbs-15k` instead. :param root_volume_size: System volume disk size. :return: :class:`Pool ` @@ -952,7 +1124,7 @@ def get_pool( self, *, pool_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Pool: """ Get a Pool in a Cluster. @@ -986,7 +1158,7 @@ def wait_for_pool( self, *, pool_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Pool, bool]] = None, ) -> Pool: """ @@ -1024,11 +1196,12 @@ def upgrade_pool( *, pool_id: str, version: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Pool: """ Upgrade a Pool in a Cluster. Upgrade the Kubernetes version of a specific pool. Note that it only works if the targeted version matches the cluster's version. + This will drain and replace the nodes in that pool. :param pool_id: ID of the pool to upgrade. :param version: New Kubernetes version for the pool. :param region: Region to target. If none is passed will use default region from the config. @@ -1068,7 +1241,7 @@ def update_pool( self, *, pool_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, autoscaling: Optional[bool] = None, size: Optional[int] = None, min_size: Optional[int] = None, @@ -1080,7 +1253,7 @@ def update_pool( ) -> Pool: """ Update a Pool in a Cluster. - Update the attributes of a specific pool, such as its desired size, autoscaling settings, and tags. + Update the attributes of a specific pool, such as its desired size, autoscaling settings, and tags. To upgrade a pool, you will need to use the dedicated endpoint. :param pool_id: ID of the pool to update. :param region: Region to target. If none is passed will use default region from the config. :param autoscaling: New value for the pool autoscaling enablement. @@ -1133,7 +1306,7 @@ def delete_pool( self, *, pool_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Pool: """ Delete a Pool in a Cluster. @@ -1163,11 +1336,117 @@ def delete_pool( self._throw_on_error(res) return unmarshal_Pool(res.json()) + def migrate_pools_to_new_images( + self, + *, + cluster_id: str, + region: Optional[ScwRegion] = None, + pool_ids: Optional[List[str]] = None, + ) -> None: + """ + Migrate specific pools or all pools of a cluster to new images. + If no pool is specified, all pools of the cluster will be migrated to new images. + :param cluster_id: + :param region: Region to target. If none is passed will use default region from the config. + :param pool_ids: + + Usage: + :: + + result = api.migrate_pools_to_new_images( + cluster_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_cluster_id = validate_path_param("cluster_id", cluster_id) + + res = self._request( + "POST", + f"/k8s/v1/regions/{param_region}/clusters/{param_cluster_id}/migrate-pools-to-new-images", + body=marshal_MigratePoolsToNewImagesRequest( + MigratePoolsToNewImagesRequest( + cluster_id=cluster_id, + region=region, + pool_ids=pool_ids, + ), + self.client, + ), + ) + + self._throw_on_error(res) + + def get_node_metadata( + self, + *, + region: Optional[ScwRegion] = None, + ) -> NodeMetadata: + """ + Fetch node metadata. + Rerieve metadata to instantiate a Kapsule/Kosmos node. This method is not intended to be called by end users but rather programmatically by the node-installer. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`NodeMetadata ` + + Usage: + :: + + result = api.get_node_metadata() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/k8s/v1/regions/{param_region}/node-metadata", + ) + + self._throw_on_error(res) + return unmarshal_NodeMetadata(res.json()) + + def auth_external_node( + self, + *, + pool_id: str, + region: Optional[ScwRegion] = None, + ) -> ExternalNodeAuth: + """ + Authenticate Kosmos external node. + Creates a newer Kosmos node and returns its token. This method is not intended to be called by end users but rather programmatically by the node-installer. + :param pool_id: Pool the node will be attached to. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ExternalNodeAuth ` + + Usage: + :: + + result = api.auth_external_node( + pool_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_pool_id = validate_path_param("pool_id", pool_id) + + res = self._request( + "POST", + f"/k8s/v1/regions/{param_region}/pools/{param_pool_id}/external-nodes/auth", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_ExternalNodeAuth(res.json()) + def create_external_node( self, *, pool_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ExternalNode: """ Create a Kosmos node. @@ -1202,7 +1481,7 @@ def list_nodes( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, pool_id: Optional[str] = None, order_by: Optional[ListNodesRequestOrderBy] = None, page: Optional[int] = None, @@ -1256,7 +1535,7 @@ def list_nodes_all( self, *, cluster_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, pool_id: Optional[str] = None, order_by: Optional[ListNodesRequestOrderBy] = None, page: Optional[int] = None, @@ -1305,7 +1584,7 @@ def get_node( self, *, node_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Node: """ Get a Node in a Cluster. @@ -1339,7 +1618,7 @@ def wait_for_node( self, *, node_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Node, bool]] = None, ) -> Node: """ @@ -1376,11 +1655,11 @@ def replace_node( self, *, node_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Node: """ Replace a Node in a Cluster. - Replace a specific Node. The node will first be cordoned (scheduling will be disabled on it). The existing pods on the node will then be drained and rescheduled onto another schedulable node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster), disruption of your applications can be expected. + Replace a specific Node. The node will first be drained and pods will be rescheduled onto another node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster, or with specific constraints), disruption of your applications may occur. :param node_id: ID of the node to replace. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Node ` @@ -1412,11 +1691,11 @@ def reboot_node( self, *, node_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Node: """ Reboot a Node in a Cluster. - Reboot a specific Node. The node will first be cordoned (scheduling will be disabled on it). The existing pods on the node will then be drained and rescheduled onto another schedulable node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster), disruption of your applications can be expected. + Reboot a specific Node. The node will first be drained and pods will be rescheduled onto another node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster, or with specific constraints), disruption of your applications may occur. :param node_id: ID of the node to reboot. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`Node ` @@ -1449,11 +1728,11 @@ def delete_node( node_id: str, skip_drain: bool, replace: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Node: """ Delete a Node in a Cluster. - Delete a specific Node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster), disruption of your applications can be expected. + Delete a specific Node. The node will first be drained and pods will be rescheduled onto another node. Note that when there is not enough space to reschedule all the pods (such as in a one-node cluster, or with specific constraints), disruption of your applications may occur. :param node_id: ID of the node to replace. :param skip_drain: Skip draining node from its workload (Note: this parameter is currently inactive). :param replace: Add a new node after the deletion of this node. @@ -1490,7 +1769,7 @@ def delete_node( def list_versions( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListVersionsResponse: """ List all available Versions. @@ -1520,7 +1799,7 @@ def get_version( self, *, version_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Version: """ Get a Version. @@ -1553,7 +1832,7 @@ def get_version( def list_cluster_types( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListClusterTypesResponse: @@ -1590,7 +1869,7 @@ def list_cluster_types( def list_cluster_types_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[ClusterType]: diff --git a/scaleway/scaleway/k8s/v1/marshalling.py b/scaleway/scaleway/k8s/v1/marshalling.py index 337381a2..0f7d2149 100644 --- a/scaleway/scaleway/k8s/v1/marshalling.py +++ b/scaleway/scaleway/k8s/v1/marshalling.py @@ -21,8 +21,12 @@ ClusterOpenIDConnectConfig, Cluster, Node, + ACLRule, + AddClusterACLRulesResponse, ExternalNodeCoreV1Taint, ExternalNode, + ExternalNodeAuth, + ListClusterACLRulesResponse, ClusterType, ListClusterAvailableTypesResponse, ListClusterAvailableVersionsResponse, @@ -31,6 +35,11 @@ ListNodesResponse, ListPoolsResponse, ListVersionsResponse, + NodeMetadataCoreV1Taint, + NodeMetadata, + SetClusterACLRulesResponse, + ACLRuleRequest, + AddClusterACLRulesRequest, CreateClusterRequestPoolConfigUpgradePolicy, CreateClusterRequestAutoUpgrade, CreateClusterRequestAutoscalerConfig, @@ -39,7 +48,8 @@ CreateClusterRequest, CreatePoolRequestUpgradePolicy, CreatePoolRequest, - MigrateToPrivateNetworkClusterRequest, + MigratePoolsToNewImagesRequest, + SetClusterACLRulesRequest, SetClusterTypeRequest, UpdateClusterRequestAutoUpgrade, UpdateClusterRequestAutoscalerConfig, @@ -111,14 +121,6 @@ def unmarshal_Pool(data: Any) -> Pool: if field is not None: args["size"] = field - field = data.get("created_at", None) - if field is not None: - args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field - - field = data.get("updated_at", None) - if field is not None: - args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field - field = data.get("min_size", None) if field is not None: args["min_size"] = field @@ -127,6 +129,18 @@ def unmarshal_Pool(data: Any) -> Pool: if field is not None: args["max_size"] = field + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + field = data.get("container_runtime", None) if field is not None: args["container_runtime"] = field @@ -162,14 +176,26 @@ def unmarshal_Pool(data: Any) -> Pool: field = data.get("placement_group_id", None) if field is not None: args["placement_group_id"] = field + else: + args["placement_group_id"] = None field = data.get("upgrade_policy", None) if field is not None: args["upgrade_policy"] = unmarshal_PoolUpgradePolicy(field) + else: + args["upgrade_policy"] = None field = data.get("root_volume_size", None) if field is not None: args["root_volume_size"] = field + else: + args["root_volume_size"] = None + + field = data.get("new_images_enabled", None) + if field is not None: + args["new_images_enabled"] = field + else: + args["new_images_enabled"] = None return Pool(**args) @@ -253,6 +279,8 @@ def unmarshal_ClusterAutoUpgrade(data: Any) -> ClusterAutoUpgrade: field = data.get("maintenance_window", None) if field is not None: args["maintenance_window"] = unmarshal_MaintenanceWindow(field) + else: + args["maintenance_window"] = None return ClusterAutoUpgrade(**args) @@ -359,7 +387,7 @@ def unmarshal_Cluster(data: Any) -> Cluster: if field is not None: args["id"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -415,43 +443,73 @@ def unmarshal_Cluster(data: Any) -> Cluster: if field is not None: args["feature_gates"] = field - field = data.get("admission_plugins", None) - if field is not None: - args["admission_plugins"] = field - - field = data.get("apiserver_cert_sans", None) - if field is not None: - args["apiserver_cert_sans"] = field - field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("autoscaler_config", None) if field is not None: args["autoscaler_config"] = unmarshal_ClusterAutoscalerConfig(field) + else: + args["autoscaler_config"] = None field = data.get("auto_upgrade", None) if field is not None: args["auto_upgrade"] = unmarshal_ClusterAutoUpgrade(field) + else: + args["auto_upgrade"] = None + + field = data.get("admission_plugins", None) + if field is not None: + args["admission_plugins"] = field + + field = data.get("apiserver_cert_sans", None) + if field is not None: + args["apiserver_cert_sans"] = field + + field = data.get("iam_nodes_group_id", None) + if field is not None: + args["iam_nodes_group_id"] = field field = data.get("open_id_connect_config", None) if field is not None: args["open_id_connect_config"] = unmarshal_ClusterOpenIDConnectConfig(field) + else: + args["open_id_connect_config"] = None field = data.get("private_network_id", None) if field is not None: args["private_network_id"] = field + else: + args["private_network_id"] = None field = data.get("commitment_ends_at", None) if field is not None: args["commitment_ends_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["commitment_ends_at"] = None + + field = data.get("acl_available", None) + if field is not None: + args["acl_available"] = field + else: + args["acl_available"] = None + + field = data.get("new_images_enabled", None) + if field is not None: + args["new_images_enabled"] = field + else: + args["new_images_enabled"] = None return Cluster(**args) @@ -491,14 +549,20 @@ def unmarshal_Node(data: Any) -> Node: field = data.get("public_ip_v4", None) if field is not None: args["public_ip_v4"] = field + else: + args["public_ip_v4"] = None field = data.get("public_ip_v6", None) if field is not None: args["public_ip_v6"] = field + else: + args["public_ip_v6"] = None field = data.get("conditions", None) if field is not None: args["conditions"] = field + else: + args["conditions"] = None field = data.get("status", None) if field is not None: @@ -507,18 +571,72 @@ def unmarshal_Node(data: Any) -> Node: field = data.get("error_message", None) if field is not None: args["error_message"] = field + else: + args["error_message"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Node(**args) +def unmarshal_ACLRule(data: Any) -> ACLRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ACLRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("ip", None) + if field is not None: + args["ip"] = field + else: + args["ip"] = None + + field = data.get("scaleway_ranges", None) + if field is not None: + args["scaleway_ranges"] = field + else: + args["scaleway_ranges"] = None + + return ACLRule(**args) + + +def unmarshal_AddClusterACLRulesResponse(data: Any) -> AddClusterACLRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AddClusterACLRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_ACLRule(v) for v in field] if field is not None else None + ) + + return AddClusterACLRulesResponse(**args) + + def unmarshal_ExternalNodeCoreV1Taint(data: Any) -> ExternalNodeCoreV1Taint: if not isinstance(data, dict): raise TypeError( @@ -606,9 +724,53 @@ def unmarshal_ExternalNode(data: Any) -> ExternalNode: else None ) + field = data.get("iam_token", None) + if field is not None: + args["iam_token"] = field + return ExternalNode(**args) +def unmarshal_ExternalNodeAuth(data: Any) -> ExternalNodeAuth: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ExternalNodeAuth' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_secret_key", None) + if field is not None: + args["node_secret_key"] = field + + field = data.get("metadata_url", None) + if field is not None: + args["metadata_url"] = field + + return ExternalNodeAuth(**args) + + +def unmarshal_ListClusterACLRulesResponse(data: Any) -> ListClusterACLRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListClusterACLRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_ACLRule(v) for v in field] if field is not None else None + ) + + return ListClusterACLRulesResponse(**args) + + def unmarshal_ClusterType(data: Any) -> ClusterType: if not isinstance(data, dict): raise TypeError( @@ -649,9 +811,15 @@ def unmarshal_ClusterType(data: Any) -> ClusterType: if field is not None: args["audit_logs_supported"] = field + field = data.get("max_etcd_size", None) + if field is not None: + args["max_etcd_size"] = field + field = data.get("commitment_delay", None) if field is not None: args["commitment_delay"] = field + else: + args["commitment_delay"] = None return ClusterType(**args) @@ -799,6 +967,143 @@ def unmarshal_ListVersionsResponse(data: Any) -> ListVersionsResponse: return ListVersionsResponse(**args) +def unmarshal_NodeMetadataCoreV1Taint(data: Any) -> NodeMetadataCoreV1Taint: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeMetadataCoreV1Taint' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key", None) + if field is not None: + args["key"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + field = data.get("effect", None) + if field is not None: + args["effect"] = field + + return NodeMetadataCoreV1Taint(**args) + + +def unmarshal_NodeMetadata(data: Any) -> NodeMetadata: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeMetadata' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("cluster_url", None) + if field is not None: + args["cluster_url"] = field + + field = data.get("cluster_ca", None) + if field is not None: + args["cluster_ca"] = field + + field = data.get("credential_provider_config", None) + if field is not None: + args["credential_provider_config"] = field + + field = data.get("pool_version", None) + if field is not None: + args["pool_version"] = field + + field = data.get("kubelet_config", None) + if field is not None: + args["kubelet_config"] = field + + field = data.get("node_labels", None) + if field is not None: + args["node_labels"] = field + + field = data.get("node_taints", None) + if field is not None: + args["node_taints"] = ( + [unmarshal_NodeMetadataCoreV1Taint(v) for v in field] + if field is not None + else None + ) + + field = data.get("has_gpu", None) + if field is not None: + args["has_gpu"] = field + + field = data.get("external_ip", None) + if field is not None: + args["external_ip"] = field + + field = data.get("repo_uri", None) + if field is not None: + args["repo_uri"] = field + + return NodeMetadata(**args) + + +def unmarshal_SetClusterACLRulesResponse(data: Any) -> SetClusterACLRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetClusterACLRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_ACLRule(v) for v in field] if field is not None else None + ) + + return SetClusterACLRulesResponse(**args) + + +def marshal_ACLRuleRequest( + request: ACLRuleRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("ip", request.ip), + OneOfPossibility("scaleway_ranges", request.scaleway_ranges), + ] + ), + ) + + if request.description is not None: + output["description"] = request.description + + return output + + +def marshal_AddClusterACLRulesRequest( + request: AddClusterACLRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.acls is not None: + output["acls"] = [ + marshal_ACLRuleRequest(item, defaults) for item in request.acls + ] + + return output + + def marshal_MaintenanceWindow( request: MaintenanceWindow, defaults: ProfileDefaults, @@ -839,8 +1144,8 @@ def marshal_CreateClusterRequestAutoUpgrade( output["enable"] = request.enable if request.maintenance_window is not None: - output["maintenance_window"] = ( - marshal_MaintenanceWindow(request.maintenance_window, defaults), + output["maintenance_window"] = marshal_MaintenanceWindow( + request.maintenance_window, defaults ) return output @@ -970,10 +1275,8 @@ def marshal_CreateClusterRequestPoolConfig( output["public_ip_disabled"] = request.public_ip_disabled if request.upgrade_policy is not None: - output["upgrade_policy"] = ( - marshal_CreateClusterRequestPoolConfigUpgradePolicy( - request.upgrade_policy, defaults - ), + output["upgrade_policy"] = marshal_CreateClusterRequestPoolConfigUpgradePolicy( + request.upgrade_policy, defaults ) if request.root_volume_size is not None: @@ -1027,15 +1330,13 @@ def marshal_CreateClusterRequest( ] if request.autoscaler_config is not None: - output["autoscaler_config"] = ( - marshal_CreateClusterRequestAutoscalerConfig( - request.autoscaler_config, defaults - ), + output["autoscaler_config"] = marshal_CreateClusterRequestAutoscalerConfig( + request.autoscaler_config, defaults ) if request.auto_upgrade is not None: - output["auto_upgrade"] = ( - marshal_CreateClusterRequestAutoUpgrade(request.auto_upgrade, defaults), + output["auto_upgrade"] = marshal_CreateClusterRequestAutoUpgrade( + request.auto_upgrade, defaults ) if request.feature_gates is not None: @@ -1048,7 +1349,7 @@ def marshal_CreateClusterRequest( output["open_id_connect_config"] = ( marshal_CreateClusterRequestOpenIDConnectConfig( request.open_id_connect_config, defaults - ), + ) ) if request.apiserver_cert_sans is not None: @@ -1120,8 +1421,8 @@ def marshal_CreatePoolRequest( } if request.upgrade_policy is not None: - output["upgrade_policy"] = ( - marshal_CreatePoolRequestUpgradePolicy(request.upgrade_policy, defaults), + output["upgrade_policy"] = marshal_CreatePoolRequestUpgradePolicy( + request.upgrade_policy, defaults ) if request.zone is not None: @@ -1136,14 +1437,28 @@ def marshal_CreatePoolRequest( return output -def marshal_MigrateToPrivateNetworkClusterRequest( - request: MigrateToPrivateNetworkClusterRequest, +def marshal_MigratePoolsToNewImagesRequest( + request: MigratePoolsToNewImagesRequest, defaults: ProfileDefaults, ) -> Dict[str, Any]: output: Dict[str, Any] = {} - if request.private_network_id is not None: - output["private_network_id"] = request.private_network_id + if request.pool_ids is not None: + output["pool_ids"] = request.pool_ids + + return output + + +def marshal_SetClusterACLRulesRequest( + request: SetClusterACLRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.acls is not None: + output["acls"] = [ + marshal_ACLRuleRequest(item, defaults) for item in request.acls + ] return output @@ -1170,8 +1485,8 @@ def marshal_UpdateClusterRequestAutoUpgrade( output["enable"] = request.enable if request.maintenance_window is not None: - output["maintenance_window"] = ( - marshal_MaintenanceWindow(request.maintenance_window, defaults), + output["maintenance_window"] = marshal_MaintenanceWindow( + request.maintenance_window, defaults ) return output @@ -1266,15 +1581,13 @@ def marshal_UpdateClusterRequest( output["tags"] = request.tags if request.autoscaler_config is not None: - output["autoscaler_config"] = ( - marshal_UpdateClusterRequestAutoscalerConfig( - request.autoscaler_config, defaults - ), + output["autoscaler_config"] = marshal_UpdateClusterRequestAutoscalerConfig( + request.autoscaler_config, defaults ) if request.auto_upgrade is not None: - output["auto_upgrade"] = ( - marshal_UpdateClusterRequestAutoUpgrade(request.auto_upgrade, defaults), + output["auto_upgrade"] = marshal_UpdateClusterRequestAutoUpgrade( + request.auto_upgrade, defaults ) if request.feature_gates is not None: @@ -1287,7 +1600,7 @@ def marshal_UpdateClusterRequest( output["open_id_connect_config"] = ( marshal_UpdateClusterRequestOpenIDConnectConfig( request.open_id_connect_config, defaults - ), + ) ) if request.apiserver_cert_sans is not None: @@ -1339,8 +1652,8 @@ def marshal_UpdatePoolRequest( output["kubelet_args"] = request.kubelet_args if request.upgrade_policy is not None: - output["upgrade_policy"] = ( - marshal_UpdatePoolRequestUpgradePolicy(request.upgrade_policy, defaults), + output["upgrade_policy"] = marshal_UpdatePoolRequestUpgradePolicy( + request.upgrade_policy, defaults ) return output diff --git a/scaleway/scaleway/k8s/v1/types.py b/scaleway/scaleway/k8s/v1/types.py index c03be2b1..d2333e28 100644 --- a/scaleway/scaleway/k8s/v1/types.py +++ b/scaleway/scaleway/k8s/v1/types.py @@ -8,8 +8,8 @@ from typing import Dict, List, Optional from scaleway_core.bridge import ( - Region, - Zone, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -100,6 +100,14 @@ def __str__(self) -> str: class ListNodesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" + UPDATED_AT_ASC = "updated_at_asc" + UPDATED_AT_DESC = "updated_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + VERSION_ASC = "version_asc" + VERSION_DESC = "version_desc" def __str__(self) -> str: return str(self.value) @@ -171,6 +179,8 @@ class PoolVolumeType(str, Enum, metaclass=StrEnumMeta): DEFAULT_VOLUME_TYPE = "default_volume_type" L_SSD = "l_ssd" B_SSD = "b_ssd" + SBS_5K = "sbs_5k" + SBS_15K = "sbs_15k" def __str__(self) -> str: return str(self.value) @@ -241,7 +251,7 @@ class ClusterAutoscalerConfig: scale_down_delay_after_add: str """ - How long after scale up that scale down evaluation resumes. + How long after scale up the scale down evaluation resumes. """ estimator: AutoscalerEstimator @@ -365,29 +375,29 @@ class Pool: Size (number of nodes) of the pool. """ - created_at: Optional[datetime] + min_size: int """ - Date on which the pool was created. + Defines the minimum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. """ - updated_at: Optional[datetime] + max_size: int """ - Date on which the pool was last updated. + Defines the maximum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. """ - min_size: int + created_at: Optional[datetime] """ - Defines the minimum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. + Date on which the pool was created. """ - max_size: int + updated_at: Optional[datetime] """ - Defines the maximum size of the pool. Note that this field is only used when autoscaling is enabled on the pool. + Date on which the pool was last updated. """ container_runtime: Runtime """ - Customization of the container runtime is available for each pool. Note that `docker` has been deprecated since version 1.20 and will be removed by version 1.24. + Customization of the container runtime is available for each pool. """ autohealing: bool @@ -397,7 +407,7 @@ class Pool: tags: List[str] """ - Tags associated with the pool. + Tags associated with the pool, see [managing tags](https://www.scaleway.com/en/docs/containers/kubernetes/api-cli/managing-tags). """ kubelet_args: Dict[str, str] @@ -405,14 +415,17 @@ class Pool: Kubelet arguments to be used by this pool. Note that this feature is experimental. """ - zone: Zone + zone: ScwZone """ Zone in which the pool's nodes will be spawned. """ root_volume_type: PoolVolumeType """ - Defines the system volume disk type. Two different types of volume (`volume_type`) are provided: `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. `b_ssd` is a remote block storage which means your system is stored on a centralized and resilient cluster. + * `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. This type is not available for all node types +* `sbs-5k` is a remote block storage which means your system is stored on a centralized and resilient cluster with 5k IOPS limits +* `sbs-15k` is a faster remote block storage which means your system is stored on a centralized and resilient cluster with 15k IOPS limits +* `b_ssd` is the legacy remote block storage which means your system is stored on a centralized and resilient cluster. Consider using `sbs-5k` or `sbs-15k` instead. """ public_ip_disabled: bool @@ -420,14 +433,14 @@ class Pool: Defines if the public IP should be removed from Nodes. To use this feature, your Cluster must have an attached Private Network set up with a Public Gateway. """ - region: Region + region: ScwRegion """ Cluster region of the pool. """ placement_group_id: Optional[str] """ - Placement group ID in which all the nodes of the pool will be created. + Placement group ID in which all the nodes of the pool will be created, placement groups are limited to 20 instances. """ upgrade_policy: Optional[PoolUpgradePolicy] @@ -440,6 +453,40 @@ class Pool: System volume disk size. """ + new_images_enabled: Optional[bool] + """ + Defines whether the pool is migrated to new images. + """ + + +@dataclass +class ACLRuleRequest: + description: str + """ + Description of the ACL. + """ + + ip: Optional[str] + + scaleway_ranges: Optional[bool] + + +@dataclass +class ACLRule: + id: str + """ + ID of the ACL rule. + """ + + description: str + """ + Description of the ACL. + """ + + ip: Optional[str] + + scaleway_ranges: Optional[bool] + @dataclass class CreateClusterRequestAutoUpgrade: @@ -473,7 +520,7 @@ class CreateClusterRequestAutoscalerConfig: scale_down_delay_after_add: Optional[str] """ - How long after scale up that scale down evaluation resumes. + How long after scale up the scale down evaluation resumes. """ ignore_daemonsets_utilization: Optional[bool] @@ -569,12 +616,12 @@ class CreateClusterRequestPoolConfig: container_runtime: Runtime """ - Customization of the container runtime is available for each pool. Note that `docker` has been deprecated since version 1.20 and will be removed by version 1.24. + Customization of the container runtime is available for each pool. """ placement_group_id: Optional[str] """ - Placement group ID in which all the nodes of the pool will be created. + Placement group ID in which all the nodes of the pool will be created, placement groups are limited to 20 instances. """ min_size: Optional[int] @@ -594,7 +641,7 @@ class CreateClusterRequestPoolConfig: tags: List[str] """ - Tags associated with the pool. + Tags associated with the pool, see [managing tags](https://www.scaleway.com/en/docs/containers/kubernetes/api-cli/managing-tags). """ kubelet_args: Dict[str, str] @@ -602,14 +649,17 @@ class CreateClusterRequestPoolConfig: Kubelet arguments to be used by this pool. Note that this feature is experimental. """ - zone: Zone + zone: ScwZone """ Zone in which the pool's nodes will be spawned. """ root_volume_type: PoolVolumeType """ - Defines the system volume disk type. Two different types of volume (`volume_type`) are provided: `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. `b_ssd` is a remote block storage which means your system is stored on a centralized and resilient cluster. + * `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. This type is not available for all node types +* `sbs-5k` is a remote block storage which means your system is stored on a centralized and resilient cluster with 5k IOPS limits +* `sbs-15k` is a faster remote block storage which means your system is stored on a centralized and resilient cluster with 15k IOPS limits +* `b_ssd` is the legacy remote block storage which means your system is stored on a centralized and resilient cluster. Consider using `sbs-5k` or `sbs-15k` instead. """ public_ip_disabled: bool @@ -686,6 +736,11 @@ class ClusterType: True if the offer allows activation of the audit log functionality. Please note that audit logs are sent to Cockpit. """ + max_etcd_size: int + """ + Maximum amount of data that can be stored in etcd for the offer. + """ + commitment_delay: Optional[str] """ Time period during which you can no longer switch to a lower offer. @@ -704,7 +759,7 @@ class Version: Label of the Kubernetes version. """ - region: Region + region: ScwRegion """ Region in which this version is available. """ @@ -762,7 +817,7 @@ class Cluster: Kubernetes version of the cluster. """ - region: Region + region: ScwRegion """ Region in which the cluster is deployed. """ @@ -812,16 +867,6 @@ class Cluster: List of enabled feature gates. """ - admission_plugins: List[str] - """ - List of enabled admission plugins. - """ - - apiserver_cert_sans: List[str] - """ - Additional Subject Alternative Names for the Kubernetes API server certificate. - """ - created_at: Optional[datetime] """ Date on which the cluster was created. @@ -839,7 +884,22 @@ class Cluster: auto_upgrade: Optional[ClusterAutoUpgrade] """ - Auto upgrade configuration of the cluster. + Auto upgrade Kubernetes version of the cluster. + """ + + admission_plugins: List[str] + """ + List of enabled admission plugins. + """ + + apiserver_cert_sans: List[str] + """ + Additional Subject Alternative Names for the Kubernetes API server certificate. + """ + + iam_nodes_group_id: str + """ + IAM group that nodes are members of (this field might be empty during early stage of cluster creation). """ open_id_connect_config: Optional[ClusterOpenIDConnectConfig] @@ -857,6 +917,16 @@ class Cluster: Date on which it will be possible to switch to a smaller offer. """ + acl_available: Optional[bool] + """ + Defines whether ACL is available on the cluster. + """ + + new_images_enabled: Optional[bool] + """ + Defines whether all pools are migrated to new images. + """ + @dataclass class Node: @@ -880,7 +950,7 @@ class Node: Underlying instance ID. It is prefixed by instance type and location information (see https://pkg.go.dev/k8s.io/api/core/v1#NodeSpec.ProviderID). """ - region: Region + region: ScwRegion """ Cluster region of the node. """ @@ -926,6 +996,15 @@ class Node: """ +@dataclass +class NodeMetadataCoreV1Taint: + key: str + + value: str + + effect: str + + @dataclass class UpdateClusterRequestAutoUpgrade: enable: Optional[bool] @@ -958,7 +1037,7 @@ class UpdateClusterRequestAutoscalerConfig: scale_down_delay_after_add: Optional[str] """ - How long after scale up that scale down evaluation resumes. + How long after scale up the scale down evaluation resumes. """ ignore_daemonsets_utilization: Optional[bool] @@ -1037,11 +1116,50 @@ class UpdatePoolRequestUpgradePolicy: max_surge: Optional[int] +@dataclass +class AddClusterACLRulesRequest: + cluster_id: str + """ + ID of the cluster whose ACLs will be added. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + acls: Optional[List[ACLRuleRequest]] + """ + ACLs to add. + """ + + +@dataclass +class AddClusterACLRulesResponse: + rules: List[ACLRule] + """ + ACLs that were added. + """ + + +@dataclass +class AuthExternalNodeRequest: + pool_id: str + """ + Pool the node will be attached to. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class CreateClusterRequest: type_: str """ - Type of the cluster (possible values are kapsule, multicloud, kapsule-dedicated-8, kapsule-dedicated-16). + Type of the cluster. See [list available cluster types](#list-available-cluster-types-for-a-cluster) for a list of valid types. """ description: str @@ -1054,7 +1172,7 @@ class CreateClusterRequest: Kubernetes version of the cluster. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1123,7 +1241,7 @@ class CreateClusterRequest: class CreateExternalNodeRequest: pool_id: str - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1131,7 +1249,7 @@ class CreateExternalNodeRequest: @dataclass class CreatePoolRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1163,7 +1281,7 @@ class CreatePoolRequest: placement_group_id: Optional[str] """ - Placement group ID in which all the nodes of the pool will be created. + Placement group ID in which all the nodes of the pool will be created, placement groups are limited to 20 instances. """ min_size: Optional[int] @@ -1188,12 +1306,12 @@ class CreatePoolRequest: container_runtime: Optional[Runtime] """ - Customization of the container runtime is available for each pool. Note that `docker` has been deprecated since version 1.20 and will be removed by version 1.24. + Customization of the container runtime is available for each pool. """ tags: Optional[List[str]] """ - Tags associated with the pool. + Tags associated with the pool, see [managing tags](https://www.scaleway.com/en/docs/containers/kubernetes/api-cli/managing-tags). """ kubelet_args: Optional[Dict[str, str]] @@ -1206,14 +1324,17 @@ class CreatePoolRequest: Pool upgrade policy. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone in which the pool's nodes will be spawned. """ root_volume_type: Optional[PoolVolumeType] """ - Defines the system volume disk type. Two different types of volume (`volume_type`) are provided: `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. `b_ssd` is a remote block storage which means your system is stored on a centralized and resilient cluster. + * `l_ssd` is a local block storage which means your system is stored locally on your node's hypervisor. This type is not available for all node types +* `sbs-5k` is a remote block storage which means your system is stored on a centralized and resilient cluster with 5k IOPS limits +* `sbs-15k` is a faster remote block storage which means your system is stored on a centralized and resilient cluster with 15k IOPS limits +* `b_ssd` is the legacy remote block storage which means your system is stored on a centralized and resilient cluster. Consider using `sbs-5k` or `sbs-15k` instead. """ root_volume_size: Optional[int] @@ -1222,6 +1343,19 @@ class CreatePoolRequest: """ +@dataclass +class DeleteACLRuleRequest: + acl_id: str + """ + ID of the ACL rule to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class DeleteClusterRequest: cluster_id: str @@ -1234,7 +1368,7 @@ class DeleteClusterRequest: Defines whether all volumes (including retain volume type), empty Private Networks and Load Balancers with a name starting with the cluster ID will also be deleted. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1257,7 +1391,7 @@ class DeleteNodeRequest: Add a new node after the deletion of this node. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1270,7 +1404,7 @@ class DeletePoolRequest: ID of the pool to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1304,6 +1438,15 @@ class ExternalNode: node_taints: List[ExternalNodeCoreV1Taint] + iam_token: str + + +@dataclass +class ExternalNodeAuth: + node_secret_key: str + + metadata_url: str + @dataclass class GetClusterKubeConfigRequest: @@ -1312,7 +1455,7 @@ class GetClusterKubeConfigRequest: Cluster ID for which to download the kubeconfig. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1330,7 +1473,15 @@ class GetClusterRequest: ID of the requested cluster. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetNodeMetadataRequest: + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1343,7 +1494,7 @@ class GetNodeRequest: ID of the requested node. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1356,7 +1507,7 @@ class GetPoolRequest: ID of the requested pool. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1369,11 +1520,47 @@ class GetVersionRequest: Requested version name. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListClusterACLRulesRequest: + cluster_id: str + """ + ID of the cluster whose ACLs will be listed. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ + page: Optional[int] + """ + Page number for the returned ACLs. + """ + + page_size: Optional[int] + """ + Maximum number of ACLs per page. + """ + + +@dataclass +class ListClusterACLRulesResponse: + total_count: int + """ + Total number of ACLs that exist for the cluster. + """ + + rules: List[ACLRule] + """ + Paginated returned ACLs. + """ + @dataclass class ListClusterAvailableTypesRequest: @@ -1382,7 +1569,7 @@ class ListClusterAvailableTypesRequest: Cluster ID for which the available Kubernetes types will be listed. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1408,7 +1595,7 @@ class ListClusterAvailableVersionsRequest: Cluster ID for which the available Kubernetes versions will be listed. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1424,7 +1611,7 @@ class ListClusterAvailableVersionsResponse: @dataclass class ListClusterTypesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1455,7 +1642,7 @@ class ListClusterTypesResponse: @dataclass class ListClustersRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1526,7 +1713,7 @@ class ListNodesRequest: Cluster ID from which the nodes will be listed from. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1582,7 +1769,7 @@ class ListPoolsRequest: ID of the cluster whose pools will be listed. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1628,7 +1815,7 @@ class ListPoolsResponse: @dataclass class ListVersionsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1643,22 +1830,43 @@ class ListVersionsResponse: @dataclass -class MigrateToPrivateNetworkClusterRequest: +class MigratePoolsToNewImagesRequest: cluster_id: str - """ - ID of the cluster to migrate. - """ - - private_network_id: str - """ - ID of the Private Network to link to the cluster. - """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ + pool_ids: Optional[List[str]] + + +@dataclass +class NodeMetadata: + id: str + + name: str + + cluster_url: str + + cluster_ca: str + + credential_provider_config: str + + pool_version: str + + kubelet_config: str + + node_labels: Dict[str, str] + + node_taints: List[NodeMetadataCoreV1Taint] + + has_gpu: bool + + external_ip: str + + repo_uri: str + @dataclass class RebootNodeRequest: @@ -1667,7 +1875,7 @@ class RebootNodeRequest: ID of the node to reboot. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1680,7 +1888,7 @@ class ReplaceNodeRequest: ID of the node to replace. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1693,11 +1901,37 @@ class ResetClusterAdminTokenRequest: Cluster ID on which the admin token will be renewed. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SetClusterACLRulesRequest: + cluster_id: str + """ + ID of the cluster whose ACLs will be set. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ + acls: Optional[List[ACLRuleRequest]] + """ + ACLs to set. + """ + + +@dataclass +class SetClusterACLRulesResponse: + rules: List[ACLRule] + """ + ACLs that were set. + """ + @dataclass class SetClusterTypeRequest: @@ -1711,7 +1945,7 @@ class SetClusterTypeRequest: Type of the cluster. Note that some migrations are not possible (please refer to product documentation). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1724,7 +1958,7 @@ class UpdateClusterRequest: ID of the cluster to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1751,7 +1985,7 @@ class UpdateClusterRequest: auto_upgrade: Optional[UpdateClusterRequestAutoUpgrade] """ - New auto upgrade configuration for the cluster. Note that all fields need to be set. + New auto upgrade configuration for the cluster. Note that all fields needs to be set. """ feature_gates: Optional[List[str]] @@ -1782,7 +2016,7 @@ class UpdatePoolRequest: ID of the pool to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1845,7 +2079,7 @@ class UpgradeClusterRequest: Defines whether pools will also be upgraded once the control plane is upgraded. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1863,7 +2097,7 @@ class UpgradePoolRequest: New Kubernetes version for the pool. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/scaleway/key_manager/__init__.py b/scaleway/scaleway/key_manager/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway/scaleway/key_manager/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/key_manager/v1alpha1/__init__.py b/scaleway/scaleway/key_manager/v1alpha1/__init__.py new file mode 100644 index 00000000..fb3ad375 --- /dev/null +++ b/scaleway/scaleway/key_manager/v1alpha1/__init__.py @@ -0,0 +1,79 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DataKeyAlgorithmSymmetricEncryption +from .types import KeyAlgorithmAsymmetricEncryption +from .types import KeyAlgorithmAsymmetricSigning +from .types import KeyAlgorithmSymmetricEncryption +from .types import KeyOrigin +from .types import KeyState +from .types import ListKeysRequestOrderBy +from .types import ListKeysRequestUsage +from .types import KeyRotationPolicy +from .types import KeyUsage +from .types import Key +from .types import CreateKeyRequest +from .types import DataKey +from .types import DecryptRequest +from .types import DecryptResponse +from .types import DeleteKeyMaterialRequest +from .types import DeleteKeyRequest +from .types import DisableKeyRequest +from .types import EnableKeyRequest +from .types import EncryptRequest +from .types import EncryptResponse +from .types import GenerateDataKeyRequest +from .types import GetKeyRequest +from .types import GetPublicKeyRequest +from .types import ImportKeyMaterialRequest +from .types import ListKeysRequest +from .types import ListKeysResponse +from .types import ProtectKeyRequest +from .types import PublicKey +from .types import RotateKeyRequest +from .types import SignRequest +from .types import SignResponse +from .types import UnprotectKeyRequest +from .types import UpdateKeyRequest +from .types import VerifyRequest +from .types import VerifyResponse +from .api import KeyManagerV1Alpha1API + +__all__ = [ + "DataKeyAlgorithmSymmetricEncryption", + "KeyAlgorithmAsymmetricEncryption", + "KeyAlgorithmAsymmetricSigning", + "KeyAlgorithmSymmetricEncryption", + "KeyOrigin", + "KeyState", + "ListKeysRequestOrderBy", + "ListKeysRequestUsage", + "KeyRotationPolicy", + "KeyUsage", + "Key", + "CreateKeyRequest", + "DataKey", + "DecryptRequest", + "DecryptResponse", + "DeleteKeyMaterialRequest", + "DeleteKeyRequest", + "DisableKeyRequest", + "EnableKeyRequest", + "EncryptRequest", + "EncryptResponse", + "GenerateDataKeyRequest", + "GetKeyRequest", + "GetPublicKeyRequest", + "ImportKeyMaterialRequest", + "ListKeysRequest", + "ListKeysResponse", + "ProtectKeyRequest", + "PublicKey", + "RotateKeyRequest", + "SignRequest", + "SignResponse", + "UnprotectKeyRequest", + "UpdateKeyRequest", + "VerifyRequest", + "VerifyResponse", + "KeyManagerV1Alpha1API", +] diff --git a/scaleway/scaleway/key_manager/v1alpha1/api.py b/scaleway/scaleway/key_manager/v1alpha1/api.py new file mode 100644 index 00000000..30aa304d --- /dev/null +++ b/scaleway/scaleway/key_manager/v1alpha1/api.py @@ -0,0 +1,878 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + validate_path_param, + fetch_all_pages, +) +from .types import ( + DataKeyAlgorithmSymmetricEncryption, + KeyOrigin, + ListKeysRequestOrderBy, + ListKeysRequestUsage, + CreateKeyRequest, + DataKey, + DecryptRequest, + DecryptResponse, + EncryptRequest, + EncryptResponse, + GenerateDataKeyRequest, + ImportKeyMaterialRequest, + Key, + KeyRotationPolicy, + KeyUsage, + ListKeysResponse, + PublicKey, + SignRequest, + SignResponse, + UpdateKeyRequest, + VerifyRequest, + VerifyResponse, +) +from .marshalling import ( + unmarshal_Key, + unmarshal_DataKey, + unmarshal_DecryptResponse, + unmarshal_EncryptResponse, + unmarshal_ListKeysResponse, + unmarshal_PublicKey, + unmarshal_SignResponse, + unmarshal_VerifyResponse, + marshal_CreateKeyRequest, + marshal_DecryptRequest, + marshal_EncryptRequest, + marshal_GenerateDataKeyRequest, + marshal_ImportKeyMaterialRequest, + marshal_SignRequest, + marshal_UpdateKeyRequest, + marshal_VerifyRequest, +) + + +class KeyManagerV1Alpha1API(API): + """ + This API allows you to create, manage and use cryptographic keys in a centralized and secure service. + """ + + def create_key( + self, + *, + unprotected: bool, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + usage: Optional[KeyUsage] = None, + description: Optional[str] = None, + tags: Optional[List[str]] = None, + rotation_policy: Optional[KeyRotationPolicy] = None, + origin: Optional[KeyOrigin] = None, + ) -> Key: + """ + Create a key. + Create a key in a given region specified by the `region` parameter. Keys only support symmetric encryption. You can use keys to encrypt or decrypt arbitrary payloads, or to generate data encryption keys. **Data encryption keys are not stored in Key Manager**. + :param unprotected: Default value is `false`. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project containing the key. + :param name: (Optional) Name of the key. + :param usage: See the `Key.Algorithm.SymmetricEncryption` enum for a description of values. + :param description: (Optional) Description of the key. + :param tags: (Optional) List of the key's tags. + :param rotation_policy: If not specified, no rotation policy will be applied to the key. + :param origin: Refer to the `Key.Origin` enum for a description of values. + :return: :class:`Key ` + + Usage: + :: + + result = api.create_key( + unprotected=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys", + body=marshal_CreateKeyRequest( + CreateKeyRequest( + unprotected=unprotected, + region=region, + project_id=project_id, + name=name, + usage=usage, + description=description, + tags=tags, + rotation_policy=rotation_policy, + origin=origin, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + def get_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Get key metadata. + Retrieve metadata for a specified key using the `region` and `key_id` parameters. + :param key_id: ID of the key to target. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = api.get_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "GET", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}", + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + def get_public_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> PublicKey: + """ + Get the public key in PEM format. + Retrieves the public portion of an asymmetric cryptographic key in PEM format. + :param key_id: ID of the key. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`PublicKey ` + + Usage: + :: + + result = api.get_public_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "GET", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/public-key", + ) + + self._throw_on_error(res) + return unmarshal_PublicKey(res.json()) + + def update_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + description: Optional[str] = None, + tags: Optional[List[str]] = None, + rotation_policy: Optional[KeyRotationPolicy] = None, + ) -> Key: + """ + Update a key. + Modify a key's metadata including name, description and tags, specified by the `key_id` and `region` parameters. + :param key_id: ID of the key to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: (Optional) Updated name of the key. + :param description: (Optional) Updated description of the key. + :param tags: (Optional) Updated list of the key's tags. + :param rotation_policy: If not specified, the key's existing rotation policy applies. + :return: :class:`Key ` + + Usage: + :: + + result = api.update_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "PATCH", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}", + body=marshal_UpdateKeyRequest( + UpdateKeyRequest( + key_id=key_id, + region=region, + name=name, + description=description, + tags=tags, + rotation_policy=rotation_policy, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + def delete_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a key. + Permanently delete a key specified by the `region` and `key_id` parameters. This action is irreversible. Any data encrypted with this key, including data encryption keys, will no longer be decipherable. + :param key_id: ID of the key to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "DELETE", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}", + ) + + self._throw_on_error(res) + + def rotate_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Rotate a key. + Generate a new version of an existing key with new key material. Previous key versions remain usable to decrypt previously encrypted data, but the key's new version will be used for subsequent encryption operations and data key generation. + :param key_id: ID of the key to rotate. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = api.rotate_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/rotate", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + def protect_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Apply key protection. + Apply protection to a given key specified by the `key_id` parameter. Applying key protection means that your key can be used and modified, but it cannot be deleted. + :param key_id: ID of the key to apply key protection to. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = api.protect_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/protect", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + def unprotect_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Remove key protection. + Remove key protection from a given key specified by the `key_id` parameter. Removing key protection means that your key can be deleted anytime. + :param key_id: ID of the key to remove key protection from. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = api.unprotect_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/unprotect", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + def enable_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Enable key. + Enable a given key to be used for cryptographic operations. Enabling a key allows you to make a disabled key usable again. You must specify the `region` and `key_id` parameters. + :param key_id: ID of the key to enable. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = api.enable_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/enable", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + def disable_key( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> Key: + """ + Disable key. + Disable a given key, preventing it to be used for cryptographic operations. Disabling a key renders it unusable. You must specify the `region` and `key_id` parameters. + :param key_id: ID of the key to disable. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Key ` + + Usage: + :: + + result = api.disable_key( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/disable", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + def list_keys( + self, + *, + region: Optional[ScwRegion] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + order_by: Optional[ListKeysRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + tags: Optional[List[str]] = None, + name: Optional[str] = None, + usage: Optional[ListKeysRequestUsage] = None, + ) -> ListKeysResponse: + """ + List keys. + Retrieve a list of keys across all Projects in an Organization or within a specific Project. You must specify the `region`, and either the `organization_id` or the `project_id`. + :param region: Region to target. If none is passed will use default region from the config. + :param organization_id: (Optional) Filter by Organization ID. + :param project_id: (Optional) Filter by Project ID. + :param order_by: + :param page: + :param page_size: + :param tags: (Optional) List of tags to filter on. + :param name: (Optional) Filter by key name. + :param usage: Select from symmetric encryption, asymmetric encryption, or asymmetric signing. + :return: :class:`ListKeysResponse ` + + Usage: + :: + + result = api.list_keys() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/key-manager/v1alpha1/regions/{param_region}/keys", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + "usage": usage, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListKeysResponse(res.json()) + + def list_keys_all( + self, + *, + region: Optional[ScwRegion] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + order_by: Optional[ListKeysRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + tags: Optional[List[str]] = None, + name: Optional[str] = None, + usage: Optional[ListKeysRequestUsage] = None, + ) -> List[Key]: + """ + List keys. + Retrieve a list of keys across all Projects in an Organization or within a specific Project. You must specify the `region`, and either the `organization_id` or the `project_id`. + :param region: Region to target. If none is passed will use default region from the config. + :param organization_id: (Optional) Filter by Organization ID. + :param project_id: (Optional) Filter by Project ID. + :param order_by: + :param page: + :param page_size: + :param tags: (Optional) List of tags to filter on. + :param name: (Optional) Filter by key name. + :param usage: Select from symmetric encryption, asymmetric encryption, or asymmetric signing. + :return: :class:`List[Key] ` + + Usage: + :: + + result = api.list_keys_all() + """ + + return fetch_all_pages( + type=ListKeysResponse, + key="keys", + fetcher=self.list_keys, + args={ + "region": region, + "organization_id": organization_id, + "project_id": project_id, + "order_by": order_by, + "page": page, + "page_size": page_size, + "tags": tags, + "name": name, + "usage": usage, + }, + ) + + def generate_data_key( + self, + *, + key_id: str, + without_plaintext: bool, + region: Optional[ScwRegion] = None, + algorithm: Optional[DataKeyAlgorithmSymmetricEncryption] = None, + ) -> DataKey: + """ + Create a data encryption key. + Create a new data encryption key for cryptographic operations outside of Key Manager. The data encryption key is encrypted and must be decrypted using the key you have created in Key Manager. + + The data encryption key is returned in plaintext and ciphertext but it should only be stored in its encrypted form (ciphertext). Key Manager does not store your data encryption key. To retrieve your key's plaintext, use the `Decrypt` method with your key's ID and ciphertext. + :param key_id: ID of the key. + :param without_plaintext: Default value is `false`, meaning that the plaintext is returned. + Set it to `true` if you do not wish the plaintext to be returned in the response object. + :param region: Region to target. If none is passed will use default region from the config. + :param algorithm: See the `DataKey.Algorithm.SymmetricEncryption` enum for a description of values. + :return: :class:`DataKey ` + + Usage: + :: + + result = api.generate_data_key( + key_id="example", + without_plaintext=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/generate-data-key", + body=marshal_GenerateDataKeyRequest( + GenerateDataKeyRequest( + key_id=key_id, + without_plaintext=without_plaintext, + region=region, + algorithm=algorithm, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DataKey(res.json()) + + def encrypt( + self, + *, + key_id: str, + plaintext: str, + region: Optional[ScwRegion] = None, + associated_data: Optional[str] = None, + ) -> EncryptResponse: + """ + Encrypt a payload. + Encrypt a payload using an existing key, specified by the `key_id` parameter. Only keys with a usage set to `symmetric_encryption` are supported by this method. The maximum payload size that can be encrypted is 64 KB of plaintext. + :param key_id: The key must have an usage set to `symmetric_encryption` or `asymmetric_encryption`. + :param plaintext: Data size must be between 1 and 65535 bytes. + :param region: Region to target. If none is passed will use default region from the config. + :param associated_data: Additional data which will not be encrypted, but authenticated and appended to the encrypted payload. Only supported by keys with a usage set to `symmetric_encryption`. + :return: :class:`EncryptResponse ` + + Usage: + :: + + result = api.encrypt( + key_id="example", + plaintext="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/encrypt", + body=marshal_EncryptRequest( + EncryptRequest( + key_id=key_id, + plaintext=plaintext, + region=region, + associated_data=associated_data, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_EncryptResponse(res.json()) + + def decrypt( + self, + *, + key_id: str, + ciphertext: str, + region: Optional[ScwRegion] = None, + associated_data: Optional[str] = None, + ) -> DecryptResponse: + """ + Decrypt an encrypted payload. + Decrypt an encrypted payload using an existing key, specified by the `key_id` parameter. The maximum payload size that can be decrypted is equivalent to the encrypted output of 64 KB of data (around 131 KB). + :param key_id: The key must have an usage set to `symmetric_encryption` or `asymmetric_encryption`. + :param ciphertext: Data size must be between 1 and 131071 bytes. + :param region: Region to target. If none is passed will use default region from the config. + :param associated_data: The additional data must match the value passed in the encryption request. Only supported by keys with a usage set to `symmetric_encryption`. + :return: :class:`DecryptResponse ` + + Usage: + :: + + result = api.decrypt( + key_id="example", + ciphertext="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/decrypt", + body=marshal_DecryptRequest( + DecryptRequest( + key_id=key_id, + ciphertext=ciphertext, + region=region, + associated_data=associated_data, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DecryptResponse(res.json()) + + def sign( + self, + *, + key_id: str, + digest: str, + region: Optional[ScwRegion] = None, + ) -> SignResponse: + """ + Sign a message digest. + Use a given key to sign a message digest. The key must have its usage set to `asymmetric_signing`. The digest must be created using the same digest algorithm that is defined in the key's algorithm configuration. + :param key_id: ID of the key to use for signing. + :param digest: The digest must be generated using the same algorithm defined in the key’s algorithm settings. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`SignResponse ` + + Usage: + :: + + result = api.sign( + key_id="example", + digest="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/sign", + body=marshal_SignRequest( + SignRequest( + key_id=key_id, + digest=digest, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SignResponse(res.json()) + + def verify( + self, + *, + key_id: str, + digest: str, + signature: str, + region: Optional[ScwRegion] = None, + ) -> VerifyResponse: + """ + Verify a message signature. + Use a given key to verify a message signature against a message digest. The key must have its usage set to `asymmetric_signing`. The message digest must be generated using the same digest algorithm that is defined in the key's algorithm configuration. + :param key_id: ID of the key to use for signature verification. + :param digest: Must be generated using the same algorithm specified in the key’s configuration. + :param signature: The message signature to verify. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`VerifyResponse ` + + Usage: + :: + + result = api.verify( + key_id="example", + digest="example", + signature="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/verify", + body=marshal_VerifyRequest( + VerifyRequest( + key_id=key_id, + digest=digest, + signature=signature, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_VerifyResponse(res.json()) + + def import_key_material( + self, + *, + key_id: str, + key_material: str, + region: Optional[ScwRegion] = None, + salt: Optional[str] = None, + ) -> Key: + """ + Import key material. + Import externally generated key material into Key Manager to derive a new cryptographic key. The key's origin must be `external`. + :param key_id: The key's origin must be `external`. + :param key_material: The key material The key material is a random sequence of bytes used to derive a cryptographic key. + :param region: Region to target. If none is passed will use default region from the config. + :param salt: A salt is random data added to key material to ensure unique derived keys, even if the input is similar. It helps strengthen security when the key material has low randomness (low entropy). + :return: :class:`Key ` + + Usage: + :: + + result = api.import_key_material( + key_id="example", + key_material="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/import-key-material", + body=marshal_ImportKeyMaterialRequest( + ImportKeyMaterialRequest( + key_id=key_id, + key_material=key_material, + region=region, + salt=salt, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Key(res.json()) + + def delete_key_material( + self, + *, + key_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete key material. + Delete previously imported key material. This renders the associated cryptographic key unusable for any operation. The key's origin must be `external`. + :param key_id: ID of the key of which to delete the key material. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_key_material( + key_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_key_id = validate_path_param("key_id", key_id) + + res = self._request( + "POST", + f"/key-manager/v1alpha1/regions/{param_region}/keys/{param_key_id}/delete-key-material", + body={}, + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/key_manager/v1alpha1/marshalling.py b/scaleway/scaleway/key_manager/v1alpha1/marshalling.py new file mode 100644 index 00000000..2f1cab95 --- /dev/null +++ b/scaleway/scaleway/key_manager/v1alpha1/marshalling.py @@ -0,0 +1,503 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + KeyRotationPolicy, + KeyUsage, + Key, + DataKey, + DecryptResponse, + EncryptResponse, + ListKeysResponse, + PublicKey, + SignResponse, + VerifyResponse, + CreateKeyRequest, + DecryptRequest, + EncryptRequest, + GenerateDataKeyRequest, + ImportKeyMaterialRequest, + SignRequest, + UpdateKeyRequest, + VerifyRequest, +) + + +def unmarshal_KeyRotationPolicy(data: Any) -> KeyRotationPolicy: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KeyRotationPolicy' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rotation_period", None) + if field is not None: + args["rotation_period"] = field + else: + args["rotation_period"] = None + + field = data.get("next_rotation_at", None) + if field is not None: + args["next_rotation_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["next_rotation_at"] = None + + return KeyRotationPolicy(**args) + + +def unmarshal_KeyUsage(data: Any) -> KeyUsage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'KeyUsage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("symmetric_encryption", None) + if field is not None: + args["symmetric_encryption"] = field + else: + args["symmetric_encryption"] = None + + field = data.get("asymmetric_encryption", None) + if field is not None: + args["asymmetric_encryption"] = field + else: + args["asymmetric_encryption"] = None + + field = data.get("asymmetric_signing", None) + if field is not None: + args["asymmetric_signing"] = field + else: + args["asymmetric_signing"] = None + + return KeyUsage(**args) + + +def unmarshal_Key(data: Any) -> Key: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Key' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("state", None) + if field is not None: + args["state"] = field + + field = data.get("rotation_count", None) + if field is not None: + args["rotation_count"] = field + + field = data.get("usage", None) + if field is not None: + args["usage"] = unmarshal_KeyUsage(field) + else: + args["usage"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("protected", None) + if field is not None: + args["protected"] = field + + field = data.get("locked", None) + if field is not None: + args["locked"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("origin", None) + if field is not None: + args["origin"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + else: + args["description"] = None + + field = data.get("rotated_at", None) + if field is not None: + args["rotated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["rotated_at"] = None + + field = data.get("rotation_policy", None) + if field is not None: + args["rotation_policy"] = unmarshal_KeyRotationPolicy(field) + else: + args["rotation_policy"] = None + + return Key(**args) + + +def unmarshal_DataKey(data: Any) -> DataKey: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DataKey' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + + field = data.get("algorithm", None) + if field is not None: + args["algorithm"] = field + + field = data.get("ciphertext", None) + if field is not None: + args["ciphertext"] = field + + field = data.get("plaintext", None) + if field is not None: + args["plaintext"] = field + else: + args["plaintext"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + return DataKey(**args) + + +def unmarshal_DecryptResponse(data: Any) -> DecryptResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DecryptResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + + field = data.get("plaintext", None) + if field is not None: + args["plaintext"] = field + + field = data.get("ciphertext", None) + if field is not None: + args["ciphertext"] = field + else: + args["ciphertext"] = None + + return DecryptResponse(**args) + + +def unmarshal_EncryptResponse(data: Any) -> EncryptResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EncryptResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + + field = data.get("ciphertext", None) + if field is not None: + args["ciphertext"] = field + + return EncryptResponse(**args) + + +def unmarshal_ListKeysResponse(data: Any) -> ListKeysResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListKeysResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("keys", None) + if field is not None: + args["keys"] = [unmarshal_Key(v) for v in field] if field is not None else None + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListKeysResponse(**args) + + +def unmarshal_PublicKey(data: Any) -> PublicKey: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicKey' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pem", None) + if field is not None: + args["pem"] = field + + return PublicKey(**args) + + +def unmarshal_SignResponse(data: Any) -> SignResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SignResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + + field = data.get("signature", None) + if field is not None: + args["signature"] = field + + return SignResponse(**args) + + +def unmarshal_VerifyResponse(data: Any) -> VerifyResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'VerifyResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + + field = data.get("valid", None) + if field is not None: + args["valid"] = field + + return VerifyResponse(**args) + + +def marshal_KeyRotationPolicy( + request: KeyRotationPolicy, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.rotation_period is not None: + output["rotation_period"] = request.rotation_period + + if request.next_rotation_at is not None: + output["next_rotation_at"] = request.next_rotation_at.isoformat() + + return output + + +def marshal_KeyUsage( + request: KeyUsage, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("symmetric_encryption", request.symmetric_encryption), + OneOfPossibility( + "asymmetric_encryption", request.asymmetric_encryption + ), + OneOfPossibility("asymmetric_signing", request.asymmetric_signing), + ] + ), + ) + + return output + + +def marshal_CreateKeyRequest( + request: CreateKeyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.unprotected is not None: + output["unprotected"] = request.unprotected + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.name is not None: + output["name"] = request.name + + if request.usage is not None: + output["usage"] = marshal_KeyUsage(request.usage, defaults) + + if request.description is not None: + output["description"] = request.description + + if request.tags is not None: + output["tags"] = request.tags + + if request.rotation_policy is not None: + output["rotation_policy"] = marshal_KeyRotationPolicy( + request.rotation_policy, defaults + ) + + if request.origin is not None: + output["origin"] = str(request.origin) + + return output + + +def marshal_DecryptRequest( + request: DecryptRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ciphertext is not None: + output["ciphertext"] = request.ciphertext + + if request.associated_data is not None: + output["associated_data"] = request.associated_data + + return output + + +def marshal_EncryptRequest( + request: EncryptRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.plaintext is not None: + output["plaintext"] = request.plaintext + + if request.associated_data is not None: + output["associated_data"] = request.associated_data + + return output + + +def marshal_GenerateDataKeyRequest( + request: GenerateDataKeyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.without_plaintext is not None: + output["without_plaintext"] = request.without_plaintext + + if request.algorithm is not None: + output["algorithm"] = str(request.algorithm) + + return output + + +def marshal_ImportKeyMaterialRequest( + request: ImportKeyMaterialRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.key_material is not None: + output["key_material"] = request.key_material + + if request.salt is not None: + output["salt"] = request.salt + + return output + + +def marshal_SignRequest( + request: SignRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.digest is not None: + output["digest"] = request.digest + + return output + + +def marshal_UpdateKeyRequest( + request: UpdateKeyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.description is not None: + output["description"] = request.description + + if request.tags is not None: + output["tags"] = request.tags + + if request.rotation_policy is not None: + output["rotation_policy"] = marshal_KeyRotationPolicy( + request.rotation_policy, defaults + ) + + return output + + +def marshal_VerifyRequest( + request: VerifyRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.digest is not None: + output["digest"] = request.digest + + if request.signature is not None: + output["signature"] = request.signature + + return output diff --git a/scaleway/scaleway/key_manager/v1alpha1/types.py b/scaleway/scaleway/key_manager/v1alpha1/types.py new file mode 100644 index 00000000..aa250709 --- /dev/null +++ b/scaleway/scaleway/key_manager/v1alpha1/types.py @@ -0,0 +1,676 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class DataKeyAlgorithmSymmetricEncryption(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SYMMETRIC_ENCRYPTION = "unknown_symmetric_encryption" + AES_256_GCM = "aes_256_gcm" + + def __str__(self) -> str: + return str(self.value) + + +class KeyAlgorithmAsymmetricEncryption(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ASYMMETRIC_ENCRYPTION = "unknown_asymmetric_encryption" + RSA_OAEP_2048_SHA256 = "rsa_oaep_2048_sha256" + RSA_OAEP_3072_SHA256 = "rsa_oaep_3072_sha256" + RSA_OAEP_4096_SHA256 = "rsa_oaep_4096_sha256" + + def __str__(self) -> str: + return str(self.value) + + +class KeyAlgorithmAsymmetricSigning(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ASYMMETRIC_SIGNING = "unknown_asymmetric_signing" + EC_P256_SHA256 = "ec_p256_sha256" + EC_P384_SHA384 = "ec_p384_sha384" + RSA_PSS_2048_SHA256 = "rsa_pss_2048_sha256" + RSA_PSS_3072_SHA256 = "rsa_pss_3072_sha256" + RSA_PSS_4096_SHA256 = "rsa_pss_4096_sha256" + RSA_PKCS1_2048_SHA256 = "rsa_pkcs1_2048_sha256" + RSA_PKCS1_3072_SHA256 = "rsa_pkcs1_3072_sha256" + RSA_PKCS1_4096_SHA256 = "rsa_pkcs1_4096_sha256" + + def __str__(self) -> str: + return str(self.value) + + +class KeyAlgorithmSymmetricEncryption(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SYMMETRIC_ENCRYPTION = "unknown_symmetric_encryption" + AES_256_GCM = "aes_256_gcm" + + def __str__(self) -> str: + return str(self.value) + + +class KeyOrigin(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ORIGIN = "unknown_origin" + SCALEWAY_KMS = "scaleway_kms" + EXTERNAL = "external" + + def __str__(self) -> str: + return str(self.value) + + +class KeyState(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATE = "unknown_state" + ENABLED = "enabled" + DISABLED = "disabled" + PENDING_KEY_MATERIAL = "pending_key_material" + + def __str__(self) -> str: + return str(self.value) + + +class ListKeysRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + UPDATED_AT_ASC = "updated_at_asc" + UPDATED_AT_DESC = "updated_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListKeysRequestUsage(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_USAGE = "unknown_usage" + SYMMETRIC_ENCRYPTION = "symmetric_encryption" + ASYMMETRIC_ENCRYPTION = "asymmetric_encryption" + ASYMMETRIC_SIGNING = "asymmetric_signing" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class KeyRotationPolicy: + rotation_period: Optional[str] + """ + Time interval between two key rotations. The minimum duration is 24 hours and the maximum duration is 1 year (876000 hours). + """ + + next_rotation_at: Optional[datetime] + """ + Timestamp indicating the next scheduled rotation. + """ + + +@dataclass +class KeyUsage: + symmetric_encryption: Optional[KeyAlgorithmSymmetricEncryption] + + asymmetric_encryption: Optional[KeyAlgorithmAsymmetricEncryption] + + asymmetric_signing: Optional[KeyAlgorithmAsymmetricSigning] + + +@dataclass +class Key: + id: str + """ + ID of the key. + """ + + project_id: str + """ + ID of the Project containing the key. + """ + + name: str + """ + Name of the key. + """ + + state: KeyState + """ + See the `Key.State` enum for a description of possible values. + """ + + rotation_count: int + """ + The rotation count tracks the number of times the key has been rotated. + """ + + usage: Optional[KeyUsage] + """ + Keys with a usage set to `symmetric_encryption` can encrypt and decrypt data using the `AES-256-GCM` key algorithm. Key Manager currently only supports `AES-256-GCM`. + """ + + created_at: Optional[datetime] + """ + Key creation date. + """ + + updated_at: Optional[datetime] + """ + Key last modification date. + """ + + protected: bool + """ + Returns `true` if key protection is applied to the key. + """ + + locked: bool + """ + Returns `true` if the key is locked. + """ + + tags: List[str] + """ + List of the key's tags. + """ + + origin: KeyOrigin + """ + Refer to the `Key.Origin` enum for a description of values. + """ + + region: ScwRegion + """ + Region where the key is stored. + """ + + description: Optional[str] + """ + Description of the key. + """ + + rotated_at: Optional[datetime] + """ + Key last rotation date. + """ + + rotation_policy: Optional[KeyRotationPolicy] + """ + Key rotation policy. + """ + + +@dataclass +class CreateKeyRequest: + unprotected: bool + """ + Default value is `false`. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project containing the key. + """ + + name: Optional[str] + """ + (Optional) Name of the key. + """ + + usage: Optional[KeyUsage] + """ + See the `Key.Algorithm.SymmetricEncryption` enum for a description of values. + """ + + description: Optional[str] + """ + (Optional) Description of the key. + """ + + tags: Optional[List[str]] + """ + (Optional) List of the key's tags. + """ + + rotation_policy: Optional[KeyRotationPolicy] + """ + If not specified, no rotation policy will be applied to the key. + """ + + origin: Optional[KeyOrigin] + """ + Refer to the `Key.Origin` enum for a description of values. + """ + + +@dataclass +class DataKey: + key_id: str + """ + ID of the data encryption key. + """ + + algorithm: DataKeyAlgorithmSymmetricEncryption + """ + Symmetric encryption algorithm of the data encryption key (`AES-256-GCM`). + """ + + ciphertext: str + """ + Your data encryption key's ciphertext can be stored safely. It can only be decrypted through the keys you create in Key Manager, using the relevant key ID. + """ + + plaintext: Optional[str] + """ + (Optional) Your data encryption key's plaintext allows you to use the key immediately upon creation. It must neither be stored or shared. + """ + + created_at: Optional[datetime] + """ + Data encryption key creation date. + """ + + +@dataclass +class DecryptRequest: + key_id: str + """ + The key must have an usage set to `symmetric_encryption` or `asymmetric_encryption`. + """ + + ciphertext: str + """ + Data size must be between 1 and 131071 bytes. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + associated_data: Optional[str] + """ + The additional data must match the value passed in the encryption request. Only supported by keys with a usage set to `symmetric_encryption`. + """ + + +@dataclass +class DecryptResponse: + key_id: str + """ + ID of the key used for decryption. + """ + + plaintext: str + """ + Key's decrypted data. + """ + + ciphertext: Optional[str] + """ + If the data was already encrypted with the latest key rotation, no output will be returned in the response object. + """ + + +@dataclass +class DeleteKeyMaterialRequest: + key_id: str + """ + ID of the key of which to delete the key material. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteKeyRequest: + key_id: str + """ + ID of the key to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DisableKeyRequest: + key_id: str + """ + ID of the key to disable. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class EnableKeyRequest: + key_id: str + """ + ID of the key to enable. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class EncryptRequest: + key_id: str + """ + The key must have an usage set to `symmetric_encryption` or `asymmetric_encryption`. + """ + + plaintext: str + """ + Data size must be between 1 and 65535 bytes. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + associated_data: Optional[str] + """ + Additional data which will not be encrypted, but authenticated and appended to the encrypted payload. Only supported by keys with a usage set to `symmetric_encryption`. + """ + + +@dataclass +class EncryptResponse: + key_id: str + """ + ID of the key used for encryption. + """ + + ciphertext: str + """ + Key's encrypted data. + """ + + +@dataclass +class GenerateDataKeyRequest: + key_id: str + """ + ID of the key. + """ + + without_plaintext: bool + """ + Default value is `false`, meaning that the plaintext is returned. +Set it to `true` if you do not wish the plaintext to be returned in the response object. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + algorithm: Optional[DataKeyAlgorithmSymmetricEncryption] + """ + See the `DataKey.Algorithm.SymmetricEncryption` enum for a description of values. + """ + + +@dataclass +class GetKeyRequest: + key_id: str + """ + ID of the key to target. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetPublicKeyRequest: + key_id: str + """ + ID of the key. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ImportKeyMaterialRequest: + key_id: str + """ + The key's origin must be `external`. + """ + + key_material: str + """ + The key material The key material is a random sequence of bytes used to derive a cryptographic key. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + salt: Optional[str] + """ + A salt is random data added to key material to ensure unique derived keys, even if the input is similar. It helps strengthen security when the key material has low randomness (low entropy). + """ + + +@dataclass +class ListKeysRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + organization_id: Optional[str] + """ + (Optional) Filter by Organization ID. + """ + + project_id: Optional[str] + """ + (Optional) Filter by Project ID. + """ + + order_by: Optional[ListKeysRequestOrderBy] + + page: Optional[int] + + page_size: Optional[int] + + tags: Optional[List[str]] + """ + (Optional) List of tags to filter on. + """ + + name: Optional[str] + """ + (Optional) Filter by key name. + """ + + usage: Optional[ListKeysRequestUsage] + """ + Select from symmetric encryption, asymmetric encryption, or asymmetric signing. + """ + + +@dataclass +class ListKeysResponse: + keys: List[Key] + """ + Single page of keys matching the requested criteria. + """ + + total_count: int + """ + Total count of keys matching the requested criteria. + """ + + +@dataclass +class ProtectKeyRequest: + key_id: str + """ + ID of the key to apply key protection to. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class PublicKey: + pem: str + + +@dataclass +class RotateKeyRequest: + key_id: str + """ + ID of the key to rotate. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SignRequest: + key_id: str + """ + ID of the key to use for signing. + """ + + digest: str + """ + The digest must be generated using the same algorithm defined in the key’s algorithm settings. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SignResponse: + key_id: str + """ + ID of the key used to generate the signature. + """ + + signature: str + """ + The message signature. + """ + + +@dataclass +class UnprotectKeyRequest: + key_id: str + """ + ID of the key to remove key protection from. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class UpdateKeyRequest: + key_id: str + """ + ID of the key to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + (Optional) Updated name of the key. + """ + + description: Optional[str] + """ + (Optional) Updated description of the key. + """ + + tags: Optional[List[str]] + """ + (Optional) Updated list of the key's tags. + """ + + rotation_policy: Optional[KeyRotationPolicy] + """ + If not specified, the key's existing rotation policy applies. + """ + + +@dataclass +class VerifyRequest: + key_id: str + """ + ID of the key to use for signature verification. + """ + + digest: str + """ + Must be generated using the same algorithm specified in the key’s configuration. + """ + + signature: str + """ + The message signature to verify. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class VerifyResponse: + key_id: str + """ + ID of the key used for verification. + """ + + valid: bool + """ + Returns `true` if the signature is valid for the digest and key, `false` otherwise. + """ diff --git a/scaleway/scaleway/lb/v1/api.py b/scaleway/scaleway/lb/v1/api.py index e1b1902a..636eb949 100644 --- a/scaleway/scaleway/lb/v1/api.py +++ b/scaleway/scaleway/lb/v1/api.py @@ -5,8 +5,8 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, - Zone, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, @@ -107,6 +107,7 @@ ZonedApiCreateLbRequest, ZonedApiCreateRouteRequest, ZonedApiCreateSubscriberRequest, + ZonedApiDetachPrivateNetworkRequest, ZonedApiMigrateLbRequest, ZonedApiRemoveBackendServersRequest, ZonedApiSetAclsRequest, @@ -183,6 +184,7 @@ marshal_ZonedApiCreateLbRequest, marshal_ZonedApiCreateRouteRequest, marshal_ZonedApiCreateSubscriberRequest, + marshal_ZonedApiDetachPrivateNetworkRequest, marshal_ZonedApiMigrateLbRequest, marshal_ZonedApiRemoveBackendServersRequest, marshal_ZonedApiSetAclsRequest, @@ -208,7 +210,7 @@ class LbV1ZonedAPI(API): def list_lbs( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListLbsRequestOrderBy] = None, page_size: Optional[int] = None, @@ -259,7 +261,7 @@ def list_lbs( def list_lbs_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListLbsRequestOrderBy] = None, page_size: Optional[int] = None, @@ -308,7 +310,7 @@ def create_lb( *, description: str, type_: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, name: Optional[str] = None, @@ -331,7 +333,7 @@ def create_lb( One-Of ('project_identifier'): at most one of 'project_id', 'organization_id' could be set. :param name: Name for the Load Balancer. :param ip_id: ID of an existing flexible IP address to attach to the Load Balancer. - :param assign_flexible_ip: Defines whether to automatically assign a flexible public IP to lb. Default value is `false` (do not assign). + :param assign_flexible_ip: Defines whether to automatically assign a flexible public IP to the Load Balancer. Default value is `true` (assign). :param assign_flexible_ipv6: Defines whether to automatically assign a flexible public IPv6 to the Load Balancer. Default value is `false` (do not assign). :param ip_ids: List of IP IDs to attach to the Load Balancer. :param tags: List of tags for the Load Balancer. @@ -378,7 +380,7 @@ def get_lb( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Lb: """ Get a Load Balancer. @@ -410,7 +412,7 @@ def wait_for_lb( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Lb, bool]] = None, ) -> Lb: """ @@ -449,7 +451,7 @@ def update_lb( lb_id: str, name: str, description: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, ssl_compatibility_level: Optional[SSLCompatibilityLevel] = None, ) -> Lb: @@ -501,7 +503,7 @@ def delete_lb( *, lb_id: str, release_ip: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a Load Balancer. @@ -537,7 +539,7 @@ def migrate_lb( *, lb_id: str, type_: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Lb: """ Migrate a Load Balancer. @@ -578,13 +580,14 @@ def migrate_lb( def list_i_ps( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ip_address: Optional[str] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, ip_type: Optional[ListIpsRequestIpType] = None, + tags: Optional[List[str]] = None, ) -> ListIpsResponse: """ List IP addresses. @@ -596,6 +599,7 @@ def list_i_ps( :param organization_id: Organization ID to filter for, only Load Balancer IP addresses from this Organization will be returned. :param project_id: Project ID to filter for, only Load Balancer IP addresses from this Project will be returned. :param ip_type: IP type to filter for. + :param tags: Tag to filter for, only IPs with one or more matching tags will be returned. :return: :class:`ListIpsResponse ` Usage: @@ -617,6 +621,7 @@ def list_i_ps( "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, + "tags": tags, }, ) @@ -626,13 +631,14 @@ def list_i_ps( def list_i_ps_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ip_address: Optional[str] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, ip_type: Optional[ListIpsRequestIpType] = None, + tags: Optional[List[str]] = None, ) -> List[Ip]: """ List IP addresses. @@ -644,6 +650,7 @@ def list_i_ps_all( :param organization_id: Organization ID to filter for, only Load Balancer IP addresses from this Organization will be returned. :param project_id: Project ID to filter for, only Load Balancer IP addresses from this Project will be returned. :param ip_type: IP type to filter for. + :param tags: Tag to filter for, only IPs with one or more matching tags will be returned. :return: :class:`List[Ip] ` Usage: @@ -664,6 +671,7 @@ def list_i_ps_all( "organization_id": organization_id, "project_id": project_id, "ip_type": ip_type, + "tags": tags, }, ) @@ -671,10 +679,11 @@ def create_ip( self, *, is_ipv6: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, reverse: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> Ip: """ Create an IP address. @@ -686,6 +695,7 @@ def create_ip( :param project_id: Project ID of the Project where the IP address should be created. One-Of ('project_identifier'): at most one of 'project_id', 'organization_id' could be set. :param reverse: Reverse DNS (domain name) for the IP address. + :param tags: List of tags for the IP. :return: :class:`Ip ` Usage: @@ -706,6 +716,7 @@ def create_ip( is_ipv6=is_ipv6, zone=zone, reverse=reverse, + tags=tags, project_id=project_id, organization_id=organization_id, ), @@ -720,7 +731,7 @@ def get_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Ip: """ Get an IP address. @@ -752,7 +763,7 @@ def release_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an IP address. @@ -782,9 +793,10 @@ def update_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, reverse: Optional[str] = None, lb_id: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> Ip: """ Update an IP address. @@ -793,6 +805,7 @@ def update_ip( :param zone: Zone to target. If none is passed will use default zone from the config. :param reverse: Reverse DNS (domain name) for the IP address. :param lb_id: ID of the server on which to attach the flexible IP. + :param tags: List of tags for the IP. :return: :class:`Ip ` Usage: @@ -815,6 +828,7 @@ def update_ip( zone=zone, reverse=reverse, lb_id=lb_id, + tags=tags, ), self.client, ), @@ -827,7 +841,7 @@ def list_backends( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListBackendsRequestOrderBy] = None, page: Optional[int] = None, @@ -873,7 +887,7 @@ def list_backends_all( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListBackendsRequestOrderBy] = None, page: Optional[int] = None, @@ -923,7 +937,7 @@ def create_backend( lb_id: str, health_check: HealthCheck, server_ip: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, send_proxy_v2: Optional[bool] = None, timeout_server: Optional[str] = None, @@ -958,7 +972,7 @@ def create_backend( :param timeout_tunnel: Maximum allowed tunnel inactivity time after Websocket is established (takes precedence over client and server timeout). :param on_marked_down_action: Action to take when a backend server is marked as down. :param proxy_protocol: Protocol to use between the Load Balancer and backend servers. Allows the backend servers to be informed of the client's real IP address. The PROXY protocol must be supported by the backend servers' software. - :param failover_host: Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + :param failover_host: Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. :param ssl_bridging: Defines whether to enable SSL bridging between the Load Balancer and backend servers. :param ignore_ssl_server_verify: Defines whether the server certificate verification should be ignored. :param redispatch_attempt_count: Whether to use another backend server on each attempt. @@ -1025,7 +1039,7 @@ def get_backend( self, *, backend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Backend: """ Get a backend of a given Load Balancer. @@ -1063,7 +1077,7 @@ def update_backend( forward_port_algorithm: ForwardPortAlgorithm, sticky_sessions: StickySessionsType, sticky_sessions_cookie_name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, send_proxy_v2: Optional[bool] = None, timeout_server: Optional[str] = None, timeout_connect: Optional[str] = None, @@ -1095,7 +1109,7 @@ def update_backend( :param timeout_tunnel: Maximum allowed tunnel inactivity time after Websocket is established (takes precedence over client and server timeout). :param on_marked_down_action: Action to take when a backend server is marked as down. :param proxy_protocol: Protocol to use between the Load Balancer and backend servers. Allows the backend servers to be informed of the client's real IP address. The PROXY protocol must be supported by the backend servers' software. - :param failover_host: Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + :param failover_host: Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. :param ssl_bridging: Defines whether to enable SSL bridging between the Load Balancer and backend servers. :param ignore_ssl_server_verify: Defines whether the server certificate verification should be ignored. :param redispatch_attempt_count: Whether to use another backend server on each attempt. @@ -1159,7 +1173,7 @@ def delete_backend( self, *, backend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a backend of a given Load Balancer. @@ -1190,7 +1204,7 @@ def add_backend_servers( *, backend_id: str, server_ip: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Backend: """ Add a set of backend servers to a given backend. @@ -1233,7 +1247,7 @@ def remove_backend_servers( *, backend_id: str, server_ip: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Backend: """ Remove a set of servers for a given backend. @@ -1276,7 +1290,7 @@ def set_backend_servers( *, backend_id: str, server_ip: List[str], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Backend: """ Define all backend servers for a given backend. @@ -1320,7 +1334,7 @@ def update_health_check( port: int, check_max_retries: int, backend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, check_delay: Optional[str] = None, check_timeout: Optional[str] = None, check_send_proxy: bool, @@ -1345,7 +1359,7 @@ def update_health_check( :param check_send_proxy: Defines whether proxy protocol should be activated for the health check. :param tcp_config: Object to configure a basic TCP health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. - :param mysql_config: Object to configure a MySQL health check. The check requires MySQL >=3.22, for older versions, use a TCP health check. + :param mysql_config: Object to configure a MySQL health check. The check requires MySQL >=3.22 or <9.0. For older or newer versions, use a TCP health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. :param pgsql_config: Object to configure a PostgreSQL health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. @@ -1406,7 +1420,7 @@ def list_frontends( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListFrontendsRequestOrderBy] = None, page: Optional[int] = None, @@ -1452,7 +1466,7 @@ def list_frontends_all( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, order_by: Optional[ListFrontendsRequestOrderBy] = None, page: Optional[int] = None, @@ -1498,11 +1512,12 @@ def create_frontend( lb_id: str, backend_id: str, enable_http3: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Create a frontend in a given Load Balancer. @@ -1516,6 +1531,7 @@ def create_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -1546,6 +1562,7 @@ def create_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -1558,7 +1575,7 @@ def get_frontend( self, *, frontend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Frontend: """ Get a frontend. @@ -1594,10 +1611,11 @@ def update_frontend( inbound_port: int, backend_id: str, enable_http3: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Update a frontend. @@ -1611,6 +1629,7 @@ def update_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -1642,6 +1661,7 @@ def update_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -1654,7 +1674,7 @@ def delete_frontend( self, *, frontend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a frontend. @@ -1683,7 +1703,7 @@ def delete_frontend( def list_routes( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -1724,7 +1744,7 @@ def list_routes( def list_routes_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -1764,7 +1784,7 @@ def create_route( *, frontend_id: str, backend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, match: Optional[RouteMatch] = None, ) -> Route: """ @@ -1808,7 +1828,7 @@ def get_route( self, *, route_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Route: """ Get a route. @@ -1841,7 +1861,7 @@ def update_route( *, route_id: str, backend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, match: Optional[RouteMatch] = None, ) -> Route: """ @@ -1886,7 +1906,7 @@ def delete_route( self, *, route_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a route. @@ -1916,7 +1936,7 @@ def get_lb_stats( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, backend_id: Optional[str] = None, ) -> LbStats: """ @@ -1953,7 +1973,7 @@ def list_backend_stats( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, backend_id: Optional[str] = None, @@ -1996,7 +2016,7 @@ def list_backend_stats_all( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, backend_id: Optional[str] = None, @@ -2036,7 +2056,7 @@ def list_acls( self, *, frontend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListAclRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2082,7 +2102,7 @@ def list_acls_all( self, *, frontend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListAclRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2128,7 +2148,7 @@ def create_acl( action: AclAction, index: int, description: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, match: Optional[AclMatch] = None, ) -> Acl: @@ -2182,7 +2202,7 @@ def get_acl( self, *, acl_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Acl: """ Get an ACL. @@ -2217,7 +2237,7 @@ def update_acl( name: str, action: AclAction, index: int, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, match: Optional[AclMatch] = None, description: Optional[str] = None, ) -> Acl: @@ -2271,7 +2291,7 @@ def delete_acl( self, *, acl_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an ACL. @@ -2302,7 +2322,7 @@ def set_acls( *, acls: List[AclSpec], frontend_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetAclsResponse: """ Define all ACLs for a given frontend. @@ -2344,7 +2364,7 @@ def create_certificate( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, letsencrypt: Optional[CreateCertificateRequestLetsencryptConfig] = None, custom_certificate: Optional[CreateCertificateRequestCustomCertificate] = None, @@ -2394,7 +2414,7 @@ def list_certificates( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListCertificatesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2440,7 +2460,7 @@ def list_certificates_all( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListCertificatesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2483,7 +2503,7 @@ def get_certificate( self, *, certificate_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Certificate: """ Get an SSL/TLS certificate. @@ -2515,7 +2535,7 @@ def wait_for_certificate( self, *, certificate_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Certificate, bool]] = None, ) -> Certificate: """ @@ -2553,7 +2573,7 @@ def update_certificate( *, certificate_id: str, name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Certificate: """ Update an SSL/TLS certificate. @@ -2595,7 +2615,7 @@ def delete_certificate( self, *, certificate_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an SSL/TLS certificate. @@ -2624,7 +2644,7 @@ def delete_certificate( def list_lb_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListLbTypesResponse: @@ -2659,7 +2679,7 @@ def list_lb_types( def list_lb_types_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[LbType]: @@ -2692,7 +2712,7 @@ def create_subscriber( self, *, name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, email_config: Optional[SubscriberEmailConfig] = None, webhook_config: Optional[SubscriberWebhookConfig] = None, organization_id: Optional[str] = None, @@ -2746,7 +2766,7 @@ def get_subscriber( self, *, subscriber_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Subscriber: """ Get a subscriber. @@ -2777,7 +2797,7 @@ def get_subscriber( def list_subscriber( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListSubscriberRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2825,7 +2845,7 @@ def list_subscriber( def list_subscriber_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListSubscriberRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2871,7 +2891,7 @@ def update_subscriber( *, subscriber_id: str, name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, email_config: Optional[SubscriberEmailConfig] = None, webhook_config: Optional[SubscriberWebhookConfig] = None, ) -> Subscriber: @@ -2921,7 +2941,7 @@ def delete_subscriber( self, *, subscriber_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a subscriber. @@ -2952,7 +2972,7 @@ def subscribe_to_lb( *, lb_id: str, subscriber_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Lb: """ Subscribe a subscriber to alerts for a given Load Balancer. @@ -2994,7 +3014,7 @@ def unsubscribe_from_lb( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Lb: """ Unsubscribe a subscriber from alerts for a given Load Balancer. @@ -3026,7 +3046,7 @@ def list_lb_private_networks( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -3069,7 +3089,7 @@ def list_lb_private_networks_all( self, *, lb_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -3110,10 +3130,11 @@ def attach_private_network( *, lb_id: str, private_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, static_config: Optional[PrivateNetworkStaticConfig] = None, dhcp_config: Optional[PrivateNetworkDHCPConfig] = None, ipam_config: Optional[PrivateNetworkIpamConfig] = None, + ipam_ids: Optional[List[str]] = None, ) -> PrivateNetwork: """ Attach a Load Balancer to a Private Network. @@ -3127,6 +3148,7 @@ def attach_private_network( One-Of ('config'): at most one of 'static_config', 'dhcp_config', 'ipam_config' could be set. :param ipam_config: For internal use only. One-Of ('config'): at most one of 'static_config', 'dhcp_config', 'ipam_config' could be set. + :param ipam_ids: IPAM ID of a pre-reserved IP address to assign to the Load Balancer on this Private Network. In the future, it will be possible to specify multiple IPs in this field (IPv4 and IPv6), for now only one ID of an IPv4 address is expected. When null, a new private IP address is created for the Load Balancer on this Private Network. :return: :class:`PrivateNetwork ` Usage: @@ -3140,18 +3162,16 @@ def attach_private_network( param_zone = validate_path_param("zone", zone or self.client.default_zone) param_lb_id = validate_path_param("lb_id", lb_id) - param_private_network_id = validate_path_param( - "private_network_id", private_network_id - ) res = self._request( "POST", - f"/lb/v1/zones/{param_zone}/lbs/{param_lb_id}/private-networks/{param_private_network_id}/attach", + f"/lb/v1/zones/{param_zone}/lbs/{param_lb_id}/attach-private-network", body=marshal_ZonedApiAttachPrivateNetworkRequest( ZonedApiAttachPrivateNetworkRequest( lb_id=lb_id, private_network_id=private_network_id, zone=zone, + ipam_ids=ipam_ids, static_config=static_config, dhcp_config=dhcp_config, ipam_config=ipam_config, @@ -3168,7 +3188,7 @@ def detach_private_network( *, lb_id: str, private_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Detach Load Balancer from Private Network. @@ -3188,14 +3208,18 @@ def detach_private_network( param_zone = validate_path_param("zone", zone or self.client.default_zone) param_lb_id = validate_path_param("lb_id", lb_id) - param_private_network_id = validate_path_param( - "private_network_id", private_network_id - ) res = self._request( "POST", - f"/lb/v1/zones/{param_zone}/lbs/{param_lb_id}/private-networks/{param_private_network_id}/detach", - body={}, + f"/lb/v1/zones/{param_zone}/lbs/{param_lb_id}/detach-private-network", + body=marshal_ZonedApiDetachPrivateNetworkRequest( + ZonedApiDetachPrivateNetworkRequest( + lb_id=lb_id, + private_network_id=private_network_id, + zone=zone, + ), + self.client, + ), ) self._throw_on_error(res) @@ -3203,13 +3227,13 @@ def detach_private_network( class LbV1API(API): """ - This API allows you to manage your load balancer service. + This API allows you to manage your Load Balancers. """ def list_lbs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListLbsRequestOrderBy] = None, page_size: Optional[int] = None, @@ -3261,7 +3285,7 @@ def list_lbs( def list_lbs_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListLbsRequestOrderBy] = None, page_size: Optional[int] = None, @@ -3309,7 +3333,7 @@ def create_lb( *, description: str, type_: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, name: Optional[str] = None, @@ -3331,7 +3355,7 @@ def create_lb( One-Of ('project_identifier'): at most one of 'project_id', 'organization_id' could be set. :param name: Name for the Load Balancer. :param ip_id: ID of an existing flexible IP address to attach to the Load Balancer. - :param assign_flexible_ip: Defines whether to automatically assign a flexible public IP to lb. Default value is `false` (do not assign). + :param assign_flexible_ip: Defines whether to automatically assign a flexible public IP to the Load Balancer. Default value is `true` (assign). :param assign_flexible_ipv6: Defines whether to automatically assign a flexible public IPv6 to the Load Balancer. Default value is `false` (do not assign). :param ip_ids: List of IP IDs to attach to the Load Balancer. :param tags: List of tags for the Load Balancer. @@ -3380,7 +3404,7 @@ def get_lb( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Lb: """ Get a load balancer. @@ -3413,7 +3437,7 @@ def wait_for_lb( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Lb, bool]] = None, ) -> Lb: """ @@ -3451,7 +3475,7 @@ def update_lb( lb_id: str, name: str, description: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, tags: Optional[List[str]] = None, ssl_compatibility_level: Optional[SSLCompatibilityLevel] = None, ) -> Lb: @@ -3504,7 +3528,7 @@ def delete_lb( *, lb_id: str, release_ip: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a load balancer. @@ -3541,7 +3565,7 @@ def migrate_lb( *, lb_id: str, type_: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Lb: """ Migrate a load balancer. @@ -3583,13 +3607,14 @@ def migrate_lb( def list_i_ps( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ip_address: Optional[str] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, ip_type: Optional[ListIpsRequestIpType] = None, + tags: Optional[List[str]] = None, ) -> ListIpsResponse: """ List IPs. @@ -3600,6 +3625,7 @@ def list_i_ps( :param organization_id: Organization ID to filter for, only Load Balancer IP addresses from this Organization will be returned. :param project_id: Project ID to filter for, only Load Balancer IP addresses from this Project will be returned. :param ip_type: IP type to filter for. + :param tags: Tag to filter for, only IPs with one or more matching tags will be returned. :return: :class:`ListIpsResponse ` Usage: @@ -3623,6 +3649,7 @@ def list_i_ps( "page": page, "page_size": page_size or self.client.default_page_size, "project_id": project_id or self.client.default_project_id, + "tags": tags, }, ) @@ -3632,13 +3659,14 @@ def list_i_ps( def list_i_ps_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ip_address: Optional[str] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, ip_type: Optional[ListIpsRequestIpType] = None, + tags: Optional[List[str]] = None, ) -> List[Ip]: """ List IPs. @@ -3649,6 +3677,7 @@ def list_i_ps_all( :param organization_id: Organization ID to filter for, only Load Balancer IP addresses from this Organization will be returned. :param project_id: Project ID to filter for, only Load Balancer IP addresses from this Project will be returned. :param ip_type: IP type to filter for. + :param tags: Tag to filter for, only IPs with one or more matching tags will be returned. :return: :class:`List[Ip] ` Usage: @@ -3669,6 +3698,7 @@ def list_i_ps_all( "organization_id": organization_id, "project_id": project_id, "ip_type": ip_type, + "tags": tags, }, ) @@ -3676,10 +3706,11 @@ def create_ip( self, *, is_ipv6: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, reverse: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> Ip: """ Create an IP. @@ -3690,6 +3721,7 @@ def create_ip( :param project_id: Project ID of the Project where the IP address should be created. One-Of ('project_identifier'): at most one of 'project_id', 'organization_id' could be set. :param reverse: Reverse DNS (domain name) for the IP address. + :param tags: List of tags for the IP. :return: :class:`Ip ` Usage: @@ -3712,6 +3744,7 @@ def create_ip( is_ipv6=is_ipv6, region=region, reverse=reverse, + tags=tags, project_id=project_id, organization_id=organization_id, ), @@ -3726,7 +3759,7 @@ def get_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Ip: """ Get an IP. @@ -3759,7 +3792,7 @@ def release_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete an IP. @@ -3790,9 +3823,10 @@ def update_ip( self, *, ip_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, reverse: Optional[str] = None, lb_id: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> Ip: """ Update an IP. @@ -3800,6 +3834,7 @@ def update_ip( :param region: Region to target. If none is passed will use default region from the config. :param reverse: Reverse DNS (domain name) for the IP address. :param lb_id: ID of the server on which to attach the flexible IP. + :param tags: List of tags for the IP. :return: :class:`Ip ` Usage: @@ -3824,6 +3859,7 @@ def update_ip( region=region, reverse=reverse, lb_id=lb_id, + tags=tags, ), self.client, ), @@ -3836,7 +3872,7 @@ def list_backends( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListBackendsRequestOrderBy] = None, page: Optional[int] = None, @@ -3883,7 +3919,7 @@ def list_backends_all( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListBackendsRequestOrderBy] = None, page: Optional[int] = None, @@ -3932,7 +3968,7 @@ def create_backend( lb_id: str, health_check: HealthCheck, server_ip: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, send_proxy_v2: Optional[bool] = None, timeout_server: Optional[str] = None, @@ -3966,7 +4002,7 @@ def create_backend( :param timeout_tunnel: Maximum allowed tunnel inactivity time after Websocket is established (takes precedence over client and server timeout). :param on_marked_down_action: Action to take when a backend server is marked as down. :param proxy_protocol: Protocol to use between the Load Balancer and backend servers. Allows the backend servers to be informed of the client's real IP address. The PROXY protocol must be supported by the backend servers' software. - :param failover_host: Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + :param failover_host: Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. :param ssl_bridging: Defines whether to enable SSL bridging between the Load Balancer and backend servers. :param ignore_ssl_server_verify: Defines whether the server certificate verification should be ignored. :param redispatch_attempt_count: Whether to use another backend server on each attempt. @@ -4035,7 +4071,7 @@ def get_backend( self, *, backend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Backend: """ Get a backend in a given load balancer. @@ -4074,7 +4110,7 @@ def update_backend( forward_port_algorithm: ForwardPortAlgorithm, sticky_sessions: StickySessionsType, sticky_sessions_cookie_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, send_proxy_v2: Optional[bool] = None, timeout_server: Optional[str] = None, timeout_connect: Optional[str] = None, @@ -4105,7 +4141,7 @@ def update_backend( :param timeout_tunnel: Maximum allowed tunnel inactivity time after Websocket is established (takes precedence over client and server timeout). :param on_marked_down_action: Action to take when a backend server is marked as down. :param proxy_protocol: Protocol to use between the Load Balancer and backend servers. Allows the backend servers to be informed of the client's real IP address. The PROXY protocol must be supported by the backend servers' software. - :param failover_host: Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + :param failover_host: Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. :param ssl_bridging: Defines whether to enable SSL bridging between the Load Balancer and backend servers. :param ignore_ssl_server_verify: Defines whether the server certificate verification should be ignored. :param redispatch_attempt_count: Whether to use another backend server on each attempt. @@ -4171,7 +4207,7 @@ def delete_backend( self, *, backend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a backend in a given load balancer. @@ -4203,7 +4239,7 @@ def add_backend_servers( *, backend_id: str, server_ip: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Backend: """ Add a set of servers in a given backend. @@ -4247,7 +4283,7 @@ def remove_backend_servers( *, backend_id: str, server_ip: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Backend: """ Remove a set of servers for a given backend. @@ -4291,7 +4327,7 @@ def set_backend_servers( *, backend_id: str, server_ip: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Backend: """ Define all servers in a given backend. @@ -4336,7 +4372,7 @@ def update_health_check( port: int, check_max_retries: int, backend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, check_delay: Optional[str] = None, check_timeout: Optional[str] = None, check_send_proxy: bool, @@ -4360,7 +4396,7 @@ def update_health_check( :param check_send_proxy: Defines whether proxy protocol should be activated for the health check. :param tcp_config: Object to configure a basic TCP health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. - :param mysql_config: Object to configure a MySQL health check. The check requires MySQL >=3.22, for older versions, use a TCP health check. + :param mysql_config: Object to configure a MySQL health check. The check requires MySQL >=3.22 or <9.0. For older or newer versions, use a TCP health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. :param pgsql_config: Object to configure a PostgreSQL health check. One-Of ('config'): at most one of 'tcp_config', 'mysql_config', 'pgsql_config', 'ldap_config', 'redis_config', 'http_config', 'https_config' could be set. @@ -4423,7 +4459,7 @@ def list_frontends( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListFrontendsRequestOrderBy] = None, page: Optional[int] = None, @@ -4470,7 +4506,7 @@ def list_frontends_all( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListFrontendsRequestOrderBy] = None, page: Optional[int] = None, @@ -4515,11 +4551,12 @@ def create_frontend( lb_id: str, backend_id: str, enable_http3: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Create a frontend in a given load balancer. @@ -4532,6 +4569,7 @@ def create_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -4564,6 +4602,7 @@ def create_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -4576,7 +4615,7 @@ def get_frontend( self, *, frontend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Frontend: """ Get a frontend. @@ -4613,10 +4652,11 @@ def update_frontend( inbound_port: int, backend_id: str, enable_http3: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, timeout_client: Optional[str] = None, certificate_id: Optional[str] = None, certificate_ids: Optional[List[str]] = None, + connection_rate_limit: Optional[int] = None, ) -> Frontend: """ Update a frontend. @@ -4629,6 +4669,7 @@ def update_frontend( :param timeout_client: Maximum allowed inactivity time on the client side. :param certificate_id: Certificate ID, deprecated in favor of certificate_ids array. :param certificate_ids: List of SSL/TLS certificate IDs to bind to the frontend. + :param connection_rate_limit: Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. :return: :class:`Frontend ` Usage: @@ -4662,6 +4703,7 @@ def update_frontend( timeout_client=timeout_client, certificate_id=certificate_id, certificate_ids=certificate_ids, + connection_rate_limit=connection_rate_limit, ), self.client, ), @@ -4674,7 +4716,7 @@ def delete_frontend( self, *, frontend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a frontend. @@ -4704,7 +4746,7 @@ def delete_frontend( def list_routes( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -4746,7 +4788,7 @@ def list_routes( def list_routes_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListRoutesRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -4785,7 +4827,7 @@ def create_route( *, frontend_id: str, backend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, match: Optional[RouteMatch] = None, ) -> Route: """ @@ -4830,7 +4872,7 @@ def get_route( self, *, route_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Route: """ Get single backend redirection. @@ -4864,7 +4906,7 @@ def update_route( *, route_id: str, backend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, match: Optional[RouteMatch] = None, ) -> Route: """ @@ -4910,7 +4952,7 @@ def delete_route( self, *, route_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a backend redirection. @@ -4941,7 +4983,7 @@ def get_lb_stats( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, backend_id: Optional[str] = None, ) -> LbStats: """ @@ -4980,7 +5022,7 @@ def list_backend_stats( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, backend_id: Optional[str] = None, @@ -5024,7 +5066,7 @@ def list_backend_stats_all( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, backend_id: Optional[str] = None, @@ -5063,7 +5105,7 @@ def list_acls( self, *, frontend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListAclRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5110,7 +5152,7 @@ def list_acls_all( self, *, frontend_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListAclRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5155,7 +5197,7 @@ def create_acl( action: AclAction, index: int, description: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, match: Optional[AclMatch] = None, ) -> Acl: @@ -5210,7 +5252,7 @@ def get_acl( self, *, acl_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Acl: """ Get an ACL. @@ -5246,7 +5288,7 @@ def update_acl( name: str, action: AclAction, index: int, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, match: Optional[AclMatch] = None, description: Optional[str] = None, ) -> Acl: @@ -5301,7 +5343,7 @@ def delete_acl( self, *, acl_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete an ACL. @@ -5332,7 +5374,7 @@ def create_certificate( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, letsencrypt: Optional[CreateCertificateRequestLetsencryptConfig] = None, custom_certificate: Optional[CreateCertificateRequestCustomCertificate] = None, @@ -5384,7 +5426,7 @@ def list_certificates( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListCertificatesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5431,7 +5473,7 @@ def list_certificates_all( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListCertificatesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5473,7 +5515,7 @@ def get_certificate( self, *, certificate_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Certificate: """ Get a TLS certificate. @@ -5506,7 +5548,7 @@ def wait_for_certificate( self, *, certificate_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Certificate, bool]] = None, ) -> Certificate: """ @@ -5543,7 +5585,7 @@ def update_certificate( *, certificate_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Certificate: """ Update a TLS certificate. @@ -5586,7 +5628,7 @@ def delete_certificate( self, *, certificate_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a TLS certificate. @@ -5616,7 +5658,7 @@ def delete_certificate( def list_lb_types( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListLbTypesResponse: @@ -5652,7 +5694,7 @@ def list_lb_types( def list_lb_types_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[LbType]: @@ -5684,7 +5726,7 @@ def create_subscriber( self, *, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, email_config: Optional[SubscriberEmailConfig] = None, webhook_config: Optional[SubscriberWebhookConfig] = None, organization_id: Optional[str] = None, @@ -5739,7 +5781,7 @@ def get_subscriber( self, *, subscriber_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Subscriber: """ Get a subscriber. @@ -5771,7 +5813,7 @@ def get_subscriber( def list_subscriber( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListSubscriberRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5820,7 +5862,7 @@ def list_subscriber( def list_subscriber_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListSubscriberRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -5865,7 +5907,7 @@ def update_subscriber( *, subscriber_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, email_config: Optional[SubscriberEmailConfig] = None, webhook_config: Optional[SubscriberWebhookConfig] = None, ) -> Subscriber: @@ -5916,7 +5958,7 @@ def delete_subscriber( self, *, subscriber_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a subscriber. @@ -5948,7 +5990,7 @@ def subscribe_to_lb( *, lb_id: str, subscriber_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Lb: """ Subscribe a subscriber to a given load balancer. @@ -5991,7 +6033,7 @@ def unsubscribe_from_lb( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Lb: """ Unsubscribe a subscriber from a given load balancer. @@ -6024,7 +6066,7 @@ def list_lb_private_networks( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -6068,7 +6110,7 @@ def list_lb_private_networks_all( self, *, lb_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page_size: Optional[int] = None, page: Optional[int] = None, @@ -6108,10 +6150,11 @@ def attach_private_network( *, lb_id: str, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, static_config: Optional[PrivateNetworkStaticConfig] = None, dhcp_config: Optional[PrivateNetworkDHCPConfig] = None, ipam_config: Optional[PrivateNetworkIpamConfig] = None, + ipam_ids: Optional[List[str]] = None, ) -> PrivateNetwork: """ Add load balancer on instance private network. @@ -6124,6 +6167,7 @@ def attach_private_network( One-Of ('config'): at most one of 'static_config', 'dhcp_config', 'ipam_config' could be set. :param ipam_config: For internal use only. One-Of ('config'): at most one of 'static_config', 'dhcp_config', 'ipam_config' could be set. + :param ipam_ids: IPAM ID of a pre-reserved IP address to assign to the Load Balancer on this Private Network. In the future, it will be possible to specify multiple IPs in this field (IPv4 and IPv6), for now only one ID of an IPv4 address is expected. When null, a new private IP address is created for the Load Balancer on this Private Network. :return: :class:`PrivateNetwork ` Usage: @@ -6151,6 +6195,7 @@ def attach_private_network( lb_id=lb_id, private_network_id=private_network_id, region=region, + ipam_ids=ipam_ids, static_config=static_config, dhcp_config=dhcp_config, ipam_config=ipam_config, @@ -6167,7 +6212,7 @@ def detach_private_network( *, lb_id: str, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Remove load balancer of private network. diff --git a/scaleway/scaleway/lb/v1/marshalling.py b/scaleway/scaleway/lb/v1/marshalling.py index b68ee34b..bbf09e77 100644 --- a/scaleway/scaleway/lb/v1/marshalling.py +++ b/scaleway/scaleway/lb/v1/marshalling.py @@ -87,6 +87,7 @@ ZonedApiCreateLbRequest, ZonedApiCreateRouteRequest, ZonedApiCreateSubscriberRequest, + ZonedApiDetachPrivateNetworkRequest, ZonedApiMigrateLbRequest, ZonedApiRemoveBackendServersRequest, AclSpec, @@ -133,6 +134,10 @@ def unmarshal_Ip(data: Any) -> Ip: if field is not None: args["reverse"] = field + field = data.get("tags", None) + if field is not None: + args["tags"] = field + field = data.get("zone", None) if field is not None: args["zone"] = field @@ -140,10 +145,14 @@ def unmarshal_Ip(data: Any) -> Ip: field = data.get("lb_id", None) if field is not None: args["lb_id"] = field + else: + args["lb_id"] = None field = data.get("region", None) if field is not None: args["region"] = field + else: + args["region"] = None return Ip(**args) @@ -197,10 +206,14 @@ def unmarshal_Subscriber(data: Any) -> Subscriber: field = data.get("email_config", None) if field is not None: args["email_config"] = unmarshal_SubscriberEmailConfig(field) + else: + args["email_config"] = None field = data.get("webhook_config", None) if field is not None: args["webhook_config"] = unmarshal_SubscriberWebhookConfig(field) + else: + args["webhook_config"] = None return Subscriber(**args) @@ -228,6 +241,8 @@ def unmarshal_HealthCheckHttpConfig(data: Any) -> HealthCheckHttpConfig: field = data.get("code", None) if field is not None: args["code"] = field + else: + args["code"] = None return HealthCheckHttpConfig(**args) @@ -259,6 +274,8 @@ def unmarshal_HealthCheckHttpsConfig(data: Any) -> HealthCheckHttpsConfig: field = data.get("code", None) if field is not None: args["code"] = field + else: + args["code"] = None return HealthCheckHttpsConfig(**args) @@ -345,18 +362,26 @@ def unmarshal_HealthCheck(data: Any) -> HealthCheck: field = data.get("check_delay", None) if field is not None: args["check_delay"] = field + else: + args["check_delay"] = None field = data.get("check_timeout", None) if field is not None: args["check_timeout"] = field + else: + args["check_timeout"] = None field = data.get("tcp_config", None) if field is not None: args["tcp_config"] = unmarshal_HealthCheckTcpConfig(field) + else: + args["tcp_config"] = None field = data.get("mysql_config", None) if field is not None: args["mysql_config"] = unmarshal_HealthCheckMysqlConfig(field) + else: + args["mysql_config"] = None field = data.get("check_send_proxy", None) if field is not None: @@ -365,26 +390,38 @@ def unmarshal_HealthCheck(data: Any) -> HealthCheck: field = data.get("pgsql_config", None) if field is not None: args["pgsql_config"] = unmarshal_HealthCheckPgsqlConfig(field) + else: + args["pgsql_config"] = None field = data.get("ldap_config", None) if field is not None: args["ldap_config"] = unmarshal_HealthCheckLdapConfig(field) + else: + args["ldap_config"] = None field = data.get("redis_config", None) if field is not None: args["redis_config"] = unmarshal_HealthCheckRedisConfig(field) + else: + args["redis_config"] = None field = data.get("http_config", None) if field is not None: args["http_config"] = unmarshal_HealthCheckHttpConfig(field) + else: + args["http_config"] = None field = data.get("https_config", None) if field is not None: args["https_config"] = unmarshal_HealthCheckHttpsConfig(field) + else: + args["https_config"] = None field = data.get("transient_check_delay", None) if field is not None: args["transient_check_delay"] = field + else: + args["transient_check_delay"] = None return HealthCheck(**args) @@ -416,14 +453,20 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("region", None) if field is not None: args["region"] = field + else: + args["region"] = None return Instance(**args) @@ -482,7 +525,7 @@ def unmarshal_Lb(data: Any) -> Lb: if field is not None: args["backend_count"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -505,18 +548,26 @@ def unmarshal_Lb(data: Any) -> Lb: field = data.get("subscriber", None) if field is not None: args["subscriber"] = unmarshal_Subscriber(field) + else: + args["subscriber"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("region", None) if field is not None: args["region"] = field + else: + args["region"] = None return Lb(**args) @@ -572,62 +623,92 @@ def unmarshal_Backend(data: Any) -> Backend: field = data.get("health_check", None) if field is not None: args["health_check"] = unmarshal_HealthCheck(field) + else: + args["health_check"] = None field = data.get("lb", None) if field is not None: args["lb"] = unmarshal_Lb(field) + else: + args["lb"] = None field = data.get("send_proxy_v2", None) if field is not None: args["send_proxy_v2"] = field + else: + args["send_proxy_v2"] = None field = data.get("timeout_server", None) if field is not None: args["timeout_server"] = field + else: + args["timeout_server"] = None field = data.get("timeout_connect", None) if field is not None: args["timeout_connect"] = field + else: + args["timeout_connect"] = None field = data.get("timeout_tunnel", None) if field is not None: args["timeout_tunnel"] = field + else: + args["timeout_tunnel"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("failover_host", None) if field is not None: args["failover_host"] = field + else: + args["failover_host"] = None field = data.get("ssl_bridging", None) if field is not None: args["ssl_bridging"] = field + else: + args["ssl_bridging"] = None field = data.get("ignore_ssl_server_verify", None) if field is not None: args["ignore_ssl_server_verify"] = field + else: + args["ignore_ssl_server_verify"] = None field = data.get("redispatch_attempt_count", None) if field is not None: args["redispatch_attempt_count"] = field + else: + args["redispatch_attempt_count"] = None field = data.get("max_retries", None) if field is not None: args["max_retries"] = field + else: + args["max_retries"] = None field = data.get("max_connections", None) if field is not None: args["max_connections"] = field + else: + args["max_connections"] = None field = data.get("timeout_queue", None) if field is not None: args["timeout_queue"] = field + else: + args["timeout_queue"] = None return Backend(**args) @@ -640,7 +721,7 @@ def unmarshal_Certificate(data: Any) -> Certificate: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -669,16 +750,22 @@ def unmarshal_Certificate(data: Any) -> Certificate: args["not_valid_before"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["not_valid_before"] = None field = data.get("not_valid_after", None) if field is not None: args["not_valid_after"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["not_valid_after"] = None field = data.get("lb", None) if field is not None: args["lb"] = unmarshal_Lb(field) + else: + args["lb"] = None field = data.get("name", None) if field is not None: @@ -687,14 +774,20 @@ def unmarshal_Certificate(data: Any) -> Certificate: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("status_details", None) if field is not None: args["status_details"] = field + else: + args["status_details"] = None return Certificate(**args) @@ -730,26 +823,44 @@ def unmarshal_Frontend(data: Any) -> Frontend: field = data.get("backend", None) if field is not None: args["backend"] = unmarshal_Backend(field) + else: + args["backend"] = None field = data.get("lb", None) if field is not None: args["lb"] = unmarshal_Lb(field) + else: + args["lb"] = None field = data.get("timeout_client", None) if field is not None: args["timeout_client"] = field + else: + args["timeout_client"] = None field = data.get("certificate", None) if field is not None: args["certificate"] = unmarshal_Certificate(field) + else: + args["certificate"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("connection_rate_limit", None) + if field is not None: + args["connection_rate_limit"] = field + else: + args["connection_rate_limit"] = None return Frontend(**args) @@ -762,7 +873,7 @@ def unmarshal_AclActionRedirect(data: Any) -> AclActionRedirect: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -773,6 +884,8 @@ def unmarshal_AclActionRedirect(data: Any) -> AclActionRedirect: field = data.get("code", None) if field is not None: args["code"] = field + else: + args["code"] = None return AclActionRedirect(**args) @@ -785,13 +898,15 @@ def unmarshal_AclAction(data: Any) -> AclAction: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field field = data.get("redirect", None) if field is not None: args["redirect"] = unmarshal_AclActionRedirect(field) + else: + args["redirect"] = None return AclAction(**args) @@ -808,6 +923,10 @@ def unmarshal_AclMatch(data: Any) -> AclMatch: if field is not None: args["ip_subnet"] = field + field = data.get("ips_edge_services", None) + if field is not None: + args["ips_edge_services"] = field + field = data.get("http_filter", None) if field is not None: args["http_filter"] = field @@ -823,6 +942,8 @@ def unmarshal_AclMatch(data: Any) -> AclMatch: field = data.get("http_filter_option", None) if field is not None: args["http_filter_option"] = field + else: + args["http_filter_option"] = None return AclMatch(**args) @@ -854,22 +975,32 @@ def unmarshal_Acl(data: Any) -> Acl: field = data.get("match", None) if field is not None: args["match"] = unmarshal_AclMatch(field) + else: + args["match"] = None field = data.get("action", None) if field is not None: args["action"] = unmarshal_AclAction(field) + else: + args["action"] = None field = data.get("frontend", None) if field is not None: args["frontend"] = unmarshal_Frontend(field) + else: + args["frontend"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Acl(**args) @@ -885,6 +1016,8 @@ def unmarshal_PrivateNetworkDHCPConfig(data: Any) -> PrivateNetworkDHCPConfig: field = data.get("ip_id", None) if field is not None: args["ip_id"] = field + else: + args["ip_id"] = None return PrivateNetworkDHCPConfig(**args) @@ -911,6 +1044,8 @@ def unmarshal_PrivateNetworkStaticConfig(data: Any) -> PrivateNetworkStaticConfi field = data.get("ip_address", None) if field is not None: args["ip_address"] = field + else: + args["ip_address"] = None return PrivateNetworkStaticConfig(**args) @@ -938,26 +1073,38 @@ def unmarshal_PrivateNetwork(data: Any) -> PrivateNetwork: field = data.get("lb", None) if field is not None: args["lb"] = unmarshal_Lb(field) + else: + args["lb"] = None field = data.get("static_config", None) if field is not None: args["static_config"] = unmarshal_PrivateNetworkStaticConfig(field) + else: + args["static_config"] = None field = data.get("dhcp_config", None) if field is not None: args["dhcp_config"] = unmarshal_PrivateNetworkDHCPConfig(field) + else: + args["dhcp_config"] = None field = data.get("ipam_config", None) if field is not None: args["ipam_config"] = unmarshal_PrivateNetworkIpamConfig(field) + else: + args["ipam_config"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return PrivateNetwork(**args) @@ -970,13 +1117,27 @@ def unmarshal_RouteMatch(data: Any) -> RouteMatch: args: Dict[str, Any] = {} + field = data.get("match_subdomains", None) + if field is not None: + args["match_subdomains"] = field + field = data.get("sni", None) if field is not None: args["sni"] = field + else: + args["sni"] = None field = data.get("host_header", None) if field is not None: args["host_header"] = field + else: + args["host_header"] = None + + field = data.get("path_begin", None) + if field is not None: + args["path_begin"] = field + else: + args["path_begin"] = None return RouteMatch(**args) @@ -1004,14 +1165,20 @@ def unmarshal_Route(data: Any) -> Route: field = data.get("match", None) if field is not None: args["match"] = unmarshal_RouteMatch(field) + else: + args["match"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Route(**args) @@ -1049,6 +1216,8 @@ def unmarshal_BackendServerStats(data: Any) -> BackendServerStats: args["server_state_changed_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["server_state_changed_at"] = None return BackendServerStats(**args) @@ -1244,6 +1413,8 @@ def unmarshal_LbType(data: Any) -> LbType: field = data.get("region", None) if field is not None: args["region"] = field + else: + args["region"] = None return LbType(**args) @@ -1409,6 +1580,9 @@ def marshal_AttachPrivateNetworkRequest( ), ) + if request.ipam_ids is not None: + output["ipam_ids"] = request.ipam_ids + return output @@ -1440,7 +1614,7 @@ def marshal_AclAction( output["type"] = str(request.type_) if request.redirect is not None: - output["redirect"] = (marshal_AclActionRedirect(request.redirect, defaults),) + output["redirect"] = marshal_AclActionRedirect(request.redirect, defaults) return output @@ -1454,6 +1628,9 @@ def marshal_AclMatch( if request.ip_subnet is not None: output["ip_subnet"] = request.ip_subnet + if request.ips_edge_services is not None: + output["ips_edge_services"] = request.ips_edge_services + if request.http_filter is not None: output["http_filter"] = str(request.http_filter) @@ -1476,7 +1653,7 @@ def marshal_CreateAclRequest( output: Dict[str, Any] = {} if request.action is not None: - output["action"] = (marshal_AclAction(request.action, defaults),) + output["action"] = marshal_AclAction(request.action, defaults) if request.index is not None: output["index"] = request.index @@ -1488,7 +1665,7 @@ def marshal_CreateAclRequest( output["name"] = request.name if request.match is not None: - output["match"] = (marshal_AclMatch(request.match, defaults),) + output["match"] = marshal_AclMatch(request.match, defaults) return output @@ -1651,7 +1828,7 @@ def marshal_CreateBackendRequest( output["sticky_sessions_cookie_name"] = request.sticky_sessions_cookie_name if request.health_check is not None: - output["health_check"] = (marshal_HealthCheck(request.health_check, defaults),) + output["health_check"] = marshal_HealthCheck(request.health_check, defaults) if request.server_ip is not None: output["server_ip"] = request.server_ip @@ -1775,6 +1952,9 @@ def marshal_CreateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -1804,6 +1984,9 @@ def marshal_CreateIpRequest( if request.reverse is not None: output["reverse"] = request.reverse + if request.tags is not None: + output["tags"] = request.tags + return output @@ -1867,10 +2050,14 @@ def marshal_RouteMatch( [ OneOfPossibility("sni", request.sni), OneOfPossibility("host_header", request.host_header), + OneOfPossibility("path_begin", request.path_begin), ] ), ) + if request.match_subdomains is not None: + output["match_subdomains"] = request.match_subdomains + return output @@ -1887,7 +2074,7 @@ def marshal_CreateRouteRequest( output["backend_id"] = request.backend_id if request.match is not None: - output["match"] = (marshal_RouteMatch(request.match, defaults),) + output["match"] = marshal_RouteMatch(request.match, defaults) return output @@ -2008,13 +2195,13 @@ def marshal_UpdateAclRequest( output["name"] = request.name if request.action is not None: - output["action"] = (marshal_AclAction(request.action, defaults),) + output["action"] = marshal_AclAction(request.action, defaults) if request.index is not None: output["index"] = request.index if request.match is not None: - output["match"] = (marshal_AclMatch(request.match, defaults),) + output["match"] = marshal_AclMatch(request.match, defaults) if request.description is not None: output["description"] = request.description @@ -2127,6 +2314,9 @@ def marshal_UpdateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2182,6 +2372,9 @@ def marshal_UpdateIpRequest( if request.lb_id is not None: output["lb_id"] = request.lb_id + if request.tags is not None: + output["tags"] = request.tags + return output @@ -2216,7 +2409,7 @@ def marshal_UpdateRouteRequest( output["backend_id"] = request.backend_id if request.match is not None: - output["match"] = (marshal_RouteMatch(request.match, defaults),) + output["match"] = marshal_RouteMatch(request.match, defaults) return output @@ -2268,6 +2461,12 @@ def marshal_ZonedApiAttachPrivateNetworkRequest( ), ) + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + if request.ipam_ids is not None: + output["ipam_ids"] = request.ipam_ids + return output @@ -2278,7 +2477,7 @@ def marshal_ZonedApiCreateAclRequest( output: Dict[str, Any] = {} if request.action is not None: - output["action"] = (marshal_AclAction(request.action, defaults),) + output["action"] = marshal_AclAction(request.action, defaults) if request.index is not None: output["index"] = request.index @@ -2290,7 +2489,7 @@ def marshal_ZonedApiCreateAclRequest( output["name"] = request.name if request.match is not None: - output["match"] = (marshal_AclMatch(request.match, defaults),) + output["match"] = marshal_AclMatch(request.match, defaults) return output @@ -2317,7 +2516,7 @@ def marshal_ZonedApiCreateBackendRequest( output["sticky_sessions_cookie_name"] = request.sticky_sessions_cookie_name if request.health_check is not None: - output["health_check"] = (marshal_HealthCheck(request.health_check, defaults),) + output["health_check"] = marshal_HealthCheck(request.health_check, defaults) if request.server_ip is not None: output["server_ip"] = request.server_ip @@ -2414,6 +2613,9 @@ def marshal_ZonedApiCreateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2443,6 +2645,9 @@ def marshal_ZonedApiCreateIpRequest( if request.reverse is not None: output["reverse"] = request.reverse + if request.tags is not None: + output["tags"] = request.tags + return output @@ -2509,7 +2714,7 @@ def marshal_ZonedApiCreateRouteRequest( output["backend_id"] = request.backend_id if request.match is not None: - output["match"] = (marshal_RouteMatch(request.match, defaults),) + output["match"] = marshal_RouteMatch(request.match, defaults) return output @@ -2548,6 +2753,18 @@ def marshal_ZonedApiCreateSubscriberRequest( return output +def marshal_ZonedApiDetachPrivateNetworkRequest( + request: ZonedApiDetachPrivateNetworkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + return output + + def marshal_ZonedApiMigrateLbRequest( request: ZonedApiMigrateLbRequest, defaults: ProfileDefaults, @@ -2582,7 +2799,7 @@ def marshal_AclSpec( output["name"] = request.name if request.action is not None: - output["action"] = (marshal_AclAction(request.action, defaults),) + output["action"] = marshal_AclAction(request.action, defaults) if request.index is not None: output["index"] = request.index @@ -2591,7 +2808,7 @@ def marshal_AclSpec( output["description"] = request.description if request.match is not None: - output["match"] = (marshal_AclMatch(request.match, defaults),) + output["match"] = marshal_AclMatch(request.match, defaults) return output @@ -2642,13 +2859,13 @@ def marshal_ZonedApiUpdateAclRequest( output["name"] = request.name if request.action is not None: - output["action"] = (marshal_AclAction(request.action, defaults),) + output["action"] = marshal_AclAction(request.action, defaults) if request.index is not None: output["index"] = request.index if request.match is not None: - output["match"] = (marshal_AclMatch(request.match, defaults),) + output["match"] = marshal_AclMatch(request.match, defaults) if request.description is not None: output["description"] = request.description @@ -2761,6 +2978,9 @@ def marshal_ZonedApiUpdateFrontendRequest( if request.certificate_ids is not None: output["certificate_ids"] = request.certificate_ids + if request.connection_rate_limit is not None: + output["connection_rate_limit"] = request.connection_rate_limit + return output @@ -2816,6 +3036,9 @@ def marshal_ZonedApiUpdateIpRequest( if request.lb_id is not None: output["lb_id"] = request.lb_id + if request.tags is not None: + output["tags"] = request.tags + return output @@ -2850,7 +3073,7 @@ def marshal_ZonedApiUpdateRouteRequest( output["backend_id"] = request.backend_id if request.match is not None: - output["match"] = (marshal_RouteMatch(request.match, defaults),) + output["match"] = marshal_RouteMatch(request.match, defaults) return output diff --git a/scaleway/scaleway/lb/v1/types.py b/scaleway/scaleway/lb/v1/types.py index 59c722e2..d66e8a69 100644 --- a/scaleway/scaleway/lb/v1/types.py +++ b/scaleway/scaleway/lb/v1/types.py @@ -8,8 +8,8 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, - Zone, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -297,7 +297,7 @@ class SubscriberWebhookConfig: class HealthCheckHttpConfig: uri: str """ - The HTTP URI to use when performing a health check on backend servers. + The HTTP path to use when performing a health check on backend servers. """ method: str @@ -320,7 +320,7 @@ class HealthCheckHttpConfig: class HealthCheckHttpsConfig: uri: str """ - The HTTP URI to use when performing a health check on backend servers. + The HTTP path to use when performing a health check on backend servers. """ method: str @@ -392,7 +392,7 @@ class Instance: Instance IP address. """ - zone: Zone + zone: ScwZone """ The zone the Instance is in. """ @@ -407,7 +407,7 @@ class Instance: Date on which the Instance was last updated. """ - region: Optional[Region] + region: Optional[ScwRegion] """ The region the Instance is in. """ @@ -440,7 +440,12 @@ class Ip: Reverse DNS (domain name) of the IP address. """ - zone: Zone + tags: List[str] + """ + IP tags. + """ + + zone: ScwZone """ The zone the IP address is in. """ @@ -450,7 +455,7 @@ class Ip: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ The region the IP address is in. """ @@ -601,7 +606,7 @@ class Lb: Number of routes configured on the Load Balancer. """ - zone: Zone + zone: ScwZone """ The zone the Load Balancer is in. """ @@ -621,7 +626,7 @@ class Lb: Date on which the Load Balancer was last updated. """ - region: Optional[Region] + region: Optional[ScwRegion] """ The region the Load Balancer is in. """ @@ -739,7 +744,7 @@ class Backend: failover_host: Optional[str] """ - Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. """ ssl_bridging: Optional[bool] @@ -861,6 +866,11 @@ class AclMatch: List of IPs or CIDR v4/v6 addresses to filter for from the client side. """ + ips_edge_services: bool + """ + Defines whether Edge Services IPs should be matched. + """ + http_filter: AclHttpFilter """ Type of HTTP filter to match. Extracts the request's URL path, which starts at the first slash and ends before the question mark (without the host part). Defines where to filter for the http_filter_value. Only supported for HTTP backends. @@ -939,6 +949,11 @@ class Frontend: Date on which the frontend was last updated. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class PrivateNetworkDHCPConfig: @@ -960,10 +975,17 @@ class PrivateNetworkStaticConfig: @dataclass class RouteMatch: + match_subdomains: bool + """ + If true, all subdomains will match. + """ + sni: Optional[str] host_header: Optional[str] + path_begin: Optional[str] + @dataclass class CreateCertificateRequestCustomCertificate: @@ -1123,12 +1145,12 @@ class LbType: Load Balancer commercial offer type description. """ - zone: Zone + zone: ScwZone """ The zone the Load Balancer stock is in. """ - region: Optional[Region] + region: Optional[ScwRegion] """ The region the Load Balancer stock is in. """ @@ -1207,7 +1229,7 @@ class AddBackendServersRequest: List of IP addresses to add to backend servers. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1225,11 +1247,16 @@ class AttachPrivateNetworkRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ + ipam_ids: Optional[List[str]] + """ + IPAM ID of a pre-reserved IP address to assign to the Load Balancer on this Private Network. In the future, it will be possible to specify multiple IPs in this field (IPv4 and IPv6), for now only one ID of an IPv4 address is expected. When null, a new private IP address is created for the Load Balancer on this Private Network. + """ + static_config: Optional[PrivateNetworkStaticConfig] dhcp_config: Optional[PrivateNetworkDHCPConfig] @@ -1263,7 +1290,7 @@ class CreateAclRequest: ACL description. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1321,7 +1348,7 @@ class CreateBackendRequest: List of backend server IP addresses (IPv4 or IPv6) the backend should forward traffic to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1363,7 +1390,7 @@ class CreateBackendRequest: failover_host: Optional[str] """ - Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. """ ssl_bridging: Optional[bool] @@ -1404,7 +1431,7 @@ class CreateCertificateRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1441,7 +1468,7 @@ class CreateFrontendRequest: Defines whether to enable HTTP/3 protocol on the frontend. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1466,6 +1493,11 @@ class CreateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class CreateIpRequest: @@ -1474,7 +1506,7 @@ class CreateIpRequest: If true, creates a Flexible IP with an ipv6 address. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1484,6 +1516,11 @@ class CreateIpRequest: Reverse DNS (domain name) for the IP address. """ + tags: Optional[List[str]] + """ + List of tags for the IP. + """ + project_id: Optional[str] organization_id: Optional[str] @@ -1501,7 +1538,7 @@ class CreateLbRequest: Load Balancer commercial offer type. Use the Load Balancer types endpoint to retrieve a list of available offer types. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1518,7 +1555,7 @@ class CreateLbRequest: assign_flexible_ip: Optional[bool] """ - Defines whether to automatically assign a flexible public IP to lb. Default value is `false` (do not assign). + Defines whether to automatically assign a flexible public IP to the Load Balancer. Default value is `true` (assign). """ assign_flexible_ipv6: Optional[bool] @@ -1558,7 +1595,7 @@ class CreateRouteRequest: ID of the target backend for the route. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1580,7 +1617,7 @@ class CreateSubscriberRequest: Subscriber name. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1601,7 +1638,7 @@ class DeleteAclRequest: ACL ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1614,7 +1651,7 @@ class DeleteBackendRequest: ID of the backend to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1627,7 +1664,7 @@ class DeleteCertificateRequest: Certificate ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1640,7 +1677,7 @@ class DeleteFrontendRequest: ID of the frontend to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1658,7 +1695,7 @@ class DeleteLbRequest: Defines whether the Load Balancer's flexible IP should be deleted. Set to true to release the flexible IP, or false to keep it available in your account for future Load Balancers. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1671,7 +1708,7 @@ class DeleteRouteRequest: Route ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1684,7 +1721,7 @@ class DeleteSubscriberRequest: Subscriber ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1702,7 +1739,7 @@ class DetachPrivateNetworkRequest: Set your instance private network id. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1715,7 +1752,7 @@ class GetAclRequest: ACL ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1728,7 +1765,7 @@ class GetBackendRequest: Backend ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1741,7 +1778,7 @@ class GetCertificateRequest: Certificate ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1754,7 +1791,7 @@ class GetFrontendRequest: Frontend ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1767,7 +1804,7 @@ class GetIpRequest: IP address ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1780,7 +1817,7 @@ class GetLbRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1797,7 +1834,7 @@ class GetLbStatsRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1815,7 +1852,7 @@ class GetRouteRequest: Route ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1828,7 +1865,7 @@ class GetSubscriberRequest: Subscriber ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1862,7 +1899,7 @@ class ListAclsRequest: Frontend ID (ACLs attached to this frontend will be returned in the response). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1895,7 +1932,7 @@ class ListBackendStatsRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1936,7 +1973,7 @@ class ListBackendsRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1982,7 +2019,7 @@ class ListCertificatesRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2028,7 +2065,7 @@ class ListFrontendsRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2069,7 +2106,7 @@ class ListFrontendsResponse: @dataclass class ListIPsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2104,6 +2141,11 @@ class ListIPsRequest: IP type to filter for. """ + tags: Optional[List[str]] + """ + Tag to filter for, only IPs with one or more matching tags will be returned. + """ + @dataclass class ListIpsResponse: @@ -2125,7 +2167,7 @@ class ListLbPrivateNetworksRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2161,7 +2203,7 @@ class ListLbPrivateNetworksResponse: @dataclass class ListLbTypesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2192,7 +2234,7 @@ class ListLbTypesResponse: @dataclass class ListLbsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2248,7 +2290,7 @@ class ListLbsResponse: @dataclass class ListRoutesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2289,7 +2331,7 @@ class ListRoutesResponse: @dataclass class ListSubscriberRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2350,7 +2392,7 @@ class MigrateLbRequest: Load Balancer type to migrate to (use the List all Load Balancer offer types endpoint to get a list of available offer types). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2363,7 +2405,7 @@ class ReleaseIpRequest: IP address ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2381,7 +2423,7 @@ class RemoveBackendServersRequest: List of IP addresses to remove from backend servers. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2412,7 +2454,7 @@ class SetBackendServersRequest: List of IP addresses for backend servers. Any other existing backend servers will be removed. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2430,7 +2472,7 @@ class SubscribeToLbRequest: Subscriber ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2443,7 +2485,7 @@ class UnsubscribeFromLbRequest: Load Balancer ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2471,7 +2513,7 @@ class UpdateAclRequest: Priority of this ACL (ACLs are applied in ascending order, 0 is the first ACL executed). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2524,7 +2566,7 @@ class UpdateBackendRequest: Cookie name for cookie-based sticky sessions. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2561,7 +2603,7 @@ class UpdateBackendRequest: failover_host: Optional[str] """ - Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. """ ssl_bridging: Optional[bool] @@ -2607,7 +2649,7 @@ class UpdateCertificateRequest: Certificate name. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2640,7 +2682,7 @@ class UpdateFrontendRequest: Defines whether to enable HTTP/3 protocol on the frontend. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2660,6 +2702,11 @@ class UpdateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class UpdateHealthCheckRequest: @@ -2683,7 +2730,7 @@ class UpdateHealthCheckRequest: Defines whether proxy protocol should be activated for the health check. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2725,7 +2772,7 @@ class UpdateIpRequest: IP address ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2740,6 +2787,11 @@ class UpdateIpRequest: ID of the server on which to attach the flexible IP. """ + tags: Optional[List[str]] + """ + List of tags for the IP. + """ + @dataclass class UpdateLbRequest: @@ -2758,7 +2810,7 @@ class UpdateLbRequest: Load Balancer description. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2786,7 +2838,7 @@ class UpdateRouteRequest: ID of the target backend for the route. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2809,7 +2861,7 @@ class UpdateSubscriberRequest: Subscriber name. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2831,7 +2883,7 @@ class ZonedApiAddBackendServersRequest: List of IP addresses to add to backend servers. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2849,11 +2901,16 @@ class ZonedApiAttachPrivateNetworkRequest: Private Network ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ + ipam_ids: Optional[List[str]] + """ + IPAM ID of a pre-reserved IP address to assign to the Load Balancer on this Private Network. In the future, it will be possible to specify multiple IPs in this field (IPv4 and IPv6), for now only one ID of an IPv4 address is expected. When null, a new private IP address is created for the Load Balancer on this Private Network. + """ + static_config: Optional[PrivateNetworkStaticConfig] dhcp_config: Optional[PrivateNetworkDHCPConfig] @@ -2887,7 +2944,7 @@ class ZonedApiCreateAclRequest: ACL description. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2945,7 +3002,7 @@ class ZonedApiCreateBackendRequest: List of backend server IP addresses (IPv4 or IPv6) the backend should forward traffic to. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -2987,7 +3044,7 @@ class ZonedApiCreateBackendRequest: failover_host: Optional[str] """ - Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. """ ssl_bridging: Optional[bool] @@ -3028,7 +3085,7 @@ class ZonedApiCreateCertificateRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3065,7 +3122,7 @@ class ZonedApiCreateFrontendRequest: Defines whether to enable HTTP/3 protocol on the frontend. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3090,6 +3147,11 @@ class ZonedApiCreateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class ZonedApiCreateIpRequest: @@ -3098,7 +3160,7 @@ class ZonedApiCreateIpRequest: If true, creates a Flexible IP with an ipv6 address. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3108,6 +3170,11 @@ class ZonedApiCreateIpRequest: Reverse DNS (domain name) for the IP address. """ + tags: Optional[List[str]] + """ + List of tags for the IP. + """ + project_id: Optional[str] organization_id: Optional[str] @@ -3125,7 +3192,7 @@ class ZonedApiCreateLbRequest: Load Balancer commercial offer type. Use the Load Balancer types endpoint to retrieve a list of available offer types. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3142,7 +3209,7 @@ class ZonedApiCreateLbRequest: assign_flexible_ip: Optional[bool] """ - Defines whether to automatically assign a flexible public IP to lb. Default value is `false` (do not assign). + Defines whether to automatically assign a flexible public IP to the Load Balancer. Default value is `true` (assign). """ assign_flexible_ipv6: Optional[bool] @@ -3182,7 +3249,7 @@ class ZonedApiCreateRouteRequest: ID of the target backend for the route. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3204,7 +3271,7 @@ class ZonedApiCreateSubscriberRequest: Subscriber name. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3225,7 +3292,7 @@ class ZonedApiDeleteAclRequest: ACL ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3238,7 +3305,7 @@ class ZonedApiDeleteBackendRequest: ID of the backend to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3251,7 +3318,7 @@ class ZonedApiDeleteCertificateRequest: Certificate ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3264,7 +3331,7 @@ class ZonedApiDeleteFrontendRequest: ID of the frontend to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3282,7 +3349,7 @@ class ZonedApiDeleteLbRequest: Defines whether the Load Balancer's flexible IP should be deleted. Set to true to release the flexible IP, or false to keep it available in your account for future Load Balancers. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3295,7 +3362,7 @@ class ZonedApiDeleteRouteRequest: Route ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3308,7 +3375,7 @@ class ZonedApiDeleteSubscriberRequest: Subscriber ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3326,7 +3393,7 @@ class ZonedApiDetachPrivateNetworkRequest: Set your instance private network id. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3339,7 +3406,7 @@ class ZonedApiGetAclRequest: ACL ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3352,7 +3419,7 @@ class ZonedApiGetBackendRequest: Backend ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3365,7 +3432,7 @@ class ZonedApiGetCertificateRequest: Certificate ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3378,7 +3445,7 @@ class ZonedApiGetFrontendRequest: Frontend ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3391,7 +3458,7 @@ class ZonedApiGetIpRequest: IP address ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3404,7 +3471,7 @@ class ZonedApiGetLbRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3421,7 +3488,7 @@ class ZonedApiGetLbStatsRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3439,7 +3506,7 @@ class ZonedApiGetRouteRequest: Route ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3452,7 +3519,7 @@ class ZonedApiGetSubscriberRequest: Subscriber ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3465,7 +3532,7 @@ class ZonedApiListAclsRequest: Frontend ID (ACLs attached to this frontend will be returned in the response). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3498,7 +3565,7 @@ class ZonedApiListBackendStatsRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3526,7 +3593,7 @@ class ZonedApiListBackendsRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3559,7 +3626,7 @@ class ZonedApiListCertificatesRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3592,7 +3659,7 @@ class ZonedApiListFrontendsRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3620,7 +3687,7 @@ class ZonedApiListFrontendsRequest: @dataclass class ZonedApiListIPsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3655,6 +3722,11 @@ class ZonedApiListIPsRequest: IP type to filter for. """ + tags: Optional[List[str]] + """ + Tag to filter for, only IPs with one or more matching tags will be returned. + """ + @dataclass class ZonedApiListLbPrivateNetworksRequest: @@ -3663,7 +3735,7 @@ class ZonedApiListLbPrivateNetworksRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3686,7 +3758,7 @@ class ZonedApiListLbPrivateNetworksRequest: @dataclass class ZonedApiListLbTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3704,7 +3776,7 @@ class ZonedApiListLbTypesRequest: @dataclass class ZonedApiListLbsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3747,7 +3819,7 @@ class ZonedApiListLbsRequest: @dataclass class ZonedApiListRoutesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3775,7 +3847,7 @@ class ZonedApiListRoutesRequest: @dataclass class ZonedApiListSubscriberRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3823,7 +3895,7 @@ class ZonedApiMigrateLbRequest: Load Balancer type to migrate to (use the List all Load Balancer offer types endpoint to get a list of available offer types). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3836,7 +3908,7 @@ class ZonedApiReleaseIpRequest: IP address ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3854,7 +3926,7 @@ class ZonedApiRemoveBackendServersRequest: List of IP addresses to remove from backend servers. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3872,7 +3944,7 @@ class ZonedApiSetAclsRequest: Frontend ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3890,7 +3962,7 @@ class ZonedApiSetBackendServersRequest: List of IP addresses for backend servers. Any other existing backend servers will be removed. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3908,7 +3980,7 @@ class ZonedApiSubscribeToLbRequest: Subscriber ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3921,7 +3993,7 @@ class ZonedApiUnsubscribeFromLbRequest: Load Balancer ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -3949,7 +4021,7 @@ class ZonedApiUpdateAclRequest: Priority of this ACL (ACLs are applied in ascending order, 0 is the first ACL executed). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4002,7 +4074,7 @@ class ZonedApiUpdateBackendRequest: Cookie name for cookie-based sticky sessions. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4039,7 +4111,7 @@ class ZonedApiUpdateBackendRequest: failover_host: Optional[str] """ - Scaleway S3 bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. + Scaleway Object Storage bucket website to be served as failover if all backend servers are down, e.g. failover-website.s3-website.fr-par.scw.cloud. """ ssl_bridging: Optional[bool] @@ -4085,7 +4157,7 @@ class ZonedApiUpdateCertificateRequest: Certificate name. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4118,7 +4190,7 @@ class ZonedApiUpdateFrontendRequest: Defines whether to enable HTTP/3 protocol on the frontend. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4138,6 +4210,11 @@ class ZonedApiUpdateFrontendRequest: List of SSL/TLS certificate IDs to bind to the frontend. """ + connection_rate_limit: Optional[int] + """ + Rate limit for new connections established on this frontend. Use 0 value to disable, else value is connections per second. + """ + @dataclass class ZonedApiUpdateHealthCheckRequest: @@ -4161,7 +4238,7 @@ class ZonedApiUpdateHealthCheckRequest: Defines whether proxy protocol should be activated for the health check. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4203,7 +4280,7 @@ class ZonedApiUpdateIpRequest: IP address ID. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4218,6 +4295,11 @@ class ZonedApiUpdateIpRequest: ID of the server on which to attach the flexible IP. """ + tags: Optional[List[str]] + """ + List of tags for the IP. + """ + @dataclass class ZonedApiUpdateLbRequest: @@ -4236,7 +4318,7 @@ class ZonedApiUpdateLbRequest: Load Balancer description. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4264,7 +4346,7 @@ class ZonedApiUpdateRouteRequest: ID of the target backend for the route. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -4287,7 +4369,7 @@ class ZonedApiUpdateSubscriberRequest: Subscriber name. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway/scaleway/marketplace/v2/api.py b/scaleway/scaleway/marketplace/v2/api.py index bb81a26f..80c7b1d4 100644 --- a/scaleway/scaleway/marketplace/v2/api.py +++ b/scaleway/scaleway/marketplace/v2/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( OneOfPossibility, @@ -40,7 +40,9 @@ class MarketplaceV2API(API): - """ """ + """ + This API allows you to find available images for use when launching a Scaleway Instance. + """ def list_images( self, @@ -267,29 +269,29 @@ def get_version( def list_local_images( self, *, - image_id: Optional[str] = None, - version_id: Optional[str] = None, page_size: Optional[int] = None, page: Optional[int] = None, order_by: Optional[ListLocalImagesRequestOrderBy] = None, + zone: Optional[ScwZone] = None, + image_id: Optional[str] = None, + version_id: Optional[str] = None, image_label: Optional[str] = None, - zone: Optional[Zone] = None, type_: Optional[LocalImageType] = None, ) -> ListLocalImagesResponse: """ List local images from a specific image or version. List information about local images in a specific Availability Zone, specified by its `image_id` (UUID format), `version_id` (UUID format) or `image_label`. Only one of these three parameters may be set. - :param image_id: + :param page_size: A positive integer lower or equal to 100 to select the number of items to display. + :param page: A positive integer to choose the page to display. + :param order_by: Ordering to use. + :param zone: Filter local images available on this Availability Zone. + :param image_id: Filter by image id. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param version_id: + :param version_id: Filter by version id. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param page_size: - :param page: - :param order_by: - :param image_label: + :param image_label: Filter by image label. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param zone: Zone to target. If none is passed will use default zone from the config. - :param type_: + :param type_: Filter by type. :return: :class:`ListLocalImagesResponse ` Usage: @@ -323,29 +325,29 @@ def list_local_images( def list_local_images_all( self, *, - image_id: Optional[str] = None, - version_id: Optional[str] = None, page_size: Optional[int] = None, page: Optional[int] = None, order_by: Optional[ListLocalImagesRequestOrderBy] = None, + zone: Optional[ScwZone] = None, + image_id: Optional[str] = None, + version_id: Optional[str] = None, image_label: Optional[str] = None, - zone: Optional[Zone] = None, type_: Optional[LocalImageType] = None, ) -> List[LocalImage]: """ List local images from a specific image or version. List information about local images in a specific Availability Zone, specified by its `image_id` (UUID format), `version_id` (UUID format) or `image_label`. Only one of these three parameters may be set. - :param image_id: + :param page_size: A positive integer lower or equal to 100 to select the number of items to display. + :param page: A positive integer to choose the page to display. + :param order_by: Ordering to use. + :param zone: Filter local images available on this Availability Zone. + :param image_id: Filter by image id. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param version_id: + :param version_id: Filter by version id. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param page_size: - :param page: - :param order_by: - :param image_label: + :param image_label: Filter by image label. One-Of ('scope'): at most one of 'image_id', 'version_id', 'image_label' could be set. - :param zone: Zone to target. If none is passed will use default zone from the config. - :param type_: + :param type_: Filter by type. :return: :class:`List[LocalImage] ` Usage: diff --git a/scaleway/scaleway/marketplace/v2/marshalling.py b/scaleway/scaleway/marketplace/v2/marshalling.py index eb495e08..c3c22a3e 100644 --- a/scaleway/scaleway/marketplace/v2/marshalling.py +++ b/scaleway/scaleway/marketplace/v2/marshalling.py @@ -74,16 +74,22 @@ def unmarshal_Image(data: Any) -> Image: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("valid_until", None) if field is not None: args["valid_until"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["valid_until"] = None return Image(**args) @@ -116,7 +122,7 @@ def unmarshal_LocalImage(data: Any) -> LocalImage: if field is not None: args["label"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -142,16 +148,22 @@ def unmarshal_Version(data: Any) -> Version: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("published_at", None) if field is not None: args["published_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["published_at"] = None return Version(**args) diff --git a/scaleway/scaleway/marketplace/v2/types.py b/scaleway/scaleway/marketplace/v2/types.py index 5c1ebd10..fd972c3a 100644 --- a/scaleway/scaleway/marketplace/v2/types.py +++ b/scaleway/scaleway/marketplace/v2/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -28,6 +28,8 @@ def __str__(self) -> str: class ListLocalImagesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + TYPE_ASC = "type_asc" + TYPE_DESC = "type_desc" CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -91,6 +93,7 @@ class Image: label: str """ Typically an identifier for a distribution (ex. "ubuntu_focal"). +This label can be used in the image field of the server creation request. """ created_at: Optional[datetime] @@ -126,14 +129,14 @@ class LocalImage: Supported architecture for this local image. """ - zone: Zone + zone: ScwZone """ Availability Zone where this local image is available. """ label: str """ - Image label this image belongs to. + This label can be used in the image field of the server creation request. """ type_: LocalImageType @@ -250,17 +253,29 @@ class ListImagesResponse: @dataclass class ListLocalImagesRequest: page_size: Optional[int] + """ + A positive integer lower or equal to 100 to select the number of items to display. + """ page: Optional[int] + """ + A positive integer to choose the page to display. + """ order_by: Optional[ListLocalImagesRequestOrderBy] + """ + Ordering to use. + """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ - Zone to target. If none is passed will use default zone from the config. + Filter local images available on this Availability Zone. """ type_: Optional[LocalImageType] + """ + Filter by type. + """ image_id: Optional[str] diff --git a/scaleway/scaleway/mnq/v1beta1/api.py b/scaleway/scaleway/mnq/v1beta1/api.py index d9183f7f..8f7f4db7 100644 --- a/scaleway/scaleway/mnq/v1beta1/api.py +++ b/scaleway/scaleway/mnq/v1beta1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( random_name, @@ -68,13 +68,13 @@ class MnqV1Beta1NatsAPI(API): """ - This API allows you to manage Scaleway Messaging and Queueing NATS accounts. + This API allows you to manage Scaleway NATS accounts. """ def create_nats_account( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, project_id: Optional[str] = None, ) -> NatsAccount: @@ -116,7 +116,7 @@ def delete_nats_account( self, *, nats_account_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a NATS account. @@ -148,7 +148,7 @@ def update_nats_account( self, *, nats_account_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, ) -> NatsAccount: """ @@ -192,7 +192,7 @@ def get_nats_account( self, *, nats_account_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> NatsAccount: """ Get a NATS account. @@ -225,7 +225,7 @@ def get_nats_account( def list_nats_accounts( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -268,7 +268,7 @@ def list_nats_accounts( def list_nats_accounts_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -307,7 +307,7 @@ def create_nats_credentials( self, *, nats_account_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, ) -> NatsCredentials: """ @@ -350,7 +350,7 @@ def delete_nats_credentials( self, *, nats_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete NATS credentials. @@ -384,7 +384,7 @@ def get_nats_credentials( self, *, nats_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> NatsCredentials: """ Get NATS credentials. @@ -419,7 +419,8 @@ def get_nats_credentials( def list_nats_credentials( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, nats_account_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -429,6 +430,7 @@ def list_nats_credentials( List NATS credentials. List existing credentials in the specified NATS account. The response contains only the metadata for the credentials, not the credentials themselves, which are only returned after a **Create Credentials** call. :param region: Region to target. If none is passed will use default region from the config. + :param project_id: Include only NATS accounts in this Project. :param nats_account_id: Include only credentials for this NATS account. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. @@ -453,6 +455,7 @@ def list_nats_credentials( "order_by": order_by, "page": page, "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, }, ) @@ -462,7 +465,8 @@ def list_nats_credentials( def list_nats_credentials_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, nats_account_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -472,6 +476,7 @@ def list_nats_credentials_all( List NATS credentials. List existing credentials in the specified NATS account. The response contains only the metadata for the credentials, not the credentials themselves, which are only returned after a **Create Credentials** call. :param region: Region to target. If none is passed will use default region from the config. + :param project_id: Include only NATS accounts in this Project. :param nats_account_id: Include only credentials for this NATS account. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. @@ -490,6 +495,7 @@ def list_nats_credentials_all( fetcher=self.list_nats_credentials, args={ "region": region, + "project_id": project_id, "nats_account_id": nats_account_id, "page": page, "page_size": page_size, @@ -500,20 +506,20 @@ def list_nats_credentials_all( class MnqV1Beta1SnsAPI(API): """ - This API allows you to manage Scaleway Messaging and Queueing SNS brokers. + This API allows you to manage your Scaleway Topics and Events. """ def activate_sns( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SnsInfo: """ - Activate SNS. - Activate SNS for the specified Project ID. SNS must be activated before any usage. Activating SNS does not trigger any billing, and you can deactivate at any time. + Activate Topics and Events. + Activate Topics and Events for the specified Project ID. Topics and Events must be activated before any usage. Activating Topics and Events does not trigger any billing, and you can deactivate at any time. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project on which to activate the SNS service. + :param project_id: Project on which to activate the Topics and Events service. :return: :class:`SnsInfo ` Usage: @@ -544,14 +550,14 @@ def activate_sns( def get_sns_info( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SnsInfo: """ - Get SNS info. - Retrieve the SNS information of the specified Project ID. Informations include the activation status and the SNS API endpoint URL. + Get Topics and Events info. + Retrieve the Topics and Events information of the specified Project ID. Informations include the activation status and the Topics and Events API endpoint URL. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project to retrieve SNS info from. + :param project_id: Project to retrieve Topics and Events info from. :return: :class:`SnsInfo ` Usage: @@ -578,14 +584,14 @@ def get_sns_info( def deactivate_sns( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SnsInfo: """ - Deactivate SNS. - Deactivate SNS for the specified Project ID.You must delete all topics and credentials before this call or you need to set the force_delete parameter. + Deactivate Topics and Events. + Deactivate Topics and Events for the specified Project ID. You must delete all topics and credentials before this call or you need to set the force_delete parameter. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project on which to deactivate the SNS service. + :param project_id: Project on which to deactivate the Topics and Events service. :return: :class:`SnsInfo ` Usage: @@ -616,16 +622,16 @@ def deactivate_sns( def create_sns_credentials( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, name: Optional[str] = None, permissions: Optional[SnsPermissions] = None, ) -> SnsCredentials: """ - Create SNS credentials. - Create a set of credentials for SNS, specified by a Project ID. Credentials give the bearer access to topics, and the level of permissions can be defined granularly. + Create Topics and Events credentials. + Create a set of credentials for Topics and Events, specified by a Project ID. Credentials give the bearer access to topics, and the level of permissions can be defined granularly. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project containing the SNS credentials. + :param project_id: Project containing the Topics and Events credentials. :param name: Name of the credentials. :param permissions: Permissions associated with these credentials. :return: :class:`SnsCredentials ` @@ -661,11 +667,11 @@ def delete_sns_credentials( self, *, sns_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ - Delete SNS credentials. - Delete a set of SNS credentials, specified by their credentials ID. Deleting credentials is irreversible and cannot be undone. The credentials can then no longer be used to access SNS. + Delete Topics and Events credentials. + Delete a set of Topics and Events credentials, specified by their credentials ID. Deleting credentials is irreversible and cannot be undone. The credentials can then no longer be used to access Topics and Events. :param sns_credentials_id: ID of the credentials to delete. :param region: Region to target. If none is passed will use default region from the config. @@ -695,14 +701,14 @@ def update_sns_credentials( self, *, sns_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, permissions: Optional[SnsPermissions] = None, ) -> SnsCredentials: """ - Update SNS credentials. - Update a set of SNS credentials. You can update the credentials' name, or their permissions. - :param sns_credentials_id: ID of the SNS credentials to update. + Update Topics and Events credentials. + Update a set of Topics and Events credentials. You can update the credentials' name, or their permissions. + :param sns_credentials_id: ID of the Topics and Events credentials to update. :param region: Region to target. If none is passed will use default region from the config. :param name: Name of the credentials. :param permissions: Permissions associated with these credentials. @@ -744,12 +750,12 @@ def get_sns_credentials( self, *, sns_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SnsCredentials: """ - Get SNS credentials. + Get Topics and Events credentials. Retrieve an existing set of credentials, identified by the `credentials_id`. The credentials themselves, as well as their metadata (name, project ID etc), are returned in the response. - :param sns_credentials_id: ID of the SNS credentials to get. + :param sns_credentials_id: ID of the Topics and Events credentials to get. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`SnsCredentials ` @@ -779,17 +785,17 @@ def get_sns_credentials( def list_sns_credentials( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSnsCredentialsRequestOrderBy] = None, ) -> ListSnsCredentialsResponse: """ - List SNS credentials. - List existing SNS credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. + List Topics and Events credentials. + List existing Topics and Events credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Include only SNS credentials in this Project. + :param project_id: Include only Topics and Events credentials in this Project. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. :param order_by: Order in which to return results. @@ -822,17 +828,17 @@ def list_sns_credentials( def list_sns_credentials_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSnsCredentialsRequestOrderBy] = None, ) -> List[SnsCredentials]: """ - List SNS credentials. - List existing SNS credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. + List Topics and Events credentials. + List existing Topics and Events credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Include only SNS credentials in this Project. + :param project_id: Include only Topics and Events credentials in this Project. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. :param order_by: Order in which to return results. @@ -860,20 +866,20 @@ def list_sns_credentials_all( class MnqV1Beta1SqsAPI(API): """ - This API allows you to manage Scaleway Messaging and Queueing SQS brokers. + This API allows you to manage your Scaleway Queues. """ def activate_sqs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SqsInfo: """ - Activate SQS. - Activate SQS for the specified Project ID. SQS must be activated before any usage such as creating credentials and queues. Activating SQS does not trigger any billing, and you can deactivate at any time. + Activate Queues. + Activate Queues for the specified Project ID. Queues must be activated before any usage such as creating credentials and queues. Activating Queues does not trigger any billing, and you can deactivate at any time. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project on which to activate the SQS service. + :param project_id: Project on which to activate the Queues service. :return: :class:`SqsInfo ` Usage: @@ -904,14 +910,14 @@ def activate_sqs( def get_sqs_info( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SqsInfo: """ - Get SQS info. - Retrieve the SQS information of the specified Project ID. Informations include the activation status and the SQS API endpoint URL. + Get Queues info. + Retrieve the Queues information of the specified Project ID. Informations include the activation status and the Queues API endpoint URL. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project to retrieve SQS info from. + :param project_id: Project to retrieve Queues info from. :return: :class:`SqsInfo ` Usage: @@ -938,14 +944,14 @@ def get_sqs_info( def deactivate_sqs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, ) -> SqsInfo: """ - Deactivate SQS. - Deactivate SQS for the specified Project ID. You must delete all queues and credentials before this call or you need to set the force_delete parameter. + Deactivate Queues. + Deactivate Queues for the specified Project ID. You must delete all queues and credentials before this call or you need to set the force_delete parameter. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project on which to deactivate the SQS service. + :param project_id: Project on which to deactivate the Queues service. :return: :class:`SqsInfo ` Usage: @@ -976,16 +982,16 @@ def deactivate_sqs( def create_sqs_credentials( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, name: Optional[str] = None, permissions: Optional[SqsPermissions] = None, ) -> SqsCredentials: """ - Create SQS credentials. - Create a set of credentials for SQS, specified by a Project ID. Credentials give the bearer access to queues, and the level of permissions can be defined granularly. + Create Queues credentials. + Create a set of credentials for Queues, specified by a Project ID. Credentials give the bearer access to queues, and the level of permissions can be defined granularly. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Project containing the SQS credentials. + :param project_id: Project containing the Queues credentials. :param name: Name of the credentials. :param permissions: Permissions associated with these credentials. :return: :class:`SqsCredentials ` @@ -1021,11 +1027,11 @@ def delete_sqs_credentials( self, *, sqs_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ - Delete SQS credentials. - Delete a set of SQS credentials, specified by their credentials ID. Deleting credentials is irreversible and cannot be undone. The credentials can then no longer be used to access SQS. + Delete Queues credentials. + Delete a set of Queues credentials, specified by their credentials ID. Deleting credentials is irreversible and cannot be undone. The credentials can then no longer be used to access Queues. :param sqs_credentials_id: ID of the credentials to delete. :param region: Region to target. If none is passed will use default region from the config. @@ -1055,14 +1061,14 @@ def update_sqs_credentials( self, *, sqs_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, permissions: Optional[SqsPermissions] = None, ) -> SqsCredentials: """ - Update SQS credentials. - Update a set of SQS credentials. You can update the credentials' name, or their permissions. - :param sqs_credentials_id: ID of the SQS credentials to update. + Update Queues credentials. + Update a set of Queues credentials. You can update the credentials' name, or their permissions. + :param sqs_credentials_id: ID of the Queues credentials to update. :param region: Region to target. If none is passed will use default region from the config. :param name: Name of the credentials. :param permissions: Permissions associated with these credentials. @@ -1104,12 +1110,12 @@ def get_sqs_credentials( self, *, sqs_credentials_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SqsCredentials: """ - Get SQS credentials. + Get Queues credentials. Retrieve an existing set of credentials, identified by the `credentials_id`. The credentials themselves, as well as their metadata (name, project ID etc), are returned in the response. - :param sqs_credentials_id: ID of the SQS credentials to get. + :param sqs_credentials_id: ID of the Queues credentials to get. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`SqsCredentials ` @@ -1139,17 +1145,17 @@ def get_sqs_credentials( def list_sqs_credentials( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSqsCredentialsRequestOrderBy] = None, ) -> ListSqsCredentialsResponse: """ - List SQS credentials. - List existing SQS credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. + List Queues credentials. + List existing Queues credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Include only SQS credentials in this Project. + :param project_id: Include only Queues credentials in this Project. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. :param order_by: Order in which to return results. @@ -1182,17 +1188,17 @@ def list_sqs_credentials( def list_sqs_credentials_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListSqsCredentialsRequestOrderBy] = None, ) -> List[SqsCredentials]: """ - List SQS credentials. - List existing SQS credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. + List Queues credentials. + List existing Queues credentials in the specified region. The response contains only the metadata for the credentials, not the credentials themselves. :param region: Region to target. If none is passed will use default region from the config. - :param project_id: Include only SQS credentials in this Project. + :param project_id: Include only Queues credentials in this Project. :param page: Page number to return. :param page_size: Maximum number of credentials to return per page. :param order_by: Order in which to return results. diff --git a/scaleway/scaleway/mnq/v1beta1/marshalling.py b/scaleway/scaleway/mnq/v1beta1/marshalling.py index 1ffebec4..a61ebfcb 100644 --- a/scaleway/scaleway/mnq/v1beta1/marshalling.py +++ b/scaleway/scaleway/mnq/v1beta1/marshalling.py @@ -64,10 +64,14 @@ def unmarshal_NatsAccount(data: Any) -> NatsAccount: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return NatsAccount(**args) @@ -118,14 +122,20 @@ def unmarshal_NatsCredentials(data: Any) -> NatsCredentials: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("credentials", None) if field is not None: args["credentials"] = unmarshal_File(field) + else: + args["credentials"] = None return NatsCredentials(**args) @@ -141,14 +151,20 @@ def unmarshal_SnsPermissions(data: Any) -> SnsPermissions: field = data.get("can_publish", None) if field is not None: args["can_publish"] = field + else: + args["can_publish"] = None field = data.get("can_receive", None) if field is not None: args["can_receive"] = field + else: + args["can_receive"] = None field = data.get("can_manage", None) if field is not None: args["can_manage"] = field + else: + args["can_manage"] = None return SnsPermissions(**args) @@ -192,14 +208,20 @@ def unmarshal_SnsCredentials(data: Any) -> SnsCredentials: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("permissions", None) if field is not None: args["permissions"] = unmarshal_SnsPermissions(field) + else: + args["permissions"] = None return SnsCredentials(**args) @@ -215,14 +237,20 @@ def unmarshal_SqsPermissions(data: Any) -> SqsPermissions: field = data.get("can_publish", None) if field is not None: args["can_publish"] = field + else: + args["can_publish"] = None field = data.get("can_receive", None) if field is not None: args["can_receive"] = field + else: + args["can_receive"] = None field = data.get("can_manage", None) if field is not None: args["can_manage"] = field + else: + args["can_manage"] = None return SqsPermissions(**args) @@ -266,14 +294,20 @@ def unmarshal_SqsCredentials(data: Any) -> SqsCredentials: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("permissions", None) if field is not None: args["permissions"] = unmarshal_SqsPermissions(field) + else: + args["permissions"] = None return SqsCredentials(**args) @@ -389,10 +423,14 @@ def unmarshal_SnsInfo(data: Any) -> SnsInfo: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return SnsInfo(**args) @@ -424,10 +462,14 @@ def unmarshal_SqsInfo(data: Any) -> SqsInfo: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return SqsInfo(**args) @@ -517,7 +559,7 @@ def marshal_SnsApiCreateSnsCredentialsRequest( output["name"] = request.name if request.permissions is not None: - output["permissions"] = (marshal_SnsPermissions(request.permissions, defaults),) + output["permissions"] = marshal_SnsPermissions(request.permissions, defaults) return output @@ -544,7 +586,7 @@ def marshal_SnsApiUpdateSnsCredentialsRequest( output["name"] = request.name if request.permissions is not None: - output["permissions"] = (marshal_SnsPermissions(request.permissions, defaults),) + output["permissions"] = marshal_SnsPermissions(request.permissions, defaults) return output @@ -592,7 +634,7 @@ def marshal_SqsApiCreateSqsCredentialsRequest( output["name"] = request.name if request.permissions is not None: - output["permissions"] = (marshal_SqsPermissions(request.permissions, defaults),) + output["permissions"] = marshal_SqsPermissions(request.permissions, defaults) return output @@ -619,6 +661,6 @@ def marshal_SqsApiUpdateSqsCredentialsRequest( output["name"] = request.name if request.permissions is not None: - output["permissions"] = (marshal_SqsPermissions(request.permissions, defaults),) + output["permissions"] = marshal_SqsPermissions(request.permissions, defaults) return output diff --git a/scaleway/scaleway/mnq/v1beta1/types.py b/scaleway/scaleway/mnq/v1beta1/types.py index d41c5607..29a4a641 100644 --- a/scaleway/scaleway/mnq/v1beta1/types.py +++ b/scaleway/scaleway/mnq/v1beta1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -98,7 +98,7 @@ class File: class SnsPermissions: can_publish: Optional[bool] """ - Defines whether the credentials bearer can publish messages to the service (publish to SNS topics). + Defines whether the credentials bearer can publish messages to the service (publish to Topics and Events topics). """ can_receive: Optional[bool] @@ -108,7 +108,7 @@ class SnsPermissions: can_manage: Optional[bool] """ - Defines whether the credentials bearer can manage the associated SNS topics or subscriptions. + Defines whether the credentials bearer can manage the associated Topics and Events topics or subscriptions. """ @@ -116,17 +116,17 @@ class SnsPermissions: class SqsPermissions: can_publish: Optional[bool] """ - Defines whether the credentials bearer can publish messages to the service (send messages to SQS queues). + Defines whether the credentials bearer can publish messages to the service (send messages to Queues queues). """ can_receive: Optional[bool] """ - Defines whether the credentials bearer can receive messages from SQS queues. + Defines whether the credentials bearer can receive messages from Queues queues. """ can_manage: Optional[bool] """ - Defines whether the credentials bearer can manage the associated SQS queues. + Defines whether the credentials bearer can manage the associated Queues queues. """ @@ -152,7 +152,7 @@ class NatsAccount: Project ID of the Project containing the NATS account. """ - region: Region + region: ScwRegion """ Region where the NATS account is deployed. """ @@ -223,7 +223,7 @@ class SnsCredentials: Project ID of the Project containing the credentials. """ - region: Region + region: ScwRegion """ Region where the credentials exists. """ @@ -235,7 +235,7 @@ class SnsCredentials: secret_key: str """ - Secret key ID (Only returned by **Create SNS Credentials** call). + Secret key ID (Only returned by **Create Topics and Events Credentials** call). """ secret_checksum: str @@ -276,7 +276,7 @@ class SqsCredentials: Project ID of the Project containing the credentials. """ - region: Region + region: ScwRegion """ Region where the credentials exists. """ @@ -288,7 +288,7 @@ class SqsCredentials: secret_key: str """ - Secret key ID (Only returned by **Create SQS Credentials** call). + Secret key ID (Only returned by **Create Queues Credentials** call). """ secret_checksum: str @@ -347,7 +347,7 @@ class ListSnsCredentialsResponse: sns_credentials: List[SnsCredentials] """ - SNS credentials on this page. + Topics and Events credentials on this page. """ @@ -360,13 +360,13 @@ class ListSqsCredentialsResponse: sqs_credentials: List[SqsCredentials] """ - SQS credentials on this page. + Queues credentials on this page. """ @dataclass class NatsApiCreateNatsAccountRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -389,7 +389,7 @@ class NatsApiCreateNatsCredentialsRequest: NATS account containing the credentials. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -407,7 +407,7 @@ class NatsApiDeleteNatsAccountRequest: ID of the NATS account to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -420,7 +420,7 @@ class NatsApiDeleteNatsCredentialsRequest: ID of the credentials to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -433,7 +433,7 @@ class NatsApiGetNatsAccountRequest: ID of the NATS account to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -446,7 +446,7 @@ class NatsApiGetNatsCredentialsRequest: ID of the credentials to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -454,7 +454,7 @@ class NatsApiGetNatsCredentialsRequest: @dataclass class NatsApiListNatsAccountsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -482,11 +482,16 @@ class NatsApiListNatsAccountsRequest: @dataclass class NatsApiListNatsCredentialsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ + project_id: Optional[str] + """ + Include only NATS accounts in this Project. + """ + nats_account_id: Optional[str] """ Include only credentials for this NATS account. @@ -515,7 +520,7 @@ class NatsApiUpdateNatsAccountRequest: ID of the NATS account to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -528,27 +533,27 @@ class NatsApiUpdateNatsAccountRequest: @dataclass class SnsApiActivateSnsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project on which to activate the SNS service. + Project on which to activate the Topics and Events service. """ @dataclass class SnsApiCreateSnsCredentialsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project containing the SNS credentials. + Project containing the Topics and Events credentials. """ name: Optional[str] @@ -564,14 +569,14 @@ class SnsApiCreateSnsCredentialsRequest: @dataclass class SnsApiDeactivateSnsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project on which to deactivate the SNS service. + Project on which to deactivate the Topics and Events service. """ @@ -582,7 +587,7 @@ class SnsApiDeleteSnsCredentialsRequest: ID of the credentials to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -592,10 +597,10 @@ class SnsApiDeleteSnsCredentialsRequest: class SnsApiGetSnsCredentialsRequest: sns_credentials_id: str """ - ID of the SNS credentials to get. + ID of the Topics and Events credentials to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -603,27 +608,27 @@ class SnsApiGetSnsCredentialsRequest: @dataclass class SnsApiGetSnsInfoRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project to retrieve SNS info from. + Project to retrieve Topics and Events info from. """ @dataclass class SnsApiListSnsCredentialsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Include only SNS credentials in this Project. + Include only Topics and Events credentials in this Project. """ page: Optional[int] @@ -646,10 +651,10 @@ class SnsApiListSnsCredentialsRequest: class SnsApiUpdateSnsCredentialsRequest: sns_credentials_id: str """ - ID of the SNS credentials to update. + ID of the Topics and Events credentials to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -672,55 +677,55 @@ class SnsInfo: Project ID of the Project containing the service. """ - region: Region + region: ScwRegion """ Region of the service. """ status: SnsInfoStatus """ - SNS activation status. + Topics and Events activation status. """ sns_endpoint_url: str """ - Endpoint of the SNS service for this region and project. + Endpoint of the Topics and Events service for this region and project. """ created_at: Optional[datetime] """ - SNS creation date. + Topics and Events creation date. """ updated_at: Optional[datetime] """ - SNS last modification date. + Topics and Events last modification date. """ @dataclass class SqsApiActivateSqsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project on which to activate the SQS service. + Project on which to activate the Queues service. """ @dataclass class SqsApiCreateSqsCredentialsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project containing the SQS credentials. + Project containing the Queues credentials. """ name: Optional[str] @@ -736,14 +741,14 @@ class SqsApiCreateSqsCredentialsRequest: @dataclass class SqsApiDeactivateSqsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project on which to deactivate the SQS service. + Project on which to deactivate the Queues service. """ @@ -754,7 +759,7 @@ class SqsApiDeleteSqsCredentialsRequest: ID of the credentials to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -764,10 +769,10 @@ class SqsApiDeleteSqsCredentialsRequest: class SqsApiGetSqsCredentialsRequest: sqs_credentials_id: str """ - ID of the SQS credentials to get. + ID of the Queues credentials to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -775,27 +780,27 @@ class SqsApiGetSqsCredentialsRequest: @dataclass class SqsApiGetSqsInfoRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Project to retrieve SQS info from. + Project to retrieve Queues info from. """ @dataclass class SqsApiListSqsCredentialsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ project_id: Optional[str] """ - Include only SQS credentials in this Project. + Include only Queues credentials in this Project. """ page: Optional[int] @@ -818,10 +823,10 @@ class SqsApiListSqsCredentialsRequest: class SqsApiUpdateSqsCredentialsRequest: sqs_credentials_id: str """ - ID of the SQS credentials to update. + ID of the Queues credentials to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -844,27 +849,27 @@ class SqsInfo: Project ID of the Project containing the service. """ - region: Region + region: ScwRegion """ Region of the service. """ status: SqsInfoStatus """ - SQS activation status. + Queues activation status. """ sqs_endpoint_url: str """ - Endpoint of the SQS service for this region and project. + Endpoint of the Queues service for this region and project. """ created_at: Optional[datetime] """ - SQS creation date. + Queues creation date. """ updated_at: Optional[datetime] """ - SQS last modification date. + Queues last modification date. """ diff --git a/scaleway/scaleway/mongodb/__init__.py b/scaleway/scaleway/mongodb/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway/scaleway/mongodb/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/mongodb/v1alpha1/__init__.py b/scaleway/scaleway/mongodb/v1alpha1/__init__.py new file mode 100644 index 00000000..697dc169 --- /dev/null +++ b/scaleway/scaleway/mongodb/v1alpha1/__init__.py @@ -0,0 +1,121 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import InstanceStatus +from .content import INSTANCE_TRANSIENT_STATUSES +from .types import ListInstancesRequestOrderBy +from .types import ListSnapshotsRequestOrderBy +from .types import ListUsersRequestOrderBy +from .types import NodeTypeStock +from .types import SettingPropertyType +from .types import SnapshotStatus +from .content import SNAPSHOT_TRANSIENT_STATUSES +from .types import UserRoleRole +from .types import VolumeType +from .types import EndpointPrivateNetworkDetails +from .types import EndpointPublicDetails +from .types import EndpointSpecPrivateNetworkDetails +from .types import EndpointSpecPublicDetails +from .types import Endpoint +from .types import InstanceSetting +from .types import Volume +from .types import NodeTypeVolumeType +from .types import SnapshotVolumeType +from .types import UserRole +from .types import Setting +from .types import EndpointSpec +from .types import CreateInstanceRequestVolumeDetails +from .types import Instance +from .types import NodeType +from .types import Snapshot +from .types import User +from .types import Version +from .types import RestoreSnapshotRequestVolumeDetails +from .types import CreateEndpointRequest +from .types import CreateInstanceRequest +from .types import CreateSnapshotRequest +from .types import CreateUserRequest +from .types import DeleteEndpointRequest +from .types import DeleteInstanceRequest +from .types import DeleteSnapshotRequest +from .types import DeleteUserRequest +from .types import GetInstanceCertificateRequest +from .types import GetInstanceRequest +from .types import GetSnapshotRequest +from .types import ListInstancesRequest +from .types import ListInstancesResponse +from .types import ListNodeTypesRequest +from .types import ListNodeTypesResponse +from .types import ListSnapshotsRequest +from .types import ListSnapshotsResponse +from .types import ListUsersRequest +from .types import ListUsersResponse +from .types import ListVersionsRequest +from .types import ListVersionsResponse +from .types import RestoreSnapshotRequest +from .types import SetUserRoleRequest +from .types import UpdateInstanceRequest +from .types import UpdateSnapshotRequest +from .types import UpdateUserRequest +from .types import UpgradeInstanceRequest +from .api import MongodbV1Alpha1API + +__all__ = [ + "InstanceStatus", + "INSTANCE_TRANSIENT_STATUSES", + "ListInstancesRequestOrderBy", + "ListSnapshotsRequestOrderBy", + "ListUsersRequestOrderBy", + "NodeTypeStock", + "SettingPropertyType", + "SnapshotStatus", + "SNAPSHOT_TRANSIENT_STATUSES", + "UserRoleRole", + "VolumeType", + "EndpointPrivateNetworkDetails", + "EndpointPublicDetails", + "EndpointSpecPrivateNetworkDetails", + "EndpointSpecPublicDetails", + "Endpoint", + "InstanceSetting", + "Volume", + "NodeTypeVolumeType", + "SnapshotVolumeType", + "UserRole", + "Setting", + "EndpointSpec", + "CreateInstanceRequestVolumeDetails", + "Instance", + "NodeType", + "Snapshot", + "User", + "Version", + "RestoreSnapshotRequestVolumeDetails", + "CreateEndpointRequest", + "CreateInstanceRequest", + "CreateSnapshotRequest", + "CreateUserRequest", + "DeleteEndpointRequest", + "DeleteInstanceRequest", + "DeleteSnapshotRequest", + "DeleteUserRequest", + "GetInstanceCertificateRequest", + "GetInstanceRequest", + "GetSnapshotRequest", + "ListInstancesRequest", + "ListInstancesResponse", + "ListNodeTypesRequest", + "ListNodeTypesResponse", + "ListSnapshotsRequest", + "ListSnapshotsResponse", + "ListUsersRequest", + "ListUsersResponse", + "ListVersionsRequest", + "ListVersionsResponse", + "RestoreSnapshotRequest", + "SetUserRoleRequest", + "UpdateInstanceRequest", + "UpdateSnapshotRequest", + "UpdateUserRequest", + "UpgradeInstanceRequest", + "MongodbV1Alpha1API", +] diff --git a/scaleway/scaleway/mongodb/v1alpha1/api.py b/scaleway/scaleway/mongodb/v1alpha1/api.py new file mode 100644 index 00000000..1af85656 --- /dev/null +++ b/scaleway/scaleway/mongodb/v1alpha1/api.py @@ -0,0 +1,1333 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from datetime import datetime +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, + ScwFile, + unmarshal_ScwFile, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + ListInstancesRequestOrderBy, + ListSnapshotsRequestOrderBy, + ListUsersRequestOrderBy, + CreateEndpointRequest, + CreateInstanceRequest, + CreateInstanceRequestVolumeDetails, + CreateSnapshotRequest, + CreateUserRequest, + Endpoint, + EndpointSpec, + Instance, + ListInstancesResponse, + ListNodeTypesResponse, + ListSnapshotsResponse, + ListUsersResponse, + ListVersionsResponse, + NodeType, + RestoreSnapshotRequest, + RestoreSnapshotRequestVolumeDetails, + SetUserRoleRequest, + Snapshot, + UpdateInstanceRequest, + UpdateSnapshotRequest, + UpdateUserRequest, + UpgradeInstanceRequest, + User, + UserRole, + Version, +) +from .content import ( + INSTANCE_TRANSIENT_STATUSES, + SNAPSHOT_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_Endpoint, + unmarshal_Instance, + unmarshal_Snapshot, + unmarshal_User, + unmarshal_ListInstancesResponse, + unmarshal_ListNodeTypesResponse, + unmarshal_ListSnapshotsResponse, + unmarshal_ListUsersResponse, + unmarshal_ListVersionsResponse, + marshal_CreateEndpointRequest, + marshal_CreateInstanceRequest, + marshal_CreateSnapshotRequest, + marshal_CreateUserRequest, + marshal_RestoreSnapshotRequest, + marshal_SetUserRoleRequest, + marshal_UpdateInstanceRequest, + marshal_UpdateSnapshotRequest, + marshal_UpdateUserRequest, + marshal_UpgradeInstanceRequest, +) + + +class MongodbV1Alpha1API(API): + """ + This API allows you to manage your Managed Databases for MongoDB®. + """ + + def list_node_types( + self, + *, + region: Optional[ScwRegion] = None, + include_disabled_types: Optional[bool] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListNodeTypesResponse: + """ + List available node types. + :param region: Region to target. If none is passed will use default region from the config. + :param include_disabled_types: Defines whether or not to include disabled types. + :param page: + :param page_size: + :return: :class:`ListNodeTypesResponse ` + + Usage: + :: + + result = api.list_node_types() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/node-types", + params={ + "include_disabled_types": include_disabled_types, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListNodeTypesResponse(res.json()) + + def list_node_types_all( + self, + *, + region: Optional[ScwRegion] = None, + include_disabled_types: Optional[bool] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[NodeType]: + """ + List available node types. + :param region: Region to target. If none is passed will use default region from the config. + :param include_disabled_types: Defines whether or not to include disabled types. + :param page: + :param page_size: + :return: :class:`List[NodeType] ` + + Usage: + :: + + result = api.list_node_types_all() + """ + + return fetch_all_pages( + type=ListNodeTypesResponse, + key="node_types", + fetcher=self.list_node_types, + args={ + "region": region, + "include_disabled_types": include_disabled_types, + "page": page, + "page_size": page_size, + }, + ) + + def list_versions( + self, + *, + region: Optional[ScwRegion] = None, + version: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListVersionsResponse: + """ + List available MongoDB® versions. + :param region: Region to target. If none is passed will use default region from the config. + :param version: + :param page: + :param page_size: + :return: :class:`ListVersionsResponse ` + + Usage: + :: + + result = api.list_versions() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/versions", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "version": version, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListVersionsResponse(res.json()) + + def list_versions_all( + self, + *, + region: Optional[ScwRegion] = None, + version: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[Version]: + """ + List available MongoDB® versions. + :param region: Region to target. If none is passed will use default region from the config. + :param version: + :param page: + :param page_size: + :return: :class:`List[Version] ` + + Usage: + :: + + result = api.list_versions_all() + """ + + return fetch_all_pages( + type=ListVersionsResponse, + key="versions", + fetcher=self.list_versions, + args={ + "region": region, + "version": version, + "page": page, + "page_size": page_size, + }, + ) + + def list_instances( + self, + *, + region: Optional[ScwRegion] = None, + tags: Optional[List[str]] = None, + name: Optional[str] = None, + order_by: Optional[ListInstancesRequestOrderBy] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListInstancesResponse: + """ + List MongoDB® Database Instances. + List all MongoDB® Database Instances in the specified region. By default, the MongoDB® Database Instances returned in the list are ordered by creation date in ascending order, though this can be modified via the order_by field. You can define additional parameters for your query, such as `tags` and `name`. For the `name` parameter, the value you include will be checked against the whole name string to see if it includes the string you put in the parameter. + :param region: Region to target. If none is passed will use default region from the config. + :param tags: List Database Instances that have a given tag. + :param name: Lists Database Instances that match a name pattern. + :param order_by: Criteria to use when ordering Database Instance listings. + :param organization_id: Organization ID of the Database Instance. + :param project_id: Project ID. + :param page: + :param page_size: + :return: :class:`ListInstancesResponse ` + + Usage: + :: + + result = api.list_instances() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/instances", + params={ + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListInstancesResponse(res.json()) + + def list_instances_all( + self, + *, + region: Optional[ScwRegion] = None, + tags: Optional[List[str]] = None, + name: Optional[str] = None, + order_by: Optional[ListInstancesRequestOrderBy] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[Instance]: + """ + List MongoDB® Database Instances. + List all MongoDB® Database Instances in the specified region. By default, the MongoDB® Database Instances returned in the list are ordered by creation date in ascending order, though this can be modified via the order_by field. You can define additional parameters for your query, such as `tags` and `name`. For the `name` parameter, the value you include will be checked against the whole name string to see if it includes the string you put in the parameter. + :param region: Region to target. If none is passed will use default region from the config. + :param tags: List Database Instances that have a given tag. + :param name: Lists Database Instances that match a name pattern. + :param order_by: Criteria to use when ordering Database Instance listings. + :param organization_id: Organization ID of the Database Instance. + :param project_id: Project ID. + :param page: + :param page_size: + :return: :class:`List[Instance] ` + + Usage: + :: + + result = api.list_instances_all() + """ + + return fetch_all_pages( + type=ListInstancesResponse, + key="instances", + fetcher=self.list_instances, + args={ + "region": region, + "tags": tags, + "name": name, + "order_by": order_by, + "organization_id": organization_id, + "project_id": project_id, + "page": page, + "page_size": page_size, + }, + ) + + def get_instance( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + ) -> Instance: + """ + Get a MongoDB® Database Instance. + Retrieve information about a given MongoDB® Database Instance, specified by the `region` and `instance_id` parameters. Its full details, including name, status, IP address and port, are returned in the response object. + :param instance_id: UUID of the Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Instance ` + + Usage: + :: + + result = api.get_instance( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}", + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + def wait_for_instance( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Instance, bool]] = None, + ) -> Instance: + """ + Get a MongoDB® Database Instance. + Retrieve information about a given MongoDB® Database Instance, specified by the `region` and `instance_id` parameters. Its full details, including name, status, IP address and port, are returned in the response object. + :param instance_id: UUID of the Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Instance ` + + Usage: + :: + + result = api.get_instance( + instance_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in INSTANCE_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_instance, + options=options, + args={ + "instance_id": instance_id, + "region": region, + }, + ) + + def create_instance( + self, + *, + version: str, + node_number: int, + node_type: str, + user_name: str, + password: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + volume: Optional[CreateInstanceRequestVolumeDetails] = None, + endpoints: Optional[List[EndpointSpec]] = None, + ) -> Instance: + """ + Create a MongoDB® Database Instance. + Create a new MongoDB® Database Instance. + :param version: Version of the MongoDB® engine. + :param node_number: Number of node to use for the Database Instance. + :param node_type: Type of node to use for the Database Instance. + :param user_name: Username created when the Database Instance is created. + :param password: Password of the initial user. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: The Project ID on which the Database Instance will be created. + :param name: Name of the Database Instance. + :param tags: Tags to apply to the Database Instance. + :param volume: Instance volume information. + :param endpoints: One or multiple EndpointSpec used to expose your Database Instance. + :return: :class:`Instance ` + + Usage: + :: + + result = api.create_instance( + version="example", + node_number=1, + node_type="example", + user_name="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/instances", + body=marshal_CreateInstanceRequest( + CreateInstanceRequest( + version=version, + node_number=node_number, + node_type=node_type, + user_name=user_name, + password=password, + region=region, + project_id=project_id, + name=name or random_name(prefix="mgdb"), + tags=tags, + volume=volume, + endpoints=endpoints, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + def update_instance( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> Instance: + """ + Update a MongoDB® Database Instance. + Update the parameters of a MongoDB® Database Instance. + :param instance_id: UUID of the Database Instance to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the Database Instance. + :param tags: Tags of a Database Instance. + :return: :class:`Instance ` + + Usage: + :: + + result = api.update_instance( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "PATCH", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}", + body=marshal_UpdateInstanceRequest( + UpdateInstanceRequest( + instance_id=instance_id, + region=region, + name=name, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + def delete_instance( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + ) -> Instance: + """ + Delete a MongoDB® Database Instance. + Delete a given MongoDB® Database Instance, specified by the `region` and `instance_id` parameters. Deleting a MongoDB® Database Instance is permanent, and cannot be undone. Note that upon deletion all your data will be lost. + :param instance_id: UUID of the Database Instance to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Instance ` + + Usage: + :: + + result = api.delete_instance( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "DELETE", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}", + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + def upgrade_instance( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + volume_size: Optional[int] = None, + ) -> Instance: + """ + Upgrade a Database Instance. + Upgrade your current Database Instance specifications like volume size. + :param instance_id: UUID of the Database Instance you want to upgrade. + :param region: Region to target. If none is passed will use default region from the config. + :param volume_size: Increase your Block Storage volume size. + One-Of ('upgrade_target'): at most one of 'volume_size' could be set. + :return: :class:`Instance ` + + Usage: + :: + + result = api.upgrade_instance( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/upgrade", + body=marshal_UpgradeInstanceRequest( + UpgradeInstanceRequest( + instance_id=instance_id, + region=region, + volume_size=volume_size, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + def get_instance_certificate( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + ) -> ScwFile: + """ + Get the certificate of a Database Instance. + Retrieve the certificate of a given Database Instance, specified by the `instance_id` parameter. + :param instance_id: UUID of the Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ScwFile ` + + Usage: + :: + + result = api.get_instance_certificate( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/certificate", + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + def create_snapshot( + self, + *, + instance_id: str, + name: str, + region: Optional[ScwRegion] = None, + expires_at: Optional[datetime] = None, + ) -> Snapshot: + """ + Create a Database Instance snapshot. + Create a new snapshot of a Database Instance. You must define the `name` and `instance_id` parameters in the request. + :param instance_id: UUID of the Database Instance to snapshot. + :param name: Name of the snapshot. + :param region: Region to target. If none is passed will use default region from the config. + :param expires_at: Expiration date of the snapshot (must follow the ISO 8601 format). + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.create_snapshot( + instance_id="example", + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/snapshots", + body=marshal_CreateSnapshotRequest( + CreateSnapshotRequest( + instance_id=instance_id, + name=name, + region=region, + expires_at=expires_at, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def get_snapshot( + self, + *, + snapshot_id: str, + region: Optional[ScwRegion] = None, + ) -> Snapshot: + """ + Get a Database Instance snapshot. + Retrieve information about a given snapshot of a Database Instance. You must specify, in the endpoint, the `snapshot_id` parameter of the snapshot you want to retrieve. + :param snapshot_id: UUID of the snapshot. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.get_snapshot( + snapshot_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def wait_for_snapshot( + self, + *, + snapshot_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Snapshot, bool]] = None, + ) -> Snapshot: + """ + Get a Database Instance snapshot. + Retrieve information about a given snapshot of a Database Instance. You must specify, in the endpoint, the `snapshot_id` parameter of the snapshot you want to retrieve. + :param snapshot_id: UUID of the snapshot. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.get_snapshot( + snapshot_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in SNAPSHOT_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_snapshot, + options=options, + args={ + "snapshot_id": snapshot_id, + "region": region, + }, + ) + + def update_snapshot( + self, + *, + snapshot_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + expires_at: Optional[datetime] = None, + ) -> Snapshot: + """ + Update a Database Instance snapshot. + Update the parameters of a snapshot of a Database Instance. You can update the `name` and `expires_at` parameters. + :param snapshot_id: UUID of the Snapshot. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the snapshot. + :param expires_at: Expiration date of the snapshot (must follow the ISO 8601 format). + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.update_snapshot( + snapshot_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/snapshots/{param_snapshot_id}", + body=marshal_UpdateSnapshotRequest( + UpdateSnapshotRequest( + snapshot_id=snapshot_id, + region=region, + name=name, + expires_at=expires_at, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def restore_snapshot( + self, + *, + snapshot_id: str, + instance_name: str, + node_type: str, + node_number: int, + volume: RestoreSnapshotRequestVolumeDetails, + region: Optional[ScwRegion] = None, + ) -> Instance: + """ + Restore a Database Instance snapshot. + Restore a given snapshot of a Database Instance. You must specify, in the endpoint, the `snapshot_id` parameter of the snapshot you want to restore, the `instance_name` of the new Database Instance, `node_type` of the new Database Instance and `node_number` of the new Database Instance. + :param snapshot_id: UUID of the snapshot. + :param instance_name: Name of the new Database Instance. + :param node_type: Node type to use for the new Database Instance. + :param node_number: Number of nodes to use for the new Database Instance. + :param volume: Instance volume information. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Instance ` + + Usage: + :: + + result = api.restore_snapshot( + snapshot_id="example", + instance_name="example", + node_type="example", + node_number=1, + volume=RestoreSnapshotRequestVolumeDetails(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/snapshots/{param_snapshot_id}/restore", + body=marshal_RestoreSnapshotRequest( + RestoreSnapshotRequest( + snapshot_id=snapshot_id, + instance_name=instance_name, + node_type=node_type, + node_number=node_number, + volume=volume, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Instance(res.json()) + + def list_snapshots( + self, + *, + region: Optional[ScwRegion] = None, + instance_id: Optional[str] = None, + name: Optional[str] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListSnapshotsResponse: + """ + List snapshots. + List snapshots. You can include the `instance_id` or `project_id` in your query to get the list of snapshots for specific Database Instances and/or Projects. By default, the details returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param instance_id: Instance ID the snapshots belongs to. + :param name: Lists database snapshots that match a name pattern. + :param order_by: Criteria to use when ordering snapshot listings. + :param organization_id: Organization ID the snapshots belongs to. + :param project_id: Project ID to list the snapshots of. + :param page: + :param page_size: + :return: :class:`ListSnapshotsResponse ` + + Usage: + :: + + result = api.list_snapshots() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/snapshots", + params={ + "instance_id": instance_id, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListSnapshotsResponse(res.json()) + + def list_snapshots_all( + self, + *, + region: Optional[ScwRegion] = None, + instance_id: Optional[str] = None, + name: Optional[str] = None, + order_by: Optional[ListSnapshotsRequestOrderBy] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[Snapshot]: + """ + List snapshots. + List snapshots. You can include the `instance_id` or `project_id` in your query to get the list of snapshots for specific Database Instances and/or Projects. By default, the details returned in the list are ordered by creation date in ascending order, though this can be modified via the `order_by` field. + :param region: Region to target. If none is passed will use default region from the config. + :param instance_id: Instance ID the snapshots belongs to. + :param name: Lists database snapshots that match a name pattern. + :param order_by: Criteria to use when ordering snapshot listings. + :param organization_id: Organization ID the snapshots belongs to. + :param project_id: Project ID to list the snapshots of. + :param page: + :param page_size: + :return: :class:`List[Snapshot] ` + + Usage: + :: + + result = api.list_snapshots_all() + """ + + return fetch_all_pages( + type=ListSnapshotsResponse, + key="snapshots", + fetcher=self.list_snapshots, + args={ + "region": region, + "instance_id": instance_id, + "name": name, + "order_by": order_by, + "organization_id": organization_id, + "project_id": project_id, + "page": page, + "page_size": page_size, + }, + ) + + def delete_snapshot( + self, + *, + snapshot_id: str, + region: Optional[ScwRegion] = None, + ) -> Snapshot: + """ + Delete a Database Instance snapshot. + Delete a given snapshot of a Database Instance. You must specify, in the endpoint, the `snapshot_id` parameter of the snapshot you want to delete. + :param snapshot_id: UUID of the snapshot. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Snapshot ` + + Usage: + :: + + result = api.delete_snapshot( + snapshot_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_snapshot_id = validate_path_param("snapshot_id", snapshot_id) + + res = self._request( + "DELETE", + f"/mongodb/v1alpha1/regions/{param_region}/snapshots/{param_snapshot_id}", + ) + + self._throw_on_error(res) + return unmarshal_Snapshot(res.json()) + + def list_users( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + order_by: Optional[ListUsersRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListUsersResponse: + """ + List users of a Database Instance. + List all users of a given Database Instance. + :param instance_id: UUID of the Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the user. + :param order_by: Criteria to use when requesting user listing. + :param page: + :param page_size: + :return: :class:`ListUsersResponse ` + + Usage: + :: + + result = api.list_users( + instance_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "GET", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/users", + params={ + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListUsersResponse(res.json()) + + def list_users_all( + self, + *, + instance_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + order_by: Optional[ListUsersRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[User]: + """ + List users of a Database Instance. + List all users of a given Database Instance. + :param instance_id: UUID of the Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the user. + :param order_by: Criteria to use when requesting user listing. + :param page: + :param page_size: + :return: :class:`List[User] ` + + Usage: + :: + + result = api.list_users_all( + instance_id="example", + ) + """ + + return fetch_all_pages( + type=ListUsersResponse, + key="users", + fetcher=self.list_users, + args={ + "instance_id": instance_id, + "region": region, + "name": name, + "order_by": order_by, + "page": page, + "page_size": page_size, + }, + ) + + def create_user( + self, + *, + instance_id: str, + name: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> User: + """ + Create an user on a Database Instance. + Create an user on a Database Instance. You must define the `name`, `password` of the user and `instance_id` parameters in the request. + :param instance_id: UUID of the Database Instance the user belongs to. + :param name: Name of the database user. + :param password: Password of the database user. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`User ` + + Usage: + :: + + result = api.create_user( + instance_id="example", + name="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/users", + body=marshal_CreateUserRequest( + CreateUserRequest( + instance_id=instance_id, + name=name, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + def update_user( + self, + *, + instance_id: str, + name: str, + region: Optional[ScwRegion] = None, + password: Optional[str] = None, + ) -> User: + """ + Update a user on a Database Instance. + Update the parameters of a user on a Database Instance. You can update the `password` parameter, but you cannot change the name of the user. + :param instance_id: UUID of the Database Instance the user belongs to. + :param name: Name of the database user. + :param region: Region to target. If none is passed will use default region from the config. + :param password: Password of the database user. + :return: :class:`User ` + + Usage: + :: + + result = api.update_user( + instance_id="example", + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + param_name = validate_path_param("name", name) + + res = self._request( + "PATCH", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/users/{param_name}", + body=marshal_UpdateUserRequest( + UpdateUserRequest( + instance_id=instance_id, + name=name, + region=region, + password=password, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + def delete_user( + self, + *, + instance_id: str, + name: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a user on a Database Instance. + Delete an existing user on a Database Instance. + :param instance_id: UUID of the Database Instance the user belongs to. + :param name: Name of the database user. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_user( + instance_id="example", + name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + param_name = validate_path_param("name", name) + + res = self._request( + "DELETE", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/users/{param_name}", + body={}, + ) + + self._throw_on_error(res) + + def set_user_role( + self, + *, + instance_id: str, + user_name: str, + region: Optional[ScwRegion] = None, + roles: Optional[List[UserRole]] = None, + ) -> User: + """ + :param instance_id: UUID of the Database Instance the user belongs to. + :param user_name: Name of the database user. + :param region: Region to target. If none is passed will use default region from the config. + :param roles: List of roles assigned to the user, along with the corresponding database where each role is granted. + :return: :class:`User ` + + Usage: + :: + + result = api.set_user_role( + instance_id="example", + user_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_instance_id = validate_path_param("instance_id", instance_id) + + res = self._request( + "PUT", + f"/mongodb/v1alpha1/regions/{param_region}/instances/{param_instance_id}/roles", + body=marshal_SetUserRoleRequest( + SetUserRoleRequest( + instance_id=instance_id, + user_name=user_name, + region=region, + roles=roles, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_User(res.json()) + + def delete_endpoint( + self, + *, + endpoint_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a Database Instance endpoint. + Delete the endpoint of a Database Instance. You must specify the `endpoint_id` parameter of the endpoint you want to delete. Note that you might need to update any environment configurations that point to the deleted endpoint. + :param endpoint_id: UUID of the Endpoint to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_endpoint( + endpoint_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_endpoint_id = validate_path_param("endpoint_id", endpoint_id) + + res = self._request( + "DELETE", + f"/mongodb/v1alpha1/regions/{param_region}/endpoints/{param_endpoint_id}", + ) + + self._throw_on_error(res) + + def create_endpoint( + self, + *, + instance_id: str, + endpoint: EndpointSpec, + region: Optional[ScwRegion] = None, + ) -> Endpoint: + """ + Create a new Instance endpoint. + Create a new endpoint for a MongoDB® Database Instance. You can add `public_network` or `private_network` specifications to the body of the request. + :param instance_id: UUID of the Database Instance. + :param endpoint: EndpointSpec used to expose your Database Instance. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Endpoint ` + + Usage: + :: + + result = api.create_endpoint( + instance_id="example", + endpoint=EndpointSpec(), + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/mongodb/v1alpha1/regions/{param_region}/endpoints", + body=marshal_CreateEndpointRequest( + CreateEndpointRequest( + instance_id=instance_id, + endpoint=endpoint, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Endpoint(res.json()) diff --git a/scaleway/scaleway/mongodb/v1alpha1/content.py b/scaleway/scaleway/mongodb/v1alpha1/content.py new file mode 100644 index 00000000..8e009220 --- /dev/null +++ b/scaleway/scaleway/mongodb/v1alpha1/content.py @@ -0,0 +1,27 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + InstanceStatus, + SnapshotStatus, +) + +INSTANCE_TRANSIENT_STATUSES: List[InstanceStatus] = [ + InstanceStatus.PROVISIONING, + InstanceStatus.CONFIGURING, + InstanceStatus.DELETING, + InstanceStatus.INITIALIZING, + InstanceStatus.SNAPSHOTTING, +] +""" +Lists transient statutes of the enum :class:`InstanceStatus `. +""" +SNAPSHOT_TRANSIENT_STATUSES: List[SnapshotStatus] = [ + SnapshotStatus.CREATING, + SnapshotStatus.RESTORING, + SnapshotStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`SnapshotStatus `. +""" diff --git a/scaleway/scaleway/mongodb/v1alpha1/marshalling.py b/scaleway/scaleway/mongodb/v1alpha1/marshalling.py new file mode 100644 index 00000000..9b267ac1 --- /dev/null +++ b/scaleway/scaleway/mongodb/v1alpha1/marshalling.py @@ -0,0 +1,903 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + EndpointPrivateNetworkDetails, + EndpointPublicDetails, + Endpoint, + InstanceSetting, + Volume, + Instance, + SnapshotVolumeType, + Snapshot, + UserRole, + User, + ListInstancesResponse, + NodeTypeVolumeType, + NodeType, + ListNodeTypesResponse, + ListSnapshotsResponse, + ListUsersResponse, + Setting, + Version, + ListVersionsResponse, + EndpointSpecPrivateNetworkDetails, + EndpointSpecPublicDetails, + EndpointSpec, + CreateEndpointRequest, + CreateInstanceRequestVolumeDetails, + CreateInstanceRequest, + CreateSnapshotRequest, + CreateUserRequest, + RestoreSnapshotRequestVolumeDetails, + RestoreSnapshotRequest, + SetUserRoleRequest, + UpdateInstanceRequest, + UpdateSnapshotRequest, + UpdateUserRequest, + UpgradeInstanceRequest, +) + + +def unmarshal_EndpointPrivateNetworkDetails(data: Any) -> EndpointPrivateNetworkDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPrivateNetworkDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + return EndpointPrivateNetworkDetails(**args) + + +def unmarshal_EndpointPublicDetails(data: Any) -> EndpointPublicDetails: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EndpointPublicDetails' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + return EndpointPublicDetails(**args) + + +def unmarshal_Endpoint(data: Any) -> Endpoint: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Endpoint' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("ips", None) + if field is not None: + args["ips"] = field + + field = data.get("dns_records", None) + if field is not None: + args["dns_records"] = field + + field = data.get("port", None) + if field is not None: + args["port"] = field + + field = data.get("private_network", None) + if field is not None: + args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None + + field = data.get("public", None) + if field is not None: + args["public"] = unmarshal_EndpointPublicDetails(field) + else: + args["public"] = None + + return Endpoint(**args) + + +def unmarshal_InstanceSetting(data: Any) -> InstanceSetting: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'InstanceSetting' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + return InstanceSetting(**args) + + +def unmarshal_Volume(data: Any) -> Volume: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Volume' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + return Volume(**args) + + +def unmarshal_Instance(data: Any) -> Instance: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Instance' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("settings", None) + if field is not None: + args["settings"] = ( + [unmarshal_InstanceSetting(v) for v in field] if field is not None else None + ) + + field = data.get("node_number", None) + if field is not None: + args["node_number"] = field + + field = data.get("node_type", None) + if field is not None: + args["node_type"] = field + + field = data.get("endpoints", None) + if field is not None: + args["endpoints"] = ( + [unmarshal_Endpoint(v) for v in field] if field is not None else None + ) + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("volume", None) + if field is not None: + args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + return Instance(**args) + + +def unmarshal_SnapshotVolumeType(data: Any) -> SnapshotVolumeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SnapshotVolumeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return SnapshotVolumeType(**args) + + +def unmarshal_Snapshot(data: Any) -> Snapshot: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Snapshot' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("instance_id", None) + if field is not None: + args["instance_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("instance_name", None) + if field is not None: + args["instance_name"] = field + + field = data.get("node_type", None) + if field is not None: + args["node_type"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("expires_at", None) + if field is not None: + args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("volume_type", None) + if field is not None: + args["volume_type"] = unmarshal_SnapshotVolumeType(field) + else: + args["volume_type"] = None + + return Snapshot(**args) + + +def unmarshal_UserRole(data: Any) -> UserRole: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'UserRole' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("role", None) + if field is not None: + args["role"] = field + + field = data.get("database", None) + if field is not None: + args["database"] = field + else: + args["database"] = None + + field = data.get("any_database", None) + if field is not None: + args["any_database"] = field + else: + args["any_database"] = None + + return UserRole(**args) + + +def unmarshal_User(data: Any) -> User: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'User' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("roles", None) + if field is not None: + args["roles"] = ( + [unmarshal_UserRole(v) for v in field] if field is not None else None + ) + + return User(**args) + + +def unmarshal_ListInstancesResponse(data: Any) -> ListInstancesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListInstancesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("instances", None) + if field is not None: + args["instances"] = ( + [unmarshal_Instance(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListInstancesResponse(**args) + + +def unmarshal_NodeTypeVolumeType(data: Any) -> NodeTypeVolumeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeTypeVolumeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("min_size", None) + if field is not None: + args["min_size"] = field + + field = data.get("max_size", None) + if field is not None: + args["max_size"] = field + + field = data.get("chunk_size", None) + if field is not None: + args["chunk_size"] = field + + return NodeTypeVolumeType(**args) + + +def unmarshal_NodeType(data: Any) -> NodeType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'NodeType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("stock_status", None) + if field is not None: + args["stock_status"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("vcpus", None) + if field is not None: + args["vcpus"] = field + + field = data.get("memory", None) + if field is not None: + args["memory"] = field + + field = data.get("available_volume_types", None) + if field is not None: + args["available_volume_types"] = ( + [unmarshal_NodeTypeVolumeType(v) for v in field] + if field is not None + else None + ) + + field = data.get("disabled", None) + if field is not None: + args["disabled"] = field + + field = data.get("beta", None) + if field is not None: + args["beta"] = field + + field = data.get("instance_range", None) + if field is not None: + args["instance_range"] = field + + return NodeType(**args) + + +def unmarshal_ListNodeTypesResponse(data: Any) -> ListNodeTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListNodeTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("node_types", None) + if field is not None: + args["node_types"] = ( + [unmarshal_NodeType(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListNodeTypesResponse(**args) + + +def unmarshal_ListSnapshotsResponse(data: Any) -> ListSnapshotsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSnapshotsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("snapshots", None) + if field is not None: + args["snapshots"] = ( + [unmarshal_Snapshot(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListSnapshotsResponse(**args) + + +def unmarshal_ListUsersResponse(data: Any) -> ListUsersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListUsersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("users", None) + if field is not None: + args["users"] = ( + [unmarshal_User(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListUsersResponse(**args) + + +def unmarshal_Setting(data: Any) -> Setting: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Setting' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("default_value", None) + if field is not None: + args["default_value"] = field + + field = data.get("hot_configurable", None) + if field is not None: + args["hot_configurable"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("property_type", None) + if field is not None: + args["property_type"] = field + + field = data.get("unit", None) + if field is not None: + args["unit"] = field + else: + args["unit"] = None + + field = data.get("string_constraint", None) + if field is not None: + args["string_constraint"] = field + else: + args["string_constraint"] = None + + field = data.get("int_min", None) + if field is not None: + args["int_min"] = field + else: + args["int_min"] = None + + field = data.get("int_max", None) + if field is not None: + args["int_max"] = field + else: + args["int_max"] = None + + field = data.get("float_min", None) + if field is not None: + args["float_min"] = field + else: + args["float_min"] = None + + field = data.get("float_max", None) + if field is not None: + args["float_max"] = field + else: + args["float_max"] = None + + return Setting(**args) + + +def unmarshal_Version(data: Any) -> Version: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Version' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("version", None) + if field is not None: + args["version"] = field + + field = data.get("available_settings", None) + if field is not None: + args["available_settings"] = ( + [unmarshal_Setting(v) for v in field] if field is not None else None + ) + + field = data.get("end_of_life_at", None) + if field is not None: + args["end_of_life_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["end_of_life_at"] = None + + return Version(**args) + + +def unmarshal_ListVersionsResponse(data: Any) -> ListVersionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListVersionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("versions", None) + if field is not None: + args["versions"] = ( + [unmarshal_Version(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListVersionsResponse(**args) + + +def marshal_EndpointSpecPrivateNetworkDetails( + request: EndpointSpecPrivateNetworkDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + return output + + +def marshal_EndpointSpecPublicDetails( + request: EndpointSpecPublicDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + return output + + +def marshal_EndpointSpec( + request: EndpointSpec, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("public", request.public), + OneOfPossibility("private_network", request.private_network), + ] + ), + ) + + return output + + +def marshal_CreateEndpointRequest( + request: CreateEndpointRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.instance_id is not None: + output["instance_id"] = request.instance_id + + if request.endpoint is not None: + output["endpoint"] = marshal_EndpointSpec(request.endpoint, defaults) + + return output + + +def marshal_CreateInstanceRequestVolumeDetails( + request: CreateInstanceRequestVolumeDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.volume_size is not None: + output["volume_size"] = request.volume_size + + if request.volume_type is not None: + output["volume_type"] = str(request.volume_type) + + return output + + +def marshal_CreateInstanceRequest( + request: CreateInstanceRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.version is not None: + output["version"] = request.version + + if request.node_number is not None: + output["node_number"] = request.node_number + + if request.node_type is not None: + output["node_type"] = request.node_type + + if request.user_name is not None: + output["user_name"] = request.user_name + + if request.password is not None: + output["password"] = request.password + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.volume is not None: + output["volume"] = marshal_CreateInstanceRequestVolumeDetails( + request.volume, defaults + ) + + if request.endpoints is not None: + output["endpoints"] = [ + marshal_EndpointSpec(item, defaults) for item in request.endpoints + ] + + return output + + +def marshal_CreateSnapshotRequest( + request: CreateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.expires_at is not None: + output["expires_at"] = request.expires_at.isoformat() + + return output + + +def marshal_CreateUserRequest( + request: CreateUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_RestoreSnapshotRequestVolumeDetails( + request: RestoreSnapshotRequestVolumeDetails, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.volume_type is not None: + output["volume_type"] = str(request.volume_type) + + return output + + +def marshal_RestoreSnapshotRequest( + request: RestoreSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.instance_name is not None: + output["instance_name"] = request.instance_name + + if request.node_type is not None: + output["node_type"] = request.node_type + + if request.node_number is not None: + output["node_number"] = request.node_number + + if request.volume is not None: + output["volume"] = marshal_RestoreSnapshotRequestVolumeDetails( + request.volume, defaults + ) + + return output + + +def marshal_UserRole( + request: UserRole, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("database", request.database), + OneOfPossibility("any_database", request.any_database), + ] + ), + ) + + if request.role is not None: + output["role"] = str(request.role) + + return output + + +def marshal_SetUserRoleRequest( + request: SetUserRoleRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.user_name is not None: + output["user_name"] = request.user_name + + if request.roles is not None: + output["roles"] = [marshal_UserRole(item, defaults) for item in request.roles] + + return output + + +def marshal_UpdateInstanceRequest( + request: UpdateInstanceRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_UpdateSnapshotRequest( + request: UpdateSnapshotRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.expires_at is not None: + output["expires_at"] = request.expires_at.isoformat() + + return output + + +def marshal_UpdateUserRequest( + request: UpdateUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_UpgradeInstanceRequest( + request: UpgradeInstanceRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("volume_size", request.volume_size), + ] + ), + ) + + return output diff --git a/scaleway/scaleway/mongodb/v1alpha1/types.py b/scaleway/scaleway/mongodb/v1alpha1/types.py new file mode 100644 index 00000000..200da384 --- /dev/null +++ b/scaleway/scaleway/mongodb/v1alpha1/types.py @@ -0,0 +1,1091 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class InstanceStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + READY = "ready" + PROVISIONING = "provisioning" + CONFIGURING = "configuring" + DELETING = "deleting" + ERROR = "error" + INITIALIZING = "initializing" + LOCKED = "locked" + SNAPSHOTTING = "snapshotting" + + def __str__(self) -> str: + return str(self.value) + + +class ListInstancesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListSnapshotsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + EXPIRES_AT_ASC = "expires_at_asc" + EXPIRES_AT_DESC = "expires_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListUsersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class NodeTypeStock(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STOCK = "unknown_stock" + LOW_STOCK = "low_stock" + OUT_OF_STOCK = "out_of_stock" + AVAILABLE = "available" + + def __str__(self) -> str: + return str(self.value) + + +class SettingPropertyType(str, Enum, metaclass=StrEnumMeta): + BOOLEAN = "boolean" + INT = "int" + STRING = "string" + FLOAT = "float" + + def __str__(self) -> str: + return str(self.value) + + +class SnapshotStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATING = "creating" + READY = "ready" + RESTORING = "restoring" + DELETING = "deleting" + ERROR = "error" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class UserRoleRole(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ROLE = "unknown_role" + READ = "read" + READ_WRITE = "read_write" + DB_ADMIN = "db_admin" + SYNC = "sync" + + def __str__(self) -> str: + return str(self.value) + + +class VolumeType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + SBS_5K = "sbs_5k" + SBS_15K = "sbs_15k" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class EndpointPrivateNetworkDetails: + """ + Private Network details. + """ + + private_network_id: str + """ + UUID of the Private Network. + """ + + +@dataclass +class EndpointPublicDetails: + pass + + +@dataclass +class EndpointSpecPrivateNetworkDetails: + private_network_id: str + """ + UUID of the Private Network. + """ + + +@dataclass +class EndpointSpecPublicDetails: + pass + + +@dataclass +class Endpoint: + id: str + """ + UUID of the endpoint. + """ + + ips: List[str] + """ + List of IPv4 addresses of the endpoint. + """ + + dns_records: List[str] + """ + List of DNS records of the endpoint. + """ + + port: int + """ + TCP port of the endpoint. + """ + + private_network: Optional[EndpointPrivateNetworkDetails] + + public: Optional[EndpointPublicDetails] + + +@dataclass +class InstanceSetting: + name: str + """ + Name of the settings. + """ + + value: str + """ + Value of the settings. + """ + + +@dataclass +class Volume: + type_: VolumeType + """ + Type of volume where data is stored. + """ + + size: int + """ + Volume size. + """ + + +@dataclass +class NodeTypeVolumeType: + type_: VolumeType + """ + Volume Type. + """ + + description: str + """ + The description of the volume. + """ + + min_size: int + """ + Minimum size required for the volume. + """ + + max_size: int + """ + Maximum size required for the volume. + """ + + chunk_size: int + """ + Minimum increment level for a Block Storage volume size. + """ + + +@dataclass +class SnapshotVolumeType: + type_: VolumeType + + +@dataclass +class UserRole: + role: UserRoleRole + + database: Optional[str] + + any_database: Optional[bool] + + +@dataclass +class Setting: + name: str + """ + Setting name from the database engine. + """ + + default_value: str + """ + Value set when not specified. + """ + + hot_configurable: bool + """ + Setting can be applied without restarting. + """ + + description: str + """ + Setting description. + """ + + property_type: SettingPropertyType + """ + Setting type. + """ + + unit: Optional[str] + """ + Setting base unit. + """ + + string_constraint: Optional[str] + """ + Validation regex for string type settings. + """ + + int_min: Optional[int] + """ + Minimum value for int types. + """ + + int_max: Optional[int] + """ + Maximum value for int types. + """ + + float_min: Optional[float] + """ + Minimum value for float types. + """ + + float_max: Optional[float] + """ + Maximum value for float types. + """ + + +@dataclass +class EndpointSpec: + public: Optional[EndpointSpecPublicDetails] + + private_network: Optional[EndpointSpecPrivateNetworkDetails] + + +@dataclass +class CreateInstanceRequestVolumeDetails: + volume_size: int + """ + Volume size. + """ + + volume_type: VolumeType + """ + Type of volume where data is stored. + """ + + +@dataclass +class Instance: + id: str + """ + UUID of the Database Instance. + """ + + name: str + """ + Name of the Database Instance. + """ + + project_id: str + """ + Project ID the Database Instance belongs to. + """ + + status: InstanceStatus + """ + Status of the Database Instance. + """ + + version: str + """ + MongoDB® engine version of the Database Instance. + """ + + tags: List[str] + """ + List of tags applied to the Database Instance. + """ + + settings: List[InstanceSetting] + """ + Advanced settings of the Database Instance. + """ + + node_number: int + """ + Number of node in the Database Instance. + """ + + node_type: str + """ + Node type of the Database Instance. + """ + + endpoints: List[Endpoint] + """ + List of Database Instance endpoints. + """ + + region: ScwRegion + """ + Region the Database Instance is in. + """ + + volume: Optional[Volume] + """ + Volumes of the Database Instance. + """ + + created_at: Optional[datetime] + """ + Creation date (must follow the ISO 8601 format). + """ + + +@dataclass +class NodeType: + name: str + """ + Node type name identifier. + """ + + stock_status: NodeTypeStock + """ + Current stock status for the node type. + """ + + description: str + """ + Current specs of the offer. + """ + + vcpus: int + """ + Number of virtual CPUs. + """ + + memory: int + """ + Quantity of RAM. + """ + + available_volume_types: List[NodeTypeVolumeType] + """ + Available storage options for the node type. + """ + + disabled: bool + """ + The node type is currently disabled. + """ + + beta: bool + """ + The node type is currently in beta. + """ + + instance_range: str + """ + Instance range associated with the node type offer. + """ + + +@dataclass +class Snapshot: + id: str + """ + UUID of the snapshot. + """ + + instance_id: str + """ + UUID of the Database Instance. + """ + + name: str + """ + Name of the snapshot. + """ + + status: SnapshotStatus + """ + Status of the snapshot. + """ + + size: int + """ + Size of the snapshot. + """ + + instance_name: str + """ + Name of the Database Instance of the snapshot. + """ + + node_type: str + """ + Source node type. + """ + + region: ScwRegion + """ + Region of the snapshot. + """ + + expires_at: Optional[datetime] + """ + Expiration date (must follow the ISO 8601 format). + """ + + created_at: Optional[datetime] + """ + Creation date (must follow the ISO 8601 format). + """ + + updated_at: Optional[datetime] + """ + Updated date (must follow the ISO 8601 format). + """ + + volume_type: Optional[SnapshotVolumeType] + """ + Type of volume where data is stored - sbs_5k or sbs_15k. + """ + + +@dataclass +class User: + name: str + """ + Name of the user (Length must be between 1 and 63 characters. First character must be an alphabet character (a-zA-Z). Only a-zA-Z0-9_$- characters are accepted). + """ + + roles: List[UserRole] + """ + List of roles assigned to the user, along with the corresponding database where each role is granted. + """ + + +@dataclass +class Version: + version: str + """ + MongoDB® engine version. + """ + + available_settings: List[Setting] + """ + Instance settings available to be updated. + """ + + end_of_life_at: Optional[datetime] + """ + Date of End of Life. + """ + + +@dataclass +class RestoreSnapshotRequestVolumeDetails: + volume_type: VolumeType + """ + Type of volume where data is stored. + """ + + +@dataclass +class CreateEndpointRequest: + instance_id: str + """ + UUID of the Database Instance. + """ + + endpoint: EndpointSpec + """ + EndpointSpec used to expose your Database Instance. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateInstanceRequest: + version: str + """ + Version of the MongoDB® engine. + """ + + node_number: int + """ + Number of node to use for the Database Instance. + """ + + node_type: str + """ + Type of node to use for the Database Instance. + """ + + user_name: str + """ + Username created when the Database Instance is created. + """ + + password: str + """ + Password of the initial user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + The Project ID on which the Database Instance will be created. + """ + + name: Optional[str] + """ + Name of the Database Instance. + """ + + tags: Optional[List[str]] + """ + Tags to apply to the Database Instance. + """ + + volume: Optional[CreateInstanceRequestVolumeDetails] + """ + Instance volume information. + """ + + endpoints: Optional[List[EndpointSpec]] + """ + One or multiple EndpointSpec used to expose your Database Instance. + """ + + +@dataclass +class CreateSnapshotRequest: + instance_id: str + """ + UUID of the Database Instance to snapshot. + """ + + name: str + """ + Name of the snapshot. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + expires_at: Optional[datetime] + """ + Expiration date of the snapshot (must follow the ISO 8601 format). + """ + + +@dataclass +class CreateUserRequest: + instance_id: str + """ + UUID of the Database Instance the user belongs to. + """ + + name: str + """ + Name of the database user. + """ + + password: str + """ + Password of the database user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteEndpointRequest: + endpoint_id: str + """ + UUID of the Endpoint to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteInstanceRequest: + instance_id: str + """ + UUID of the Database Instance to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteUserRequest: + instance_id: str + """ + UUID of the Database Instance the user belongs to. + """ + + name: str + """ + Name of the database user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetInstanceCertificateRequest: + instance_id: str + """ + UUID of the Database Instance. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetInstanceRequest: + instance_id: str + """ + UUID of the Database Instance. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListInstancesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + tags: Optional[List[str]] + """ + List Database Instances that have a given tag. + """ + + name: Optional[str] + """ + Lists Database Instances that match a name pattern. + """ + + order_by: Optional[ListInstancesRequestOrderBy] + """ + Criteria to use when ordering Database Instance listings. + """ + + organization_id: Optional[str] + """ + Organization ID of the Database Instance. + """ + + project_id: Optional[str] + """ + Project ID. + """ + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListInstancesResponse: + instances: List[Instance] + """ + List of all Database Instances available in an Organization or Project. + """ + + total_count: int + """ + Total count of Database Instances available in an Organization or Project. + """ + + +@dataclass +class ListNodeTypesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + include_disabled_types: Optional[bool] + """ + Defines whether or not to include disabled types. + """ + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListNodeTypesResponse: + node_types: List[NodeType] + """ + Types of the node. + """ + + total_count: int + """ + Total count of node-types available. + """ + + +@dataclass +class ListSnapshotsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + instance_id: Optional[str] + """ + Instance ID the snapshots belongs to. + """ + + name: Optional[str] + """ + Lists database snapshots that match a name pattern. + """ + + order_by: Optional[ListSnapshotsRequestOrderBy] + """ + Criteria to use when ordering snapshot listings. + """ + + organization_id: Optional[str] + """ + Organization ID the snapshots belongs to. + """ + + project_id: Optional[str] + """ + Project ID to list the snapshots of. + """ + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListSnapshotsResponse: + snapshots: List[Snapshot] + """ + List of all database snapshots available in an Organization or Project. + """ + + total_count: int + """ + Total count of database snapshots available in a Organization or Project. + """ + + +@dataclass +class ListUsersRequest: + instance_id: str + """ + UUID of the Database Instance. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the user. + """ + + order_by: Optional[ListUsersRequestOrderBy] + """ + Criteria to use when requesting user listing. + """ + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListUsersResponse: + users: List[User] + """ + List of users in a Database Instance. + """ + + total_count: int + """ + Total count of users present on a Database Instance. + """ + + +@dataclass +class ListVersionsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + version: Optional[str] + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListVersionsResponse: + versions: List[Version] + """ + Available MongoDB® engine version. + """ + + total_count: int + """ + Total count of MongoDB® engine version available. + """ + + +@dataclass +class RestoreSnapshotRequest: + snapshot_id: str + """ + UUID of the snapshot. + """ + + instance_name: str + """ + Name of the new Database Instance. + """ + + node_type: str + """ + Node type to use for the new Database Instance. + """ + + node_number: int + """ + Number of nodes to use for the new Database Instance. + """ + + volume: RestoreSnapshotRequestVolumeDetails + """ + Instance volume information. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SetUserRoleRequest: + instance_id: str + """ + UUID of the Database Instance the user belongs to. + """ + + user_name: str + """ + Name of the database user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + roles: Optional[List[UserRole]] + """ + List of roles assigned to the user, along with the corresponding database where each role is granted. + """ + + +@dataclass +class UpdateInstanceRequest: + instance_id: str + """ + UUID of the Database Instance to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the Database Instance. + """ + + tags: Optional[List[str]] + """ + Tags of a Database Instance. + """ + + +@dataclass +class UpdateSnapshotRequest: + snapshot_id: str + """ + UUID of the Snapshot. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the snapshot. + """ + + expires_at: Optional[datetime] + """ + Expiration date of the snapshot (must follow the ISO 8601 format). + """ + + +@dataclass +class UpdateUserRequest: + instance_id: str + """ + UUID of the Database Instance the user belongs to. + """ + + name: str + """ + Name of the database user. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + password: Optional[str] + """ + Password of the database user. + """ + + +@dataclass +class UpgradeInstanceRequest: + instance_id: str + """ + UUID of the Database Instance you want to upgrade. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + volume_size: Optional[int] diff --git a/scaleway/scaleway/product_catalog/__init__.py b/scaleway/scaleway/product_catalog/__init__.py new file mode 100644 index 00000000..8b74a5ed --- /dev/null +++ b/scaleway/scaleway/product_catalog/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/product_catalog/v2alpha1/__init__.py b/scaleway/scaleway/product_catalog/v2alpha1/__init__.py new file mode 100644 index 00000000..323b1122 --- /dev/null +++ b/scaleway/scaleway/product_catalog/v2alpha1/__init__.py @@ -0,0 +1,53 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import PublicCatalogProductPropertiesHardwareCPUArch +from .types import PublicCatalogProductStatus +from .types import PublicCatalogProductUnitOfMeasureCountableUnit +from .types import PublicCatalogProductPropertiesHardwareCPUPhysical +from .types import PublicCatalogProductPropertiesHardwareCPUVirtual +from .types import PublicCatalogProductPropertiesHardwareCPU +from .types import PublicCatalogProductPropertiesHardwareGPU +from .types import PublicCatalogProductPropertiesHardwareNetwork +from .types import PublicCatalogProductPropertiesHardwareRAM +from .types import PublicCatalogProductPropertiesHardwareStorage +from .types import PublicCatalogProductPropertiesAppleSilicon +from .types import PublicCatalogProductPropertiesDedibox +from .types import PublicCatalogProductPropertiesElasticMetal +from .types import PublicCatalogProductPropertiesHardware +from .types import PublicCatalogProductPropertiesInstance +from .types import PublicCatalogProductEnvironmentalImpactEstimation +from .types import PublicCatalogProductLocality +from .types import PublicCatalogProductPrice +from .types import PublicCatalogProductProperties +from .types import PublicCatalogProductUnitOfMeasure +from .types import PublicCatalogProduct +from .types import ListPublicCatalogProductsResponse +from .types import PublicCatalogApiListPublicCatalogProductsRequest +from .api import ProductCatalogV2Alpha1PublicCatalogAPI + +__all__ = [ + "PublicCatalogProductPropertiesHardwareCPUArch", + "PublicCatalogProductStatus", + "PublicCatalogProductUnitOfMeasureCountableUnit", + "PublicCatalogProductPropertiesHardwareCPUPhysical", + "PublicCatalogProductPropertiesHardwareCPUVirtual", + "PublicCatalogProductPropertiesHardwareCPU", + "PublicCatalogProductPropertiesHardwareGPU", + "PublicCatalogProductPropertiesHardwareNetwork", + "PublicCatalogProductPropertiesHardwareRAM", + "PublicCatalogProductPropertiesHardwareStorage", + "PublicCatalogProductPropertiesAppleSilicon", + "PublicCatalogProductPropertiesDedibox", + "PublicCatalogProductPropertiesElasticMetal", + "PublicCatalogProductPropertiesHardware", + "PublicCatalogProductPropertiesInstance", + "PublicCatalogProductEnvironmentalImpactEstimation", + "PublicCatalogProductLocality", + "PublicCatalogProductPrice", + "PublicCatalogProductProperties", + "PublicCatalogProductUnitOfMeasure", + "PublicCatalogProduct", + "ListPublicCatalogProductsResponse", + "PublicCatalogApiListPublicCatalogProductsRequest", + "ProductCatalogV2Alpha1PublicCatalogAPI", +] diff --git a/scaleway/scaleway/product_catalog/v2alpha1/api.py b/scaleway/scaleway/product_catalog/v2alpha1/api.py new file mode 100644 index 00000000..7d029767 --- /dev/null +++ b/scaleway/scaleway/product_catalog/v2alpha1/api.py @@ -0,0 +1,80 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.utils import ( + fetch_all_pages, +) +from .types import ( + ListPublicCatalogProductsResponse, + PublicCatalogProduct, +) +from .marshalling import ( + unmarshal_ListPublicCatalogProductsResponse, +) + + +class ProductCatalogV2Alpha1PublicCatalogAPI(API): + """ """ + + def list_public_catalog_products( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListPublicCatalogProductsResponse: + """ + List all available products. + List all available products in the Scaleway catalog. Returns a complete list of products with their corresponding description, locations, prices and properties. You can define the `page` number and `page_size` for your query in the request. + :param page: Number of the page. Value must be greater or equal to 1. + :param page_size: The number of products per page. Value must be greater or equal to 1. + :return: :class:`ListPublicCatalogProductsResponse ` + + Usage: + :: + + result = api.list_public_catalog_products() + """ + + res = self._request( + "GET", + "/product-catalog/v2alpha1/public-catalog/products", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPublicCatalogProductsResponse(res.json()) + + def list_public_catalog_products_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[PublicCatalogProduct]: + """ + List all available products. + List all available products in the Scaleway catalog. Returns a complete list of products with their corresponding description, locations, prices and properties. You can define the `page` number and `page_size` for your query in the request. + :param page: Number of the page. Value must be greater or equal to 1. + :param page_size: The number of products per page. Value must be greater or equal to 1. + :return: :class:`List[PublicCatalogProduct] ` + + Usage: + :: + + result = api.list_public_catalog_products_all() + """ + + return fetch_all_pages( + type=ListPublicCatalogProductsResponse, + key="products", + fetcher=self.list_public_catalog_products, + args={ + "page": page, + "page_size": page_size, + }, + ) diff --git a/scaleway/scaleway/product_catalog/v2alpha1/marshalling.py b/scaleway/scaleway/product_catalog/v2alpha1/marshalling.py new file mode 100644 index 00000000..e1f552a6 --- /dev/null +++ b/scaleway/scaleway/product_catalog/v2alpha1/marshalling.py @@ -0,0 +1,589 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.bridge import ( + unmarshal_Money, +) +from .types import ( + PublicCatalogProductPropertiesHardwareCPUPhysical, + PublicCatalogProductPropertiesHardwareCPUVirtual, + PublicCatalogProductPropertiesHardwareCPU, + PublicCatalogProductPropertiesHardwareGPU, + PublicCatalogProductPropertiesHardwareNetwork, + PublicCatalogProductPropertiesHardwareRAM, + PublicCatalogProductPropertiesHardwareStorage, + PublicCatalogProductPropertiesAppleSilicon, + PublicCatalogProductPropertiesDedibox, + PublicCatalogProductPropertiesElasticMetal, + PublicCatalogProductPropertiesHardware, + PublicCatalogProductPropertiesInstance, + PublicCatalogProductEnvironmentalImpactEstimation, + PublicCatalogProductLocality, + PublicCatalogProductPrice, + PublicCatalogProductProperties, + PublicCatalogProductUnitOfMeasure, + PublicCatalogProduct, + ListPublicCatalogProductsResponse, +) + + +def unmarshal_PublicCatalogProductPropertiesHardwareCPUPhysical( + data: Any, +) -> PublicCatalogProductPropertiesHardwareCPUPhysical: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareCPUPhysical' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sockets", None) + if field is not None: + args["sockets"] = field + + field = data.get("cores_per_socket", None) + if field is not None: + args["cores_per_socket"] = field + + field = data.get("threads_per_core", None) + if field is not None: + args["threads_per_core"] = field + + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + + field = data.get("benchmark", None) + if field is not None: + args["benchmark"] = field + + return PublicCatalogProductPropertiesHardwareCPUPhysical(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareCPUVirtual( + data: Any, +) -> PublicCatalogProductPropertiesHardwareCPUVirtual: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareCPUVirtual' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("count", None) + if field is not None: + args["count"] = field + + return PublicCatalogProductPropertiesHardwareCPUVirtual(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareCPU( + data: Any, +) -> PublicCatalogProductPropertiesHardwareCPU: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareCPU' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("arch", None) + if field is not None: + args["arch"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("threads", None) + if field is not None: + args["threads"] = field + + field = data.get("virtual", None) + if field is not None: + args["virtual"] = unmarshal_PublicCatalogProductPropertiesHardwareCPUVirtual( + field + ) + else: + args["virtual"] = None + + field = data.get("physical", None) + if field is not None: + args["physical"] = unmarshal_PublicCatalogProductPropertiesHardwareCPUPhysical( + field + ) + else: + args["physical"] = None + + return PublicCatalogProductPropertiesHardwareCPU(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareGPU( + data: Any, +) -> PublicCatalogProductPropertiesHardwareGPU: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareGPU' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("count", None) + if field is not None: + args["count"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return PublicCatalogProductPropertiesHardwareGPU(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareNetwork( + data: Any, +) -> PublicCatalogProductPropertiesHardwareNetwork: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareNetwork' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("internal_bandwidth", None) + if field is not None: + args["internal_bandwidth"] = field + + field = data.get("public_bandwidth", None) + if field is not None: + args["public_bandwidth"] = field + + field = data.get("max_public_bandwidth", None) + if field is not None: + args["max_public_bandwidth"] = field + + return PublicCatalogProductPropertiesHardwareNetwork(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareRAM( + data: Any, +) -> PublicCatalogProductPropertiesHardwareRAM: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareRAM' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + return PublicCatalogProductPropertiesHardwareRAM(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardwareStorage( + data: Any, +) -> PublicCatalogProductPropertiesHardwareStorage: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardwareStorage' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("total", None) + if field is not None: + args["total"] = field + + return PublicCatalogProductPropertiesHardwareStorage(**args) + + +def unmarshal_PublicCatalogProductPropertiesAppleSilicon( + data: Any, +) -> PublicCatalogProductPropertiesAppleSilicon: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesAppleSilicon' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("range", None) + if field is not None: + args["range"] = field + + return PublicCatalogProductPropertiesAppleSilicon(**args) + + +def unmarshal_PublicCatalogProductPropertiesDedibox( + data: Any, +) -> PublicCatalogProductPropertiesDedibox: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesDedibox' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("range", None) + if field is not None: + args["range"] = field + + return PublicCatalogProductPropertiesDedibox(**args) + + +def unmarshal_PublicCatalogProductPropertiesElasticMetal( + data: Any, +) -> PublicCatalogProductPropertiesElasticMetal: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesElasticMetal' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("range", None) + if field is not None: + args["range"] = field + + return PublicCatalogProductPropertiesElasticMetal(**args) + + +def unmarshal_PublicCatalogProductPropertiesHardware( + data: Any, +) -> PublicCatalogProductPropertiesHardware: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesHardware' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("cpu", None) + if field is not None: + args["cpu"] = unmarshal_PublicCatalogProductPropertiesHardwareCPU(field) + else: + args["cpu"] = None + + field = data.get("ram", None) + if field is not None: + args["ram"] = unmarshal_PublicCatalogProductPropertiesHardwareRAM(field) + else: + args["ram"] = None + + field = data.get("storage", None) + if field is not None: + args["storage"] = unmarshal_PublicCatalogProductPropertiesHardwareStorage(field) + else: + args["storage"] = None + + field = data.get("network", None) + if field is not None: + args["network"] = unmarshal_PublicCatalogProductPropertiesHardwareNetwork(field) + else: + args["network"] = None + + field = data.get("gpu", None) + if field is not None: + args["gpu"] = unmarshal_PublicCatalogProductPropertiesHardwareGPU(field) + else: + args["gpu"] = None + + return PublicCatalogProductPropertiesHardware(**args) + + +def unmarshal_PublicCatalogProductPropertiesInstance( + data: Any, +) -> PublicCatalogProductPropertiesInstance: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPropertiesInstance' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("range", None) + if field is not None: + args["range"] = field + + field = data.get("offer_id", None) + if field is not None: + args["offer_id"] = field + + field = data.get("recommended_replacement_offer_ids", None) + if field is not None: + args["recommended_replacement_offer_ids"] = field + + return PublicCatalogProductPropertiesInstance(**args) + + +def unmarshal_PublicCatalogProductEnvironmentalImpactEstimation( + data: Any, +) -> PublicCatalogProductEnvironmentalImpactEstimation: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductEnvironmentalImpactEstimation' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("kg_co2_equivalent", None) + if field is not None: + args["kg_co2_equivalent"] = field + else: + args["kg_co2_equivalent"] = None + + field = data.get("m3_water_usage", None) + if field is not None: + args["m3_water_usage"] = field + else: + args["m3_water_usage"] = None + + return PublicCatalogProductEnvironmentalImpactEstimation(**args) + + +def unmarshal_PublicCatalogProductLocality(data: Any) -> PublicCatalogProductLocality: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductLocality' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("global", None) + if field is not None: + args["global_"] = field + else: + args["global_"] = None + + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("datacenter", None) + if field is not None: + args["datacenter"] = field + else: + args["datacenter"] = None + + return PublicCatalogProductLocality(**args) + + +def unmarshal_PublicCatalogProductPrice(data: Any) -> PublicCatalogProductPrice: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductPrice' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("retail_price", None) + if field is not None: + args["retail_price"] = unmarshal_Money(field) + else: + args["retail_price"] = None + + return PublicCatalogProductPrice(**args) + + +def unmarshal_PublicCatalogProductProperties( + data: Any, +) -> PublicCatalogProductProperties: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductProperties' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("hardware", None) + if field is not None: + args["hardware"] = unmarshal_PublicCatalogProductPropertiesHardware(field) + else: + args["hardware"] = None + + field = data.get("dedibox", None) + if field is not None: + args["dedibox"] = unmarshal_PublicCatalogProductPropertiesDedibox(field) + else: + args["dedibox"] = None + + field = data.get("elastic_metal", None) + if field is not None: + args["elastic_metal"] = unmarshal_PublicCatalogProductPropertiesElasticMetal( + field + ) + else: + args["elastic_metal"] = None + + field = data.get("apple_silicon", None) + if field is not None: + args["apple_silicon"] = unmarshal_PublicCatalogProductPropertiesAppleSilicon( + field + ) + else: + args["apple_silicon"] = None + + field = data.get("instance", None) + if field is not None: + args["instance"] = unmarshal_PublicCatalogProductPropertiesInstance(field) + else: + args["instance"] = None + + return PublicCatalogProductProperties(**args) + + +def unmarshal_PublicCatalogProductUnitOfMeasure( + data: Any, +) -> PublicCatalogProductUnitOfMeasure: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProductUnitOfMeasure' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("unit", None) + if field is not None: + args["unit"] = field + + field = data.get("size", None) + if field is not None: + args["size"] = field + + return PublicCatalogProductUnitOfMeasure(**args) + + +def unmarshal_PublicCatalogProduct(data: Any) -> PublicCatalogProduct: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PublicCatalogProduct' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("sku", None) + if field is not None: + args["sku"] = field + + field = data.get("service_category", None) + if field is not None: + args["service_category"] = field + + field = data.get("product", None) + if field is not None: + args["product"] = field + + field = data.get("variant", None) + if field is not None: + args["variant"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("locality", None) + if field is not None: + args["locality"] = unmarshal_PublicCatalogProductLocality(field) + else: + args["locality"] = None + + field = data.get("price", None) + if field is not None: + args["price"] = unmarshal_PublicCatalogProductPrice(field) + else: + args["price"] = None + + field = data.get("properties", None) + if field is not None: + args["properties"] = unmarshal_PublicCatalogProductProperties(field) + else: + args["properties"] = None + + field = data.get("environmental_impact_estimation", None) + if field is not None: + args["environmental_impact_estimation"] = ( + unmarshal_PublicCatalogProductEnvironmentalImpactEstimation(field) + ) + else: + args["environmental_impact_estimation"] = None + + field = data.get("unit_of_measure", None) + if field is not None: + args["unit_of_measure"] = unmarshal_PublicCatalogProductUnitOfMeasure(field) + else: + args["unit_of_measure"] = None + + field = data.get("end_of_life_at", None) + if field is not None: + args["end_of_life_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["end_of_life_at"] = None + + return PublicCatalogProduct(**args) + + +def unmarshal_ListPublicCatalogProductsResponse( + data: Any, +) -> ListPublicCatalogProductsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPublicCatalogProductsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("products", None) + if field is not None: + args["products"] = ( + [unmarshal_PublicCatalogProduct(v) for v in field] + if field is not None + else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPublicCatalogProductsResponse(**args) diff --git a/scaleway/scaleway/product_catalog/v2alpha1/types.py b/scaleway/scaleway/product_catalog/v2alpha1/types.py new file mode 100644 index 00000000..0e1043d8 --- /dev/null +++ b/scaleway/scaleway/product_catalog/v2alpha1/types.py @@ -0,0 +1,417 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Money, + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class PublicCatalogProductPropertiesHardwareCPUArch(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ARCH = "unknown_arch" + X64 = "x64" + ARM64 = "arm64" + RISCV = "riscv" + APPLE_SILICON = "apple_silicon" + + def __str__(self) -> str: + return str(self.value) + + +class PublicCatalogProductStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + PUBLIC_BETA = "public_beta" + PREVIEW = "preview" + GENERAL_AVAILABILITY = "general_availability" + END_OF_DEPLOYMENT = "end_of_deployment" + END_OF_SUPPORT = "end_of_support" + + def __str__(self) -> str: + return str(self.value) + + +class PublicCatalogProductUnitOfMeasureCountableUnit(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_COUNTABLE_UNIT = "unknown_countable_unit" + CHUNK = "chunk" + CORE = "core" + CURRENCY = "currency" + DEVICE = "device" + DOMAIN = "domain" + EMAIL = "email" + GB_S = "gb_s" + GIGABYTE = "gigabyte" + HOUR = "hour" + IOPS_GIGABYTE = "iops_gigabyte" + IP = "ip" + MONTH = "month" + NODE = "node" + PLAN = "plan" + QUERY = "query" + REQUEST = "request" + SESSION = "session" + VCPU_S = "vcpu_s" + VERSION = "version" + YEAR = "year" + KEY = "key" + TOKEN = "token" + MINUTE = "minute" + SETUP = "setup" + DAY = "day" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class PublicCatalogProductPropertiesHardwareCPUPhysical: + sockets: int + """ + The number of sockets of the CPU. + """ + + cores_per_socket: int + """ + The number of cores per socket. + """ + + threads_per_core: int + """ + The number of threads per core. + """ + + frequency: int + """ + The frequency of the CPU in Hertz. + """ + + benchmark: int + """ + The benchmark score of the CPU. + """ + + +@dataclass +class PublicCatalogProductPropertiesHardwareCPUVirtual: + count: int + """ + The number of vCPUs. + """ + + +@dataclass +class PublicCatalogProductPropertiesHardwareCPU: + description: str + """ + A human readable description of the CPU. + """ + + arch: PublicCatalogProductPropertiesHardwareCPUArch + """ + The architecture of the CPU. + """ + + type_: str + """ + The type of the CPU. + """ + + threads: int + """ + The total number of threads. + """ + + virtual: Optional[PublicCatalogProductPropertiesHardwareCPUVirtual] + + physical: Optional[PublicCatalogProductPropertiesHardwareCPUPhysical] + + +@dataclass +class PublicCatalogProductPropertiesHardwareGPU: + description: str + """ + A human-readable description of the GPU. + """ + + count: int + """ + The number of GPUs. + """ + + type_: str + """ + The type of the GPU. + """ + + +@dataclass +class PublicCatalogProductPropertiesHardwareNetwork: + description: str + """ + A human-readable description of the network. + """ + + internal_bandwidth: int + """ + The internal bandwidth in bits per second. + """ + + public_bandwidth: int + """ + The default public bandwidth in bits per second. + """ + + max_public_bandwidth: int + """ + The maximum public bandwidth in bits per second (may require subscription to options). + """ + + +@dataclass +class PublicCatalogProductPropertiesHardwareRAM: + description: str + """ + A human-readable description of the RAM. + """ + + size: int + """ + The size of the RAM in bytes. + """ + + type_: str + """ + The type of the RAM. + """ + + +@dataclass +class PublicCatalogProductPropertiesHardwareStorage: + description: str + """ + A human-readable description of the storage. + """ + + total: int + """ + The total size of the storage in bytes. + """ + + +@dataclass +class PublicCatalogProductPropertiesAppleSilicon: + range: str + """ + The range of the Apple Silicon server. + """ + + +@dataclass +class PublicCatalogProductPropertiesDedibox: + range: str + """ + The range of the Dedibox server. + """ + + +@dataclass +class PublicCatalogProductPropertiesElasticMetal: + range: str + """ + The range of the Elastic Metal server. + """ + + +@dataclass +class PublicCatalogProductPropertiesHardware: + cpu: Optional[PublicCatalogProductPropertiesHardwareCPU] + """ + The CPU hardware properties. + """ + + ram: Optional[PublicCatalogProductPropertiesHardwareRAM] + """ + The RAM hardware properties. + """ + + storage: Optional[PublicCatalogProductPropertiesHardwareStorage] + """ + The storage hardware properties. + """ + + network: Optional[PublicCatalogProductPropertiesHardwareNetwork] + """ + The network hardware properties. + """ + + gpu: Optional[PublicCatalogProductPropertiesHardwareGPU] + """ + The GPU hardware properties. + """ + + +@dataclass +class PublicCatalogProductPropertiesInstance: + range: str + """ + The range of the Instance server. + """ + + offer_id: str + """ + The offer ID of the Instance server. + """ + + recommended_replacement_offer_ids: List[str] + """ + The recommended replacement offer IDs of the Instance server. + """ + + +@dataclass +class PublicCatalogProductEnvironmentalImpactEstimation: + kg_co2_equivalent: Optional[float] + + m3_water_usage: Optional[float] + + +@dataclass +class PublicCatalogProductLocality: + global_: Optional[bool] + + region: Optional[ScwRegion] + + zone: Optional[ScwZone] + + datacenter: Optional[str] + + +@dataclass +class PublicCatalogProductPrice: + retail_price: Optional[Money] + """ + The retail price of the product. + """ + + +@dataclass +class PublicCatalogProductProperties: + hardware: Optional[PublicCatalogProductPropertiesHardware] + """ + The hardware properties of the product (if supported). + """ + + dedibox: Optional[PublicCatalogProductPropertiesDedibox] + + elastic_metal: Optional[PublicCatalogProductPropertiesElasticMetal] + + apple_silicon: Optional[PublicCatalogProductPropertiesAppleSilicon] + + instance: Optional[PublicCatalogProductPropertiesInstance] + + +@dataclass +class PublicCatalogProductUnitOfMeasure: + unit: PublicCatalogProductUnitOfMeasureCountableUnit + + size: int + + +@dataclass +class PublicCatalogProduct: + sku: str + """ + The unique identifier of the product. + """ + + service_category: str + """ + The category of the product. + """ + + product: str + """ + The product name. + """ + + variant: str + """ + The product variant. + """ + + description: str + """ + The product description. + """ + + status: PublicCatalogProductStatus + """ + The status of the product. + """ + + locality: Optional[PublicCatalogProductLocality] + """ + The locality of the product. + """ + + price: Optional[PublicCatalogProductPrice] + """ + The price of the product. + """ + + properties: Optional[PublicCatalogProductProperties] + """ + The properties of the product. + """ + + environmental_impact_estimation: Optional[ + PublicCatalogProductEnvironmentalImpactEstimation + ] + """ + The environmental impact estimation of the product. + """ + + unit_of_measure: Optional[PublicCatalogProductUnitOfMeasure] + """ + The unit of measure of the product. + """ + + end_of_life_at: Optional[datetime] + """ + The end of life date of the product. + """ + + +@dataclass +class ListPublicCatalogProductsResponse: + products: List[PublicCatalogProduct] + """ + The list of products. + """ + + total_count: int + """ + The total number of products in the catalog. + """ + + +@dataclass +class PublicCatalogApiListPublicCatalogProductsRequest: + page: Optional[int] + """ + Number of the page. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + The number of products per page. Value must be greater or equal to 1. + """ diff --git a/scaleway/scaleway/qaas/v1alpha1/__init__.py b/scaleway/scaleway/qaas/v1alpha1/__init__.py index db40cd45..eb2ff39c 100644 --- a/scaleway/scaleway/qaas/v1alpha1/__init__.py +++ b/scaleway/scaleway/qaas/v1alpha1/__init__.py @@ -11,6 +11,7 @@ from .types import ListProcessesRequestOrderBy from .types import ListSessionACLsRequestOrderBy from .types import ListSessionsRequestOrderBy +from .types import PlatformAvailability from .types import PlatformTechnology from .types import PlatformType from .types import ProcessStatus @@ -19,6 +20,7 @@ from .types import SessionOriginType from .types import SessionStatus from .content import SESSION_TRANSIENT_STATUSES +from .types import PlatformHardware from .types import JobCircuit from .types import Application from .types import JobResult @@ -75,6 +77,7 @@ "ListProcessesRequestOrderBy", "ListSessionACLsRequestOrderBy", "ListSessionsRequestOrderBy", + "PlatformAvailability", "PlatformTechnology", "PlatformType", "ProcessStatus", @@ -83,6 +86,7 @@ "SessionOriginType", "SessionStatus", "SESSION_TRANSIENT_STATUSES", + "PlatformHardware", "JobCircuit", "Application", "JobResult", diff --git a/scaleway/scaleway/qaas/v1alpha1/api.py b/scaleway/scaleway/qaas/v1alpha1/api.py index 68b4a16c..e83bb033 100644 --- a/scaleway/scaleway/qaas/v1alpha1/api.py +++ b/scaleway/scaleway/qaas/v1alpha1/api.py @@ -521,6 +521,7 @@ def list_platforms( self, *, provider_name: Optional[str] = None, + backend_name: Optional[str] = None, name: Optional[str] = None, platform_type: Optional[PlatformType] = None, platform_technology: Optional[PlatformTechnology] = None, @@ -532,6 +533,7 @@ def list_platforms( List all available platforms. Retrieve information about all platforms. :param provider_name: List platforms with this provider name. + :param backend_name: List platforms with this backend name. :param name: List platforms with this name. :param platform_type: List platforms with this type. :param platform_technology: List platforms with this technology. @@ -550,6 +552,7 @@ def list_platforms( "GET", "/qaas/v1alpha1/platforms", params={ + "backend_name": backend_name, "name": name, "order_by": order_by, "page": page, @@ -567,6 +570,7 @@ def list_platforms_all( self, *, provider_name: Optional[str] = None, + backend_name: Optional[str] = None, name: Optional[str] = None, platform_type: Optional[PlatformType] = None, platform_technology: Optional[PlatformTechnology] = None, @@ -578,6 +582,7 @@ def list_platforms_all( List all available platforms. Retrieve information about all platforms. :param provider_name: List platforms with this provider name. + :param backend_name: List platforms with this backend name. :param name: List platforms with this name. :param platform_type: List platforms with this type. :param platform_technology: List platforms with this technology. @@ -598,6 +603,7 @@ def list_platforms_all( fetcher=self.list_platforms, args={ "provider_name": provider_name, + "backend_name": backend_name, "name": name, "platform_type": platform_type, "platform_technology": platform_technology, diff --git a/scaleway/scaleway/qaas/v1alpha1/marshalling.py b/scaleway/scaleway/qaas/v1alpha1/marshalling.py index 7ea0ec5d..e8ad932f 100644 --- a/scaleway/scaleway/qaas/v1alpha1/marshalling.py +++ b/scaleway/scaleway/qaas/v1alpha1/marshalling.py @@ -5,6 +5,9 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) from scaleway_core.utils import ( OneOfPossibility, resolve_one_of, @@ -14,6 +17,7 @@ JobCircuit, Application, Job, + PlatformHardware, Platform, Process, Session, @@ -47,10 +51,14 @@ def unmarshal_JobCircuit(data: Any) -> JobCircuit: field = data.get("perceval_circuit", None) if field is not None: args["perceval_circuit"] = field + else: + args["perceval_circuit"] = None field = data.get("qiskit_circuit", None) if field is not None: args["qiskit_circuit"] = field + else: + args["qiskit_circuit"] = None return JobCircuit(**args) @@ -71,7 +79,7 @@ def unmarshal_Application(data: Any) -> Application: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -113,34 +121,83 @@ def unmarshal_Job(data: Any) -> Job: field = data.get("tags", None) if field is not None: args["tags"] = field + else: + args["tags"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("progress_message", None) if field is not None: args["progress_message"] = field + else: + args["progress_message"] = None field = data.get("job_duration", None) if field is not None: args["job_duration"] = field + else: + args["job_duration"] = None field = data.get("result_distribution", None) if field is not None: args["result_distribution"] = field + else: + args["result_distribution"] = None return Job(**args) +def unmarshal_PlatformHardware(data: Any) -> PlatformHardware: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlatformHardware' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("vcpus", None) + if field is not None: + args["vcpus"] = field + + field = data.get("gpus", None) + if field is not None: + args["gpus"] = field + + field = data.get("gpus_network", None) + if field is not None: + args["gpus_network"] = field + + field = data.get("ram", None) + if field is not None: + args["ram"] = field + + field = data.get("vram", None) + if field is not None: + args["vram"] = field + + return PlatformHardware(**args) + + def unmarshal_Platform(data: Any) -> Platform: if not isinstance(data, dict): raise TypeError( @@ -165,7 +222,11 @@ def unmarshal_Platform(data: Any) -> Platform: if field is not None: args["provider_name"] = field - field = data.get("type_", None) + field = data.get("backend_name", None) + if field is not None: + args["backend_name"] = field + + field = data.get("type", None) if field is not None: args["type_"] = field @@ -177,10 +238,46 @@ def unmarshal_Platform(data: Any) -> Platform: if field is not None: args["max_qubit_count"] = field + field = data.get("max_shot_count", None) + if field is not None: + args["max_shot_count"] = field + + field = data.get("max_circuit_count", None) + if field is not None: + args["max_circuit_count"] = field + + field = data.get("availability", None) + if field is not None: + args["availability"] = field + field = data.get("metadata", None) if field is not None: args["metadata"] = field + field = data.get("price_per_hour", None) + if field is not None: + args["price_per_hour"] = unmarshal_Money(field) + else: + args["price_per_hour"] = None + + field = data.get("price_per_shot", None) + if field is not None: + args["price_per_shot"] = unmarshal_Money(field) + else: + args["price_per_shot"] = None + + field = data.get("price_per_circuit", None) + if field is not None: + args["price_per_circuit"] = unmarshal_Money(field) + else: + args["price_per_circuit"] = None + + field = data.get("hardware", None) + if field is not None: + args["hardware"] = unmarshal_PlatformHardware(field) + else: + args["hardware"] = None + return Platform(**args) @@ -207,6 +304,8 @@ def unmarshal_Process(data: Any) -> Process: field = data.get("application_id", None) if field is not None: args["application_id"] = field + else: + args["application_id"] = None field = data.get("status", None) if field is not None: @@ -223,36 +322,52 @@ def unmarshal_Process(data: Any) -> Process: field = data.get("platform_id", None) if field is not None: args["platform_id"] = field + else: + args["platform_id"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("finished_at", None) if field is not None: args["finished_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["finished_at"] = None field = data.get("progress", None) if field is not None: args["progress"] = field + else: + args["progress"] = None field = data.get("progress_message", None) if field is not None: args["progress_message"] = field + else: + args["progress_message"] = None field = data.get("input", None) if field is not None: args["input"] = field + else: + args["input"] = None return Process(**args) @@ -284,6 +399,8 @@ def unmarshal_Session(data: Any) -> Session: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("finished_job_count", None) if field is not None: @@ -308,32 +425,52 @@ def unmarshal_Session(data: Any) -> Session: field = data.get("started_at", None) if field is not None: args["started_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["started_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("terminated_at", None) if field is not None: args["terminated_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["terminated_at"] = None field = data.get("max_idle_duration", None) if field is not None: args["max_idle_duration"] = field + else: + args["max_idle_duration"] = None field = data.get("max_duration", None) if field is not None: args["max_duration"] = field + else: + args["max_duration"] = None field = data.get("tags", None) if field is not None: args["tags"] = field + else: + args["tags"] = None field = data.get("origin_id", None) if field is not None: args["origin_id"] = field + else: + args["origin_id"] = None + + field = data.get("progress_message", None) + if field is not None: + args["progress_message"] = field + else: + args["progress_message"] = None return Session(**args) @@ -374,14 +511,20 @@ def unmarshal_JobResult(data: Any) -> JobResult: field = data.get("result", None) if field is not None: args["result"] = field + else: + args["result"] = None field = data.get("url", None) if field is not None: args["url"] = field + else: + args["url"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return JobResult(**args) @@ -466,6 +609,8 @@ def unmarshal_ProcessResult(data: Any) -> ProcessResult: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return ProcessResult(**args) @@ -582,7 +727,7 @@ def marshal_CreateJobRequest( output["session_id"] = request.session_id if request.circuit is not None: - output["circuit"] = (marshal_JobCircuit(request.circuit, defaults),) + output["circuit"] = marshal_JobCircuit(request.circuit, defaults) if request.tags is not None: output["tags"] = request.tags diff --git a/scaleway/scaleway/qaas/v1alpha1/types.py b/scaleway/scaleway/qaas/v1alpha1/types.py index e97fdfe5..ccb14a04 100644 --- a/scaleway/scaleway/qaas/v1alpha1/types.py +++ b/scaleway/scaleway/qaas/v1alpha1/types.py @@ -7,6 +7,9 @@ from enum import Enum from typing import List, Optional +from scaleway_core.bridge import ( + Money, +) from scaleway_core.utils import ( StrEnumMeta, ) @@ -76,6 +79,8 @@ class ListPlatformsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): TYPE_DESC = "type_desc" TECHNOLOGY_ASC = "technology_asc" TECHNOLOGY_DESC = "technology_desc" + BACKEND_NAME_ASC = "backend_name_asc" + BACKEND_NAME_DESC = "backend_name_desc" def __str__(self) -> str: return str(self.value) @@ -125,10 +130,23 @@ def __str__(self) -> str: return str(self.value) +class PlatformAvailability(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_AVAILABILITY = "unknown_availability" + AVAILABLE = "available" + SHORTAGE = "shortage" + SCARCE = "scarce" + MAINTENANCE = "maintenance" + + def __str__(self) -> str: + return str(self.value) + + class PlatformTechnology(str, Enum, metaclass=StrEnumMeta): UNKNOWN_TECHNOLOGY = "unknown_technology" PHOTONIC = "photonic" GENERAL_PURPOSE = "general_purpose" + TRAPPED_ION = "trapped_ion" + SUPERCONDUCTING = "superconducting" def __str__(self) -> str: return str(self.value) @@ -190,6 +208,39 @@ def __str__(self) -> str: return str(self.value) +@dataclass +class PlatformHardware: + name: str + """ + Product name of the hardware. + """ + + vcpus: int + """ + Number of vCPUs available. + """ + + gpus: int + """ + Number of GPUs available (0 if no GPU). + """ + + gpus_network: str + """ + Network topology of GPUs (PCIe, NVLink...). + """ + + ram: int + """ + Amount of RAM available in byte. + """ + + vram: int + """ + Amount of VRAM available in byte (0 if no GPU). + """ + + @dataclass class JobCircuit: perceval_circuit: Optional[str] @@ -315,7 +366,7 @@ class Platform: version: str """ - Verison of the platform. + Version of the platform. """ name: str @@ -328,6 +379,11 @@ class Platform: Provider name of the platform. """ + backend_name: str + """ + Name of the running backend over the platform (ascella, qsim, aer...). + """ + type_: PlatformType """ Type of the platform. @@ -340,7 +396,22 @@ class Platform: max_qubit_count: int """ - Maximum number of qubits supported by the platform. + Estimated maximum number of qubits supported by the platform. + """ + + max_shot_count: int + """ + Maximum number of shots during a circuit execution. + """ + + max_circuit_count: int + """ + Maximum number of circuit that can be executed in one call. + """ + + availability: PlatformAvailability + """ + Availability of the platform. """ metadata: str @@ -348,6 +419,26 @@ class Platform: Metadata provided by the platform. """ + price_per_hour: Optional[Money] + """ + Price to be paid per hour (excluding free tiers). + """ + + price_per_shot: Optional[Money] + """ + Price to be paid per shot (excluding free tiers). + """ + + price_per_circuit: Optional[Money] + """ + Price to be paid per circuit setup before its execution (excluding free tiers). + """ + + hardware: Optional[PlatformHardware] + """ + Specifications of the underlying hardware. + """ + @dataclass class ProcessResult: @@ -532,6 +623,11 @@ class Session: Unique ID of the session's origin resource (if exists). """ + progress_message: Optional[str] + """ + Any progress of the session. + """ + @dataclass class CancelJobRequest: @@ -844,6 +940,11 @@ class ListPlatformsRequest: List platforms with this provider name. """ + backend_name: Optional[str] + """ + List platforms with this backend name. + """ + name: Optional[str] """ List platforms with this name. diff --git a/scaleway/scaleway/rdb/v1/__init__.py b/scaleway/scaleway/rdb/v1/__init__.py index f2affddf..1ba2fa88 100644 --- a/scaleway/scaleway/rdb/v1/__init__.py +++ b/scaleway/scaleway/rdb/v1/__init__.py @@ -5,6 +5,7 @@ from .types import ACLRuleProtocol from .types import DatabaseBackupStatus from .content import DATABASE_BACKUP_TRANSIENT_STATUSES +from .types import EndpointPrivateNetworkDetailsProvisioningMode from .types import EngineSettingPropertyType from .types import InstanceLogStatus from .content import INSTANCE_LOG_TRANSIENT_STATUSES @@ -41,6 +42,7 @@ from .types import ReadReplicaEndpointSpecPrivateNetwork from .types import EngineVersion from .types import BackupSchedule +from .types import EncryptionAtRest from .types import InstanceSetting from .types import LogsPolicy from .types import Maintenance @@ -150,6 +152,7 @@ "ACLRuleProtocol", "DatabaseBackupStatus", "DATABASE_BACKUP_TRANSIENT_STATUSES", + "EndpointPrivateNetworkDetailsProvisioningMode", "EngineSettingPropertyType", "InstanceLogStatus", "INSTANCE_LOG_TRANSIENT_STATUSES", @@ -186,6 +189,7 @@ "ReadReplicaEndpointSpecPrivateNetwork", "EngineVersion", "BackupSchedule", + "EncryptionAtRest", "InstanceSetting", "LogsPolicy", "Maintenance", diff --git a/scaleway/scaleway/rdb/v1/api.py b/scaleway/scaleway/rdb/v1/api.py index 87cf754a..0fe6d950 100644 --- a/scaleway/scaleway/rdb/v1/api.py +++ b/scaleway/scaleway/rdb/v1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ScwFile, unmarshal_ScwFile, ) @@ -50,6 +50,7 @@ DeleteInstanceACLRulesResponse, DeleteInstanceSettingsRequest, DeleteInstanceSettingsResponse, + EncryptionAtRest, Endpoint, EndpointSpec, Instance, @@ -159,12 +160,14 @@ class RdbV1API(API): - """ """ + """ + This API allows you to manage your Managed Databases for PostgreSQL and MySQL. + """ def list_database_engines( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, version: Optional[str] = None, page: Optional[int] = None, @@ -207,7 +210,7 @@ def list_database_engines( def list_database_engines_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, version: Optional[str] = None, page: Optional[int] = None, @@ -246,7 +249,7 @@ def list_node_types( self, *, include_disabled_types: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListNodeTypesResponse: @@ -288,7 +291,7 @@ def list_node_types_all( self, *, include_disabled_types: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[NodeType]: @@ -324,7 +327,7 @@ def list_node_types_all( def list_database_backups( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListDatabaseBackupsRequestOrderBy] = None, instance_id: Optional[str] = None, @@ -377,7 +380,7 @@ def list_database_backups( def list_database_backups_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListDatabaseBackupsRequestOrderBy] = None, instance_id: Optional[str] = None, @@ -426,7 +429,7 @@ def create_database_backup( *, instance_id: str, database_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, expires_at: Optional[datetime] = None, ) -> DatabaseBackup: @@ -475,7 +478,7 @@ def get_database_backup( self, *, database_backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DatabaseBackup: """ Get a database backup. @@ -511,7 +514,7 @@ def wait_for_database_backup( self, *, database_backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[DatabaseBackup, bool]] = None, ) -> DatabaseBackup: """ @@ -550,7 +553,7 @@ def update_database_backup( self, *, database_backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, expires_at: Optional[datetime] = None, ) -> DatabaseBackup: @@ -599,7 +602,7 @@ def delete_database_backup( self, *, database_backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DatabaseBackup: """ Delete a database backup. @@ -636,7 +639,7 @@ def restore_database_backup( *, database_backup_id: str, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, database_name: Optional[str] = None, ) -> DatabaseBackup: """ @@ -685,7 +688,7 @@ def export_database_backup( self, *, database_backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DatabaseBackup: """ Export a database backup. @@ -722,7 +725,7 @@ def upgrade_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, node_type: Optional[str] = None, enable_ha: Optional[bool] = None, volume_size: Optional[int] = None, @@ -731,6 +734,7 @@ def upgrade_instance( major_upgrade_workflow: Optional[ UpgradeInstanceRequestMajorUpgradeWorkflow ] = None, + enable_encryption: Optional[bool] = None, ) -> Instance: """ Upgrade a Database Instance. @@ -738,17 +742,19 @@ def upgrade_instance( :param instance_id: UUID of the Database Instance you want to upgrade. :param region: Region to target. If none is passed will use default region from the config. :param node_type: Node type of the Database Instance you want to upgrade to. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :param enable_ha: Defines whether or not high availability should be enabled on the Database Instance. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :param volume_size: Increase your block storage volume size. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :param volume_type: Change your Database Instance storage type. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :param upgradable_version_id: This will create a new Database Instance with same specifications as the current one and perform a Database Engine upgrade. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :param major_upgrade_workflow: Upgrade your database engine to a new major version including instance endpoints. - One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow' could be set. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. + :param enable_encryption: Defines whether or not encryption should be enabled on the Database Instance. + One-Of ('upgrade_target'): at most one of 'node_type', 'enable_ha', 'volume_size', 'volume_type', 'upgradable_version_id', 'major_upgrade_workflow', 'enable_encryption' could be set. :return: :class:`Instance ` Usage: @@ -777,6 +783,7 @@ def upgrade_instance( volume_type=volume_type, upgradable_version_id=upgradable_version_id, major_upgrade_workflow=major_upgrade_workflow, + enable_encryption=enable_encryption, ), self.client, ), @@ -788,7 +795,7 @@ def upgrade_instance( def list_instances( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, tags: Optional[List[str]] = None, name: Optional[str] = None, order_by: Optional[ListInstancesRequestOrderBy] = None, @@ -841,7 +848,7 @@ def list_instances( def list_instances_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, tags: Optional[List[str]] = None, name: Optional[str] = None, order_by: Optional[ListInstancesRequestOrderBy] = None, @@ -889,7 +896,7 @@ def get_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Instance: """ Get a Database Instance. @@ -923,7 +930,7 @@ def wait_for_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Instance, bool]] = None, ) -> Instance: """ @@ -963,7 +970,7 @@ def create_instance( user_name: str, password: str, node_type: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, name: Optional[str] = None, @@ -975,13 +982,14 @@ def create_instance( init_settings: Optional[List[InstanceSetting]] = None, volume_type: Optional[VolumeType] = None, init_endpoints: Optional[List[EndpointSpec]] = None, + encryption: Optional[EncryptionAtRest] = None, ) -> Instance: """ Create a Database Instance. Create a new Database Instance. You must set the `engine`, `user_name`, `password` and `node_type` parameters. Optionally, you can specify the volume type and size. :param engine: Database engine of the Database Instance (PostgreSQL, MySQL, ...). :param user_name: Username created when the Database Instance is created. - :param password: Password of the user. + :param password: Password of the user. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. :param node_type: Type of node to use for the Database Instance. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Please use project_id instead. @@ -997,6 +1005,7 @@ def create_instance( :param init_settings: List of engine settings to be set upon Database Instance initialization. :param volume_type: Type of volume where data is stored (lssd, bssd, ...). :param init_endpoints: One or multiple EndpointSpec used to expose your Database Instance. A load_balancer public endpoint is systematically created. + :param encryption: Encryption at rest settings for your Database Instance. :return: :class:`Instance ` Usage: @@ -1037,6 +1046,7 @@ def create_instance( init_settings=init_settings, volume_type=volume_type, init_endpoints=init_endpoints, + encryption=encryption, project_id=project_id, organization_id=organization_id, ), @@ -1051,7 +1061,7 @@ def update_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, backup_schedule_frequency: Optional[int] = None, backup_schedule_retention: Optional[int] = None, is_backup_schedule_disabled: Optional[bool] = None, @@ -1116,7 +1126,7 @@ def delete_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Instance: """ Delete a Database Instance. @@ -1151,7 +1161,7 @@ def clone_instance( *, instance_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, node_type: Optional[str] = None, ) -> Instance: """ @@ -1198,7 +1208,7 @@ def restart_instance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Instance: """ Restart Database Instance. @@ -1233,7 +1243,7 @@ def get_instance_certificate( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ScwFile: """ Get the TLS certificate of a Database Instance. @@ -1267,7 +1277,7 @@ def renew_instance_certificate( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Renew the TLS certificate of a Database Instance. @@ -1300,7 +1310,7 @@ def get_instance_metrics( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, start_date: Optional[datetime] = None, end_date: Optional[datetime] = None, metric_name: Optional[str] = None, @@ -1345,7 +1355,7 @@ def create_read_replica( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, endpoint_spec: Optional[List[ReadReplicaEndpointSpec]] = None, same_zone: Optional[bool] = None, ) -> ReadReplica: @@ -1391,7 +1401,7 @@ def get_read_replica( self, *, read_replica_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ReadReplica: """ Get a Read Replica. @@ -1425,7 +1435,7 @@ def wait_for_read_replica( self, *, read_replica_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[ReadReplica, bool]] = None, ) -> ReadReplica: """ @@ -1462,7 +1472,7 @@ def delete_read_replica( self, *, read_replica_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ReadReplica: """ Delete a Read Replica. @@ -1496,7 +1506,7 @@ def reset_read_replica( self, *, read_replica_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ReadReplica: """ Resync a Read Replica. @@ -1532,7 +1542,7 @@ def promote_read_replica( self, *, read_replica_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Instance: """ Promote a Read Replica. @@ -1568,7 +1578,7 @@ def create_read_replica_endpoint( *, read_replica_id: str, endpoint_spec: List[ReadReplicaEndpointSpec], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ReadReplica: """ Create an endpoint for a Read Replica. @@ -1612,7 +1622,7 @@ def prepare_instance_logs( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, start_date: Optional[datetime] = None, end_date: Optional[datetime] = None, ) -> PrepareInstanceLogsResponse: @@ -1659,7 +1669,7 @@ def list_instance_logs( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListInstanceLogsRequestOrderBy] = None, ) -> ListInstanceLogsResponse: """ @@ -1698,7 +1708,7 @@ def get_instance_log( self, *, instance_log_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> InstanceLog: """ Get given logs of a Database Instance. @@ -1732,7 +1742,7 @@ def wait_for_instance_log( self, *, instance_log_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[InstanceLog, bool]] = None, ) -> InstanceLog: """ @@ -1769,7 +1779,7 @@ def purge_instance_logs( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, log_name: Optional[str] = None, ) -> None: """ @@ -1811,7 +1821,7 @@ def list_instance_logs_details( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> ListInstanceLogsDetailsResponse: """ List remote Database Instance logs details. @@ -1846,7 +1856,7 @@ def add_instance_settings( *, instance_id: str, settings: List[InstanceSetting], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> AddInstanceSettingsResponse: """ Add Database Instance advanced settings. @@ -1891,7 +1901,7 @@ def delete_instance_settings( *, instance_id: str, setting_names: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DeleteInstanceSettingsResponse: """ Delete Database Instance advanced settings. @@ -1936,11 +1946,11 @@ def set_instance_settings( *, instance_id: str, settings: List[InstanceSetting], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SetInstanceSettingsResponse: """ Set Database Instance advanced settings. - Update an advanced setting for a Database Instance. Settings added upon database engine initalization can only be defined once, and cannot, therefore, be updated. + Update an advanced setting for a Database Instance. Settings added upon database engine initialization can only be defined once, and cannot, therefore, be updated. :param instance_id: UUID of the Database Instance where the settings must be set. :param settings: Settings to define for the Database Instance. :param region: Region to target. If none is passed will use default region from the config. @@ -1980,7 +1990,7 @@ def list_instance_acl_rules( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListInstanceACLRulesResponse: @@ -2022,7 +2032,7 @@ def list_instance_acl_rules_all( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[ACLRule]: @@ -2060,7 +2070,7 @@ def add_instance_acl_rules( *, instance_id: str, rules: List[ACLRuleRequest], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> AddInstanceACLRulesResponse: """ Add an ACL rule to a Database Instance. @@ -2105,7 +2115,7 @@ def set_instance_acl_rules( *, instance_id: str, rules: List[ACLRuleRequest], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SetInstanceACLRulesResponse: """ Set ACL rules for a Database Instance. @@ -2150,7 +2160,7 @@ def delete_instance_acl_rules( *, instance_id: str, acl_rule_ips: List[str], - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DeleteInstanceACLRulesResponse: """ Delete ACL rules of a Database Instance. @@ -2194,7 +2204,7 @@ def list_users( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListUsersRequestOrderBy] = None, page: Optional[int] = None, @@ -2242,7 +2252,7 @@ def list_users_all( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListUsersRequestOrderBy] = None, page: Optional[int] = None, @@ -2288,14 +2298,14 @@ def create_user( name: str, password: str, is_admin: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> User: """ Create a user for a Database Instance. Create a new user for a Database Instance. You must define the `name`, `password` and `is_admin` parameters. :param instance_id: UUID of the Database Instance in which you want to create a user. :param name: Name of the user you want to create. - :param password: Password of the user you want to create. + :param password: Password of the user you want to create. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. :param is_admin: Defines whether the user will have administrative privileges. :param region: Region to target. If none is passed will use default region from the config. :return: :class:`User ` @@ -2339,7 +2349,7 @@ def update_user( *, instance_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, password: Optional[str] = None, is_admin: Optional[bool] = None, ) -> User: @@ -2349,7 +2359,7 @@ def update_user( :param instance_id: UUID of the Database Instance the user belongs to. :param name: Name of the database user. :param region: Region to target. If none is passed will use default region from the config. - :param password: Password of the database user. + :param password: Password of the database user. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. :param is_admin: Defines whether or not this user got administrative privileges. :return: :class:`User ` @@ -2391,7 +2401,7 @@ def delete_user( *, instance_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a user on a Database Instance. @@ -2426,7 +2436,7 @@ def list_databases( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, managed: Optional[bool] = None, owner: Optional[str] = None, @@ -2480,7 +2490,7 @@ def list_databases_all( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, managed: Optional[bool] = None, owner: Optional[str] = None, @@ -2530,7 +2540,7 @@ def create_database( *, instance_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Database: """ Create a database in a Database Instance. @@ -2575,7 +2585,7 @@ def delete_database( *, instance_id: str, name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a database in a Database Instance. @@ -2610,7 +2620,7 @@ def list_privileges( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivilegesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2661,7 +2671,7 @@ def list_privileges_all( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivilegesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -2709,7 +2719,7 @@ def set_privilege( instance_id: str, database_name: str, user_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, permission: Optional[Permission] = None, ) -> Privilege: """ @@ -2758,7 +2768,7 @@ def set_privilege( def list_snapshots( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListSnapshotsRequestOrderBy] = None, instance_id: Optional[str] = None, @@ -2811,7 +2821,7 @@ def list_snapshots( def list_snapshots_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, order_by: Optional[ListSnapshotsRequestOrderBy] = None, instance_id: Optional[str] = None, @@ -2859,7 +2869,7 @@ def get_snapshot( self, *, snapshot_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Snapshot: """ Get a Database Instance snapshot. @@ -2893,7 +2903,7 @@ def wait_for_snapshot( self, *, snapshot_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Snapshot, bool]] = None, ) -> Snapshot: """ @@ -2930,7 +2940,7 @@ def create_snapshot( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, expires_at: Optional[datetime] = None, ) -> Snapshot: @@ -2977,7 +2987,7 @@ def update_snapshot( self, *, snapshot_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, expires_at: Optional[datetime] = None, ) -> Snapshot: @@ -3024,7 +3034,7 @@ def delete_snapshot( self, *, snapshot_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Snapshot: """ Delete a Database Instance snapshot. @@ -3059,7 +3069,7 @@ def create_instance_from_snapshot( *, snapshot_id: str, instance_name: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, is_ha_cluster: Optional[bool] = None, node_type: Optional[str] = None, ) -> Instance: @@ -3109,7 +3119,7 @@ def create_endpoint( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, endpoint_spec: Optional[EndpointSpec] = None, ) -> Endpoint: """ @@ -3153,7 +3163,7 @@ def delete_endpoint( self, *, endpoint_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a Database Instance endpoint. @@ -3185,7 +3195,7 @@ def get_endpoint( self, *, endpoint_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Endpoint: """ Get a Database Instance endpoint. @@ -3220,7 +3230,7 @@ def migrate_endpoint( *, endpoint_id: str, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Endpoint: """ Migrate an existing instance endpoint to another instance. @@ -3263,7 +3273,7 @@ def apply_instance_maintenance( self, *, instance_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Maintenance: """ Apply Database Instance maintenance. diff --git a/scaleway/scaleway/rdb/v1/marshalling.py b/scaleway/scaleway/rdb/v1/marshalling.py index a480738f..6ae68f62 100644 --- a/scaleway/scaleway/rdb/v1/marshalling.py +++ b/scaleway/scaleway/rdb/v1/marshalling.py @@ -23,6 +23,7 @@ Database, InstanceLog, BackupSchedule, + EncryptionAtRest, InstanceSetting, LogsPolicy, UpgradableVersion, @@ -140,6 +141,10 @@ def unmarshal_EndpointPrivateNetworkDetails(data: Any) -> EndpointPrivateNetwork if field is not None: args["zone"] = field + field = data.get("provisioning_mode", None) + if field is not None: + args["provisioning_mode"] = field + return EndpointPrivateNetworkDetails(**args) @@ -162,26 +167,38 @@ def unmarshal_Endpoint(data: Any) -> Endpoint: field = data.get("ip", None) if field is not None: args["ip"] = field + else: + args["ip"] = None field = data.get("name", None) if field is not None: args["name"] = field + else: + args["name"] = None field = data.get("private_network", None) if field is not None: args["private_network"] = unmarshal_EndpointPrivateNetworkDetails(field) + else: + args["private_network"] = None field = data.get("load_balancer", None) if field is not None: args["load_balancer"] = unmarshal_EndpointLoadBalancerDetails(field) + else: + args["load_balancer"] = None field = data.get("direct_access", None) if field is not None: args["direct_access"] = unmarshal_EndpointDirectAccessDetails(field) + else: + args["direct_access"] = None field = data.get("hostname", None) if field is not None: args["hostname"] = field + else: + args["hostname"] = None return Endpoint(**args) @@ -205,18 +222,26 @@ def unmarshal_Maintenance(data: Any) -> Maintenance: field = data.get("starts_at", None) if field is not None: args["starts_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["starts_at"] = None field = data.get("stops_at", None) if field is not None: args["stops_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stops_at"] = None field = data.get("closed_at", None) if field is not None: args["closed_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["closed_at"] = None field = data.get("forced_at", None) if field is not None: args["forced_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["forced_at"] = None return Maintenance(**args) @@ -289,18 +314,26 @@ def unmarshal_DatabaseBackup(data: Any) -> DatabaseBackup: field = data.get("size", None) if field is not None: args["size"] = field + else: + args["size"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("instance_name", None) if field is not None: @@ -317,12 +350,16 @@ def unmarshal_DatabaseBackup(data: Any) -> DatabaseBackup: field = data.get("download_url", None) if field is not None: args["download_url"] = field + else: + args["download_url"] = None field = data.get("download_url_expires_at", None) if field is not None: args["download_url_expires_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["download_url_expires_at"] = None return DatabaseBackup(**args) @@ -381,14 +418,20 @@ def unmarshal_InstanceLog(data: Any) -> InstanceLog: field = data.get("download_url", None) if field is not None: args["download_url"] = field + else: + args["download_url"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return InstanceLog(**args) @@ -418,10 +461,27 @@ def unmarshal_BackupSchedule(data: Any) -> BackupSchedule: args["next_run_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["next_run_at"] = None return BackupSchedule(**args) +def unmarshal_EncryptionAtRest(data: Any) -> EncryptionAtRest: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EncryptionAtRest' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + return EncryptionAtRest(**args) + + def unmarshal_InstanceSetting(data: Any) -> InstanceSetting: if not isinstance(data, dict): raise TypeError( @@ -452,10 +512,14 @@ def unmarshal_LogsPolicy(data: Any) -> LogsPolicy: field = data.get("max_age_retention", None) if field is not None: args["max_age_retention"] = field + else: + args["max_age_retention"] = None field = data.get("total_disk_retention", None) if field is not None: args["total_disk_retention"] = field + else: + args["total_disk_retention"] = None return LogsPolicy(**args) @@ -495,7 +559,7 @@ def unmarshal_Volume(data: Any) -> Volume: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -503,7 +567,7 @@ def unmarshal_Volume(data: Any) -> Volume: if field is not None: args["size"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -537,10 +601,14 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("volume", None) if field is not None: args["volume"] = unmarshal_Volume(field) + else: + args["volume"] = None field = data.get("project_id", None) if field is not None: @@ -579,10 +647,14 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("endpoint", None) if field is not None: args["endpoint"] = unmarshal_Endpoint(field) + else: + args["endpoint"] = None field = data.get("backup_schedule", None) if field is not None: args["backup_schedule"] = unmarshal_BackupSchedule(field) + else: + args["backup_schedule"] = None field = data.get("read_replicas", None) if field is not None: @@ -619,6 +691,14 @@ def unmarshal_Instance(data: Any) -> Instance: field = data.get("logs_policy", None) if field is not None: args["logs_policy"] = unmarshal_LogsPolicy(field) + else: + args["logs_policy"] = None + + field = data.get("encryption", None) + if field is not None: + args["encryption"] = unmarshal_EncryptionAtRest(field) + else: + args["encryption"] = None return Instance(**args) @@ -654,11 +734,11 @@ def unmarshal_SnapshotVolumeType(data: Any) -> SnapshotVolumeType: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -704,22 +784,32 @@ def unmarshal_Snapshot(data: Any) -> Snapshot: field = data.get("size", None) if field is not None: args["size"] = field + else: + args["size"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("volume_type", None) if field is not None: args["volume_type"] = unmarshal_SnapshotVolumeType(field) + else: + args["volume_type"] = None return Snapshot(**args) @@ -774,6 +864,8 @@ def unmarshal_ACLRule(data: Any) -> ACLRule: field = data.get("port", None) if field is not None: args["port"] = field + else: + args["port"] = None return ACLRule(**args) @@ -919,26 +1011,38 @@ def unmarshal_EngineSetting(data: Any) -> EngineSetting: field = data.get("unit", None) if field is not None: args["unit"] = field + else: + args["unit"] = None field = data.get("string_constraint", None) if field is not None: args["string_constraint"] = field + else: + args["string_constraint"] = None field = data.get("int_min", None) if field is not None: args["int_min"] = field + else: + args["int_min"] = None field = data.get("int_max", None) if field is not None: args["int_max"] = field + else: + args["int_max"] = None field = data.get("float_min", None) if field is not None: args["float_min"] = field + else: + args["float_min"] = None field = data.get("float_max", None) if field is not None: args["float_max"] = field + else: + args["float_max"] = None return EngineSetting(**args) @@ -984,6 +1088,8 @@ def unmarshal_EngineVersion(data: Any) -> EngineVersion: args["end_of_life"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["end_of_life"] = None return EngineVersion(**args) @@ -1190,7 +1296,7 @@ def unmarshal_NodeTypeVolumeType(data: Any) -> NodeTypeVolumeType: args: Dict[str, Any] = {} - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -1210,7 +1316,7 @@ def unmarshal_NodeTypeVolumeType(data: Any) -> NodeTypeVolumeType: if field is not None: args["chunk_size"] = field - field = data.get("class_", None) + field = data.get("class", None) if field is not None: args["class_"] = field @@ -1256,10 +1362,14 @@ def unmarshal_NodeType(data: Any) -> NodeType: field = data.get("volume_constraint", None) if field is not None: args["volume_constraint"] = unmarshal_NodeTypeVolumeConstraintSizes(field) + else: + args["volume_constraint"] = None field = data.get("is_bssd_compatible", None) if field is not None: args["is_bssd_compatible"] = field + else: + args["is_bssd_compatible"] = None field = data.get("available_volume_types", None) if field is not None: @@ -1512,7 +1622,7 @@ def marshal_CreateDatabaseBackupRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -1591,9 +1701,7 @@ def marshal_CreateEndpointRequest( output: Dict[str, Any] = {} if request.endpoint_spec is not None: - output["endpoint_spec"] = ( - marshal_EndpointSpec(request.endpoint_spec, defaults), - ) + output["endpoint_spec"] = marshal_EndpointSpec(request.endpoint_spec, defaults) return output @@ -1616,6 +1724,18 @@ def marshal_CreateInstanceFromSnapshotRequest( return output +def marshal_EncryptionAtRest( + request: EncryptionAtRest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.enabled is not None: + output["enabled"] = request.enabled + + return output + + def marshal_CreateInstanceRequest( request: CreateInstanceRequest, defaults: ProfileDefaults, @@ -1679,6 +1799,9 @@ def marshal_CreateInstanceRequest( marshal_EndpointSpec(item, defaults) for item in request.init_endpoints ] + if request.encryption is not None: + output["encryption"] = marshal_EncryptionAtRest(request.encryption, defaults) + return output @@ -1783,7 +1906,7 @@ def marshal_CreateSnapshotRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -1849,10 +1972,10 @@ def marshal_PrepareInstanceLogsRequest( output: Dict[str, Any] = {} if request.start_date is not None: - output["start_date"] = request.start_date + output["start_date"] = request.start_date.isoformat() if request.end_date is not None: - output["end_date"] = request.end_date + output["end_date"] = request.end_date.isoformat() return output @@ -1940,7 +2063,7 @@ def marshal_UpdateDatabaseBackupRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -1982,7 +2105,7 @@ def marshal_UpdateInstanceRequest( output["tags"] = request.tags if request.logs_policy is not None: - output["logs_policy"] = (marshal_LogsPolicy(request.logs_policy, defaults),) + output["logs_policy"] = marshal_LogsPolicy(request.logs_policy, defaults) if request.backup_same_region is not None: output["backup_same_region"] = request.backup_same_region @@ -2003,7 +2126,7 @@ def marshal_UpdateSnapshotRequest( output["name"] = request.name if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() return output @@ -2056,6 +2179,7 @@ def marshal_UpgradeInstanceRequest( OneOfPossibility( "major_upgrade_workflow", request.major_upgrade_workflow ), + OneOfPossibility("enable_encryption", request.enable_encryption), ] ), ) diff --git a/scaleway/scaleway/rdb/v1/types.py b/scaleway/scaleway/rdb/v1/types.py index ef41a5e2..2b86e74a 100644 --- a/scaleway/scaleway/rdb/v1/types.py +++ b/scaleway/scaleway/rdb/v1/types.py @@ -8,9 +8,9 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, TimeSeries, - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -56,6 +56,14 @@ def __str__(self) -> str: return str(self.value) +class EndpointPrivateNetworkDetailsProvisioningMode(str, Enum, metaclass=StrEnumMeta): + STATIC = "static" + IPAM = "ipam" + + def __str__(self) -> str: + return str(self.value) + + class EngineSettingPropertyType(str, Enum, metaclass=StrEnumMeta): BOOLEAN = "boolean" INT = "int" @@ -281,11 +289,16 @@ class EndpointPrivateNetworkDetails: CIDR notation of the endpoint IPv4 address. """ - zone: Zone + zone: ScwZone """ Private network zone. """ + provisioning_mode: EndpointPrivateNetworkDetailsProvisioningMode + """ + How endpoint ips are provisioned. + """ + @dataclass class EndpointSpecPrivateNetworkIpamConfig: @@ -478,6 +491,11 @@ class BackupSchedule: """ +@dataclass +class EncryptionAtRest: + enabled: bool + + @dataclass class InstanceSetting: name: str @@ -548,7 +566,7 @@ class ReadReplica: Read replica status. """ - region: Region + region: ScwRegion """ Region the Read Replica is in. """ @@ -588,7 +606,7 @@ class Volume: class NodeTypeVolumeConstraintSizes: min_size: int """ - [deprecated] Mimimum size required for the Volume. + [deprecated] Minimum size required for the Volume. """ max_size: int @@ -611,7 +629,7 @@ class NodeTypeVolumeType: min_size: int """ - Mimimum size required for the Volume. + Minimum size required for the Volume. """ max_size: int @@ -725,7 +743,7 @@ class DatabaseBackup: Name of the Database Instance of the backup. """ - region: Region + region: ScwRegion """ Region of the database backup. """ @@ -763,7 +781,7 @@ class DatabaseEngine: Available versions. """ - region: Region + region: ScwRegion """ Region of this Database Instance. """ @@ -816,14 +834,14 @@ class InstanceLog: Name of the underlying node. """ - region: Region + region: ScwRegion """ Region the Database Instance is in. """ download_url: Optional[str] """ - Presigned S3 URL to download your log file. + Presigned Object Storage URL to download your log file. """ expires_at: Optional[datetime] @@ -839,7 +857,7 @@ class InstanceLog: @dataclass class Instance: - region: Region + region: ScwRegion """ Region the Database Instance is in. """ @@ -949,6 +967,11 @@ class Instance: Logs policy of the Database Instance. """ + encryption: Optional[EncryptionAtRest] + """ + Encryption at rest settings for your Database Instance. + """ + @dataclass class NodeType: @@ -1017,7 +1040,7 @@ class NodeType: Instance range associated with the NodeType offer. """ - region: Region + region: ScwRegion """ Region the Node Type is in. """ @@ -1073,7 +1096,7 @@ class Snapshot: Source node type. """ - region: Region + region: ScwRegion """ Region of this snapshot. """ @@ -1142,7 +1165,7 @@ class AddInstanceACLRulesRequest: ACL rules to add to the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1168,7 +1191,7 @@ class AddInstanceSettingsRequest: Settings to add to the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1189,7 +1212,7 @@ class ApplyInstanceMaintenanceRequest: UUID of the Database Instance you want to apply maintenance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1207,7 +1230,7 @@ class CloneInstanceRequest: Name of the Database Instance clone. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1230,7 +1253,7 @@ class CreateDatabaseBackupRequest: Name of the database you want to back up. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1258,7 +1281,7 @@ class CreateDatabaseRequest: Name of the database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1271,7 +1294,7 @@ class CreateEndpointRequest: UUID of the Database Instance you to which you want to add an endpoint. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1294,7 +1317,7 @@ class CreateInstanceFromSnapshotRequest: Name of the Database Instance created with the snapshot. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1324,7 +1347,7 @@ class CreateInstanceRequest: password: str """ - Password of the user. + Password of the user. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. """ node_type: str @@ -1332,7 +1355,7 @@ class CreateInstanceRequest: Type of node to use for the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1382,6 +1405,11 @@ class CreateInstanceRequest: One or multiple EndpointSpec used to expose your Database Instance. A load_balancer public endpoint is systematically created. """ + encryption: Optional[EncryptionAtRest] + """ + Encryption at rest settings for your Database Instance. + """ + project_id: Optional[str] organization_id: Optional[str] @@ -1399,7 +1427,7 @@ class CreateReadReplicaEndpointRequest: Specification of the endpoint you want to create. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1412,7 +1440,7 @@ class CreateReadReplicaRequest: UUID of the Database Instance you want to create a Read Replica from. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1435,7 +1463,7 @@ class CreateSnapshotRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1465,7 +1493,7 @@ class CreateUserRequest: password: str """ - Password of the user you want to create. + Password of the user you want to create. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. """ is_admin: bool @@ -1473,7 +1501,7 @@ class CreateUserRequest: Defines whether the user will have administrative privileges. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1486,7 +1514,7 @@ class DeleteDatabaseBackupRequest: UUID of the database backup to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1504,7 +1532,7 @@ class DeleteDatabaseRequest: Name of the database to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1517,7 +1545,7 @@ class DeleteEndpointRequest: This endpoint can also be used to delete a Read Replica endpoint. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1535,7 +1563,7 @@ class DeleteInstanceACLRulesRequest: IP addresses defined in the ACL rules of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1556,7 +1584,7 @@ class DeleteInstanceRequest: UUID of the Database Instance to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1574,7 +1602,7 @@ class DeleteInstanceSettingsRequest: Settings names to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1595,7 +1623,7 @@ class DeleteReadReplicaRequest: UUID of the Read Replica. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1608,7 +1636,7 @@ class DeleteSnapshotRequest: UUID of the snapshot to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1626,7 +1654,7 @@ class DeleteUserRequest: Name of the user. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1639,7 +1667,7 @@ class ExportDatabaseBackupRequest: UUID of the database backup you want to export. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1652,7 +1680,7 @@ class GetDatabaseBackupRequest: UUID of the database backup. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1665,7 +1693,7 @@ class GetEndpointRequest: UUID of the endpoint you want to get. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1678,7 +1706,7 @@ class GetInstanceCertificateRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1691,7 +1719,7 @@ class GetInstanceLogRequest: UUID of the instance_log you want. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1704,7 +1732,7 @@ class GetInstanceMetricsRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1732,7 +1760,7 @@ class GetInstanceRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1745,7 +1773,7 @@ class GetReadReplicaRequest: UUID of the Read Replica. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1758,7 +1786,7 @@ class GetSnapshotRequest: UUID of the snapshot. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1774,7 +1802,7 @@ class InstanceMetrics: @dataclass class ListDatabaseBackupsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1824,7 +1852,7 @@ class ListDatabaseBackupsResponse: @dataclass class ListDatabaseEnginesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1864,7 +1892,7 @@ class ListDatabasesRequest: UUID of the Database Instance to list the databases of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1914,7 +1942,7 @@ class ListInstanceACLRulesRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1944,7 +1972,7 @@ class ListInstanceLogsDetailsRequest: UUID of the Database Instance you want logs of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1965,7 +1993,7 @@ class ListInstanceLogsRequest: UUID of the Database Instance you want logs of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -1986,7 +2014,7 @@ class ListInstanceLogsResponse: @dataclass class ListInstancesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2041,7 +2069,7 @@ class ListNodeTypesRequest: Defines whether or not to include disabled types. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2071,7 +2099,7 @@ class ListPrivilegesRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2111,7 +2139,7 @@ class ListPrivilegesResponse: @dataclass class ListSnapshotsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2166,7 +2194,7 @@ class ListUsersRequest: UUID of the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2211,7 +2239,7 @@ class MigrateEndpointRequest: UUID of the instance you want to attach the endpoint to. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2224,7 +2252,7 @@ class PrepareInstanceLogsRequest: UUID of the Database Instance you want logs of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2255,7 +2283,7 @@ class PromoteReadReplicaRequest: UUID of the Read Replica. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2268,7 +2296,7 @@ class PurgeInstanceLogsRequest: UUID of the Database Instance you want logs of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2286,7 +2314,7 @@ class RenewInstanceCertificateRequest: UUID of the Database Instance you want logs of. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2299,7 +2327,7 @@ class ResetReadReplicaRequest: UUID of the Read Replica. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2312,7 +2340,7 @@ class RestartInstanceRequest: UUID of the Database Instance you want to restart. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2330,7 +2358,7 @@ class RestoreDatabaseBackupRequest: Defines the Database Instance where the backup has to be restored. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2353,7 +2381,7 @@ class SetInstanceACLRulesRequest: ACL rules to define for the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2379,7 +2407,7 @@ class SetInstanceSettingsRequest: Settings to define for the Database Instance. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2410,7 +2438,7 @@ class SetPrivilegeRequest: Name of the user. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2428,7 +2456,7 @@ class UpdateDatabaseBackupRequest: UUID of the database backup to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2451,7 +2479,7 @@ class UpdateInstanceRequest: UUID of the Database Instance to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2504,7 +2532,7 @@ class UpdateSnapshotRequest: UUID of the snapshot to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2532,14 +2560,14 @@ class UpdateUserRequest: Name of the database user. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ password: Optional[str] """ - Password of the database user. + Password of the database user. Password must be between 8 and 128 characters, contain at least one digit, one uppercase, one lowercase and one special character. """ is_admin: Optional[bool] @@ -2555,7 +2583,7 @@ class UpgradeInstanceRequest: UUID of the Database Instance you want to upgrade. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -2571,3 +2599,5 @@ class UpgradeInstanceRequest: upgradable_version_id: Optional[str] major_upgrade_workflow: Optional[UpgradeInstanceRequestMajorUpgradeWorkflow] + + enable_encryption: Optional[bool] diff --git a/scaleway/scaleway/redis/v1/api.py b/scaleway/scaleway/redis/v1/api.py index 12546595..6c85c30e 100644 --- a/scaleway/scaleway/redis/v1/api.py +++ b/scaleway/scaleway/redis/v1/api.py @@ -7,7 +7,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( ScwFile, - Zone, + Zone as ScwZone, unmarshal_ScwFile, ) from scaleway_core.utils import ( @@ -79,14 +79,16 @@ class RedisV1API(API): - """ """ + """ + This API allows you to manage your Managed Databases for Redisâ„¢. + """ def create_cluster( self, *, version: str, node_type: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project_id: Optional[str] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, @@ -160,7 +162,7 @@ def update_cluster( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, user_name: Optional[str] = None, @@ -211,7 +213,7 @@ def get_cluster( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Get a Redisâ„¢ Database Instance. @@ -243,7 +245,7 @@ def wait_for_cluster( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Cluster, bool]] = None, ) -> Cluster: """ @@ -279,7 +281,7 @@ def wait_for_cluster( def list_clusters( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, name: Optional[str] = None, order_by: Optional[ListClustersRequestOrderBy] = None, @@ -333,7 +335,7 @@ def list_clusters( def list_clusters_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, name: Optional[str] = None, order_by: Optional[ListClustersRequestOrderBy] = None, @@ -384,7 +386,7 @@ def migrate_cluster( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, version: Optional[str] = None, node_type: Optional[str] = None, cluster_size: Optional[int] = None, @@ -435,7 +437,7 @@ def delete_cluster( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Delete a Redisâ„¢ Database Instance. @@ -467,7 +469,7 @@ def get_cluster_metrics( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, start_at: Optional[datetime] = None, end_at: Optional[datetime] = None, metric_name: Optional[str] = None, @@ -510,7 +512,7 @@ def list_node_types( self, *, include_disabled_types: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListNodeTypesResponse: @@ -550,7 +552,7 @@ def list_node_types_all( self, *, include_disabled_types: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[NodeType]: @@ -589,7 +591,7 @@ def list_cluster_versions( include_disabled: bool, include_beta: bool, include_deprecated: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, version: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -640,7 +642,7 @@ def list_cluster_versions_all( include_disabled: bool, include_beta: bool, include_deprecated: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, version: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -686,7 +688,7 @@ def get_cluster_certificate( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ScwFile: """ Get the TLS certificate of a cluster. @@ -718,7 +720,7 @@ def renew_cluster_certificate( self, *, cluster_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Renew the TLS certificate of a cluster. @@ -752,7 +754,7 @@ def add_cluster_settings( *, cluster_id: str, settings: List[ClusterSetting], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ClusterSettingsResponse: """ Add advanced settings. @@ -795,7 +797,7 @@ def delete_cluster_setting( *, cluster_id: str, setting_name: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Delete advanced setting. @@ -831,11 +833,11 @@ def set_cluster_settings( *, cluster_id: str, settings: List[ClusterSetting], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ClusterSettingsResponse: """ Set advanced settings. - Update an advanced setting for a Redisâ„¢ Database Instance (Redisâ„¢ cluster). Settings added upon database engine initalization can only be defined once, and cannot, therefore, be updated. + Update an advanced setting for a Redisâ„¢ Database Instance (Redisâ„¢ cluster). Settings added upon database engine initialization can only be defined once, and cannot, therefore, be updated. :param cluster_id: UUID of the Database Instance where the settings must be set. :param settings: Settings to define for the Database Instance. :param zone: Zone to target. If none is passed will use default zone from the config. @@ -874,7 +876,7 @@ def set_acl_rules( *, cluster_id: str, acl_rules: List[ACLRuleSpec], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetAclRulesResponse: """ Set ACL rules for a cluster. @@ -917,7 +919,7 @@ def add_acl_rules( *, cluster_id: str, acl_rules: List[ACLRuleSpec], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> AddAclRulesResponse: """ Add ACL rules for a cluster. @@ -959,7 +961,7 @@ def delete_acl_rule( self, *, acl_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Delete an ACL rule for a cluster. @@ -991,7 +993,7 @@ def get_acl_rule( self, *, acl_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ACLRule: """ Get an ACL rule. @@ -1024,7 +1026,7 @@ def set_endpoints( *, cluster_id: str, endpoints: List[EndpointSpec], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetEndpointsResponse: """ Set endpoints for a cluster. @@ -1067,7 +1069,7 @@ def add_endpoints( *, cluster_id: str, endpoints: List[EndpointSpec], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> AddEndpointsResponse: """ Add endpoints for a cluster. @@ -1109,7 +1111,7 @@ def delete_endpoint( self, *, endpoint_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Cluster: """ Delete an endpoint for a cluster. @@ -1141,7 +1143,7 @@ def get_endpoint( self, *, endpoint_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Endpoint: """ Get an endpoint. @@ -1173,7 +1175,7 @@ def update_endpoint( self, *, endpoint_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, private_network: Optional[EndpointSpecPrivateNetworkSpec] = None, public_network: Optional[EndpointSpecPublicNetworkSpec] = None, ) -> Endpoint: diff --git a/scaleway/scaleway/redis/v1/marshalling.py b/scaleway/scaleway/redis/v1/marshalling.py index f72dabcb..91b1befd 100644 --- a/scaleway/scaleway/redis/v1/marshalling.py +++ b/scaleway/scaleway/redis/v1/marshalling.py @@ -64,10 +64,14 @@ def unmarshal_ACLRule(data: Any) -> ACLRule: field = data.get("ip_cidr", None) if field is not None: args["ip_cidr"] = field + else: + args["ip_cidr"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None return ACLRule(**args) @@ -133,10 +137,14 @@ def unmarshal_Endpoint(data: Any) -> Endpoint: field = data.get("private_network", None) if field is not None: args["private_network"] = unmarshal_PrivateNetwork(field) + else: + args["private_network"] = None field = data.get("public_network", None) if field is not None: args["public_network"] = unmarshal_PublicNetwork(field) + else: + args["public_network"] = None return Endpoint(**args) @@ -215,10 +223,14 @@ def unmarshal_Cluster(data: Any) -> Cluster: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("acl_rules", None) if field is not None: @@ -333,7 +345,7 @@ def unmarshal_AvailableClusterSetting(data: Any) -> AvailableClusterSetting: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -348,18 +360,26 @@ def unmarshal_AvailableClusterSetting(data: Any) -> AvailableClusterSetting: field = data.get("default_value", None) if field is not None: args["default_value"] = field + else: + args["default_value"] = None field = data.get("max_value", None) if field is not None: args["max_value"] = field + else: + args["max_value"] = None field = data.get("min_value", None) if field is not None: args["min_value"] = field + else: + args["min_value"] = None field = data.get("regex", None) if field is not None: args["regex"] = field + else: + args["regex"] = None return AvailableClusterSetting(**args) @@ -397,6 +417,8 @@ def unmarshal_ClusterVersion(data: Any) -> ClusterVersion: args["end_of_life_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["end_of_life_at"] = None return ClusterVersion(**args) @@ -621,10 +643,8 @@ def marshal_EndpointSpecPrivateNetworkSpec( output["service_ips"] = request.service_ips if request.ipam_config is not None: - output["ipam_config"] = ( - marshal_EndpointSpecPrivateNetworkSpecIpamConfig( - request.ipam_config, defaults - ), + output["ipam_config"] = marshal_EndpointSpecPrivateNetworkSpecIpamConfig( + request.ipam_config, defaults ) return output diff --git a/scaleway/scaleway/redis/v1/types.py b/scaleway/scaleway/redis/v1/types.py index 108a9712..a4a9c8ea 100644 --- a/scaleway/scaleway/redis/v1/types.py +++ b/scaleway/scaleway/redis/v1/types.py @@ -9,7 +9,7 @@ from scaleway_core.bridge import ( TimeSeries, - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -87,7 +87,7 @@ class PrivateNetwork: List of IPv4 CIDR notation addresses of the endpoint. """ - zone: Zone + zone: ScwZone """ Zone of the Private Network. """ @@ -259,7 +259,7 @@ class ClusterVersion: Redisâ„¢ logo url. """ - zone: Zone + zone: ScwZone """ Zone of the Redisâ„¢ Database Instance. """ @@ -342,7 +342,7 @@ class Cluster: Number of nodes of the Database Instance cluster. """ - zone: Zone + zone: ScwZone """ Zone of the Database Instance. """ @@ -395,7 +395,7 @@ class NodeType: Defines whether node type is currently in beta. """ - zone: Zone + zone: ScwZone """ Zone of the node type. """ @@ -413,7 +413,7 @@ class AddAclRulesRequest: ACLs rules to add to the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -444,7 +444,7 @@ class AddClusterSettingsRequest: Settings to add to the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -462,7 +462,7 @@ class AddEndpointsRequest: Endpoints to add to the Database Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -509,7 +509,7 @@ class CreateClusterRequest: Type of node to use for the Database Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -572,7 +572,7 @@ class DeleteAclRuleRequest: UUID of the ACL rule you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -585,7 +585,7 @@ class DeleteClusterRequest: UUID of the Database Instance to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -603,7 +603,7 @@ class DeleteClusterSettingRequest: Setting name to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -616,7 +616,7 @@ class DeleteEndpointRequest: UUID of the endpoint you want to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -629,7 +629,7 @@ class GetAclRuleRequest: UUID of the ACL rule you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -642,7 +642,7 @@ class GetClusterCertificateRequest: UUID of the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -655,7 +655,7 @@ class GetClusterMetricsRequest: UUID of the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -683,7 +683,7 @@ class GetClusterRequest: UUID of the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -696,7 +696,7 @@ class GetEndpointRequest: UUID of the endpoint you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -719,7 +719,7 @@ class ListClusterVersionsRequest: Defines whether or not to include deprecated Redisâ„¢ engine versions. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -749,7 +749,7 @@ class ListClusterVersionsResponse: @dataclass class ListClustersRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -809,7 +809,7 @@ class ListNodeTypesRequest: Defines whether or not to include disabled types. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -839,7 +839,7 @@ class MigrateClusterRequest: UUID of the Database Instance to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -858,7 +858,7 @@ class RenewClusterCertificateRequest: UUID of the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -876,7 +876,7 @@ class SetAclRulesRequest: ACLs rules to define for the cluster. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -902,7 +902,7 @@ class SetClusterSettingsRequest: Settings to define for the Database Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -920,7 +920,7 @@ class SetEndpointsRequest: Endpoints to define for the Database Instance. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -941,7 +941,7 @@ class UpdateClusterRequest: UUID of the Database Instance to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -974,7 +974,7 @@ class UpdateEndpointRequest: UUID of the endpoint you want to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ diff --git a/scaleway/scaleway/registry/v1/api.py b/scaleway/scaleway/registry/v1/api.py index b38424ad..0753a736 100644 --- a/scaleway/scaleway/registry/v1/api.py +++ b/scaleway/scaleway/registry/v1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( WaitForOptions, @@ -49,13 +49,13 @@ class RegistryV1API(API): """ - Container Registry API. + This API allows you to manage your Container Registry resources. """ def list_namespaces( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -105,7 +105,7 @@ def list_namespaces( def list_namespaces_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListNamespacesRequestOrderBy] = None, @@ -150,7 +150,7 @@ def get_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Get a namespace. @@ -184,7 +184,7 @@ def wait_for_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Namespace, bool]] = None, ) -> Namespace: """ @@ -222,7 +222,7 @@ def create_namespace( *, description: str, is_public: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, @@ -276,7 +276,7 @@ def update_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, is_public: Optional[bool] = None, ) -> Namespace: @@ -323,7 +323,7 @@ def delete_namespace( self, *, namespace_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Namespace: """ Delete a namespace. @@ -356,7 +356,7 @@ def delete_namespace( def list_images( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListImagesRequestOrderBy] = None, @@ -409,7 +409,7 @@ def list_images( def list_images_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListImagesRequestOrderBy] = None, @@ -457,7 +457,7 @@ def get_image( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Image: """ Get an image. @@ -491,7 +491,7 @@ def wait_for_image( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Image, bool]] = None, ) -> Image: """ @@ -528,7 +528,7 @@ def update_image( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, visibility: Optional[ImageVisibility] = None, ) -> Image: """ @@ -572,7 +572,7 @@ def delete_image( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Image: """ Delete an image. @@ -606,7 +606,7 @@ def list_tags( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTagsRequestOrderBy] = None, @@ -654,7 +654,7 @@ def list_tags_all( self, *, image_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListTagsRequestOrderBy] = None, @@ -697,7 +697,7 @@ def get_tag( self, *, tag_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Tag: """ Get a tag. @@ -731,7 +731,7 @@ def wait_for_tag( self, *, tag_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Tag, bool]] = None, ) -> Tag: """ @@ -768,7 +768,7 @@ def delete_tag( self, *, tag_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, force: Optional[bool] = None, ) -> Tag: """ diff --git a/scaleway/scaleway/registry/v1/marshalling.py b/scaleway/scaleway/registry/v1/marshalling.py index d720c137..1ffa9c7f 100644 --- a/scaleway/scaleway/registry/v1/marshalling.py +++ b/scaleway/scaleway/registry/v1/marshalling.py @@ -61,14 +61,20 @@ def unmarshal_Image(data: Any) -> Image: field = data.get("status_message", None) if field is not None: args["status_message"] = field + else: + args["status_message"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Image(**args) @@ -132,10 +138,14 @@ def unmarshal_Namespace(data: Any) -> Namespace: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Namespace(**args) @@ -171,10 +181,14 @@ def unmarshal_Tag(data: Any) -> Tag: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Tag(**args) diff --git a/scaleway/scaleway/registry/v1/types.py b/scaleway/scaleway/registry/v1/types.py index 8caf3e1f..e5e425da 100644 --- a/scaleway/scaleway/registry/v1/types.py +++ b/scaleway/scaleway/registry/v1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -152,7 +152,7 @@ class Namespace: name: str """ - Name of the namespace, unique in a region accross all organizations. + Name of the namespace, unique in a region across all organizations. """ description: str @@ -200,7 +200,7 @@ class Namespace: Number of images in the namespace. """ - region: Region + region: ScwRegion """ Region the namespace belongs to. """ @@ -266,7 +266,7 @@ class CreateNamespaceRequest: Defines whether or not namespace is public. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -288,7 +288,7 @@ class DeleteImageRequest: UUID of the image. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -301,7 +301,7 @@ class DeleteNamespaceRequest: UUID of the namespace. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -314,7 +314,7 @@ class DeleteTagRequest: UUID of the tag. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -332,7 +332,7 @@ class GetImageRequest: UUID of the image. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -345,7 +345,7 @@ class GetNamespaceRequest: UUID of the namespace. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -358,7 +358,7 @@ class GetTagRequest: UUID of the tag. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -366,7 +366,7 @@ class GetTagRequest: @dataclass class ListImagesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -422,7 +422,7 @@ class ListImagesResponse: @dataclass class ListNamespacesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -478,7 +478,7 @@ class ListTagsRequest: UUID of the image. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -524,7 +524,7 @@ class UpdateImageRequest: ID of the image to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -542,7 +542,7 @@ class UpdateNamespaceRequest: ID of the namespace to update. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/scaleway/secret/v1alpha1/api.py b/scaleway/scaleway/secret/v1alpha1/api.py index 3308b88a..91420bef 100644 --- a/scaleway/scaleway/secret/v1alpha1/api.py +++ b/scaleway/scaleway/secret/v1alpha1/api.py @@ -57,7 +57,7 @@ class SecretV1Alpha1API(API): """ - This API allows you to conveniently store, access and share sensitive data. + This API allows you to manage your Secret Manager services, for storing, accessing and sharing sensitive data such as passwords, API keys and certificates. """ def create_secret( diff --git a/scaleway/scaleway/secret/v1alpha1/marshalling.py b/scaleway/scaleway/secret/v1alpha1/marshalling.py index 6c6efd10..8be5c217 100644 --- a/scaleway/scaleway/secret/v1alpha1/marshalling.py +++ b/scaleway/scaleway/secret/v1alpha1/marshalling.py @@ -58,6 +58,8 @@ def unmarshal_Folder(data: Any) -> Folder: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return Folder(**args) @@ -77,10 +79,14 @@ def unmarshal_EphemeralProperties(data: Any) -> EphemeralProperties: field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("expires_once_accessed", None) if field is not None: args["expires_once_accessed"] = field + else: + args["expires_once_accessed"] = None return EphemeralProperties(**args) @@ -112,18 +118,26 @@ def unmarshal_SecretVersion(data: Any) -> SecretVersion: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("ephemeral_properties", None) if field is not None: args["ephemeral_properties"] = unmarshal_EphemeralProperties(field) + else: + args["ephemeral_properties"] = None return SecretVersion(**args) @@ -143,10 +157,14 @@ def unmarshal_EphemeralPolicy(data: Any) -> EphemeralPolicy: field = data.get("time_to_live", None) if field is not None: args["time_to_live"] = field + else: + args["time_to_live"] = None field = data.get("expires_once_accessed", None) if field is not None: args["expires_once_accessed"] = field + else: + args["expires_once_accessed"] = None return EphemeralPolicy(**args) @@ -178,10 +196,14 @@ def unmarshal_Secret(data: Any) -> Secret: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("tags", None) if field is not None: @@ -199,7 +221,7 @@ def unmarshal_Secret(data: Any) -> Secret: if field is not None: args["is_protected"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -214,10 +236,14 @@ def unmarshal_Secret(data: Any) -> Secret: field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("ephemeral_policy", None) if field is not None: args["ephemeral_policy"] = unmarshal_EphemeralPolicy(field) + else: + args["ephemeral_policy"] = None return Secret(**args) @@ -245,6 +271,8 @@ def unmarshal_AccessSecretVersionResponse(data: Any) -> AccessSecretVersionRespo field = data.get("data_crc32", None) if field is not None: args["data_crc32"] = field + else: + args["data_crc32"] = None return AccessSecretVersionResponse(**args) @@ -410,8 +438,8 @@ def marshal_CreateSecretRequest( output["path"] = request.path if request.ephemeral_policy is not None: - output["ephemeral_policy"] = ( - marshal_EphemeralPolicy(request.ephemeral_policy, defaults), + output["ephemeral_policy"] = marshal_EphemeralPolicy( + request.ephemeral_policy, defaults ) return output @@ -457,8 +485,8 @@ def marshal_CreateSecretVersionRequest( output["disable_previous"] = request.disable_previous if request.password_generation is not None: - output["password_generation"] = ( - marshal_PasswordGenerationParams(request.password_generation, defaults), + output["password_generation"] = marshal_PasswordGenerationParams( + request.password_generation, defaults ) if request.data_crc32 is not None: @@ -516,8 +544,8 @@ def marshal_UpdateSecretRequest( output["path"] = request.path if request.ephemeral_policy is not None: - output["ephemeral_policy"] = ( - marshal_EphemeralPolicy(request.ephemeral_policy, defaults), + output["ephemeral_policy"] = marshal_EphemeralPolicy( + request.ephemeral_policy, defaults ) return output @@ -533,7 +561,7 @@ def marshal_EphemeralProperties( output["action"] = str(request.action) if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() if request.expires_once_accessed is not None: output["expires_once_accessed"] = request.expires_once_accessed @@ -551,8 +579,8 @@ def marshal_UpdateSecretVersionRequest( output["description"] = request.description if request.ephemeral_properties is not None: - output["ephemeral_properties"] = ( - marshal_EphemeralProperties(request.ephemeral_properties, defaults), + output["ephemeral_properties"] = marshal_EphemeralProperties( + request.ephemeral_properties, defaults ) return output diff --git a/scaleway/scaleway/secret/v1beta1/__init__.py b/scaleway/scaleway/secret/v1beta1/__init__.py index b00f3efc..531ccc83 100644 --- a/scaleway/scaleway/secret/v1beta1/__init__.py +++ b/scaleway/scaleway/secret/v1beta1/__init__.py @@ -14,19 +14,24 @@ from .types import BrowseSecretsResponseItem from .types import SecretVersion from .types import Secret +from .types import AccessSecretVersionByPathRequest from .types import AccessSecretVersionRequest from .types import AccessSecretVersionResponse from .types import AddSecretOwnerRequest +from .types import BasicCredentials from .types import BrowseSecretsRequest from .types import BrowseSecretsResponse from .types import CreateSecretRequest from .types import CreateSecretVersionRequest +from .types import DatabaseCredentials from .types import DeleteSecretRequest from .types import DeleteSecretVersionRequest from .types import DisableSecretVersionRequest from .types import EnableSecretVersionRequest from .types import GetSecretRequest from .types import GetSecretVersionRequest +from .types import ListSecretTypesRequest +from .types import ListSecretTypesResponse from .types import ListSecretVersionsRequest from .types import ListSecretVersionsResponse from .types import ListSecretsRequest @@ -34,6 +39,9 @@ from .types import ListTagsRequest from .types import ListTagsResponse from .types import ProtectSecretRequest +from .types import RestoreSecretRequest +from .types import RestoreSecretVersionRequest +from .types import SSHKey from .types import UnprotectSecretRequest from .types import UpdateSecretRequest from .types import UpdateSecretVersionRequest @@ -54,19 +62,24 @@ "BrowseSecretsResponseItem", "SecretVersion", "Secret", + "AccessSecretVersionByPathRequest", "AccessSecretVersionRequest", "AccessSecretVersionResponse", "AddSecretOwnerRequest", + "BasicCredentials", "BrowseSecretsRequest", "BrowseSecretsResponse", "CreateSecretRequest", "CreateSecretVersionRequest", + "DatabaseCredentials", "DeleteSecretRequest", "DeleteSecretVersionRequest", "DisableSecretVersionRequest", "EnableSecretVersionRequest", "GetSecretRequest", "GetSecretVersionRequest", + "ListSecretTypesRequest", + "ListSecretTypesResponse", "ListSecretVersionsRequest", "ListSecretVersionsResponse", "ListSecretsRequest", @@ -74,6 +87,9 @@ "ListTagsRequest", "ListTagsResponse", "ProtectSecretRequest", + "RestoreSecretRequest", + "RestoreSecretVersionRequest", + "SSHKey", "UnprotectSecretRequest", "UpdateSecretRequest", "UpdateSecretVersionRequest", diff --git a/scaleway/scaleway/secret/v1beta1/api.py b/scaleway/scaleway/secret/v1beta1/api.py index 172561c0..d3ebd241 100644 --- a/scaleway/scaleway/secret/v1beta1/api.py +++ b/scaleway/scaleway/secret/v1beta1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( validate_path_param, @@ -24,6 +24,7 @@ CreateSecretVersionRequest, EphemeralPolicy, EphemeralProperties, + ListSecretTypesResponse, ListSecretVersionsResponse, ListSecretsResponse, ListTagsResponse, @@ -37,6 +38,7 @@ unmarshal_Secret, unmarshal_AccessSecretVersionResponse, unmarshal_BrowseSecretsResponse, + unmarshal_ListSecretTypesResponse, unmarshal_ListSecretVersionsResponse, unmarshal_ListSecretsResponse, unmarshal_ListTagsResponse, @@ -50,7 +52,7 @@ class SecretV1Beta1API(API): """ - This API allows you to conveniently store, access and share sensitive data such as passwords, API keys and certificates. + This API allows you to manage your Secret Manager services, for storing, accessing and sharing sensitive data such as passwords, API keys and certificates. """ def create_secret( @@ -58,26 +60,28 @@ def create_secret( *, name: str, protected: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, description: Optional[str] = None, type_: Optional[SecretType] = None, path: Optional[str] = None, ephemeral_policy: Optional[EphemeralPolicy] = None, + key_id: Optional[str] = None, ) -> Secret: """ Create a secret. - You must specify the `region` to create a secret. + Create a secret in a given region specified by the `region` parameter. :param name: Name of the secret. :param protected: A protected secret cannot be deleted. :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the Project containing the secret. :param tags: List of the secret's tags. :param description: Description of the secret. - :param type_: (Optional.) See `Secret.Type` enum for description of values. If not specified, the type is `Opaque`. + :param type_: (Optional.) See the `Secret.Type` enum for a description of values. If not specified, the type is `Opaque`. :param path: (Optional.) Location of the secret in the directory structure. If not specified, the path is `/`. :param ephemeral_policy: (Optional.) Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions. + :param key_id: (Optional.) The Scaleway Key Manager key ID will be used to encrypt and decrypt secret versions. If not specified, Secret Manager will use a Key Manager internal key. :return: :class:`Secret ` Usage: @@ -107,6 +111,7 @@ def create_secret( type_=type_, path=path, ephemeral_policy=ephemeral_policy, + key_id=key_id, ), self.client, ), @@ -119,7 +124,7 @@ def get_secret( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Secret: """ Get metadata using the secret's ID. @@ -153,7 +158,7 @@ def update_secret( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, description: Optional[str] = None, @@ -209,7 +214,7 @@ def delete_secret( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a secret. @@ -240,7 +245,8 @@ def delete_secret( def list_secrets( self, *, - region: Optional[Region] = None, + scheduled_for_deletion: bool, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, order_by: Optional[ListSecretsRequestOrderBy] = None, @@ -255,6 +261,7 @@ def list_secrets( """ List secrets. Retrieve the list of secrets created within an Organization and/or Project. You must specify either the `organization_id` or the `project_id` and the `region`. + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by Organization ID (optional). :param project_id: Filter by Project ID (optional). @@ -271,7 +278,9 @@ def list_secrets( Usage: :: - result = api.list_secrets() + result = api.list_secrets( + scheduled_for_deletion=False, + ) """ param_region = validate_path_param( @@ -291,6 +300,7 @@ def list_secrets( "page_size": page_size or self.client.default_page_size, "path": path, "project_id": project_id or self.client.default_project_id, + "scheduled_for_deletion": scheduled_for_deletion, "tags": tags, "type": type_, }, @@ -302,7 +312,8 @@ def list_secrets( def list_secrets_all( self, *, - region: Optional[Region] = None, + scheduled_for_deletion: bool, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, order_by: Optional[ListSecretsRequestOrderBy] = None, @@ -317,6 +328,7 @@ def list_secrets_all( """ List secrets. Retrieve the list of secrets created within an Organization and/or Project. You must specify either the `organization_id` or the `project_id` and the `region`. + :param scheduled_for_deletion: Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by Organization ID (optional). :param project_id: Filter by Project ID (optional). @@ -333,7 +345,9 @@ def list_secrets_all( Usage: :: - result = api.list_secrets_all() + result = api.list_secrets_all( + scheduled_for_deletion=False, + ) """ return fetch_all_pages( @@ -341,6 +355,7 @@ def list_secrets_all( key="secrets", fetcher=self.list_secrets, args={ + "scheduled_for_deletion": scheduled_for_deletion, "region": region, "organization_id": organization_id, "project_id": project_id, @@ -359,12 +374,13 @@ def browse_secrets( self, *, prefix: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, order_by: Optional[BrowseSecretsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, tags: Optional[List[str]] = None, + type_: Optional[SecretType] = None, ) -> BrowseSecretsResponse: """ Browse secrets. @@ -376,6 +392,7 @@ def browse_secrets( :param page: :param page_size: :param tags: Filter secrets by tags. + :param type_: Filter by secret type (optional). :return: :class:`BrowseSecretsResponse ` Usage: @@ -400,6 +417,7 @@ def browse_secrets( "prefix": prefix, "project_id": project_id or self.client.default_project_id, "tags": tags, + "type": type_, }, ) @@ -410,7 +428,7 @@ def protect_secret( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Secret: """ Enable secret protection. @@ -445,7 +463,7 @@ def unprotect_secret( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Secret: """ Disable secret protection. @@ -480,7 +498,7 @@ def add_secret_owner( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, product: Optional[Product] = None, ) -> None: """ @@ -522,7 +540,7 @@ def create_secret_version( *, secret_id: str, data: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, disable_previous: Optional[bool] = None, data_crc32: Optional[int] = None, @@ -576,7 +594,7 @@ def get_secret_version( *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SecretVersion: """ Get metadata of a secret's version using the secret's ID. @@ -617,7 +635,7 @@ def update_secret_version( *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, description: Optional[str] = None, ephemeral_properties: Optional[EphemeralProperties] = None, ) -> SecretVersion: @@ -672,7 +690,7 @@ def delete_secret_version( *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a version. @@ -710,7 +728,7 @@ def list_secret_versions( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, status: Optional[List[SecretVersionStatus]] = None, @@ -755,7 +773,7 @@ def list_secret_versions_all( self, *, secret_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, status: Optional[List[SecretVersionStatus]] = None, @@ -796,7 +814,7 @@ def access_secret_version( *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> AccessSecretVersionResponse: """ Access a secret's version using the secret's ID. @@ -832,12 +850,62 @@ def access_secret_version( self._throw_on_error(res) return unmarshal_AccessSecretVersionResponse(res.json()) + def access_secret_version_by_path( + self, + *, + secret_path: str, + secret_name: str, + revision: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> AccessSecretVersionResponse: + """ + Access a secret's version using the secret's name and path. + Access sensitive data in a secret's version specified by the `region`, `secret_name`, `secret_path` and `revision` parameters. + :param secret_path: Secret's path. + :param secret_name: Secret's name. + :param revision: The first version of the secret is numbered 1, and all subsequent revisions augment by 1. Value can be either: + - an integer (the revision number) + - "latest" (the latest revision) + - "latest_enabled" (the latest enabled revision). + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to target. + :return: :class:`AccessSecretVersionResponse ` + + Usage: + :: + + result = api.access_secret_version_by_path( + secret_path="example", + secret_name="example", + revision="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_revision = validate_path_param("revision", revision) + + res = self._request( + "GET", + f"/secret-manager/v1beta1/regions/{param_region}/secrets-by-path/versions/{param_revision}/access", + params={ + "project_id": project_id or self.client.default_project_id, + "secret_name": secret_name, + "secret_path": secret_path, + }, + ) + + self._throw_on_error(res) + return unmarshal_AccessSecretVersionResponse(res.json()) + def enable_secret_version( self, *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SecretVersion: """ Enable a version. @@ -879,7 +947,7 @@ def disable_secret_version( *, secret_id: str, revision: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> SecretVersion: """ Disable a version. @@ -919,7 +987,7 @@ def disable_secret_version( def list_tags( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -959,7 +1027,7 @@ def list_tags( def list_tags_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -990,3 +1058,152 @@ def list_tags_all( "page_size": page_size, }, ) + + def list_secret_types( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListSecretTypesResponse: + """ + List secret types. + List all secret types created within a given Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to target. + :param page: + :param page_size: + :return: :class:`ListSecretTypesResponse ` + + Usage: + :: + + result = api.list_secret_types() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/secret-manager/v1beta1/regions/{param_region}/secret-types", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListSecretTypesResponse(res.json()) + + def list_secret_types_all( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[SecretType]: + """ + List secret types. + List all secret types created within a given Project. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project to target. + :param page: + :param page_size: + :return: :class:`List[SecretType] ` + + Usage: + :: + + result = api.list_secret_types_all() + """ + + return fetch_all_pages( + type=ListSecretTypesResponse, + key="types", + fetcher=self.list_secret_types, + args={ + "region": region, + "project_id": project_id, + "page": page, + "page_size": page_size, + }, + ) + + def restore_secret_version( + self, + *, + secret_id: str, + revision: str, + region: Optional[ScwRegion] = None, + ) -> SecretVersion: + """ + Restore a version. + Restore a secret's version specified by the `region`, `secret_id` and `revision` parameters. + :param secret_id: + :param revision: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`SecretVersion ` + + Usage: + :: + + result = api.restore_secret_version( + secret_id="example", + revision="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_secret_id = validate_path_param("secret_id", secret_id) + param_revision = validate_path_param("revision", revision) + + res = self._request( + "POST", + f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/versions/{param_revision}/restore", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_SecretVersion(res.json()) + + def restore_secret( + self, + *, + secret_id: str, + region: Optional[ScwRegion] = None, + ) -> Secret: + """ + Restore a secret. + Restore a secret and all its versions scheduled for deletion specified by the `region` and `secret_id` parameters. + :param secret_id: + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Secret ` + + Usage: + :: + + result = api.restore_secret( + secret_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_secret_id = validate_path_param("secret_id", secret_id) + + res = self._request( + "POST", + f"/secret-manager/v1beta1/regions/{param_region}/secrets/{param_secret_id}/restore", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Secret(res.json()) diff --git a/scaleway/scaleway/secret/v1beta1/marshalling.py b/scaleway/scaleway/secret/v1beta1/marshalling.py index c38b8cbe..3bf186c9 100644 --- a/scaleway/scaleway/secret/v1beta1/marshalling.py +++ b/scaleway/scaleway/secret/v1beta1/marshalling.py @@ -6,6 +6,8 @@ from scaleway_core.profile import ProfileDefaults from .types import ( + Product, + SecretType, EphemeralProperties, SecretVersion, EphemeralPolicy, @@ -15,6 +17,7 @@ BrowseSecretsResponseItemSecretDetails, BrowseSecretsResponseItem, BrowseSecretsResponse, + ListSecretTypesResponse, ListSecretVersionsResponse, ListSecretsResponse, ListTagsResponse, @@ -41,10 +44,14 @@ def unmarshal_EphemeralProperties(data: Any) -> EphemeralProperties: field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("expires_once_accessed", None) if field is not None: args["expires_once_accessed"] = field + else: + args["expires_once_accessed"] = None return EphemeralProperties(**args) @@ -76,18 +83,40 @@ def unmarshal_SecretVersion(data: Any) -> SecretVersion: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("deleted_at", None) + if field is not None: + args["deleted_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["deleted_at"] = None field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("ephemeral_properties", None) if field is not None: args["ephemeral_properties"] = unmarshal_EphemeralProperties(field) + else: + args["ephemeral_properties"] = None + + field = data.get("deletion_requested_at", None) + if field is not None: + args["deletion_requested_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["deletion_requested_at"] = None return SecretVersion(**args) @@ -107,10 +136,14 @@ def unmarshal_EphemeralPolicy(data: Any) -> EphemeralPolicy: field = data.get("time_to_live", None) if field is not None: args["time_to_live"] = field + else: + args["time_to_live"] = None field = data.get("expires_once_accessed", None) if field is not None: args["expires_once_accessed"] = field + else: + args["expires_once_accessed"] = None return EphemeralPolicy(**args) @@ -139,14 +172,6 @@ def unmarshal_Secret(data: Any) -> Secret: if field is not None: args["status"] = field - field = data.get("created_at", None) - if field is not None: - args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field - - field = data.get("updated_at", None) - if field is not None: - args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field - field = data.get("tags", None) if field is not None: args["tags"] = field @@ -163,7 +188,7 @@ def unmarshal_Secret(data: Any) -> Secret: if field is not None: args["protected"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -171,17 +196,51 @@ def unmarshal_Secret(data: Any) -> Secret: if field is not None: args["path"] = field + field = data.get("used_by", None) + if field is not None: + args["used_by"] = [Product(v) for v in field] if field is not None else None + field = data.get("region", None) if field is not None: args["region"] = field + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + field = data.get("description", None) if field is not None: args["description"] = field + else: + args["description"] = None field = data.get("ephemeral_policy", None) if field is not None: args["ephemeral_policy"] = unmarshal_EphemeralPolicy(field) + else: + args["ephemeral_policy"] = None + + field = data.get("deletion_requested_at", None) + if field is not None: + args["deletion_requested_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["deletion_requested_at"] = None + + field = data.get("key_id", None) + if field is not None: + args["key_id"] = field + else: + args["key_id"] = None return Secret(**args) @@ -206,9 +265,15 @@ def unmarshal_AccessSecretVersionResponse(data: Any) -> AccessSecretVersionRespo if field is not None: args["data"] = field + field = data.get("type", None) + if field is not None: + args["type_"] = field + field = data.get("data_crc32", None) if field is not None: args["data_crc32"] = field + else: + args["data_crc32"] = None return AccessSecretVersionResponse(**args) @@ -252,9 +317,15 @@ def unmarshal_BrowseSecretsResponseItemSecretDetails( if field is not None: args["protected"] = field + field = data.get("type", None) + if field is not None: + args["type_"] = field + field = data.get("ephemeral_policy", None) if field is not None: args["ephemeral_policy"] = unmarshal_EphemeralPolicy(field) + else: + args["ephemeral_policy"] = None return BrowseSecretsResponseItemSecretDetails(**args) @@ -274,18 +345,26 @@ def unmarshal_BrowseSecretsResponseItem(data: Any) -> BrowseSecretsResponseItem: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("secret", None) if field is not None: args["secret"] = unmarshal_BrowseSecretsResponseItemSecretDetails(field) + else: + args["secret"] = None field = data.get("folder", None) if field is not None: args["folder"] = unmarshal_BrowseSecretsResponseItemFolderDetails(field) + else: + args["folder"] = None return BrowseSecretsResponseItem(**args) @@ -317,6 +396,25 @@ def unmarshal_BrowseSecretsResponse(data: Any) -> BrowseSecretsResponse: return BrowseSecretsResponse(**args) +def unmarshal_ListSecretTypesResponse(data: Any) -> ListSecretTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSecretTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("types", None) + if field is not None: + args["types"] = [SecretType(v) for v in field] if field is not None else None + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListSecretTypesResponse(**args) + + def unmarshal_ListSecretVersionsResponse(data: Any) -> ListSecretVersionsResponse: if not isinstance(data, dict): raise TypeError( @@ -436,10 +534,13 @@ def marshal_CreateSecretRequest( output["path"] = request.path if request.ephemeral_policy is not None: - output["ephemeral_policy"] = ( - marshal_EphemeralPolicy(request.ephemeral_policy, defaults), + output["ephemeral_policy"] = marshal_EphemeralPolicy( + request.ephemeral_policy, defaults ) + if request.key_id is not None: + output["key_id"] = request.key_id + return output @@ -483,8 +584,8 @@ def marshal_UpdateSecretRequest( output["path"] = request.path if request.ephemeral_policy is not None: - output["ephemeral_policy"] = ( - marshal_EphemeralPolicy(request.ephemeral_policy, defaults), + output["ephemeral_policy"] = marshal_EphemeralPolicy( + request.ephemeral_policy, defaults ) return output @@ -500,7 +601,7 @@ def marshal_EphemeralProperties( output["action"] = str(request.action) if request.expires_at is not None: - output["expires_at"] = request.expires_at + output["expires_at"] = request.expires_at.isoformat() if request.expires_once_accessed is not None: output["expires_once_accessed"] = request.expires_once_accessed @@ -518,8 +619,8 @@ def marshal_UpdateSecretVersionRequest( output["description"] = request.description if request.ephemeral_properties is not None: - output["ephemeral_properties"] = ( - marshal_EphemeralProperties(request.ephemeral_properties, defaults), + output["ephemeral_properties"] = marshal_EphemeralProperties( + request.ephemeral_properties, defaults ) return output diff --git a/scaleway/scaleway/secret/v1beta1/types.py b/scaleway/scaleway/secret/v1beta1/types.py index a03d231f..aa5423e8 100644 --- a/scaleway/scaleway/secret/v1beta1/types.py +++ b/scaleway/scaleway/secret/v1beta1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -83,6 +83,7 @@ class SecretVersionStatus(str, Enum, metaclass=StrEnumMeta): ENABLED = "enabled" DISABLED = "disabled" DELETED = "deleted" + SCHEDULED_FOR_DELETION = "scheduled_for_deletion" def __str__(self) -> str: return str(self.value) @@ -121,6 +122,8 @@ class BrowseSecretsResponseItemSecretDetails: protected: bool + type_: SecretType + ephemeral_policy: Optional[EphemeralPolicy] @@ -169,9 +172,10 @@ class SecretVersion: status: SecretVersionStatus """ - * `unknown`: the version is in an invalid state. + * `unknown_status`: the version is in an invalid state. * `enabled`: the version is accessible. * `disabled`: the version is not accessible but can be enabled. +* `scheduled_for_deletion`: the version is scheduled for deletion. It will be deleted in 7 days. * `deleted`: the version is permanently deleted. It is not possible to recover it. """ @@ -190,6 +194,11 @@ class SecretVersion: Last update of the version. """ + deleted_at: Optional[datetime] + """ + Date and time of the version's deletion. + """ + description: Optional[str] """ Description of the version. @@ -200,6 +209,11 @@ class SecretVersion: Returns the version's expiration date, whether it expires after being accessed once, and the action to perform (disable or delete) once the version expires. """ + deletion_requested_at: Optional[datetime] + """ + Returns the time at which deletion was requested. + """ + @dataclass class Secret: @@ -224,16 +238,6 @@ class Secret: * `locked`: no action can be performed on the secret. This status can only be applied and removed by Scaleway. """ - created_at: Optional[datetime] - """ - Date and time of the secret's creation. - """ - - updated_at: Optional[datetime] - """ - Last update of the secret. - """ - tags: List[str] """ List of the secret's tags. @@ -256,7 +260,7 @@ class Secret: type_: SecretType """ - See `Secret.Type` enum for description of values. + See the `Secret.Type` enum for a description of values. """ path: str @@ -264,11 +268,26 @@ class Secret: Location of the secret in the directory structure. """ - region: Region + used_by: List[Product] + """ + List of Scaleway resources that can access and manage the secret. + """ + + region: ScwRegion """ Region of the secret. """ + created_at: Optional[datetime] + """ + Date and time of the secret's creation. + """ + + updated_at: Optional[datetime] + """ + Last update of the secret. + """ + description: Optional[str] """ Updated description of the secret. @@ -279,6 +298,47 @@ class Secret: (Optional.) Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions. """ + deletion_requested_at: Optional[datetime] + """ + Returns the time at which deletion was requested. + """ + + key_id: Optional[str] + """ + (Optional.) The Scaleway Key Manager key ID used to encrypt and decrypt secret versions. + """ + + +@dataclass +class AccessSecretVersionByPathRequest: + secret_path: str + """ + Secret's path. + """ + + secret_name: str + """ + Secret's name. + """ + + revision: str + """ + The first version of the secret is numbered 1, and all subsequent revisions augment by 1. Value can be either: +- an integer (the revision number) +- "latest" (the latest revision) +- "latest_enabled" (the latest enabled revision). + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + @dataclass class AccessSecretVersionRequest: @@ -295,7 +355,7 @@ class AccessSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -318,6 +378,11 @@ class AccessSecretVersionResponse: The base64-encoded secret payload of the version. """ + type_: SecretType + """ + See the `Secret.Type` enum for a description of values. + """ + data_crc32: Optional[int] """ This field is only available if a CRC32 was supplied during the creation of the version. @@ -331,7 +396,7 @@ class AddSecretOwnerRequest: ID of the secret. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -342,6 +407,19 @@ class AddSecretOwnerRequest: """ +@dataclass +class BasicCredentials: + username: str + """ + The username or identifier associated with the credentials. + """ + + password: str + """ + The password associated with the credentials. + """ + + @dataclass class BrowseSecretsRequest: prefix: str @@ -349,7 +427,7 @@ class BrowseSecretsRequest: Filter secrets and folders for a given prefix (default /). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -370,6 +448,11 @@ class BrowseSecretsRequest: Filter secrets by tags. """ + type_: Optional[SecretType] + """ + Filter by secret type (optional). + """ + @dataclass class BrowseSecretsResponse: @@ -401,7 +484,7 @@ class CreateSecretRequest: A protected secret cannot be deleted. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -423,7 +506,7 @@ class CreateSecretRequest: type_: Optional[SecretType] """ - (Optional.) See `Secret.Type` enum for description of values. If not specified, the type is `Opaque`. + (Optional.) See the `Secret.Type` enum for a description of values. If not specified, the type is `Opaque`. """ path: Optional[str] @@ -436,6 +519,11 @@ class CreateSecretRequest: (Optional.) Policy that defines whether/when a secret's versions expire. By default, the policy is applied to all the secret's versions. """ + key_id: Optional[str] + """ + (Optional.) The Scaleway Key Manager key ID will be used to encrypt and decrypt secret versions. If not specified, Secret Manager will use a Key Manager internal key. + """ + @dataclass class CreateSecretVersionRequest: @@ -449,7 +537,7 @@ class CreateSecretVersionRequest: The base64-encoded secret payload of the version. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -470,6 +558,39 @@ class CreateSecretVersionRequest: """ +@dataclass +class DatabaseCredentials: + engine: str + """ + Supported database engines are: 'postgres', 'mysql', 'other'. + """ + + username: str + """ + The username used to authenticate to the database server. + """ + + password: str + """ + The password used to authenticate to the database server. + """ + + host: str + """ + The hostname or resolvable DNS name of the database server. + """ + + dbname: str + """ + The name of the database to connect to. + """ + + port: str + """ + The port must be an integer ranging from 0 to 65535. + """ + + @dataclass class DeleteSecretRequest: secret_id: str @@ -477,7 +598,7 @@ class DeleteSecretRequest: ID of the secret. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -498,7 +619,7 @@ class DeleteSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -519,7 +640,7 @@ class DisableSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -540,7 +661,7 @@ class EnableSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -553,7 +674,7 @@ class GetSecretRequest: ID of the secret. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -574,12 +695,42 @@ class GetSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class ListSecretTypesRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project to target. + """ + + page: Optional[int] + + page_size: Optional[int] + + +@dataclass +class ListSecretTypesResponse: + types: List[SecretType] + """ + List of secret types. + """ + + total_count: int + """ + Count of all secret types matching the requested criteria. + """ + + @dataclass class ListSecretVersionsRequest: secret_id: str @@ -587,7 +738,7 @@ class ListSecretVersionsRequest: ID of the secret. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -617,7 +768,12 @@ class ListSecretVersionsResponse: @dataclass class ListSecretsRequest: - region: Optional[Region] + scheduled_for_deletion: bool + """ + Filter by whether the secret was scheduled for deletion / not scheduled for deletion. By default, it will display only not scheduled for deletion secrets. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -679,7 +835,7 @@ class ListSecretsResponse: @dataclass class ListTagsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -714,12 +870,42 @@ class ProtectSecretRequest: ID of the secret to enable secret protection for. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class RestoreSecretRequest: + secret_id: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class RestoreSecretVersionRequest: + secret_id: str + + revision: str + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class SSHKey: + ssh_private_key: str + """ + The private SSH key. + """ + + @dataclass class UnprotectSecretRequest: secret_id: str @@ -727,7 +913,7 @@ class UnprotectSecretRequest: ID of the secret to disable secret protection for. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -740,7 +926,7 @@ class UpdateSecretRequest: ID of the secret. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -786,7 +972,7 @@ class UpdateSecretVersionRequest: - "latest_enabled" (the latest enabled revision). """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/scaleway/serverless_sqldb/v1alpha1/api.py b/scaleway/scaleway/serverless_sqldb/v1alpha1/api.py index 1d2dfdbe..3896528f 100644 --- a/scaleway/scaleway/serverless_sqldb/v1alpha1/api.py +++ b/scaleway/scaleway/serverless_sqldb/v1alpha1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( WaitForOptions, @@ -40,7 +40,7 @@ class ServerlessSqldbV1Alpha1API(API): """ - This API allows you to manage your Serverless SQL DB databases. + This API allows you to manage your Serverless SQL Databases. """ def create_database( @@ -49,7 +49,7 @@ def create_database( name: str, cpu_min: int, cpu_max: int, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, from_backup_id: Optional[str] = None, ) -> Database: @@ -101,7 +101,7 @@ def get_database( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Database: """ Get a database information. @@ -135,7 +135,7 @@ def wait_for_database( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Database, bool]] = None, ) -> Database: """ @@ -172,7 +172,7 @@ def delete_database( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Database: """ Delete a database. @@ -205,7 +205,7 @@ def delete_database( def list_databases( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, page: Optional[int] = None, @@ -255,7 +255,7 @@ def list_databases( def list_databases_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, page: Optional[int] = None, @@ -300,7 +300,7 @@ def update_database( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, cpu_min: Optional[int] = None, cpu_max: Optional[int] = None, ) -> Database: @@ -348,7 +348,7 @@ def restore_database_from_backup( *, database_id: str, backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Database: """ Restore a database from a backup. @@ -392,7 +392,7 @@ def get_database_backup( self, *, backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DatabaseBackup: """ Get a database backup information. @@ -426,7 +426,7 @@ def list_database_backups( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, page: Optional[int] = None, @@ -435,7 +435,7 @@ def list_database_backups( ) -> ListDatabaseBackupsResponse: """ List your Serverless SQL Database backups. - List all Serverless SQL Database backups for a given Scaleway Project or Database. By default, the backups returned in the list are ordered by creation date in ascending order, though this can be modified via the order_by field. + List all Serverless SQL Database backups for a given Scaleway Project or Database. By default, the backups returned in the list are ordered by creation date in descending order, though this can be modified via the order_by field. :param database_id: Filter by the UUID of the Serverless SQL Database. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by the UUID of the Scaleway organization. @@ -478,7 +478,7 @@ def list_database_backups_all( self, *, database_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, organization_id: Optional[str] = None, project_id: Optional[str] = None, page: Optional[int] = None, @@ -487,7 +487,7 @@ def list_database_backups_all( ) -> List[DatabaseBackup]: """ List your Serverless SQL Database backups. - List all Serverless SQL Database backups for a given Scaleway Project or Database. By default, the backups returned in the list are ordered by creation date in ascending order, though this can be modified via the order_by field. + List all Serverless SQL Database backups for a given Scaleway Project or Database. By default, the backups returned in the list are ordered by creation date in descending order, though this can be modified via the order_by field. :param database_id: Filter by the UUID of the Serverless SQL Database. :param region: Region to target. If none is passed will use default region from the config. :param organization_id: Filter by the UUID of the Scaleway organization. @@ -524,7 +524,7 @@ def export_database_backup( self, *, backup_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DatabaseBackup: """ Export a database backup. diff --git a/scaleway/scaleway/serverless_sqldb/v1alpha1/marshalling.py b/scaleway/scaleway/serverless_sqldb/v1alpha1/marshalling.py index 88f441a6..13a841b1 100644 --- a/scaleway/scaleway/serverless_sqldb/v1alpha1/marshalling.py +++ b/scaleway/scaleway/serverless_sqldb/v1alpha1/marshalling.py @@ -51,24 +51,40 @@ def unmarshal_DatabaseBackup(data: Any) -> DatabaseBackup: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("expires_at", None) if field is not None: args["expires_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["expires_at"] = None field = data.get("size", None) if field is not None: args["size"] = field + else: + args["size"] = None + + field = data.get("db_size", None) + if field is not None: + args["db_size"] = field + else: + args["db_size"] = None field = data.get("download_url", None) if field is not None: args["download_url"] = field + else: + args["download_url"] = None field = data.get("download_url_expires_at", None) if field is not None: args["download_url_expires_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["download_url_expires_at"] = None return DatabaseBackup(**args) @@ -132,6 +148,8 @@ def unmarshal_Database(data: Any) -> Database: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None return Database(**args) diff --git a/scaleway/scaleway/serverless_sqldb/v1alpha1/types.py b/scaleway/scaleway/serverless_sqldb/v1alpha1/types.py index d7b885d7..6ec7e725 100644 --- a/scaleway/scaleway/serverless_sqldb/v1alpha1/types.py +++ b/scaleway/scaleway/serverless_sqldb/v1alpha1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -39,8 +39,8 @@ def __str__(self) -> str: class ListDatabaseBackupsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): - CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" def __str__(self) -> str: return str(self.value) @@ -83,7 +83,7 @@ class DatabaseBackup: UUID of the source Serverless SQL Database the backup is created from. """ - region: Region + region: ScwRegion """ Region of the database backup. """ @@ -100,7 +100,12 @@ class DatabaseBackup: size: Optional[int] """ - Size of the database backup. + Size (in bytes) of the database backup file. + """ + + db_size: Optional[int] + """ + Size (in bytes) of the database when backup has been done. """ download_url: Optional[str] @@ -146,7 +151,7 @@ class Database: Project ID the database belongs to. """ - region: Region + region: ScwRegion """ Region of the database. """ @@ -199,7 +204,7 @@ class CreateDatabaseRequest: The maximum number of CPU units for your Serverless SQL Database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -222,7 +227,7 @@ class DeleteDatabaseRequest: UUID of the Serverless SQL Database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -235,7 +240,7 @@ class ExportDatabaseBackupRequest: UUID of the Serverless SQL Database backup. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -248,7 +253,7 @@ class GetDatabaseBackupRequest: UUID of the Serverless SQL Database backup. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -261,7 +266,7 @@ class GetDatabaseRequest: UUID of the Serverless SQL DB database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -274,7 +279,7 @@ class ListDatabaseBackupsRequest: Filter by the UUID of the Serverless SQL Database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -320,7 +325,7 @@ class ListDatabaseBackupsResponse: @dataclass class ListDatabasesRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -381,7 +386,7 @@ class RestoreDatabaseFromBackupRequest: UUID of the Serverless SQL Database backup to restore. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -394,7 +399,7 @@ class UpdateDatabaseRequest: UUID of the Serverless SQL Database. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/scaleway/tem/v1alpha1/__init__.py b/scaleway/scaleway/tem/v1alpha1/__init__.py index 19db4a37..53ba0d7c 100644 --- a/scaleway/scaleway/tem/v1alpha1/__init__.py +++ b/scaleway/scaleway/tem/v1alpha1/__init__.py @@ -1,5 +1,7 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import BlocklistType +from .types import DomainLastStatusAutoconfigStateReason from .types import DomainLastStatusRecordStatus from .types import DomainReputationStatus from .types import DomainStatus @@ -8,39 +10,84 @@ from .types import EmailRcptType from .types import EmailStatus from .content import EMAIL_TRANSIENT_STATUSES +from .types import ListBlocklistsRequestOrderBy from .types import ListEmailsRequestOrderBy +from .types import ListWebhookEventsRequestOrderBy +from .types import ListWebhooksRequestOrderBy +from .types import OfferName +from .types import PoolStatus +from .types import ProjectSettingsPeriodicReportFrequency +from .types import WebhookEventStatus +from .types import WebhookEventType from .types import DomainRecordsDMARC from .types import EmailTry from .types import DomainRecords from .types import DomainReputation from .types import DomainStatistics +from .types import Blocklist from .types import CreateEmailRequestAddress from .types import CreateEmailRequestAttachment from .types import CreateEmailRequestHeader from .types import Email +from .types import DomainLastStatusAutoconfigState from .types import DomainLastStatusDkimRecord from .types import DomainLastStatusDmarcRecord from .types import DomainLastStatusSpfRecord from .types import Domain +from .types import OfferSubscription +from .types import Offer +from .types import Pool +from .types import WebhookEvent +from .types import Webhook +from .types import ProjectSettingsPeriodicReport +from .types import UpdateProjectSettingsRequestUpdatePeriodicReport +from .types import BulkCreateBlocklistsRequest +from .types import BulkCreateBlocklistsResponse from .types import CancelEmailRequest from .types import CheckDomainRequest from .types import CreateDomainRequest from .types import CreateEmailRequest from .types import CreateEmailResponse +from .types import CreateWebhookRequest +from .types import DeleteBlocklistRequest +from .types import DeleteWebhookRequest from .types import DomainLastStatus from .types import GetDomainLastStatusRequest from .types import GetDomainRequest from .types import GetEmailRequest +from .types import GetProjectConsumptionRequest +from .types import GetProjectSettingsRequest from .types import GetStatisticsRequest +from .types import GetWebhookRequest +from .types import ListBlocklistsRequest +from .types import ListBlocklistsResponse from .types import ListDomainsRequest from .types import ListDomainsResponse from .types import ListEmailsRequest from .types import ListEmailsResponse +from .types import ListOfferSubscriptionsRequest +from .types import ListOfferSubscriptionsResponse +from .types import ListOffersRequest +from .types import ListOffersResponse +from .types import ListPoolsRequest +from .types import ListPoolsResponse +from .types import ListWebhookEventsRequest +from .types import ListWebhookEventsResponse +from .types import ListWebhooksRequest +from .types import ListWebhooksResponse +from .types import ProjectConsumption +from .types import ProjectSettings from .types import RevokeDomainRequest from .types import Statistics +from .types import UpdateDomainRequest +from .types import UpdateOfferSubscriptionRequest +from .types import UpdateProjectSettingsRequest +from .types import UpdateWebhookRequest from .api import TemV1Alpha1API __all__ = [ + "BlocklistType", + "DomainLastStatusAutoconfigStateReason", "DomainLastStatusRecordStatus", "DomainReputationStatus", "DomainStatus", @@ -49,35 +96,78 @@ "EmailRcptType", "EmailStatus", "EMAIL_TRANSIENT_STATUSES", + "ListBlocklistsRequestOrderBy", "ListEmailsRequestOrderBy", + "ListWebhookEventsRequestOrderBy", + "ListWebhooksRequestOrderBy", + "OfferName", + "PoolStatus", + "ProjectSettingsPeriodicReportFrequency", + "WebhookEventStatus", + "WebhookEventType", "DomainRecordsDMARC", "EmailTry", "DomainRecords", "DomainReputation", "DomainStatistics", + "Blocklist", "CreateEmailRequestAddress", "CreateEmailRequestAttachment", "CreateEmailRequestHeader", "Email", + "DomainLastStatusAutoconfigState", "DomainLastStatusDkimRecord", "DomainLastStatusDmarcRecord", "DomainLastStatusSpfRecord", "Domain", + "OfferSubscription", + "Offer", + "Pool", + "WebhookEvent", + "Webhook", + "ProjectSettingsPeriodicReport", + "UpdateProjectSettingsRequestUpdatePeriodicReport", + "BulkCreateBlocklistsRequest", + "BulkCreateBlocklistsResponse", "CancelEmailRequest", "CheckDomainRequest", "CreateDomainRequest", "CreateEmailRequest", "CreateEmailResponse", + "CreateWebhookRequest", + "DeleteBlocklistRequest", + "DeleteWebhookRequest", "DomainLastStatus", "GetDomainLastStatusRequest", "GetDomainRequest", "GetEmailRequest", + "GetProjectConsumptionRequest", + "GetProjectSettingsRequest", "GetStatisticsRequest", + "GetWebhookRequest", + "ListBlocklistsRequest", + "ListBlocklistsResponse", "ListDomainsRequest", "ListDomainsResponse", "ListEmailsRequest", "ListEmailsResponse", + "ListOfferSubscriptionsRequest", + "ListOfferSubscriptionsResponse", + "ListOffersRequest", + "ListOffersResponse", + "ListPoolsRequest", + "ListPoolsResponse", + "ListWebhookEventsRequest", + "ListWebhookEventsResponse", + "ListWebhooksRequest", + "ListWebhooksResponse", + "ProjectConsumption", + "ProjectSettings", "RevokeDomainRequest", "Statistics", + "UpdateDomainRequest", + "UpdateOfferSubscriptionRequest", + "UpdateProjectSettingsRequest", + "UpdateWebhookRequest", "TemV1Alpha1API", ] diff --git a/scaleway/scaleway/tem/v1alpha1/api.py b/scaleway/scaleway/tem/v1alpha1/api.py index 9205df0b..3c6e7d77 100644 --- a/scaleway/scaleway/tem/v1alpha1/api.py +++ b/scaleway/scaleway/tem/v1alpha1/api.py @@ -6,7 +6,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( WaitForOptions, @@ -15,22 +15,50 @@ wait_for_resource, ) from .types import ( + BlocklistType, DomainStatus, EmailFlag, EmailStatus, + ListBlocklistsRequestOrderBy, ListEmailsRequestOrderBy, + ListWebhookEventsRequestOrderBy, + ListWebhooksRequestOrderBy, + OfferName, + WebhookEventStatus, + WebhookEventType, + Blocklist, + BulkCreateBlocklistsRequest, + BulkCreateBlocklistsResponse, CreateDomainRequest, CreateEmailRequest, CreateEmailRequestAddress, CreateEmailRequestAttachment, CreateEmailRequestHeader, CreateEmailResponse, + CreateWebhookRequest, Domain, DomainLastStatus, Email, + ListBlocklistsResponse, ListDomainsResponse, ListEmailsResponse, + ListOfferSubscriptionsResponse, + ListOffersResponse, + ListPoolsResponse, + ListWebhookEventsResponse, + ListWebhooksResponse, + OfferSubscription, + Pool, + ProjectConsumption, + ProjectSettings, Statistics, + UpdateDomainRequest, + UpdateOfferSubscriptionRequest, + UpdateProjectSettingsRequest, + UpdateProjectSettingsRequestUpdatePeriodicReport, + UpdateWebhookRequest, + Webhook, + WebhookEvent, ) from .content import ( DOMAIN_TRANSIENT_STATUSES, @@ -39,27 +67,46 @@ from .marshalling import ( unmarshal_Email, unmarshal_Domain, + unmarshal_OfferSubscription, + unmarshal_Webhook, + unmarshal_BulkCreateBlocklistsResponse, unmarshal_CreateEmailResponse, unmarshal_DomainLastStatus, + unmarshal_ListBlocklistsResponse, unmarshal_ListDomainsResponse, unmarshal_ListEmailsResponse, + unmarshal_ListOfferSubscriptionsResponse, + unmarshal_ListOffersResponse, + unmarshal_ListPoolsResponse, + unmarshal_ListWebhookEventsResponse, + unmarshal_ListWebhooksResponse, + unmarshal_ProjectConsumption, + unmarshal_ProjectSettings, unmarshal_Statistics, + marshal_BulkCreateBlocklistsRequest, marshal_CreateDomainRequest, marshal_CreateEmailRequest, + marshal_CreateWebhookRequest, + marshal_UpdateDomainRequest, + marshal_UpdateOfferSubscriptionRequest, + marshal_UpdateProjectSettingsRequest, + marshal_UpdateWebhookRequest, ) class TemV1Alpha1API(API): - """ """ + """ + This API allows you to manage your Transactional Email services. + """ def create_email( self, *, + from_: CreateEmailRequestAddress, subject: str, text: str, html: str, - region: Optional[Region] = None, - from_: Optional[CreateEmailRequestAddress] = None, + region: Optional[ScwRegion] = None, to: Optional[List[CreateEmailRequestAddress]] = None, cc: Optional[List[CreateEmailRequestAddress]] = None, bcc: Optional[List[CreateEmailRequestAddress]] = None, @@ -71,11 +118,11 @@ def create_email( """ Send an email. You must specify the `region`, the sender and the recipient's information and the `project_id` to send an email from a checked domain. The subject of the email must contain at least 6 characters. + :param from_: Sender information. Must be from a checked domain declared in the Project. :param subject: Subject of the email. :param text: Text content. :param html: HTML content. :param region: Region to target. If none is passed will use default region from the config. - :param from_: Sender information. Must be from a checked domain declared in the Project. :param to: An array of the primary recipient's information. :param cc: An array of the carbon copy recipient's information. :param bcc: An array of the blind carbon copy recipient's information. @@ -89,6 +136,7 @@ def create_email( :: result = api.create_email( + from=CreateEmailRequestAddress(), subject="example", text="example", html="example", @@ -104,11 +152,11 @@ def create_email( f"/transactional-email/v1alpha1/regions/{param_region}/emails", body=marshal_CreateEmailRequest( CreateEmailRequest( + from_=from_, subject=subject, text=text, html=html, region=region, - from_=from_, to=to, cc=cc, bcc=bcc, @@ -128,7 +176,7 @@ def get_email( self, *, email_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Email: """ Get an email. @@ -162,7 +210,7 @@ def wait_for_email( self, *, email_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Email, bool]] = None, ) -> Email: """ @@ -198,7 +246,7 @@ def wait_for_email( def list_emails( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, @@ -227,7 +275,7 @@ def list_emails( :param since: (Optional) List emails created after this date. :param until: (Optional) List emails created before this date. :param mail_from: (Optional) List emails sent with this sender's email address. - :param mail_to: List emails sent to this recipient's email address. + :param mail_to: Deprecated. List emails sent to this recipient's email address. :param mail_rcpt: (Optional) List emails sent to this recipient's email address. :param statuses: (Optional) List emails with any of these statuses. :param subject: (Optional) List emails with this subject. @@ -274,7 +322,7 @@ def list_emails( def list_emails_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, @@ -303,7 +351,7 @@ def list_emails_all( :param since: (Optional) List emails created after this date. :param until: (Optional) List emails created before this date. :param mail_from: (Optional) List emails sent with this sender's email address. - :param mail_to: List emails sent to this recipient's email address. + :param mail_to: Deprecated. List emails sent to this recipient's email address. :param mail_rcpt: (Optional) List emails sent to this recipient's email address. :param statuses: (Optional) List emails with any of these statuses. :param subject: (Optional) List emails with this subject. @@ -345,7 +393,7 @@ def list_emails_all( def get_statistics( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, domain_id: Optional[str] = None, since: Optional[datetime] = None, @@ -392,7 +440,7 @@ def cancel_email( self, *, email_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Email: """ Cancel an email. @@ -427,17 +475,19 @@ def create_domain( self, *, domain_name: str, - accept_tos: bool, - region: Optional[Region] = None, + autoconfig: bool, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, + accept_tos: Optional[bool] = None, ) -> Domain: """ Register a domain in a project. You must specify the `region`, `project_id` and `domain_name` to register a domain in a specific Project. :param domain_name: Fully qualified domain dame. - :param accept_tos: Accept Scaleway's Terms of Service. + :param autoconfig: Activate auto-configuration of the domain's DNS zone. :param region: Region to target. If none is passed will use default region from the config. :param project_id: ID of the project to which the domain belongs. + :param accept_tos: Deprecated. Accept Scaleway's Terms of Service. :return: :class:`Domain ` Usage: @@ -445,7 +495,7 @@ def create_domain( result = api.create_domain( domain_name="example", - accept_tos=False, + autoconfig=False, ) """ @@ -459,9 +509,10 @@ def create_domain( body=marshal_CreateDomainRequest( CreateDomainRequest( domain_name=domain_name, - accept_tos=accept_tos, + autoconfig=autoconfig, region=region, project_id=project_id, + accept_tos=accept_tos, ), self.client, ), @@ -474,7 +525,7 @@ def get_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Get information about a domain. @@ -508,7 +559,7 @@ def wait_for_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Domain, bool]] = None, ) -> Domain: """ @@ -544,7 +595,7 @@ def wait_for_domain( def list_domains( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, @@ -557,11 +608,11 @@ def list_domains( Retrieve domains in a specific Project or in a specific Organization using the `region` parameter. :param region: Region to target. If none is passed will use default region from the config. :param page: Requested page number. Value must be greater or equal to 1. - :param page_size: Page size. - :param project_id: - :param status: - :param organization_id: - :param name: + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: (Optional) ID of the Project in which to list the domains. + :param status: (Optional) List domains under specific statuses. + :param organization_id: (Optional) ID of the Organization in which to list the domains. + :param name: (Optional) Names of the domains to list. :return: :class:`ListDomainsResponse ` Usage: @@ -594,7 +645,7 @@ def list_domains( def list_domains_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, project_id: Optional[str] = None, @@ -607,11 +658,11 @@ def list_domains_all( Retrieve domains in a specific Project or in a specific Organization using the `region` parameter. :param region: Region to target. If none is passed will use default region from the config. :param page: Requested page number. Value must be greater or equal to 1. - :param page_size: Page size. - :param project_id: - :param status: - :param organization_id: - :param name: + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: (Optional) ID of the Project in which to list the domains. + :param status: (Optional) List domains under specific statuses. + :param organization_id: (Optional) ID of the Organization in which to list the domains. + :param name: (Optional) Names of the domains to list. :return: :class:`List[Domain] ` Usage: @@ -639,7 +690,7 @@ def revoke_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Delete a domain. @@ -674,7 +725,7 @@ def check_domain( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Domain: """ Domain DNS check. @@ -709,7 +760,7 @@ def get_domain_last_status( self, *, domain_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DomainLastStatus: """ Display SPF and DKIM records status and potential errors. @@ -738,3 +789,908 @@ def get_domain_last_status( self._throw_on_error(res) return unmarshal_DomainLastStatus(res.json()) + + def update_domain( + self, + *, + domain_id: str, + region: Optional[ScwRegion] = None, + autoconfig: Optional[bool] = None, + ) -> Domain: + """ + Update a domain. + Update a domain auto-configuration. + :param domain_id: ID of the domain to update. + :param region: Region to target. If none is passed will use default region from the config. + :param autoconfig: (Optional) If set to true, activate auto-configuration of the domain's DNS zone. + :return: :class:`Domain ` + + Usage: + :: + + result = api.update_domain( + domain_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain_id = validate_path_param("domain_id", domain_id) + + res = self._request( + "PATCH", + f"/transactional-email/v1alpha1/regions/{param_region}/domains/{param_domain_id}", + body=marshal_UpdateDomainRequest( + UpdateDomainRequest( + domain_id=domain_id, + region=region, + autoconfig=autoconfig, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Domain(res.json()) + + def create_webhook( + self, + *, + domain_id: str, + name: str, + sns_arn: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + event_types: Optional[List[WebhookEventType]] = None, + ) -> Webhook: + """ + Create a Webhook. + Create a new Webhook triggered by a list of event types and pushed to a Scaleway SNS ARN. + :param domain_id: ID of the Domain to watch for triggering events. + :param name: Name of the Webhook. + :param sns_arn: Scaleway SNS ARN topic to push the events to. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project to which the Webhook belongs. + :param event_types: List of event types that will trigger an event. + :return: :class:`Webhook ` + + Usage: + :: + + result = api.create_webhook( + domain_id="example", + name="example", + sns_arn="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks", + body=marshal_CreateWebhookRequest( + CreateWebhookRequest( + domain_id=domain_id, + name=name, + sns_arn=sns_arn, + region=region, + project_id=project_id, + event_types=event_types, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Webhook(res.json()) + + def list_webhooks( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListWebhooksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + domain_id: Optional[str] = None, + ) -> ListWebhooksResponse: + """ + List Webhooks. + Retrieve Webhooks in a specific Project or in a specific Organization using the `region` parameter. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List Webhooks corresponding to specific criteria. + :param page: (Optional) Requested page number. Value must be greater or equal to 1. + :param page_size: (Optional) Requested page size. Value must be between 1 and 100. + :param project_id: (Optional) ID of the Project for which to list the Webhooks. + :param organization_id: (Optional) ID of the Organization for which to list the Webhooks. + :param domain_id: (Optional) ID of the Domain for which to list the Webhooks. + :return: :class:`ListWebhooksResponse ` + + Usage: + :: + + result = api.list_webhooks() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks", + params={ + "domain_id": domain_id, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWebhooksResponse(res.json()) + + def list_webhooks_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListWebhooksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + domain_id: Optional[str] = None, + ) -> List[Webhook]: + """ + List Webhooks. + Retrieve Webhooks in a specific Project or in a specific Organization using the `region` parameter. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List Webhooks corresponding to specific criteria. + :param page: (Optional) Requested page number. Value must be greater or equal to 1. + :param page_size: (Optional) Requested page size. Value must be between 1 and 100. + :param project_id: (Optional) ID of the Project for which to list the Webhooks. + :param organization_id: (Optional) ID of the Organization for which to list the Webhooks. + :param domain_id: (Optional) ID of the Domain for which to list the Webhooks. + :return: :class:`List[Webhook] ` + + Usage: + :: + + result = api.list_webhooks_all() + """ + + return fetch_all_pages( + type=ListWebhooksResponse, + key="webhooks", + fetcher=self.list_webhooks, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "project_id": project_id, + "organization_id": organization_id, + "domain_id": domain_id, + }, + ) + + def get_webhook( + self, + *, + webhook_id: str, + region: Optional[ScwRegion] = None, + ) -> Webhook: + """ + Get information about a Webhook. + Retrieve information about a specific Webhook using the `webhook_id` and `region` parameters. + :param webhook_id: ID of the Webhook to check. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Webhook ` + + Usage: + :: + + result = api.get_webhook( + webhook_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_webhook_id = validate_path_param("webhook_id", webhook_id) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks/{param_webhook_id}", + ) + + self._throw_on_error(res) + return unmarshal_Webhook(res.json()) + + def update_webhook( + self, + *, + webhook_id: str, + region: Optional[ScwRegion] = None, + name: Optional[str] = None, + event_types: Optional[List[WebhookEventType]] = None, + sns_arn: Optional[str] = None, + ) -> Webhook: + """ + Update a Webhook. + Update a Webhook events type, SNS ARN or name. + :param webhook_id: ID of the Webhook to update. + :param region: Region to target. If none is passed will use default region from the config. + :param name: Name of the Webhook to update. + :param event_types: List of event types to update. + :param sns_arn: Scaleway SNS ARN topic to update. + :return: :class:`Webhook ` + + Usage: + :: + + result = api.update_webhook( + webhook_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_webhook_id = validate_path_param("webhook_id", webhook_id) + + res = self._request( + "PATCH", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks/{param_webhook_id}", + body=marshal_UpdateWebhookRequest( + UpdateWebhookRequest( + webhook_id=webhook_id, + region=region, + name=name, + event_types=event_types, + sns_arn=sns_arn, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Webhook(res.json()) + + def delete_webhook( + self, + *, + webhook_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a Webhook. + You must specify the Webhook you want to delete by the `region` and `webhook_id`. Deleting a Webhook is permanent and cannot be undone. + :param webhook_id: ID of the Webhook to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_webhook( + webhook_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_webhook_id = validate_path_param("webhook_id", webhook_id) + + res = self._request( + "DELETE", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks/{param_webhook_id}", + ) + + self._throw_on_error(res) + + def list_webhook_events( + self, + *, + webhook_id: str, + region: Optional[ScwRegion] = None, + order_by: Optional[ListWebhookEventsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + email_id: Optional[str] = None, + event_types: Optional[List[WebhookEventType]] = None, + statuses: Optional[List[WebhookEventStatus]] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + domain_id: Optional[str] = None, + ) -> ListWebhookEventsResponse: + """ + List Webhook triggered events. + Retrieve the list of Webhook events triggered from a specific Webhook or for a specific Project or Organization. You must specify the `region`. + :param webhook_id: ID of the Webhook linked to the events. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List Webhook events corresponding to specific criteria. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 100. + :param email_id: ID of the email linked to the events. + :param event_types: List of event types linked to the events. + :param statuses: List of event statuses. + :param project_id: ID of the webhook Project. + :param organization_id: ID of the webhook Organization. + :param domain_id: ID of the domain to watch for triggering events. + :return: :class:`ListWebhookEventsResponse ` + + Usage: + :: + + result = api.list_webhook_events( + webhook_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_webhook_id = validate_path_param("webhook_id", webhook_id) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/webhooks/{param_webhook_id}/events", + params={ + "domain_id": domain_id, + "email_id": email_id, + "event_types": event_types, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "statuses": statuses, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWebhookEventsResponse(res.json()) + + def list_webhook_events_all( + self, + *, + webhook_id: str, + region: Optional[ScwRegion] = None, + order_by: Optional[ListWebhookEventsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + email_id: Optional[str] = None, + event_types: Optional[List[WebhookEventType]] = None, + statuses: Optional[List[WebhookEventStatus]] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + domain_id: Optional[str] = None, + ) -> List[WebhookEvent]: + """ + List Webhook triggered events. + Retrieve the list of Webhook events triggered from a specific Webhook or for a specific Project or Organization. You must specify the `region`. + :param webhook_id: ID of the Webhook linked to the events. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List Webhook events corresponding to specific criteria. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 100. + :param email_id: ID of the email linked to the events. + :param event_types: List of event types linked to the events. + :param statuses: List of event statuses. + :param project_id: ID of the webhook Project. + :param organization_id: ID of the webhook Organization. + :param domain_id: ID of the domain to watch for triggering events. + :return: :class:`List[WebhookEvent] ` + + Usage: + :: + + result = api.list_webhook_events_all( + webhook_id="example", + ) + """ + + return fetch_all_pages( + type=ListWebhookEventsResponse, + key="webhook_events", + fetcher=self.list_webhook_events, + args={ + "webhook_id": webhook_id, + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "email_id": email_id, + "event_types": event_types, + "statuses": statuses, + "project_id": project_id, + "organization_id": organization_id, + "domain_id": domain_id, + }, + ) + + def get_project_settings( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> ProjectSettings: + """ + List project settings. + Retrieve the project settings including periodic reports. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project. + :return: :class:`ProjectSettings ` + + Usage: + :: + + result = api.get_project_settings() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/project/{param_project_id}/settings", + ) + + self._throw_on_error(res) + return unmarshal_ProjectSettings(res.json()) + + def update_project_settings( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + periodic_report: Optional[ + UpdateProjectSettingsRequestUpdatePeriodicReport + ] = None, + ) -> ProjectSettings: + """ + Update project settings. + Update the project settings including periodic reports. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project. + :param periodic_report: Periodic report update details - all fields are optional. + :return: :class:`ProjectSettings ` + + Usage: + :: + + result = api.update_project_settings() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_project_id = validate_path_param( + "project_id", project_id or self.client.default_project_id + ) + + res = self._request( + "PATCH", + f"/transactional-email/v1alpha1/regions/{param_region}/project/{param_project_id}/settings", + body=marshal_UpdateProjectSettingsRequest( + UpdateProjectSettingsRequest( + region=region, + project_id=project_id, + periodic_report=periodic_report, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ProjectSettings(res.json()) + + def list_blocklists( + self, + *, + domain_id: str, + region: Optional[ScwRegion] = None, + order_by: Optional[ListBlocklistsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + email: Optional[str] = None, + type_: Optional[BlocklistType] = None, + custom: Optional[bool] = None, + ) -> ListBlocklistsResponse: + """ + List blocklists. + Retrieve the list of blocklists. + :param domain_id: (Optional) Filter by a domain ID. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List blocklist corresponding to specific criteria. + :param page: (Optional) Requested page number. Value must be greater or equal to 1. + :param page_size: (Optional) Requested page size. Value must be between 1 and 100. + :param email: (Optional) Filter by an email address. + :param type_: (Optional) Filter by a blocklist type. + :param custom: (Optional) Filter by custom blocklist (true) or automatic Transactional Email blocklist (false). + :return: :class:`ListBlocklistsResponse ` + + Usage: + :: + + result = api.list_blocklists( + domain_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/blocklists", + params={ + "custom": custom, + "domain_id": domain_id, + "email": email, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "type": type_, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListBlocklistsResponse(res.json()) + + def list_blocklists_all( + self, + *, + domain_id: str, + region: Optional[ScwRegion] = None, + order_by: Optional[ListBlocklistsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + email: Optional[str] = None, + type_: Optional[BlocklistType] = None, + custom: Optional[bool] = None, + ) -> List[Blocklist]: + """ + List blocklists. + Retrieve the list of blocklists. + :param domain_id: (Optional) Filter by a domain ID. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: (Optional) List blocklist corresponding to specific criteria. + :param page: (Optional) Requested page number. Value must be greater or equal to 1. + :param page_size: (Optional) Requested page size. Value must be between 1 and 100. + :param email: (Optional) Filter by an email address. + :param type_: (Optional) Filter by a blocklist type. + :param custom: (Optional) Filter by custom blocklist (true) or automatic Transactional Email blocklist (false). + :return: :class:`List[Blocklist] ` + + Usage: + :: + + result = api.list_blocklists_all( + domain_id="example", + ) + """ + + return fetch_all_pages( + type=ListBlocklistsResponse, + key="blocklists", + fetcher=self.list_blocklists, + args={ + "domain_id": domain_id, + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "email": email, + "type_": type_, + "custom": custom, + }, + ) + + def bulk_create_blocklists( + self, + *, + domain_id: str, + region: Optional[ScwRegion] = None, + emails: Optional[List[str]] = None, + type_: Optional[BlocklistType] = None, + reason: Optional[str] = None, + ) -> BulkCreateBlocklistsResponse: + """ + Bulk create blocklists. + Create multiple blocklists in a specific Project or Organization using the `region` parameter. + :param domain_id: Domain ID linked to the blocklist. + :param region: Region to target. If none is passed will use default region from the config. + :param emails: Email blocked by the blocklist. + :param type_: Type of blocklist. + :param reason: Reason to block the email. + :return: :class:`BulkCreateBlocklistsResponse ` + + Usage: + :: + + result = api.bulk_create_blocklists( + domain_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/transactional-email/v1alpha1/regions/{param_region}/blocklists", + body=marshal_BulkCreateBlocklistsRequest( + BulkCreateBlocklistsRequest( + domain_id=domain_id, + region=region, + emails=emails, + type_=type_, + reason=reason, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_BulkCreateBlocklistsResponse(res.json()) + + def delete_blocklist( + self, + *, + blocklist_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a blocklist. + You must specify the blocklist you want to delete by the `region` and `blocklist_id`. + :param blocklist_id: ID of the blocklist to delete. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_blocklist( + blocklist_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_blocklist_id = validate_path_param("blocklist_id", blocklist_id) + + res = self._request( + "DELETE", + f"/transactional-email/v1alpha1/regions/{param_region}/blocklists/{param_blocklist_id}", + ) + + self._throw_on_error(res) + + def list_offer_subscriptions( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> ListOfferSubscriptionsResponse: + """ + Get information about subscribed offers. + Retrieve information about the offers you are subscribed to using the `project_id` and `region` parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :return: :class:`ListOfferSubscriptionsResponse ` + + Usage: + :: + + result = api.list_offer_subscriptions() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/offer-subscriptions", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListOfferSubscriptionsResponse(res.json()) + + def update_offer_subscription( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + name: Optional[OfferName] = None, + ) -> OfferSubscription: + """ + Update a subscribed offer. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Project. + :param name: Name of the offer-subscription. + :return: :class:`OfferSubscription ` + + Usage: + :: + + result = api.update_offer_subscription() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "PATCH", + f"/transactional-email/v1alpha1/regions/{param_region}/offer-subscriptions", + body=marshal_UpdateOfferSubscriptionRequest( + UpdateOfferSubscriptionRequest( + region=region, + project_id=project_id, + name=name, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_OfferSubscription(res.json()) + + def list_offers( + self, + *, + region: Optional[ScwRegion] = None, + ) -> ListOffersResponse: + """ + List the available offers. + Retrieve the list of the available and free-of-charge offers you can subscribe to. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ListOffersResponse ` + + Usage: + :: + + result = api.list_offers() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/offers", + ) + + self._throw_on_error(res) + return unmarshal_ListOffersResponse(res.json()) + + def list_pools( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> ListPoolsResponse: + """ + Get information about a sending pool. + Retrieve information about a sending pool, including its creation status and configuration parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: ID of the Project. + :return: :class:`ListPoolsResponse ` + + Usage: + :: + + result = api.list_pools() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/pools", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPoolsResponse(res.json()) + + def list_pools_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + project_id: Optional[str] = None, + ) -> List[Pool]: + """ + Get information about a sending pool. + Retrieve information about a sending pool, including its creation status and configuration parameters. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Requested page number. Value must be greater or equal to 1. + :param page_size: Requested page size. Value must be between 1 and 1000. + :param project_id: ID of the Project. + :return: :class:`List[Pool] ` + + Usage: + :: + + result = api.list_pools_all() + """ + + return fetch_all_pages( + type=ListPoolsResponse, + key="pools", + fetcher=self.list_pools, + args={ + "region": region, + "page": page, + "page_size": page_size, + "project_id": project_id, + }, + ) + + def get_project_consumption( + self, + *, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> ProjectConsumption: + """ + Get project resource consumption. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project. + :return: :class:`ProjectConsumption ` + + Usage: + :: + + result = api.get_project_consumption() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/transactional-email/v1alpha1/regions/{param_region}/project-consumption", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_ProjectConsumption(res.json()) diff --git a/scaleway/scaleway/tem/v1alpha1/content.py b/scaleway/scaleway/tem/v1alpha1/content.py index 3ae5890b..80c9895d 100644 --- a/scaleway/scaleway/tem/v1alpha1/content.py +++ b/scaleway/scaleway/tem/v1alpha1/content.py @@ -9,6 +9,7 @@ DOMAIN_TRANSIENT_STATUSES: List[DomainStatus] = [ DomainStatus.PENDING, + DomainStatus.AUTOCONFIGURING, ] """ Lists transient statutes of the enum :class:`DomainStatus `. diff --git a/scaleway/scaleway/tem/v1alpha1/marshalling.py b/scaleway/scaleway/tem/v1alpha1/marshalling.py index 5d15e237..522b5dec 100644 --- a/scaleway/scaleway/tem/v1alpha1/marshalling.py +++ b/scaleway/scaleway/tem/v1alpha1/marshalling.py @@ -7,6 +7,7 @@ from scaleway_core.profile import ProfileDefaults from .types import ( EmailFlag, + WebhookEventType, EmailTry, Email, DomainRecordsDMARC, @@ -14,19 +15,43 @@ DomainReputation, DomainStatistics, Domain, + OfferSubscription, + Webhook, + Blocklist, + BulkCreateBlocklistsResponse, CreateEmailResponse, + DomainLastStatusAutoconfigState, DomainLastStatusDkimRecord, DomainLastStatusDmarcRecord, DomainLastStatusSpfRecord, DomainLastStatus, + ListBlocklistsResponse, ListDomainsResponse, ListEmailsResponse, + ListOfferSubscriptionsResponse, + Offer, + ListOffersResponse, + Pool, + ListPoolsResponse, + WebhookEvent, + ListWebhookEventsResponse, + ListWebhooksResponse, + ProjectConsumption, + ProjectSettingsPeriodicReport, + ProjectSettings, Statistics, + BulkCreateBlocklistsRequest, CreateDomainRequest, CreateEmailRequestAddress, CreateEmailRequestAttachment, CreateEmailRequestHeader, CreateEmailRequest, + CreateWebhookRequest, + UpdateDomainRequest, + UpdateOfferSubscriptionRequest, + UpdateProjectSettingsRequestUpdatePeriodicReport, + UpdateProjectSettingsRequest, + UpdateWebhookRequest, ) @@ -53,6 +78,8 @@ def unmarshal_EmailTry(data: Any) -> EmailTry: field = data.get("tried_at", None) if field is not None: args["tried_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["tried_at"] = None return EmailTry(**args) @@ -88,6 +115,8 @@ def unmarshal_Email(data: Any) -> Email: field = data.get("rcpt_to", None) if field is not None: args["rcpt_to"] = field + else: + args["rcpt_to"] = None field = data.get("rcpt_type", None) if field is not None: @@ -118,14 +147,20 @@ def unmarshal_Email(data: Any) -> Email: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("status_details", None) if field is not None: args["status_details"] = field + else: + args["status_details"] = None return Email(**args) @@ -160,6 +195,8 @@ def unmarshal_DomainRecords(data: Any) -> DomainRecords: field = data.get("dmarc", None) if field is not None: args["dmarc"] = unmarshal_DomainRecordsDMARC(field) + else: + args["dmarc"] = None return DomainRecords(**args) @@ -183,16 +220,22 @@ def unmarshal_DomainReputation(data: Any) -> DomainReputation: field = data.get("scored_at", None) if field is not None: args["scored_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["scored_at"] = None field = data.get("previous_score", None) if field is not None: args["previous_score"] = field + else: + args["previous_score"] = None field = data.get("previous_scored_at", None) if field is not None: args["previous_scored_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["previous_scored_at"] = None return DomainReputation(**args) @@ -256,25 +299,35 @@ def unmarshal_Domain(data: Any) -> Domain: if field is not None: args["spf_config"] = field + field = data.get("dkim_config", None) + if field is not None: + args["dkim_config"] = field + field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("next_check_at", None) if field is not None: args["next_check_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["next_check_at"] = None field = data.get("last_valid_at", None) if field is not None: args["last_valid_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_valid_at"] = None - field = data.get("dkim_config", None) + field = data.get("autoconfig", None) if field is not None: - args["dkim_config"] = field + args["autoconfig"] = field field = data.get("region", None) if field is not None: @@ -283,26 +336,222 @@ def unmarshal_Domain(data: Any) -> Domain: field = data.get("revoked_at", None) if field is not None: args["revoked_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["revoked_at"] = None field = data.get("last_error", None) if field is not None: args["last_error"] = field + else: + args["last_error"] = None field = data.get("statistics", None) if field is not None: args["statistics"] = unmarshal_DomainStatistics(field) + else: + args["statistics"] = None field = data.get("reputation", None) if field is not None: args["reputation"] = unmarshal_DomainReputation(field) + else: + args["reputation"] = None field = data.get("records", None) if field is not None: args["records"] = unmarshal_DomainRecords(field) + else: + args["records"] = None return Domain(**args) +def unmarshal_OfferSubscription(data: Any) -> OfferSubscription: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferSubscription' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("sla", None) + if field is not None: + args["sla"] = field + + field = data.get("max_domains", None) + if field is not None: + args["max_domains"] = field + + field = data.get("max_dedicated_ips", None) + if field is not None: + args["max_dedicated_ips"] = field + + field = data.get("max_webhooks_per_domain", None) + if field is not None: + args["max_webhooks_per_domain"] = field + + field = data.get("max_custom_blocklists_per_domain", None) + if field is not None: + args["max_custom_blocklists_per_domain"] = field + + field = data.get("included_monthly_emails", None) + if field is not None: + args["included_monthly_emails"] = field + + field = data.get("subscribed_at", None) + if field is not None: + args["subscribed_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["subscribed_at"] = None + + field = data.get("cancellation_available_at", None) + if field is not None: + args["cancellation_available_at"] = ( + parser.isoparse(field) if isinstance(field, str) else field + ) + else: + args["cancellation_available_at"] = None + + return OfferSubscription(**args) + + +def unmarshal_Webhook(data: Any) -> Webhook: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Webhook' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("domain_id", None) + if field is not None: + args["domain_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("event_types", None) + if field is not None: + args["event_types"] = ( + [WebhookEventType(v) for v in field] if field is not None else None + ) + + field = data.get("sns_arn", None) + if field is not None: + args["sns_arn"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Webhook(**args) + + +def unmarshal_Blocklist(data: Any) -> Blocklist: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Blocklist' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("domain_id", None) + if field is not None: + args["domain_id"] = field + + field = data.get("email", None) + if field is not None: + args["email"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("reason", None) + if field is not None: + args["reason"] = field + + field = data.get("custom", None) + if field is not None: + args["custom"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("ends_at", None) + if field is not None: + args["ends_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["ends_at"] = None + + return Blocklist(**args) + + +def unmarshal_BulkCreateBlocklistsResponse(data: Any) -> BulkCreateBlocklistsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'BulkCreateBlocklistsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("blocklists", None) + if field is not None: + args["blocklists"] = ( + [unmarshal_Blocklist(v) for v in field] if field is not None else None + ) + + return BulkCreateBlocklistsResponse(**args) + + def unmarshal_CreateEmailResponse(data: Any) -> CreateEmailResponse: if not isinstance(data, dict): raise TypeError( @@ -320,6 +569,33 @@ def unmarshal_CreateEmailResponse(data: Any) -> CreateEmailResponse: return CreateEmailResponse(**args) +def unmarshal_DomainLastStatusAutoconfigState( + data: Any, +) -> DomainLastStatusAutoconfigState: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DomainLastStatusAutoconfigState' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + field = data.get("autoconfigurable", None) + if field is not None: + args["autoconfigurable"] = field + + field = data.get("reason", None) + if field is not None: + args["reason"] = field + else: + args["reason"] = None + + return DomainLastStatusAutoconfigState(**args) + + def unmarshal_DomainLastStatusDkimRecord(data: Any) -> DomainLastStatusDkimRecord: if not isinstance(data, dict): raise TypeError( @@ -337,10 +613,14 @@ def unmarshal_DomainLastStatusDkimRecord(data: Any) -> DomainLastStatusDkimRecor args["last_valid_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_valid_at"] = None field = data.get("error", None) if field is not None: args["error"] = field + else: + args["error"] = None return DomainLastStatusDkimRecord(**args) @@ -362,10 +642,14 @@ def unmarshal_DomainLastStatusDmarcRecord(data: Any) -> DomainLastStatusDmarcRec args["last_valid_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_valid_at"] = None field = data.get("error", None) if field is not None: args["error"] = field + else: + args["error"] = None return DomainLastStatusDmarcRecord(**args) @@ -387,10 +671,14 @@ def unmarshal_DomainLastStatusSpfRecord(data: Any) -> DomainLastStatusSpfRecord: args["last_valid_at"] = ( parser.isoparse(field) if isinstance(field, str) else field ) + else: + args["last_valid_at"] = None field = data.get("error", None) if field is not None: args["error"] = field + else: + args["error"] = None return DomainLastStatusSpfRecord(**args) @@ -414,18 +702,51 @@ def unmarshal_DomainLastStatus(data: Any) -> DomainLastStatus: field = data.get("spf_record", None) if field is not None: args["spf_record"] = unmarshal_DomainLastStatusSpfRecord(field) + else: + args["spf_record"] = None field = data.get("dkim_record", None) if field is not None: args["dkim_record"] = unmarshal_DomainLastStatusDkimRecord(field) + else: + args["dkim_record"] = None field = data.get("dmarc_record", None) if field is not None: args["dmarc_record"] = unmarshal_DomainLastStatusDmarcRecord(field) + else: + args["dmarc_record"] = None + + field = data.get("autoconfig_state", None) + if field is not None: + args["autoconfig_state"] = unmarshal_DomainLastStatusAutoconfigState(field) + else: + args["autoconfig_state"] = None return DomainLastStatus(**args) +def unmarshal_ListBlocklistsResponse(data: Any) -> ListBlocklistsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListBlocklistsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("blocklists", None) + if field is not None: + args["blocklists"] = ( + [unmarshal_Blocklist(v) for v in field] if field is not None else None + ) + + return ListBlocklistsResponse(**args) + + def unmarshal_ListDomainsResponse(data: Any) -> ListDomainsResponse: if not isinstance(data, dict): raise TypeError( @@ -468,6 +789,347 @@ def unmarshal_ListEmailsResponse(data: Any) -> ListEmailsResponse: return ListEmailsResponse(**args) +def unmarshal_ListOfferSubscriptionsResponse( + data: Any, +) -> ListOfferSubscriptionsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOfferSubscriptionsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offer_subscriptions", None) + if field is not None: + args["offer_subscriptions"] = ( + [unmarshal_OfferSubscription(v) for v in field] + if field is not None + else None + ) + + return ListOfferSubscriptionsResponse(**args) + + +def unmarshal_Offer(data: Any) -> Offer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Offer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("sla", None) + if field is not None: + args["sla"] = field + + field = data.get("max_domains", None) + if field is not None: + args["max_domains"] = field + + field = data.get("max_dedicated_ips", None) + if field is not None: + args["max_dedicated_ips"] = field + + field = data.get("included_monthly_emails", None) + if field is not None: + args["included_monthly_emails"] = field + + field = data.get("max_webhooks_per_domain", None) + if field is not None: + args["max_webhooks_per_domain"] = field + + field = data.get("max_custom_blocklists_per_domain", None) + if field is not None: + args["max_custom_blocklists_per_domain"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("commitment_period", None) + if field is not None: + args["commitment_period"] = field + else: + args["commitment_period"] = None + + return Offer(**args) + + +def unmarshal_ListOffersResponse(data: Any) -> ListOffersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOffersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offers", None) + if field is not None: + args["offers"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return ListOffersResponse(**args) + + +def unmarshal_Pool(data: Any) -> Pool: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Pool' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("ips", None) + if field is not None: + args["ips"] = field + + field = data.get("details", None) + if field is not None: + args["details"] = field + else: + args["details"] = None + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("reverse", None) + if field is not None: + args["reverse"] = field + else: + args["reverse"] = None + + return Pool(**args) + + +def unmarshal_ListPoolsResponse(data: Any) -> ListPoolsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPoolsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("pools", None) + if field is not None: + args["pools"] = ( + [unmarshal_Pool(v) for v in field] if field is not None else None + ) + + return ListPoolsResponse(**args) + + +def unmarshal_WebhookEvent(data: Any) -> WebhookEvent: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'WebhookEvent' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("webhook_id", None) + if field is not None: + args["webhook_id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("domain_id", None) + if field is not None: + args["domain_id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("data", None) + if field is not None: + args["data"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("email_id", None) + if field is not None: + args["email_id"] = field + else: + args["email_id"] = None + + return WebhookEvent(**args) + + +def unmarshal_ListWebhookEventsResponse(data: Any) -> ListWebhookEventsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListWebhookEventsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("webhook_events", None) + if field is not None: + args["webhook_events"] = ( + [unmarshal_WebhookEvent(v) for v in field] if field is not None else None + ) + + return ListWebhookEventsResponse(**args) + + +def unmarshal_ListWebhooksResponse(data: Any) -> ListWebhooksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListWebhooksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("webhooks", None) + if field is not None: + args["webhooks"] = ( + [unmarshal_Webhook(v) for v in field] if field is not None else None + ) + + return ListWebhooksResponse(**args) + + +def unmarshal_ProjectConsumption(data: Any) -> ProjectConsumption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectConsumption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("domains_count", None) + if field is not None: + args["domains_count"] = field + + field = data.get("dedicated_ips_count", None) + if field is not None: + args["dedicated_ips_count"] = field + + field = data.get("monthly_emails_count", None) + if field is not None: + args["monthly_emails_count"] = field + + field = data.get("webhooks_count", None) + if field is not None: + args["webhooks_count"] = field + + field = data.get("custom_blocklists_count", None) + if field is not None: + args["custom_blocklists_count"] = field + + return ProjectConsumption(**args) + + +def unmarshal_ProjectSettingsPeriodicReport(data: Any) -> ProjectSettingsPeriodicReport: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectSettingsPeriodicReport' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("enabled", None) + if field is not None: + args["enabled"] = field + + field = data.get("frequency", None) + if field is not None: + args["frequency"] = field + + field = data.get("sending_hour", None) + if field is not None: + args["sending_hour"] = field + + field = data.get("sending_day", None) + if field is not None: + args["sending_day"] = field + + return ProjectSettingsPeriodicReport(**args) + + +def unmarshal_ProjectSettings(data: Any) -> ProjectSettings: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectSettings' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("periodic_report", None) + if field is not None: + args["periodic_report"] = unmarshal_ProjectSettingsPeriodicReport(field) + else: + args["periodic_report"] = None + + return ProjectSettings(**args) + + def unmarshal_Statistics(data: Any) -> Statistics: if not isinstance(data, dict): raise TypeError( @@ -503,6 +1165,27 @@ def unmarshal_Statistics(data: Any) -> Statistics: return Statistics(**args) +def marshal_BulkCreateBlocklistsRequest( + request: BulkCreateBlocklistsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain_id is not None: + output["domain_id"] = request.domain_id + + if request.emails is not None: + output["emails"] = request.emails + + if request.type_ is not None: + output["type"] = str(request.type_) + + if request.reason is not None: + output["reason"] = request.reason + + return output + + def marshal_CreateDomainRequest( request: CreateDomainRequest, defaults: ProfileDefaults, @@ -512,12 +1195,15 @@ def marshal_CreateDomainRequest( if request.domain_name is not None: output["domain_name"] = request.domain_name - if request.accept_tos is not None: - output["accept_tos"] = request.accept_tos + if request.autoconfig is not None: + output["autoconfig"] = request.autoconfig if request.project_id is not None: output["project_id"] = request.project_id or defaults.default_project_id + if request.accept_tos is not None: + output["accept_tos"] = request.accept_tos + return output @@ -575,6 +1261,9 @@ def marshal_CreateEmailRequest( ) -> Dict[str, Any]: output: Dict[str, Any] = {} + if request.from_ is not None: + output["from"] = marshal_CreateEmailRequestAddress(request.from_, defaults) + if request.subject is not None: output["subject"] = request.subject @@ -584,9 +1273,6 @@ def marshal_CreateEmailRequest( if request.html is not None: output["html"] = request.html - if request.from_ is not None: - output["from"] = (marshal_CreateEmailRequestAddress(request.from_, defaults),) - if request.to is not None: output["to"] = [ marshal_CreateEmailRequestAddress(item, defaults) for item in request.to @@ -612,7 +1298,7 @@ def marshal_CreateEmailRequest( ] if request.send_before is not None: - output["send_before"] = request.send_before + output["send_before"] = request.send_before.isoformat() if request.additional_headers is not None: output["additional_headers"] = [ @@ -621,3 +1307,109 @@ def marshal_CreateEmailRequest( ] return output + + +def marshal_CreateWebhookRequest( + request: CreateWebhookRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain_id is not None: + output["domain_id"] = request.domain_id + + if request.name is not None: + output["name"] = request.name + + if request.sns_arn is not None: + output["sns_arn"] = request.sns_arn + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.event_types is not None: + output["event_types"] = [str(item) for item in request.event_types] + + return output + + +def marshal_UpdateDomainRequest( + request: UpdateDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.autoconfig is not None: + output["autoconfig"] = request.autoconfig + + return output + + +def marshal_UpdateOfferSubscriptionRequest( + request: UpdateOfferSubscriptionRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.name is not None: + output["name"] = str(request.name) + + return output + + +def marshal_UpdateProjectSettingsRequestUpdatePeriodicReport( + request: UpdateProjectSettingsRequestUpdatePeriodicReport, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.enabled is not None: + output["enabled"] = request.enabled + + if request.frequency is not None: + output["frequency"] = str(request.frequency) + + if request.sending_hour is not None: + output["sending_hour"] = request.sending_hour + + if request.sending_day is not None: + output["sending_day"] = request.sending_day + + return output + + +def marshal_UpdateProjectSettingsRequest( + request: UpdateProjectSettingsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.periodic_report is not None: + output["periodic_report"] = ( + marshal_UpdateProjectSettingsRequestUpdatePeriodicReport( + request.periodic_report, defaults + ) + ) + + return output + + +def marshal_UpdateWebhookRequest( + request: UpdateWebhookRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.event_types is not None: + output["event_types"] = [str(item) for item in request.event_types] + + if request.sns_arn is not None: + output["sns_arn"] = request.sns_arn + + return output diff --git a/scaleway/scaleway/tem/v1alpha1/types.py b/scaleway/scaleway/tem/v1alpha1/types.py index a8dfc4a3..0f40682c 100644 --- a/scaleway/scaleway/tem/v1alpha1/types.py +++ b/scaleway/scaleway/tem/v1alpha1/types.py @@ -8,13 +8,32 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, ) +class BlocklistType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + MAILBOX_FULL = "mailbox_full" + MAILBOX_NOT_FOUND = "mailbox_not_found" + + def __str__(self) -> str: + return str(self.value) + + +class DomainLastStatusAutoconfigStateReason(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_REASON = "unknown_reason" + PERMISSION_DENIED = "permission_denied" + DOMAIN_NOT_FOUND = "domain_not_found" + + def __str__(self) -> str: + return str(self.value) + + class DomainLastStatusRecordStatus(str, Enum, metaclass=StrEnumMeta): UNKNOWN_RECORD_STATUS = "unknown_record_status" VALID = "valid" @@ -44,6 +63,7 @@ class DomainStatus(str, Enum, metaclass=StrEnumMeta): LOCKED = "locked" REVOKED = "revoked" PENDING = "pending" + AUTOCONFIGURING = "autoconfiguring" def __str__(self) -> str: return str(self.value) @@ -58,6 +78,7 @@ class EmailFlag(str, Enum, metaclass=StrEnumMeta): MAILBOX_NOT_FOUND = "mailbox_not_found" GREYLISTED = "greylisted" SEND_BEFORE_EXPIRATION = "send_before_expiration" + BLOCKLISTED = "blocklisted" def __str__(self) -> str: return str(self.value) @@ -85,6 +106,16 @@ def __str__(self) -> str: return str(self.value) +class ListBlocklistsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + ENDS_AT_DESC = "ends_at_desc" + ENDS_AT_ASC = "ends_at_asc" + + def __str__(self) -> str: + return str(self.value) + + class ListEmailsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_DESC = "created_at_desc" CREATED_AT_ASC = "created_at_asc" @@ -103,6 +134,77 @@ def __str__(self) -> str: return str(self.value) +class ListWebhookEventsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ListWebhooksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_DESC = "created_at_desc" + CREATED_AT_ASC = "created_at_asc" + + def __str__(self) -> str: + return str(self.value) + + +class OfferName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + ESSENTIAL = "essential" + SCALE = "scale" + + def __str__(self) -> str: + return str(self.value) + + +class PoolStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DISABLED = "disabled" + CREATING = "creating" + READY = "ready" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class ProjectSettingsPeriodicReportFrequency(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_FREQUENCY = "unknown_frequency" + MONTHLY = "monthly" + WEEKLY = "weekly" + DAILY = "daily" + + def __str__(self) -> str: + return str(self.value) + + +class WebhookEventStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + SENDING = "sending" + SENT = "sent" + FAILED = "failed" + + def __str__(self) -> str: + return str(self.value) + + +class WebhookEventType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + EMAIL_QUEUED = "email_queued" + EMAIL_DROPPED = "email_dropped" + EMAIL_DEFERRED = "email_deferred" + EMAIL_DELIVERED = "email_delivered" + EMAIL_SPAM = "email_spam" + EMAIL_MAILBOX_NOT_FOUND = "email_mailbox_not_found" + EMAIL_BLOCKLISTED = "email_blocklisted" + BLOCKLIST_CREATED = "blocklist_created" + + def __str__(self) -> str: + return str(self.value) + + @dataclass class DomainRecordsDMARC: name: str @@ -186,6 +288,54 @@ class DomainStatistics: canceled_count: int +@dataclass +class Blocklist: + id: str + """ + ID of the blocklist. + """ + + domain_id: str + """ + Domain ID linked to the blocklist. + """ + + email: str + """ + Email blocked by the blocklist. + """ + + type_: BlocklistType + """ + Type of block for this email. + """ + + reason: str + """ + Reason to block this email. + """ + + custom: bool + """ + True if this blocklist was created manually. False for an automatic Transactional Email blocklist. + """ + + created_at: Optional[datetime] + """ + Date and time of the blocklist creation. + """ + + updated_at: Optional[datetime] + """ + Date and time of the blocklist's last update. + """ + + ends_at: Optional[datetime] + """ + Date and time when the blocklist ends. Empty if the blocklist has no end. + """ + + @dataclass class CreateEmailRequestAddress: email: str @@ -259,7 +409,7 @@ class Email: rcpt_to: Optional[str] """ - Email address of the recipient. + Deprecated. Email address of the recipient. """ rcpt_type: EmailRcptType @@ -308,6 +458,24 @@ class Email: """ +@dataclass +class DomainLastStatusAutoconfigState: + enabled: bool + """ + Enable or disable the auto-configuration of domain DNS records. + """ + + autoconfigurable: bool + """ + Whether the domain can be auto-configured or not. + """ + + reason: Optional[DomainLastStatusAutoconfigStateReason] + """ + The reason that the domain cannot be auto-configurable. + """ + + @dataclass class DomainLastStatusDkimRecord: status: DomainLastStatusRecordStatus @@ -394,6 +562,11 @@ class Domain: Snippet of the SPF record to register in the DNS zone. """ + dkim_config: str + """ + DKIM public key to record in the DNS zone. + """ + created_at: Optional[datetime] """ Date and time of domain creation. @@ -409,12 +582,12 @@ class Domain: Date and time the domain was last valid. """ - dkim_config: str + autoconfig: bool """ - DKIM public key to record in the DNS zone. + Status of auto-configuration for the domain's DNS zone. """ - region: Region + region: ScwRegion """ Region to target. If none is passed will use default region from the config. """ @@ -426,7 +599,7 @@ class Domain: last_error: Optional[str] """ - Error message returned if the last check failed. + Deprecated. Error message returned if the last check failed. """ statistics: Optional[DomainStatistics] @@ -446,266 +619,772 @@ class Domain: @dataclass -class CancelEmailRequest: - email_id: str +class OfferSubscription: + organization_id: str """ - ID of the email to cancel. + ID of the offer-subscription Organization. """ - region: Optional[Region] + project_id: str """ - Region to target. If none is passed will use default region from the config. + ID of the offer-subscription Project. """ + offer_name: OfferName + """ + Name of the offer associated with the Project. + """ -@dataclass -class CheckDomainRequest: - domain_id: str + sla: float """ - ID of the domain to check. + Service Level Agreement percentage of the offer-subscription. """ - region: Optional[Region] + max_domains: int """ - Region to target. If none is passed will use default region from the config. + Max number of domains that can be associated with the offer-subscription for a particular Project. """ + max_dedicated_ips: int + """ + Max number of dedicated IPs that can be associated with the offer-subscription for a particular Project. + """ -@dataclass -class CreateDomainRequest: - domain_name: str + max_webhooks_per_domain: int """ - Fully qualified domain dame. + Max number of webhooks that can be associated with the offer-subscription for a particular Project. """ - accept_tos: bool + max_custom_blocklists_per_domain: int """ - Accept Scaleway's Terms of Service. + Max number of custom blocklists that can be associated with the offer-subscription for a particular Project. """ - region: Optional[Region] + included_monthly_emails: int """ - Region to target. If none is passed will use default region from the config. + Number of emails included in the offer-subscription per month. """ - project_id: Optional[str] + subscribed_at: Optional[datetime] """ - ID of the project to which the domain belongs. + Date and time of the subscription. + """ + + cancellation_available_at: Optional[datetime] + """ + Date and time of the end of the offer-subscription commitment. """ @dataclass -class CreateEmailRequest: - subject: str +class Offer: + name: OfferName """ - Subject of the email. + Name of the offer. """ - text: str + sla: float """ - Text content. + Service Level Agreement percentage of the offer. """ - html: str + max_domains: int """ - HTML content. + Max number of checked domains that can be associated with the offer. """ - region: Optional[Region] + max_dedicated_ips: int """ - Region to target. If none is passed will use default region from the config. + Max number of dedicated IPs that can be associated with the offer. """ - from_: Optional[CreateEmailRequestAddress] + included_monthly_emails: int """ - Sender information. Must be from a checked domain declared in the Project. + Number of emails included in the offer per month. """ - to: Optional[List[CreateEmailRequestAddress]] + max_webhooks_per_domain: int """ - An array of the primary recipient's information. + Max number of webhooks that can be associated with the offer. """ - cc: Optional[List[CreateEmailRequestAddress]] + max_custom_blocklists_per_domain: int """ - An array of the carbon copy recipient's information. + Max number of active custom blocklists that can be associated with the offer. """ - bcc: Optional[List[CreateEmailRequestAddress]] + created_at: Optional[datetime] """ - An array of the blind carbon copy recipient's information. + Date and time of the offer creation. """ - project_id: Optional[str] + commitment_period: Optional[str] """ - ID of the Project in which to create the email. + Period of commitment. """ - attachments: Optional[List[CreateEmailRequestAttachment]] + +@dataclass +class Pool: + project_id: str """ - Array of attachments. + ID of the Project. """ - send_before: Optional[datetime] + status: PoolStatus """ - Maximum date to deliver the email. + Status of the pool. """ - additional_headers: Optional[List[CreateEmailRequestHeader]] + ips: List[str] """ - Array of additional headers as key-value. + IPs of the pool. """ + details: Optional[str] + """ + Details of the pool. + """ -@dataclass -class CreateEmailResponse: - emails: List[Email] + zone: Optional[ScwZone] """ - Single page of emails matching the requested criteria. + Zone of the pool. + """ + + reverse: Optional[str] + """ + Reverse hostname of all IPs of the pool. """ @dataclass -class DomainLastStatus: - domain_id: str +class WebhookEvent: + id: str """ - The ID of the domain. + ID of the Webhook Event. """ - domain_name: str + webhook_id: str """ - The domain name (example.com). + ID of the Webhook that triggers the Event. """ - spf_record: Optional[DomainLastStatusSpfRecord] + organization_id: str """ - The SPF record verification data. + ID of the Webhook Event Organization. """ - dkim_record: Optional[DomainLastStatusDkimRecord] + project_id: str """ - The DKIM record verification data. + ID of the Webhook Event Project. """ - dmarc_record: Optional[DomainLastStatusDmarcRecord] + domain_id: str """ - The DMARC record verification data. + ID of the webhook event domain. """ + type_: WebhookEventType + """ + Type of the Webhook Event. + """ -@dataclass -class GetDomainLastStatusRequest: - domain_id: str + status: WebhookEventStatus """ - ID of the domain to delete. + Status of the Webhook Event. """ - region: Optional[Region] + data: str """ - Region to target. If none is passed will use default region from the config. + Data sent to the Webhook destination. """ + created_at: Optional[datetime] + """ + Date and time of the Webhook Event creation. + """ -@dataclass -class GetDomainRequest: - domain_id: str + updated_at: Optional[datetime] """ - ID of the domain. + Date and time of last Webhook Event updates. """ - region: Optional[Region] + email_id: Optional[str] """ - Region to target. If none is passed will use default region from the config. + Optional Email ID if the event is triggered by an Email resource. """ @dataclass -class GetEmailRequest: - email_id: str +class Webhook: + id: str """ - ID of the email to retrieve. + ID of the Webhook. """ - region: Optional[Region] + domain_id: str """ - Region to target. If none is passed will use default region from the config. + ID of the Domain to watch for triggering events. """ + organization_id: str + """ + ID of the Webhook Organization. + """ -@dataclass -class GetStatisticsRequest: - region: Optional[Region] + project_id: str """ - Region to target. If none is passed will use default region from the config. + ID of the Webhook Project. """ - project_id: Optional[str] + name: str """ - (Optional) Number of emails for this Project. + Name of the Webhook. """ - domain_id: Optional[str] + event_types: List[WebhookEventType] """ - (Optional) Number of emails sent from this domain (must be coherent with the `project_id` and the `organization_id`). + List of event types that will trigger a Webhook Event. """ - since: Optional[datetime] + sns_arn: str """ - (Optional) Number of emails created after this date. + Scaleway SNS ARN topic to push the events to. """ - until: Optional[datetime] + created_at: Optional[datetime] """ - (Optional) Number of emails created before this date. + Date and time of the Webhook creation. """ - mail_from: Optional[str] + updated_at: Optional[datetime] """ - (Optional) Number of emails sent with this sender's email address. + Date and time of last Webhook updates. """ @dataclass -class ListDomainsRequest: - region: Optional[Region] +class ProjectSettingsPeriodicReport: + enabled: bool """ - Region to target. If none is passed will use default region from the config. + Enable or disable periodic report notifications. """ - page: Optional[int] + frequency: ProjectSettingsPeriodicReportFrequency """ - Requested page number. Value must be greater or equal to 1. + At which frequency you receive periodic report notifications. """ - page_size: Optional[int] + sending_hour: int """ - Page size. + At which hour you receive periodic report notifications. """ - project_id: Optional[str] - - status: Optional[List[DomainStatus]] - - organization_id: Optional[str] - - name: Optional[str] - - -@dataclass -class ListDomainsResponse: - total_count: int + sending_day: int """ - Number of domains that match the request (without pagination). + On which day you receive periodic report notifications (1-7 weekly, 1-28 monthly). """ - domains: List[Domain] - @dataclass -class ListEmailsRequest: - region: Optional[Region] +class UpdateProjectSettingsRequestUpdatePeriodicReport: + enabled: Optional[bool] """ - Region to target. If none is passed will use default region from the config. + (Optional) Enable or disable periodic report notifications. + """ + + frequency: Optional[ProjectSettingsPeriodicReportFrequency] + """ + (Optional) Frequency at which you receive periodic report notifications. + """ + + sending_hour: Optional[int] + """ + (Optional) Hour at which you receive periodic report notifications. + """ + + sending_day: Optional[int] + """ + (Optional) On which day you receive periodic report notifications (1-7 weekly, 1-28 monthly). + """ + + +@dataclass +class BulkCreateBlocklistsRequest: + domain_id: str + """ + Domain ID linked to the blocklist. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + emails: Optional[List[str]] + """ + Email blocked by the blocklist. + """ + + type_: Optional[BlocklistType] + """ + Type of blocklist. + """ + + reason: Optional[str] + """ + Reason to block the email. + """ + + +@dataclass +class BulkCreateBlocklistsResponse: + blocklists: List[Blocklist] + """ + List of blocklist created. + """ + + +@dataclass +class CancelEmailRequest: + email_id: str + """ + ID of the email to cancel. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CheckDomainRequest: + domain_id: str + """ + ID of the domain to check. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class CreateDomainRequest: + domain_name: str + """ + Fully qualified domain dame. + """ + + autoconfig: bool + """ + Activate auto-configuration of the domain's DNS zone. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project to which the domain belongs. + """ + + accept_tos: Optional[bool] + """ + Deprecated. Accept Scaleway's Terms of Service. + """ + + +@dataclass +class CreateEmailRequest: + from_: CreateEmailRequestAddress + """ + Sender information. Must be from a checked domain declared in the Project. + """ + + subject: str + """ + Subject of the email. + """ + + text: str + """ + Text content. + """ + + html: str + """ + HTML content. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + to: Optional[List[CreateEmailRequestAddress]] + """ + An array of the primary recipient's information. + """ + + cc: Optional[List[CreateEmailRequestAddress]] + """ + An array of the carbon copy recipient's information. + """ + + bcc: Optional[List[CreateEmailRequestAddress]] + """ + An array of the blind carbon copy recipient's information. + """ + + project_id: Optional[str] + """ + ID of the Project in which to create the email. + """ + + attachments: Optional[List[CreateEmailRequestAttachment]] + """ + Array of attachments. + """ + + send_before: Optional[datetime] + """ + Maximum date to deliver the email. + """ + + additional_headers: Optional[List[CreateEmailRequestHeader]] + """ + Array of additional headers as key-value. + """ + + +@dataclass +class CreateEmailResponse: + emails: List[Email] + """ + Single page of emails matching the requested criteria. + """ + + +@dataclass +class CreateWebhookRequest: + domain_id: str + """ + ID of the Domain to watch for triggering events. + """ + + name: str + """ + Name of the Webhook. + """ + + sns_arn: str + """ + Scaleway SNS ARN topic to push the events to. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project to which the Webhook belongs. + """ + + event_types: Optional[List[WebhookEventType]] + """ + List of event types that will trigger an event. + """ + + +@dataclass +class DeleteBlocklistRequest: + blocklist_id: str + """ + ID of the blocklist to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteWebhookRequest: + webhook_id: str + """ + ID of the Webhook to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DomainLastStatus: + domain_id: str + """ + The ID of the domain. + """ + + domain_name: str + """ + The domain name (example.com). + """ + + spf_record: Optional[DomainLastStatusSpfRecord] + """ + The SPF record verification data. + """ + + dkim_record: Optional[DomainLastStatusDkimRecord] + """ + The DKIM record verification data. + """ + + dmarc_record: Optional[DomainLastStatusDmarcRecord] + """ + The DMARC record verification data. + """ + + autoconfig_state: Optional[DomainLastStatusAutoconfigState] + """ + The verification state of domain auto-configuration. + """ + + +@dataclass +class GetDomainLastStatusRequest: + domain_id: str + """ + ID of the domain to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetDomainRequest: + domain_id: str + """ + ID of the domain. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetEmailRequest: + email_id: str + """ + ID of the email to retrieve. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetProjectConsumptionRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project. + """ + + +@dataclass +class GetProjectSettingsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project. + """ + + +@dataclass +class GetStatisticsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + (Optional) Number of emails for this Project. + """ + + domain_id: Optional[str] + """ + (Optional) Number of emails sent from this domain (must be coherent with the `project_id` and the `organization_id`). + """ + + since: Optional[datetime] + """ + (Optional) Number of emails created after this date. + """ + + until: Optional[datetime] + """ + (Optional) Number of emails created before this date. + """ + + mail_from: Optional[str] + """ + (Optional) Number of emails sent with this sender's email address. + """ + + +@dataclass +class GetWebhookRequest: + webhook_id: str + """ + ID of the Webhook to check. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListBlocklistsRequest: + domain_id: str + """ + (Optional) Filter by a domain ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListBlocklistsRequestOrderBy] + """ + (Optional) List blocklist corresponding to specific criteria. + """ + + page: Optional[int] + """ + (Optional) Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + (Optional) Requested page size. Value must be between 1 and 100. + """ + + email: Optional[str] + """ + (Optional) Filter by an email address. + """ + + type_: Optional[BlocklistType] + """ + (Optional) Filter by a blocklist type. + """ + + custom: Optional[bool] + """ + (Optional) Filter by custom blocklist (true) or automatic Transactional Email blocklist (false). + """ + + +@dataclass +class ListBlocklistsResponse: + total_count: int + """ + Number of blocklists matching the requested criteria. + """ + + blocklists: List[Blocklist] + """ + Single page of blocklists matching the requested criteria. + """ + + +@dataclass +class ListDomainsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + Requested page size. Value must be between 1 and 1000. + """ + + project_id: Optional[str] + """ + (Optional) ID of the Project in which to list the domains. + """ + + status: Optional[List[DomainStatus]] + """ + (Optional) List domains under specific statuses. + """ + + organization_id: Optional[str] + """ + (Optional) ID of the Organization in which to list the domains. + """ + + name: Optional[str] + """ + (Optional) Names of the domains to list. + """ + + +@dataclass +class ListDomainsResponse: + total_count: int + """ + Number of domains that match the request (without pagination). + """ + + domains: List[Domain] + """ + Single page of domains matching the requested criteria. + """ + + +@dataclass +class ListEmailsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. """ page: Optional[int] @@ -744,7 +1423,7 @@ class ListEmailsRequest: mail_to: Optional[str] """ - List emails sent to this recipient's email address. + Deprecated. List emails sent to this recipient's email address. """ mail_rcpt: Optional[str] @@ -791,6 +1470,252 @@ class ListEmailsResponse: """ +@dataclass +class ListOfferSubscriptionsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class ListOfferSubscriptionsResponse: + total_count: int + """ + Number of offer-subscriptions matching the requested criteria. + """ + + offer_subscriptions: List[OfferSubscription] + """ + Single page of offer-subscriptions matching the requested criteria. + """ + + +@dataclass +class ListOffersRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ListOffersResponse: + total_count: int + """ + Number of offers matching the requested criteria. + """ + + offers: List[Offer] + """ + Single page of offers matching the requested criteria. + """ + + +@dataclass +class ListPoolsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + Requested page size. Value must be between 1 and 1000. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + +@dataclass +class ListPoolsResponse: + total_count: int + """ + Number of pools matching the requested criteria. + """ + + pools: List[Pool] + """ + Single page of pools matching the requested criteria. + """ + + +@dataclass +class ListWebhookEventsRequest: + webhook_id: str + """ + ID of the Webhook linked to the events. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListWebhookEventsRequestOrderBy] + """ + (Optional) List Webhook events corresponding to specific criteria. + """ + + page: Optional[int] + """ + Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + Requested page size. Value must be between 1 and 100. + """ + + email_id: Optional[str] + """ + ID of the email linked to the events. + """ + + event_types: Optional[List[WebhookEventType]] + """ + List of event types linked to the events. + """ + + statuses: Optional[List[WebhookEventStatus]] + """ + List of event statuses. + """ + + project_id: Optional[str] + """ + ID of the webhook Project. + """ + + organization_id: Optional[str] + """ + ID of the webhook Organization. + """ + + domain_id: Optional[str] + """ + ID of the domain to watch for triggering events. + """ + + +@dataclass +class ListWebhookEventsResponse: + total_count: int + """ + Number of Webhook events matching the requested criteria. + """ + + webhook_events: List[WebhookEvent] + """ + Single page of Webhook events matching the requested criteria. + """ + + +@dataclass +class ListWebhooksRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListWebhooksRequestOrderBy] + """ + (Optional) List Webhooks corresponding to specific criteria. + """ + + page: Optional[int] + """ + (Optional) Requested page number. Value must be greater or equal to 1. + """ + + page_size: Optional[int] + """ + (Optional) Requested page size. Value must be between 1 and 100. + """ + + project_id: Optional[str] + """ + (Optional) ID of the Project for which to list the Webhooks. + """ + + organization_id: Optional[str] + """ + (Optional) ID of the Organization for which to list the Webhooks. + """ + + domain_id: Optional[str] + """ + (Optional) ID of the Domain for which to list the Webhooks. + """ + + +@dataclass +class ListWebhooksResponse: + total_count: int + """ + Number of Webhooks matching the requested criteria. + """ + + webhooks: List[Webhook] + """ + Single page of Webhooks matching the requested criteria. + """ + + +@dataclass +class ProjectConsumption: + project_id: str + """ + ID of the project. + """ + + domains_count: int + """ + Number of domains in the project. + """ + + dedicated_ips_count: int + """ + Number of dedicated IP in the project. + """ + + monthly_emails_count: int + """ + Number of emails sent during the current month in the project. + """ + + webhooks_count: int + """ + Number of webhooks in the project. + """ + + custom_blocklists_count: int + """ + Number of custom blocklists in the project. + """ + + +@dataclass +class ProjectSettings: + periodic_report: Optional[ProjectSettingsPeriodicReport] + """ + Information about your periodic report. + """ + + @dataclass class RevokeDomainRequest: domain_id: str @@ -798,7 +1723,7 @@ class RevokeDomainRequest: ID of the domain to delete. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -835,3 +1760,85 @@ class Statistics: """ Number of emails in the final `canceled` state. This means emails that have been canceled upon request. """ + + +@dataclass +class UpdateDomainRequest: + domain_id: str + """ + ID of the domain to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + autoconfig: Optional[bool] + """ + (Optional) If set to true, activate auto-configuration of the domain's DNS zone. + """ + + +@dataclass +class UpdateOfferSubscriptionRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Project. + """ + + name: Optional[OfferName] + """ + Name of the offer-subscription. + """ + + +@dataclass +class UpdateProjectSettingsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project. + """ + + periodic_report: Optional[UpdateProjectSettingsRequestUpdatePeriodicReport] + """ + Periodic report update details - all fields are optional. + """ + + +@dataclass +class UpdateWebhookRequest: + webhook_id: str + """ + ID of the Webhook to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + name: Optional[str] + """ + Name of the Webhook to update. + """ + + event_types: Optional[List[WebhookEventType]] + """ + List of event types to update. + """ + + sns_arn: Optional[str] + """ + Scaleway SNS ARN topic to update. + """ diff --git a/scaleway/scaleway/test/v1/marshalling.py b/scaleway/scaleway/test/v1/marshalling.py index 357241bf..6c3c3e84 100644 --- a/scaleway/scaleway/test/v1/marshalling.py +++ b/scaleway/scaleway/test/v1/marshalling.py @@ -58,10 +58,14 @@ def unmarshal_Human(data: Any) -> Human: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("hair_count", None) if field is not None: diff --git a/scaleway/scaleway/vpc/v1/api.py b/scaleway/scaleway/vpc/v1/api.py index 612886b8..d03e985f 100644 --- a/scaleway/scaleway/vpc/v1/api.py +++ b/scaleway/scaleway/vpc/v1/api.py @@ -29,7 +29,7 @@ class VpcV1API(API): """ - VPC API. + This API allows you to manage your Virtual Private Clouds (VPCs) and Private Networks. """ def list_private_networks( diff --git a/scaleway/scaleway/vpc/v1/marshalling.py b/scaleway/scaleway/vpc/v1/marshalling.py index 32514e39..b67881a3 100644 --- a/scaleway/scaleway/vpc/v1/marshalling.py +++ b/scaleway/scaleway/vpc/v1/marshalling.py @@ -52,10 +52,14 @@ def unmarshal_PrivateNetwork(data: Any) -> PrivateNetwork: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return PrivateNetwork(**args) diff --git a/scaleway/scaleway/vpc/v2/__init__.py b/scaleway/scaleway/vpc/v2/__init__.py index 9ab28205..81cbc5da 100644 --- a/scaleway/scaleway/vpc/v2/__init__.py +++ b/scaleway/scaleway/vpc/v2/__init__.py @@ -1,57 +1,83 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from .types import AclRuleProtocol +from .types import Action from .types import ListPrivateNetworksRequestOrderBy +from .types import ListSubnetsRequestOrderBy from .types import ListVPCsRequestOrderBy from .types import Subnet from .types import PrivateNetwork +from .types import Route +from .types import AclRule from .types import VPC from .types import AddSubnetsRequest from .types import AddSubnetsResponse from .types import CreatePrivateNetworkRequest +from .types import CreateRouteRequest from .types import CreateVPCRequest from .types import DeletePrivateNetworkRequest +from .types import DeleteRouteRequest from .types import DeleteSubnetsRequest from .types import DeleteSubnetsResponse from .types import DeleteVPCRequest from .types import EnableDHCPRequest +from .types import EnableRoutingRequest +from .types import GetAclRequest +from .types import GetAclResponse from .types import GetPrivateNetworkRequest +from .types import GetRouteRequest from .types import GetVPCRequest from .types import ListPrivateNetworksRequest from .types import ListPrivateNetworksResponse +from .types import ListSubnetsRequest +from .types import ListSubnetsResponse from .types import ListVPCsRequest from .types import ListVPCsResponse -from .types import MigrateZonalPrivateNetworksRequest -from .types import SetSubnetsRequest -from .types import SetSubnetsResponse +from .types import SetAclRequest +from .types import SetAclResponse from .types import UpdatePrivateNetworkRequest +from .types import UpdateRouteRequest from .types import UpdateVPCRequest from .api import VpcV2API __all__ = [ + "AclRuleProtocol", + "Action", "ListPrivateNetworksRequestOrderBy", + "ListSubnetsRequestOrderBy", "ListVPCsRequestOrderBy", "Subnet", "PrivateNetwork", + "Route", + "AclRule", "VPC", "AddSubnetsRequest", "AddSubnetsResponse", "CreatePrivateNetworkRequest", + "CreateRouteRequest", "CreateVPCRequest", "DeletePrivateNetworkRequest", + "DeleteRouteRequest", "DeleteSubnetsRequest", "DeleteSubnetsResponse", "DeleteVPCRequest", "EnableDHCPRequest", + "EnableRoutingRequest", + "GetAclRequest", + "GetAclResponse", "GetPrivateNetworkRequest", + "GetRouteRequest", "GetVPCRequest", "ListPrivateNetworksRequest", "ListPrivateNetworksResponse", + "ListSubnetsRequest", + "ListSubnetsResponse", "ListVPCsRequest", "ListVPCsResponse", - "MigrateZonalPrivateNetworksRequest", - "SetSubnetsRequest", - "SetSubnetsResponse", + "SetAclRequest", + "SetAclResponse", "UpdatePrivateNetworkRequest", + "UpdateRouteRequest", "UpdateVPCRequest", "VpcV2API", ] diff --git a/scaleway/scaleway/vpc/v2/api.py b/scaleway/scaleway/vpc/v2/api.py index 45ee44cf..ac1a6e00 100644 --- a/scaleway/scaleway/vpc/v2/api.py +++ b/scaleway/scaleway/vpc/v2/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( random_name, @@ -13,52 +13,64 @@ fetch_all_pages, ) from .types import ( + Action, ListPrivateNetworksRequestOrderBy, + ListSubnetsRequestOrderBy, ListVPCsRequestOrderBy, + AclRule, AddSubnetsRequest, AddSubnetsResponse, CreatePrivateNetworkRequest, + CreateRouteRequest, CreateVPCRequest, DeleteSubnetsRequest, DeleteSubnetsResponse, + GetAclResponse, ListPrivateNetworksResponse, + ListSubnetsResponse, ListVPCsResponse, - MigrateZonalPrivateNetworksRequest, PrivateNetwork, - SetSubnetsRequest, - SetSubnetsResponse, + Route, + SetAclRequest, + SetAclResponse, + Subnet, UpdatePrivateNetworkRequest, + UpdateRouteRequest, UpdateVPCRequest, VPC, ) from .marshalling import ( unmarshal_PrivateNetwork, + unmarshal_Route, unmarshal_VPC, unmarshal_AddSubnetsResponse, unmarshal_DeleteSubnetsResponse, + unmarshal_GetAclResponse, unmarshal_ListPrivateNetworksResponse, + unmarshal_ListSubnetsResponse, unmarshal_ListVPCsResponse, - unmarshal_SetSubnetsResponse, + unmarshal_SetAclResponse, marshal_AddSubnetsRequest, marshal_CreatePrivateNetworkRequest, + marshal_CreateRouteRequest, marshal_CreateVPCRequest, marshal_DeleteSubnetsRequest, - marshal_MigrateZonalPrivateNetworksRequest, - marshal_SetSubnetsRequest, + marshal_SetAclRequest, marshal_UpdatePrivateNetworkRequest, + marshal_UpdateRouteRequest, marshal_UpdateVPCRequest, ) class VpcV2API(API): """ - VPC API. + This API allows you to manage your Virtual Private Clouds (VPCs) and Private Networks. """ def list_vp_cs( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListVPCsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -77,7 +89,7 @@ def list_vp_cs( :param page: Page number to return, from the paginated results. :param page_size: Maximum number of VPCs to return per page. :param name: Name to filter for. Only VPCs with names containing this string will be returned. - :param tags: Tags to filter for. Only VPCs with one more more matching tags will be returned. + :param tags: Tags to filter for. Only VPCs with one or more matching tags will be returned. :param organization_id: Organization ID to filter for. Only VPCs belonging to this Organization will be returned. :param project_id: Project ID to filter for. Only VPCs belonging to this Project will be returned. :param is_default: Defines whether to filter only for VPCs which are the default one for their Project. @@ -117,7 +129,7 @@ def list_vp_cs( def list_vp_cs_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListVPCsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -136,7 +148,7 @@ def list_vp_cs_all( :param page: Page number to return, from the paginated results. :param page_size: Maximum number of VPCs to return per page. :param name: Name to filter for. Only VPCs with names containing this string will be returned. - :param tags: Tags to filter for. Only VPCs with one more more matching tags will be returned. + :param tags: Tags to filter for. Only VPCs with one or more matching tags will be returned. :param organization_id: Organization ID to filter for. Only VPCs belonging to this Organization will be returned. :param project_id: Project ID to filter for. Only VPCs belonging to this Project will be returned. :param is_default: Defines whether to filter only for VPCs which are the default one for their Project. @@ -171,7 +183,7 @@ def create_vpc( self, *, enable_routing: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, @@ -220,7 +232,7 @@ def get_vpc( self, *, vpc_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> VPC: """ Get a VPC. @@ -254,7 +266,7 @@ def update_vpc( self, *, vpc_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, ) -> VPC: @@ -301,7 +313,7 @@ def delete_vpc( self, *, vpc_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a VPC. @@ -332,7 +344,7 @@ def delete_vpc( def list_private_networks( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -394,7 +406,7 @@ def list_private_networks( def list_private_networks_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListPrivateNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -450,7 +462,8 @@ def list_private_networks_all( def create_private_network( self, *, - region: Optional[Region] = None, + default_route_propagation_enabled: bool, + region: Optional[ScwRegion] = None, name: Optional[str] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, @@ -460,6 +473,7 @@ def create_private_network( """ Create a Private Network. Create a new Private Network. Once created, you can attach Scaleway resources which are in the same region. + :param default_route_propagation_enabled: Defines whether default v4 and v6 routes are propagated for this Private Network. :param region: Region to target. If none is passed will use default region from the config. :param name: Name for the Private Network. :param project_id: Scaleway Project in which to create the Private Network. @@ -471,7 +485,9 @@ def create_private_network( Usage: :: - result = api.create_private_network() + result = api.create_private_network( + default_route_propagation_enabled=False, + ) """ param_region = validate_path_param( @@ -483,6 +499,7 @@ def create_private_network( f"/vpc/v2/regions/{param_region}/private-networks", body=marshal_CreatePrivateNetworkRequest( CreatePrivateNetworkRequest( + default_route_propagation_enabled=default_route_propagation_enabled, region=region, name=name or random_name(prefix="pn"), project_id=project_id, @@ -501,7 +518,7 @@ def get_private_network( self, *, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> PrivateNetwork: """ Get a Private Network. @@ -537,9 +554,10 @@ def update_private_network( self, *, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, + default_route_propagation_enabled: Optional[bool] = None, ) -> PrivateNetwork: """ Update Private Network. @@ -548,6 +566,7 @@ def update_private_network( :param region: Region to target. If none is passed will use default region from the config. :param name: Name for the Private Network. :param tags: Tags for the Private Network. + :param default_route_propagation_enabled: Defines whether default v4 and v6 routes are propagated for this Private Network. :return: :class:`PrivateNetwork ` Usage: @@ -574,6 +593,7 @@ def update_private_network( region=region, name=name, tags=tags, + default_route_propagation_enabled=default_route_propagation_enabled, ), self.client, ), @@ -586,7 +606,7 @@ def delete_private_network( self, *, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> None: """ Delete a Private Network. @@ -616,138 +636,183 @@ def delete_private_network( self._throw_on_error(res) - def migrate_zonal_private_networks( + def enable_dhcp( self, *, - region: Optional[Region] = None, - organization_id: Optional[str] = None, - project_id: Optional[str] = None, - private_network_ids: Optional[List[str]] = None, - ) -> None: + private_network_id: str, + region: Optional[ScwRegion] = None, + ) -> PrivateNetwork: """ - Migrate Private Networks from zoned to regional. - Transform multiple existing zoned Private Networks (scoped to a single Availability Zone) into regional Private Networks, scoped to an entire region. You can transform one or many Private Networks (specified by their Private Network IDs) within a single Scaleway Organization or Project, with the same call. + Enable DHCP on a Private Network. + Enable DHCP managed on an existing Private Network. Note that you will not be able to deactivate it afterwards. + :param private_network_id: Private Network ID. :param region: Region to target. If none is passed will use default region from the config. - :param organization_id: Organization ID to target. The specified zoned Private Networks within this Organization will be migrated to regional. - One-Of ('scope'): at most one of 'organization_id', 'project_id' could be set. - :param project_id: Project to target. The specified zoned Private Networks within this Project will be migrated to regional. - One-Of ('scope'): at most one of 'organization_id', 'project_id' could be set. - :param private_network_ids: IDs of the Private Networks to migrate. + :return: :class:`PrivateNetwork ` Usage: :: - result = api.migrate_zonal_private_networks() + result = api.enable_dhcp( + private_network_id="example", + ) """ param_region = validate_path_param( "region", region or self.client.default_region ) + param_private_network_id = validate_path_param( + "private_network_id", private_network_id + ) res = self._request( "POST", - f"/vpc/v2/regions/{param_region}/private-networks/migrate-zonal", - body=marshal_MigrateZonalPrivateNetworksRequest( - MigrateZonalPrivateNetworksRequest( - region=region, - private_network_ids=private_network_ids, - organization_id=organization_id, - project_id=project_id, - ), - self.client, - ), + f"/vpc/v2/regions/{param_region}/private-networks/{param_private_network_id}/enable-dhcp", + body={}, ) self._throw_on_error(res) + return unmarshal_PrivateNetwork(res.json()) - def enable_dhcp( + def enable_routing( self, *, - private_network_id: str, - region: Optional[Region] = None, - ) -> PrivateNetwork: + vpc_id: str, + region: Optional[ScwRegion] = None, + ) -> VPC: """ - Enable DHCP on a Private Network. - Enable DHCP managed on an existing Private Network. Note that you will not be able to deactivate it afterwards. - :param private_network_id: Private Network ID. + Enable routing on a VPC. + Enable routing on an existing VPC. Note that you will not be able to deactivate it afterwards. + :param vpc_id: VPC ID. :param region: Region to target. If none is passed will use default region from the config. - :return: :class:`PrivateNetwork ` + :return: :class:`VPC ` Usage: :: - result = api.enable_dhcp( - private_network_id="example", + result = api.enable_routing( + vpc_id="example", ) """ param_region = validate_path_param( "region", region or self.client.default_region ) - param_private_network_id = validate_path_param( - "private_network_id", private_network_id - ) + param_vpc_id = validate_path_param("vpc_id", vpc_id) res = self._request( "POST", - f"/vpc/v2/regions/{param_region}/private-networks/{param_private_network_id}/enable-dhcp", + f"/vpc/v2/regions/{param_region}/vpcs/{param_vpc_id}/enable-routing", body={}, ) self._throw_on_error(res) - return unmarshal_PrivateNetwork(res.json()) + return unmarshal_VPC(res.json()) - def set_subnets( + def list_subnets( self, *, - private_network_id: str, - region: Optional[Region] = None, - subnets: Optional[List[str]] = None, - ) -> SetSubnetsResponse: + region: Optional[ScwRegion] = None, + order_by: Optional[ListSubnetsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + subnet_ids: Optional[List[str]] = None, + vpc_id: Optional[str] = None, + ) -> ListSubnetsResponse: """ - Set the subnets of a Private Network. - Set subnets for an existing Private Network. Note that the method is PUT and not PATCH. Any existing subnets will be removed in favor of the new specified set of subnets. - :param private_network_id: Private Network ID. + List subnets. + List any Private Network's subnets. See ListPrivateNetworks to list a specific Private Network's subnets. :param region: Region to target. If none is passed will use default region from the config. - :param subnets: Private Network subnets CIDR. - :return: :class:`SetSubnetsResponse ` + :param order_by: Sort order of the returned subnets. + :param page: Page number to return, from the paginated results. + :param page_size: Maximum number of Private Networks to return per page. + :param organization_id: Organization ID to filter for. Only subnets belonging to this Organization will be returned. + :param project_id: Project ID to filter for. Only subnets belonging to this Project will be returned. + :param subnet_ids: Subnet IDs to filter for. Only subnets matching the specified IDs will be returned. + :param vpc_id: VPC ID to filter for. Only subnets belonging to this VPC will be returned. + :return: :class:`ListSubnetsResponse ` Usage: :: - result = api.set_subnets( - private_network_id="example", - ) + result = api.list_subnets() """ param_region = validate_path_param( "region", region or self.client.default_region ) - param_private_network_id = validate_path_param( - "private_network_id", private_network_id - ) res = self._request( - "PUT", - f"/vpc/v2/regions/{param_region}/private-networks/{param_private_network_id}/subnets", - body=marshal_SetSubnetsRequest( - SetSubnetsRequest( - private_network_id=private_network_id, - region=region, - subnets=subnets, - ), - self.client, - ), + "GET", + f"/vpc/v2/regions/{param_region}/subnets", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "subnet_ids": subnet_ids, + "vpc_id": vpc_id, + }, ) self._throw_on_error(res) - return unmarshal_SetSubnetsResponse(res.json()) + return unmarshal_ListSubnetsResponse(res.json()) + + def list_subnets_all( + self, + *, + region: Optional[ScwRegion] = None, + order_by: Optional[ListSubnetsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + subnet_ids: Optional[List[str]] = None, + vpc_id: Optional[str] = None, + ) -> List[Subnet]: + """ + List subnets. + List any Private Network's subnets. See ListPrivateNetworks to list a specific Private Network's subnets. + :param region: Region to target. If none is passed will use default region from the config. + :param order_by: Sort order of the returned subnets. + :param page: Page number to return, from the paginated results. + :param page_size: Maximum number of Private Networks to return per page. + :param organization_id: Organization ID to filter for. Only subnets belonging to this Organization will be returned. + :param project_id: Project ID to filter for. Only subnets belonging to this Project will be returned. + :param subnet_ids: Subnet IDs to filter for. Only subnets matching the specified IDs will be returned. + :param vpc_id: VPC ID to filter for. Only subnets belonging to this VPC will be returned. + :return: :class:`List[Subnet] ` + + Usage: + :: + + result = api.list_subnets_all() + """ + + return fetch_all_pages( + type=ListSubnetsResponse, + key="subnets", + fetcher=self.list_subnets, + args={ + "region": region, + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "subnet_ids": subnet_ids, + "vpc_id": vpc_id, + }, + ) def add_subnets( self, *, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, subnets: Optional[List[str]] = None, ) -> AddSubnetsResponse: """ @@ -793,7 +858,7 @@ def delete_subnets( self, *, private_network_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, subnets: Optional[List[str]] = None, ) -> DeleteSubnetsResponse: """ @@ -834,3 +899,275 @@ def delete_subnets( self._throw_on_error(res) return unmarshal_DeleteSubnetsResponse(res.json()) + + def create_route( + self, + *, + description: str, + vpc_id: str, + destination: str, + region: Optional[ScwRegion] = None, + tags: Optional[List[str]] = None, + nexthop_resource_id: Optional[str] = None, + nexthop_private_network_id: Optional[str] = None, + ) -> Route: + """ + Create a Route. + Create a new custom Route. + :param description: Route description. + :param vpc_id: VPC the Route belongs to. + :param destination: Destination of the Route. + :param region: Region to target. If none is passed will use default region from the config. + :param tags: Tags of the Route. + :param nexthop_resource_id: ID of the nexthop resource. + :param nexthop_private_network_id: ID of the nexthop private network. + :return: :class:`Route ` + + Usage: + :: + + result = api.create_route( + description="example", + vpc_id="example", + destination="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/vpc/v2/regions/{param_region}/routes", + body=marshal_CreateRouteRequest( + CreateRouteRequest( + description=description, + vpc_id=vpc_id, + destination=destination, + region=region, + tags=tags, + nexthop_resource_id=nexthop_resource_id, + nexthop_private_network_id=nexthop_private_network_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Route(res.json()) + + def get_route( + self, + *, + route_id: str, + region: Optional[ScwRegion] = None, + ) -> Route: + """ + Get a Route. + Retrieve details of an existing Route, specified by its Route ID. + :param route_id: Route ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Route ` + + Usage: + :: + + result = api.get_route( + route_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_route_id = validate_path_param("route_id", route_id) + + res = self._request( + "GET", + f"/vpc/v2/regions/{param_region}/routes/{param_route_id}", + ) + + self._throw_on_error(res) + return unmarshal_Route(res.json()) + + def update_route( + self, + *, + route_id: str, + region: Optional[ScwRegion] = None, + description: Optional[str] = None, + tags: Optional[List[str]] = None, + destination: Optional[str] = None, + nexthop_resource_id: Optional[str] = None, + nexthop_private_network_id: Optional[str] = None, + ) -> Route: + """ + Update Route. + Update parameters of the specified Route. + :param route_id: Route ID. + :param region: Region to target. If none is passed will use default region from the config. + :param description: Route description. + :param tags: Tags of the Route. + :param destination: Destination of the Route. + :param nexthop_resource_id: ID of the nexthop resource. + :param nexthop_private_network_id: ID of the nexthop private network. + :return: :class:`Route ` + + Usage: + :: + + result = api.update_route( + route_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_route_id = validate_path_param("route_id", route_id) + + res = self._request( + "PATCH", + f"/vpc/v2/regions/{param_region}/routes/{param_route_id}", + body=marshal_UpdateRouteRequest( + UpdateRouteRequest( + route_id=route_id, + region=region, + description=description, + tags=tags, + destination=destination, + nexthop_resource_id=nexthop_resource_id, + nexthop_private_network_id=nexthop_private_network_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Route(res.json()) + + def delete_route( + self, + *, + route_id: str, + region: Optional[ScwRegion] = None, + ) -> None: + """ + Delete a Route. + Delete a Route specified by its Route ID. + :param route_id: Route ID. + :param region: Region to target. If none is passed will use default region from the config. + + Usage: + :: + + result = api.delete_route( + route_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_route_id = validate_path_param("route_id", route_id) + + res = self._request( + "DELETE", + f"/vpc/v2/regions/{param_region}/routes/{param_route_id}", + ) + + self._throw_on_error(res) + + def get_acl( + self, + *, + vpc_id: str, + is_ipv6: bool, + region: Optional[ScwRegion] = None, + ) -> GetAclResponse: + """ + Get ACL Rules for VPC. + Retrieve a list of ACL rules for a VPC, specified by its VPC ID. + :param vpc_id: ID of the Network ACL's VPC. + :param is_ipv6: Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`GetAclResponse ` + + Usage: + :: + + result = api.get_acl( + vpc_id="example", + is_ipv6=False, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_vpc_id = validate_path_param("vpc_id", vpc_id) + + res = self._request( + "GET", + f"/vpc/v2/regions/{param_region}/vpcs/{param_vpc_id}/acl-rules", + params={ + "is_ipv6": is_ipv6, + }, + ) + + self._throw_on_error(res) + return unmarshal_GetAclResponse(res.json()) + + def set_acl( + self, + *, + vpc_id: str, + rules: List[AclRule], + is_ipv6: bool, + default_policy: Action, + region: Optional[ScwRegion] = None, + ) -> SetAclResponse: + """ + Set VPC ACL rules. + Set the list of ACL rules and the default routing policy for a VPC. + :param vpc_id: ID of the Network ACL's VPC. + :param rules: List of Network ACL rules. + :param is_ipv6: Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + :param default_policy: Action to take for packets which do not match any rules. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`SetAclResponse ` + + Usage: + :: + + result = api.set_acl( + vpc_id="example", + rules=[], + is_ipv6=False, + default_policy=Action.unknown_action, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_vpc_id = validate_path_param("vpc_id", vpc_id) + + res = self._request( + "PUT", + f"/vpc/v2/regions/{param_region}/vpcs/{param_vpc_id}/acl-rules", + body=marshal_SetAclRequest( + SetAclRequest( + vpc_id=vpc_id, + rules=rules, + is_ipv6=is_ipv6, + default_policy=default_policy, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetAclResponse(res.json()) diff --git a/scaleway/scaleway/vpc/v2/marshalling.py b/scaleway/scaleway/vpc/v2/marshalling.py index 760ec692..9229bba7 100644 --- a/scaleway/scaleway/vpc/v2/marshalling.py +++ b/scaleway/scaleway/vpc/v2/marshalling.py @@ -5,26 +5,27 @@ from dateutil import parser from scaleway_core.profile import ProfileDefaults -from scaleway_core.utils import ( - OneOfPossibility, - resolve_one_of, -) from .types import ( Subnet, PrivateNetwork, + Route, VPC, AddSubnetsResponse, DeleteSubnetsResponse, + AclRule, + GetAclResponse, ListPrivateNetworksResponse, + ListSubnetsResponse, ListVPCsResponse, - SetSubnetsResponse, + SetAclResponse, AddSubnetsRequest, CreatePrivateNetworkRequest, + CreateRouteRequest, CreateVPCRequest, DeleteSubnetsRequest, - MigrateZonalPrivateNetworksRequest, - SetSubnetsRequest, + SetAclRequest, UpdatePrivateNetworkRequest, + UpdateRouteRequest, UpdateVPCRequest, ) @@ -45,13 +46,29 @@ def unmarshal_Subnet(data: Any) -> Subnet: if field is not None: args["subnet"] = field + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + field = data.get("vpc_id", None) + if field is not None: + args["vpc_id"] = field + field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return Subnet(**args) @@ -102,17 +119,88 @@ def unmarshal_PrivateNetwork(data: Any) -> PrivateNetwork: if field is not None: args["dhcp_enabled"] = field + field = data.get("default_route_propagation_enabled", None) + if field is not None: + args["default_route_propagation_enabled"] = field + field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return PrivateNetwork(**args) +def unmarshal_Route(data: Any) -> Route: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Route' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("vpc_id", None) + if field is not None: + args["vpc_id"] = field + + field = data.get("destination", None) + if field is not None: + args["destination"] = field + + field = data.get("is_read_only", None) + if field is not None: + args["is_read_only"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("nexthop_resource_id", None) + if field is not None: + args["nexthop_resource_id"] = field + else: + args["nexthop_resource_id"] = None + + field = data.get("nexthop_private_network_id", None) + if field is not None: + args["nexthop_private_network_id"] = field + else: + args["nexthop_private_network_id"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return Route(**args) + + def unmarshal_VPC(data: Any) -> VPC: if not isinstance(data, dict): raise TypeError( @@ -160,10 +248,14 @@ def unmarshal_VPC(data: Any) -> VPC: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return VPC(**args) @@ -198,6 +290,76 @@ def unmarshal_DeleteSubnetsResponse(data: Any) -> DeleteSubnetsResponse: return DeleteSubnetsResponse(**args) +def unmarshal_AclRule(data: Any) -> AclRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AclRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("protocol", None) + if field is not None: + args["protocol"] = field + + field = data.get("source", None) + if field is not None: + args["source"] = field + + field = data.get("src_port_low", None) + if field is not None: + args["src_port_low"] = field + + field = data.get("src_port_high", None) + if field is not None: + args["src_port_high"] = field + + field = data.get("destination", None) + if field is not None: + args["destination"] = field + + field = data.get("dst_port_low", None) + if field is not None: + args["dst_port_low"] = field + + field = data.get("dst_port_high", None) + if field is not None: + args["dst_port_high"] = field + + field = data.get("action", None) + if field is not None: + args["action"] = field + + field = data.get("description", None) + if field is not None: + args["description"] = field + else: + args["description"] = None + + return AclRule(**args) + + +def unmarshal_GetAclResponse(data: Any) -> GetAclResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GetAclResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("rules", None) + if field is not None: + args["rules"] = ( + [unmarshal_AclRule(v) for v in field] if field is not None else None + ) + + field = data.get("default_policy", None) + if field is not None: + args["default_policy"] = field + + return GetAclResponse(**args) + + def unmarshal_ListPrivateNetworksResponse(data: Any) -> ListPrivateNetworksResponse: if not isinstance(data, dict): raise TypeError( @@ -219,6 +381,27 @@ def unmarshal_ListPrivateNetworksResponse(data: Any) -> ListPrivateNetworksRespo return ListPrivateNetworksResponse(**args) +def unmarshal_ListSubnetsResponse(data: Any) -> ListSubnetsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListSubnetsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("subnets", None) + if field is not None: + args["subnets"] = ( + [unmarshal_Subnet(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListSubnetsResponse(**args) + + def unmarshal_ListVPCsResponse(data: Any) -> ListVPCsResponse: if not isinstance(data, dict): raise TypeError( @@ -238,19 +421,25 @@ def unmarshal_ListVPCsResponse(data: Any) -> ListVPCsResponse: return ListVPCsResponse(**args) -def unmarshal_SetSubnetsResponse(data: Any) -> SetSubnetsResponse: +def unmarshal_SetAclResponse(data: Any) -> SetAclResponse: if not isinstance(data, dict): raise TypeError( - "Unmarshalling the type 'SetSubnetsResponse' failed as data isn't a dictionary." + "Unmarshalling the type 'SetAclResponse' failed as data isn't a dictionary." ) args: Dict[str, Any] = {} - field = data.get("subnets", None) + field = data.get("rules", None) if field is not None: - args["subnets"] = field + args["rules"] = ( + [unmarshal_AclRule(v) for v in field] if field is not None else None + ) + + field = data.get("default_policy", None) + if field is not None: + args["default_policy"] = field - return SetSubnetsResponse(**args) + return SetAclResponse(**args) def marshal_AddSubnetsRequest( @@ -271,6 +460,11 @@ def marshal_CreatePrivateNetworkRequest( ) -> Dict[str, Any]: output: Dict[str, Any] = {} + if request.default_route_propagation_enabled is not None: + output["default_route_propagation_enabled"] = ( + request.default_route_propagation_enabled + ) + if request.name is not None: output["name"] = request.name @@ -289,6 +483,33 @@ def marshal_CreatePrivateNetworkRequest( return output +def marshal_CreateRouteRequest( + request: CreateRouteRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.description is not None: + output["description"] = request.description + + if request.vpc_id is not None: + output["vpc_id"] = request.vpc_id + + if request.destination is not None: + output["destination"] = request.destination + + if request.tags is not None: + output["tags"] = request.tags + + if request.nexthop_resource_id is not None: + output["nexthop_resource_id"] = request.nexthop_resource_id + + if request.nexthop_private_network_id is not None: + output["nexthop_private_network_id"] = request.nexthop_private_network_id + + return output + + def marshal_CreateVPCRequest( request: CreateVPCRequest, defaults: ProfileDefaults, @@ -322,40 +543,56 @@ def marshal_DeleteSubnetsRequest( return output -def marshal_MigrateZonalPrivateNetworksRequest( - request: MigrateZonalPrivateNetworksRequest, +def marshal_AclRule( + request: AclRule, defaults: ProfileDefaults, ) -> Dict[str, Any]: output: Dict[str, Any] = {} - output.update( - resolve_one_of( - [ - OneOfPossibility( - "organization_id", - request.organization_id, - defaults.default_organization_id, - ), - OneOfPossibility( - "project_id", request.project_id, defaults.default_project_id - ), - ] - ), - ) - - if request.private_network_ids is not None: - output["private_network_ids"] = request.private_network_ids + + if request.protocol is not None: + output["protocol"] = str(request.protocol) + + if request.source is not None: + output["source"] = request.source + + if request.src_port_low is not None: + output["src_port_low"] = request.src_port_low + + if request.src_port_high is not None: + output["src_port_high"] = request.src_port_high + + if request.destination is not None: + output["destination"] = request.destination + + if request.dst_port_low is not None: + output["dst_port_low"] = request.dst_port_low + + if request.dst_port_high is not None: + output["dst_port_high"] = request.dst_port_high + + if request.action is not None: + output["action"] = str(request.action) + + if request.description is not None: + output["description"] = request.description return output -def marshal_SetSubnetsRequest( - request: SetSubnetsRequest, +def marshal_SetAclRequest( + request: SetAclRequest, defaults: ProfileDefaults, ) -> Dict[str, Any]: output: Dict[str, Any] = {} - if request.subnets is not None: - output["subnets"] = request.subnets + if request.rules is not None: + output["rules"] = [marshal_AclRule(item, defaults) for item in request.rules] + + if request.is_ipv6 is not None: + output["is_ipv6"] = request.is_ipv6 + + if request.default_policy is not None: + output["default_policy"] = str(request.default_policy) return output @@ -372,6 +609,35 @@ def marshal_UpdatePrivateNetworkRequest( if request.tags is not None: output["tags"] = request.tags + if request.default_route_propagation_enabled is not None: + output["default_route_propagation_enabled"] = ( + request.default_route_propagation_enabled + ) + + return output + + +def marshal_UpdateRouteRequest( + request: UpdateRouteRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.description is not None: + output["description"] = request.description + + if request.tags is not None: + output["tags"] = request.tags + + if request.destination is not None: + output["destination"] = request.destination + + if request.nexthop_resource_id is not None: + output["nexthop_resource_id"] = request.nexthop_resource_id + + if request.nexthop_private_network_id is not None: + output["nexthop_private_network_id"] = request.nexthop_private_network_id + return output diff --git a/scaleway/scaleway/vpc/v2/types.py b/scaleway/scaleway/vpc/v2/types.py index c74e7bd3..09a06570 100644 --- a/scaleway/scaleway/vpc/v2/types.py +++ b/scaleway/scaleway/vpc/v2/types.py @@ -8,13 +8,32 @@ from typing import List, Optional from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, ) +class AclRuleProtocol(str, Enum, metaclass=StrEnumMeta): + ANY = "any" + TCP = "tcp" + UDP = "udp" + ICMP = "icmp" + + def __str__(self) -> str: + return str(self.value) + + +class Action(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + ACCEPT = "accept" + DROP = "drop" + + def __str__(self) -> str: + return str(self.value) + + class ListPrivateNetworksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -25,6 +44,14 @@ def __str__(self) -> str: return str(self.value) +class ListSubnetsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + class ListVPCsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): CREATED_AT_ASC = "created_at_asc" CREATED_AT_DESC = "created_at_desc" @@ -47,6 +74,21 @@ class Subnet: Subnet CIDR. """ + project_id: str + """ + Scaleway Project the subnet belongs to. + """ + + private_network_id: str + """ + Private Network the subnet belongs to. + """ + + vpc_id: str + """ + VPC the subnet belongs to. + """ + created_at: Optional[datetime] """ Subnet creation date. @@ -80,7 +122,7 @@ class PrivateNetwork: Scaleway Project the Private Network belongs to. """ - region: Region + region: ScwRegion """ Region in which the Private Network is available. """ @@ -105,6 +147,11 @@ class PrivateNetwork: Defines whether managed DHCP is enabled for this Private Network. """ + default_route_propagation_enabled: bool + """ + Defines whether default v4 and v6 routes are propagated for this Private Network. + """ + created_at: Optional[datetime] """ Date the Private Network was created. @@ -116,6 +163,112 @@ class PrivateNetwork: """ +@dataclass +class Route: + id: str + """ + Route ID. + """ + + description: str + """ + Route description. + """ + + tags: List[str] + """ + Tags of the Route. + """ + + vpc_id: str + """ + VPC the Route belongs to. + """ + + destination: str + """ + Destination of the Route. + """ + + is_read_only: bool + """ + Defines whether the route can be modified or deleted by the user. + """ + + region: ScwRegion + """ + Region of the Route. + """ + + nexthop_resource_id: Optional[str] + """ + ID of the nexthop resource. + """ + + nexthop_private_network_id: Optional[str] + """ + ID of the nexthop private network. + """ + + created_at: Optional[datetime] + """ + Date the Route was created. + """ + + updated_at: Optional[datetime] + """ + Date the Route was last modified. + """ + + +@dataclass +class AclRule: + protocol: AclRuleProtocol + """ + Protocol to which this rule applies. + """ + + source: str + """ + Source IP range to which this rule applies (CIDR notation with subnet mask). + """ + + src_port_low: int + """ + Starting port of the source port range to which this rule applies (inclusive). + """ + + src_port_high: int + """ + Ending port of the source port range to which this rule applies (inclusive). + """ + + destination: str + """ + Destination IP range to which this rule applies (CIDR notation with subnet mask). + """ + + dst_port_low: int + """ + Starting port of the destination port range to which this rule applies (inclusive). + """ + + dst_port_high: int + """ + Ending port of the destination port range to which this rule applies (inclusive). + """ + + action: Action + """ + Policy to apply to the packet. + """ + + description: Optional[str] + """ + Rule description. + """ + + @dataclass class VPC: id: str @@ -138,7 +291,7 @@ class VPC: Scaleway Project the VPC belongs to. """ - region: Region + region: ScwRegion """ Region of the VPC. """ @@ -181,7 +334,7 @@ class AddSubnetsRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -199,7 +352,12 @@ class AddSubnetsResponse: @dataclass class CreatePrivateNetworkRequest: - region: Optional[Region] + default_route_propagation_enabled: bool + """ + Defines whether default v4 and v6 routes are propagated for this Private Network. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -230,6 +388,44 @@ class CreatePrivateNetworkRequest: """ +@dataclass +class CreateRouteRequest: + description: str + """ + Route description. + """ + + vpc_id: str + """ + VPC the Route belongs to. + """ + + destination: str + """ + Destination of the Route. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + tags: Optional[List[str]] + """ + Tags of the Route. + """ + + nexthop_resource_id: Optional[str] + """ + ID of the nexthop resource. + """ + + nexthop_private_network_id: Optional[str] + """ + ID of the nexthop private network. + """ + + @dataclass class CreateVPCRequest: enable_routing: bool @@ -237,7 +433,7 @@ class CreateVPCRequest: Enable routing between Private Networks in the VPC. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -265,7 +461,20 @@ class DeletePrivateNetworkRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DeleteRouteRequest: + route_id: str + """ + Route ID. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -278,7 +487,7 @@ class DeleteSubnetsRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -301,7 +510,7 @@ class DeleteVPCRequest: VPC ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -314,12 +523,50 @@ class EnableDHCPRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class EnableRoutingRequest: + vpc_id: str + """ + VPC ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetAclRequest: + vpc_id: str + """ + ID of the Network ACL's VPC. + """ + + is_ipv6: bool + """ + Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetAclResponse: + rules: List[AclRule] + + default_policy: Action + + @dataclass class GetPrivateNetworkRequest: private_network_id: str @@ -327,7 +574,20 @@ class GetPrivateNetworkRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class GetRouteRequest: + route_id: str + """ + Route ID. + """ + + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -340,7 +600,7 @@ class GetVPCRequest: VPC ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -348,7 +608,7 @@ class GetVPCRequest: @dataclass class ListPrivateNetworksRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -411,9 +671,59 @@ class ListPrivateNetworksResponse: total_count: int +@dataclass +class ListSubnetsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + order_by: Optional[ListSubnetsRequestOrderBy] + """ + Sort order of the returned subnets. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] + """ + Maximum number of Private Networks to return per page. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for. Only subnets belonging to this Organization will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for. Only subnets belonging to this Project will be returned. + """ + + subnet_ids: Optional[List[str]] + """ + Subnet IDs to filter for. Only subnets matching the specified IDs will be returned. + """ + + vpc_id: Optional[str] + """ + VPC ID to filter for. Only subnets belonging to this VPC will be returned. + """ + + +@dataclass +class ListSubnetsResponse: + subnets: List[Subnet] + + total_count: int + + @dataclass class ListVPCsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -440,7 +750,7 @@ class ListVPCsRequest: tags: Optional[List[str]] """ - Tags to filter for. Only VPCs with one more more matching tags will be returned. + Tags to filter for. Only VPCs with one or more matching tags will be returned. """ organization_id: Optional[str] @@ -472,43 +782,38 @@ class ListVPCsResponse: @dataclass -class MigrateZonalPrivateNetworksRequest: - region: Optional[Region] +class SetAclRequest: + vpc_id: str """ - Region to target. If none is passed will use default region from the config. + ID of the Network ACL's VPC. """ - private_network_ids: Optional[List[str]] + rules: List[AclRule] """ - IDs of the Private Networks to migrate. + List of Network ACL rules. """ - organization_id: Optional[str] - - project_id: Optional[str] - - -@dataclass -class SetSubnetsRequest: - private_network_id: str + is_ipv6: bool """ - Private Network ID. + Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type. """ - region: Optional[Region] + default_policy: Action """ - Region to target. If none is passed will use default region from the config. + Action to take for packets which do not match any rules. """ - subnets: Optional[List[str]] + region: Optional[ScwRegion] """ - Private Network subnets CIDR. + Region to target. If none is passed will use default region from the config. """ @dataclass -class SetSubnetsResponse: - subnets: List[str] +class SetAclResponse: + rules: List[AclRule] + + default_policy: Action @dataclass @@ -518,7 +823,7 @@ class UpdatePrivateNetworkRequest: Private Network ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -533,6 +838,49 @@ class UpdatePrivateNetworkRequest: Tags for the Private Network. """ + default_route_propagation_enabled: Optional[bool] + """ + Defines whether default v4 and v6 routes are propagated for this Private Network. + """ + + +@dataclass +class UpdateRouteRequest: + route_id: str + """ + Route ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + description: Optional[str] + """ + Route description. + """ + + tags: Optional[List[str]] + """ + Tags of the Route. + """ + + destination: Optional[str] + """ + Destination of the Route. + """ + + nexthop_resource_id: Optional[str] + """ + ID of the nexthop resource. + """ + + nexthop_private_network_id: Optional[str] + """ + ID of the nexthop private network. + """ + @dataclass class UpdateVPCRequest: @@ -541,7 +889,7 @@ class UpdateVPCRequest: VPC ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/scaleway/vpcgw/v1/__init__.py b/scaleway/scaleway/vpcgw/v1/__init__.py index d02eb818..99525258 100644 --- a/scaleway/scaleway/vpcgw/v1/__init__.py +++ b/scaleway/scaleway/vpcgw/v1/__init__.py @@ -57,6 +57,7 @@ from .types import ListIPsResponse from .types import ListPATRulesRequest from .types import ListPATRulesResponse +from .types import MigrateToV2Request from .types import RefreshSSHKeysRequest from .types import SetDHCPEntriesRequest from .types import SetDHCPEntriesResponse @@ -129,6 +130,7 @@ "ListIPsResponse", "ListPATRulesRequest", "ListPATRulesResponse", + "MigrateToV2Request", "RefreshSSHKeysRequest", "SetDHCPEntriesRequest", "SetDHCPEntriesResponse", diff --git a/scaleway/scaleway/vpcgw/v1/api.py b/scaleway/scaleway/vpcgw/v1/api.py index 0f719e58..17073244 100644 --- a/scaleway/scaleway/vpcgw/v1/api.py +++ b/scaleway/scaleway/vpcgw/v1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( WaitForOptions, @@ -58,6 +58,7 @@ UpdateGatewayRequest, UpdateIPRequest, UpdatePATRuleRequest, + UpgradeGatewayRequest, ) from .content import ( GATEWAY_NETWORK_TRANSIENT_STATUSES, @@ -93,18 +94,19 @@ marshal_UpdateGatewayRequest, marshal_UpdateIPRequest, marshal_UpdatePATRuleRequest, + marshal_UpgradeGatewayRequest, ) class VpcgwV1API(API): """ - Public Gateways API. + This API allows you to manage your Public Gateways. """ def list_gateways( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListGatewaysRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -131,6 +133,7 @@ def list_gateways( :param status: Filter for gateways with this current status. Use `unknown` to include all statuses. :param private_network_id: Filter for gateways attached to this Private nNetwork. :return: :class:`ListGatewaysResponse ` + :deprecated Usage: :: @@ -164,7 +167,7 @@ def list_gateways( def list_gateways_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListGatewaysRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -191,6 +194,7 @@ def list_gateways_all( :param status: Filter for gateways with this current status. Use `unknown` to include all statuses. :param private_network_id: Filter for gateways attached to this Private nNetwork. :return: :class:`List[Gateway] ` + :deprecated Usage: :: @@ -221,7 +225,7 @@ def get_gateway( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Gateway: """ Get a Public Gateway. @@ -229,6 +233,7 @@ def get_gateway( :param gateway_id: ID of the gateway to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`Gateway ` + :deprecated Usage: :: @@ -253,7 +258,7 @@ def wait_for_gateway( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[Gateway, bool]] = None, ) -> Gateway: """ @@ -262,6 +267,7 @@ def wait_for_gateway( :param gateway_id: ID of the gateway to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`Gateway ` + :deprecated Usage: :: @@ -292,7 +298,7 @@ def create_gateway( type_: str, enable_smtp: bool, enable_bastion: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project_id: Optional[str] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, @@ -314,6 +320,7 @@ def create_gateway( :param ip_id: Existing IP address to attach to the gateway. :param bastion_port: Port of the SSH bastion. :return: :class:`Gateway ` + :deprecated Usage: :: @@ -354,7 +361,7 @@ def update_gateway( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, name: Optional[str] = None, tags: Optional[List[str]] = None, upstream_dns_servers: Optional[List[str]] = None, @@ -374,6 +381,7 @@ def update_gateway( :param bastion_port: Port of the SSH bastion. :param enable_smtp: Defines whether SMTP traffic should be allowed to pass through the gateway. :return: :class:`Gateway ` + :deprecated Usage: :: @@ -412,7 +420,7 @@ def delete_gateway( *, gateway_id: str, cleanup_dhcp: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a Public Gateway. @@ -420,6 +428,7 @@ def delete_gateway( :param gateway_id: ID of the gateway to delete. :param cleanup_dhcp: Defines whether to clean up attached DHCP configurations (if any, and if not attached to another Gateway Network). :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -447,14 +456,17 @@ def upgrade_gateway( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, + type_: Optional[str] = None, ) -> Gateway: """ - Upgrade a Public Gateway to the latest version. - Upgrade a given Public Gateway to the newest software version. This applies the latest bugfixes and features to your Public Gateway, but its service will be interrupted during the update. + Upgrade a Public Gateway to the latest version and/or to a different commercial offer type. + Upgrade a given Public Gateway to the newest software version or to a different commercial offer type. This applies the latest bugfixes and features to your Public Gateway. Note that gateway service will be interrupted during the update. :param gateway_id: ID of the gateway to upgrade. :param zone: Zone to target. If none is passed will use default zone from the config. + :param type_: Gateway type (commercial offer). :return: :class:`Gateway ` + :deprecated Usage: :: @@ -470,7 +482,14 @@ def upgrade_gateway( res = self._request( "POST", f"/vpc-gw/v1/zones/{param_zone}/gateways/{param_gateway_id}/upgrade", - body={}, + body=marshal_UpgradeGatewayRequest( + UpgradeGatewayRequest( + gateway_id=gateway_id, + zone=zone, + type_=type_, + ), + self.client, + ), ) self._throw_on_error(res) @@ -480,13 +499,14 @@ def enable_ip_mobility( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Upgrade a Public Gateway to IP mobility. Upgrade a Public Gateway to IP mobility (move from NAT IP to routed IP). This is idempotent: repeated calls after the first will return no error but have no effect. :param gateway_id: ID of the gateway to upgrade to IP mobility. :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -510,7 +530,7 @@ def enable_ip_mobility( def list_gateway_networks( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListGatewayNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -533,6 +553,7 @@ def list_gateway_networks( :param dhcp_id: Filter for GatewayNetworks using this DHCP configuration. :param status: Filter for GatewayNetworks with this current status this status. Use `unknown` to include all statuses. :return: :class:`ListGatewayNetworksResponse ` + :deprecated Usage: :: @@ -563,7 +584,7 @@ def list_gateway_networks( def list_gateway_networks_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListGatewayNetworksRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -586,6 +607,7 @@ def list_gateway_networks_all( :param dhcp_id: Filter for GatewayNetworks using this DHCP configuration. :param status: Filter for GatewayNetworks with this current status this status. Use `unknown` to include all statuses. :return: :class:`List[GatewayNetwork] ` + :deprecated Usage: :: @@ -614,7 +636,7 @@ def get_gateway_network( self, *, gateway_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> GatewayNetwork: """ Get a Public Gateway connection to a Private Network. @@ -622,6 +644,7 @@ def get_gateway_network( :param gateway_network_id: ID of the GatewayNetwork to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`GatewayNetwork ` + :deprecated Usage: :: @@ -648,7 +671,7 @@ def wait_for_gateway_network( self, *, gateway_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, options: Optional[WaitForOptions[GatewayNetwork, bool]] = None, ) -> GatewayNetwork: """ @@ -657,6 +680,7 @@ def wait_for_gateway_network( :param gateway_network_id: ID of the GatewayNetwork to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`GatewayNetwork ` + :deprecated Usage: :: @@ -689,7 +713,7 @@ def create_gateway_network( gateway_id: str, private_network_id: str, enable_masquerade: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, enable_dhcp: Optional[bool] = None, dhcp_id: Optional[str] = None, dhcp: Optional[CreateDHCPRequest] = None, @@ -709,11 +733,12 @@ def create_gateway_network( One-Of ('ip_config'): at most one of 'dhcp_id', 'dhcp', 'address', 'ipam_config' could be set. :param dhcp: New DHCP configuration object to use for this GatewayNetwork. One-Of ('ip_config'): at most one of 'dhcp_id', 'dhcp', 'address', 'ipam_config' could be set. - :param address: Static IP address in CIDR format to to use without DHCP. + :param address: Static IP address in CIDR format to use without DHCP. One-Of ('ip_config'): at most one of 'dhcp_id', 'dhcp', 'address', 'ipam_config' could be set. :param ipam_config: Note: all or none of the GatewayNetworks for a single gateway can use the IPAM. DHCP and IPAM configurations cannot be mixed. Some products may require that the Public Gateway uses the IPAM, to ensure correct functionality. One-Of ('ip_config'): at most one of 'dhcp_id', 'dhcp', 'address', 'ipam_config' could be set. :return: :class:`GatewayNetwork ` + :deprecated Usage: :: @@ -753,7 +778,7 @@ def update_gateway_network( self, *, gateway_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, enable_masquerade: Optional[bool] = None, enable_dhcp: Optional[bool] = None, dhcp_id: Optional[str] = None, @@ -775,6 +800,7 @@ def update_gateway_network( :param ipam_config: Note: all or none of the GatewayNetworks for a single gateway can use the IPAM. DHCP and IPAM configurations cannot be mixed. Some products may require that the Public Gateway uses the IPAM, to ensure correct functionality. One-Of ('ip_config'): at most one of 'dhcp_id', 'address', 'ipam_config' could be set. :return: :class:`GatewayNetwork ` + :deprecated Usage: :: @@ -814,7 +840,7 @@ def delete_gateway_network( *, gateway_network_id: str, cleanup_dhcp: bool, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Detach a Public Gateway from a Private Network. @@ -822,6 +848,7 @@ def delete_gateway_network( :param gateway_network_id: ID of the GatewayNetwork to delete. :param cleanup_dhcp: Defines whether to clean up attached DHCP configurations (if any, and if not attached to another Gateway Network). :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -850,7 +877,7 @@ def delete_gateway_network( def list_dhc_ps( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListDHCPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -871,6 +898,7 @@ def list_dhc_ps( :param address: Filter for DHCP configuration objects with this DHCP server IP address (the gateway's address in the Private Network). :param has_address: Filter for DHCP configuration objects with subnets containing this IP address. :return: :class:`ListDHCPsResponse ` + :deprecated Usage: :: @@ -901,7 +929,7 @@ def list_dhc_ps( def list_dhc_ps_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListDHCPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -922,6 +950,7 @@ def list_dhc_ps_all( :param address: Filter for DHCP configuration objects with this DHCP server IP address (the gateway's address in the Private Network). :param has_address: Filter for DHCP configuration objects with subnets containing this IP address. :return: :class:`List[DHCP] ` + :deprecated Usage: :: @@ -949,7 +978,7 @@ def get_dhcp( self, *, dhcp_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> DHCP: """ Get a DHCP configuration. @@ -957,6 +986,7 @@ def get_dhcp( :param dhcp_id: ID of the DHCP configuration to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`DHCP ` + :deprecated Usage: :: @@ -981,7 +1011,7 @@ def create_dhcp( self, *, subnet: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project_id: Optional[str] = None, address: Optional[str] = None, pool_low: Optional[str] = None, @@ -1015,6 +1045,7 @@ def create_dhcp( :param dns_search: Array of search paths in addition to the pushed DNS configuration. :param dns_local_name: TLD given to hostnames in the Private Network. Allowed characters are `a-z0-9-.`. Defaults to the slugified Private Network name if created along a GatewayNetwork, or else to `priv`. :return: :class:`DHCP ` + :deprecated Usage: :: @@ -1058,7 +1089,7 @@ def update_dhcp( self, *, dhcp_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, subnet: Optional[str] = None, address: Optional[str] = None, pool_low: Optional[str] = None, @@ -1092,6 +1123,7 @@ def update_dhcp( :param dns_search: Array of search paths in addition to the pushed DNS configuration. :param dns_local_name: TLD given to hostnames in the Private Networks. If an instance with hostname `foo` gets a lease, and this is set to `bar`, `foo.bar` will resolve. Allowed characters are `a-z0-9-.`. :return: :class:`DHCP ` + :deprecated Usage: :: @@ -1136,13 +1168,14 @@ def delete_dhcp( self, *, dhcp_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a DHCP configuration. Delete a DHCP configuration object, identified by its DHCP ID. Note that you cannot delete a DHCP configuration object that is currently being used by a Gateway Network. :param dhcp_id: DHCP configuration ID to delete. :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -1165,7 +1198,7 @@ def delete_dhcp( def list_dhcp_entries( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListDHCPEntriesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1188,6 +1221,7 @@ def list_dhcp_entries( :param hostname: Filter for entries with this hostname substring. :param type_: Filter for entries of this type. :return: :class:`ListDHCPEntriesResponse ` + :deprecated Usage: :: @@ -1218,7 +1252,7 @@ def list_dhcp_entries( def list_dhcp_entries_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListDHCPEntriesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1241,6 +1275,7 @@ def list_dhcp_entries_all( :param hostname: Filter for entries with this hostname substring. :param type_: Filter for entries of this type. :return: :class:`List[DHCPEntry] ` + :deprecated Usage: :: @@ -1269,7 +1304,7 @@ def get_dhcp_entry( self, *, dhcp_entry_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> DHCPEntry: """ Get a DHCP entry. @@ -1277,6 +1312,7 @@ def get_dhcp_entry( :param dhcp_entry_id: ID of the DHCP entry to fetch. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`DHCPEntry ` + :deprecated Usage: :: @@ -1303,7 +1339,7 @@ def create_dhcp_entry( gateway_network_id: str, mac_address: str, ip_address: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> DHCPEntry: """ Create a DHCP entry. @@ -1313,6 +1349,7 @@ def create_dhcp_entry( :param ip_address: IP address to give to the device. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`DHCPEntry ` + :deprecated Usage: :: @@ -1347,7 +1384,7 @@ def update_dhcp_entry( self, *, dhcp_entry_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ip_address: Optional[str] = None, ) -> DHCPEntry: """ @@ -1357,6 +1394,7 @@ def update_dhcp_entry( :param zone: Zone to target. If none is passed will use default zone from the config. :param ip_address: New IP address to give to the device. :return: :class:`DHCPEntry ` + :deprecated Usage: :: @@ -1389,7 +1427,7 @@ def set_dhcp_entries( self, *, gateway_network_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, dhcp_entries: Optional[List[SetDHCPEntriesRequestEntry]] = None, ) -> SetDHCPEntriesResponse: """ @@ -1399,6 +1437,7 @@ def set_dhcp_entries( :param zone: Zone to target. If none is passed will use default zone from the config. :param dhcp_entries: New list of DHCP reservations. :return: :class:`SetDHCPEntriesResponse ` + :deprecated Usage: :: @@ -1430,13 +1469,14 @@ def delete_dhcp_entry( self, *, dhcp_entry_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a DHCP entry. Delete a static DHCP reservation, identified by its DHCP entry ID. Note that you cannot delete DHCP entries of type `lease`, these are deleted automatically when their time-to-live expires. :param dhcp_entry_id: ID of the DHCP entry to delete. :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -1459,7 +1499,7 @@ def delete_dhcp_entry( def list_pat_rules( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListPATRulesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1478,6 +1518,7 @@ def list_pat_rules( :param private_ip: Filter for PAT rules targeting this private ip. :param protocol: Filter for PAT rules with this protocol. :return: :class:`ListPATRulesResponse ` + :deprecated Usage: :: @@ -1506,7 +1547,7 @@ def list_pat_rules( def list_pat_rules_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListPATRulesRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1525,6 +1566,7 @@ def list_pat_rules_all( :param private_ip: Filter for PAT rules targeting this private ip. :param protocol: Filter for PAT rules with this protocol. :return: :class:`List[PATRule] ` + :deprecated Usage: :: @@ -1551,7 +1593,7 @@ def get_pat_rule( self, *, pat_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> PATRule: """ Get a PAT rule. @@ -1559,6 +1601,7 @@ def get_pat_rule( :param pat_rule_id: ID of the PAT rule to get. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`PATRule ` + :deprecated Usage: :: @@ -1586,7 +1629,7 @@ def create_pat_rule( public_port: int, private_ip: str, private_port: int, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, protocol: Optional[PATRuleProtocol] = None, ) -> PATRule: """ @@ -1599,6 +1642,7 @@ def create_pat_rule( :param zone: Zone to target. If none is passed will use default zone from the config. :param protocol: Protocol the rule should apply to. :return: :class:`PATRule ` + :deprecated Usage: :: @@ -1636,7 +1680,7 @@ def update_pat_rule( self, *, pat_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, public_port: Optional[int] = None, private_ip: Optional[str] = None, private_port: Optional[int] = None, @@ -1652,6 +1696,7 @@ def update_pat_rule( :param private_port: Private port to translate to. :param protocol: Protocol the rule should apply to. :return: :class:`PATRule ` + :deprecated Usage: :: @@ -1688,7 +1733,7 @@ def set_pat_rules( *, gateway_id: str, pat_rules: List[SetPATRulesRequestRule], - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> SetPATRulesResponse: """ Set all PAT rules. @@ -1697,6 +1742,7 @@ def set_pat_rules( :param pat_rules: New list of PAT rules. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`SetPATRulesResponse ` + :deprecated Usage: :: @@ -1729,13 +1775,14 @@ def delete_pat_rule( self, *, pat_rule_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete a PAT rule. Delete a PAT rule, identified by its PAT rule ID. This action is irreversible. :param pat_rule_id: ID of the PAT rule to delete. :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -1758,13 +1805,14 @@ def delete_pat_rule( def list_gateway_types( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> ListGatewayTypesResponse: """ List Public Gateway types. List the different Public Gateway commercial offer types available at Scaleway. The response is an array of objects describing the name and technical details of each available gateway type. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`ListGatewayTypesResponse ` + :deprecated Usage: :: @@ -1785,7 +1833,7 @@ def list_gateway_types( def list_i_ps( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1808,6 +1856,7 @@ def list_i_ps( :param reverse: Filter for IP addresses that have a reverse containing this string. :param is_free: Filter based on whether the IP is attached to a gateway or not. :return: :class:`ListIPsResponse ` + :deprecated Usage: :: @@ -1839,7 +1888,7 @@ def list_i_ps( def list_i_ps_all( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, order_by: Optional[ListIPsRequestOrderBy] = None, page: Optional[int] = None, page_size: Optional[int] = None, @@ -1862,6 +1911,7 @@ def list_i_ps_all( :param reverse: Filter for IP addresses that have a reverse containing this string. :param is_free: Filter based on whether the IP is attached to a gateway or not. :return: :class:`List[IP] ` + :deprecated Usage: :: @@ -1890,7 +1940,7 @@ def get_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> IP: """ Get an IP. @@ -1898,6 +1948,7 @@ def get_ip( :param ip_id: ID of the IP address to get. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`IP ` + :deprecated Usage: :: @@ -1921,7 +1972,7 @@ def get_ip( def create_ip( self, *, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, project_id: Optional[str] = None, tags: Optional[List[str]] = None, ) -> IP: @@ -1932,6 +1983,7 @@ def create_ip( :param project_id: Project to create the IP address in. :param tags: Tags to give to the IP address. :return: :class:`IP ` + :deprecated Usage: :: @@ -1961,7 +2013,7 @@ def update_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, tags: Optional[List[str]] = None, reverse: Optional[str] = None, gateway_id: Optional[str] = None, @@ -1975,6 +2027,7 @@ def update_ip( :param reverse: Reverse to set on the address. Empty string to unset. :param gateway_id: Gateway to attach the IP address to. Empty string to detach. :return: :class:`IP ` + :deprecated Usage: :: @@ -2009,13 +2062,14 @@ def delete_ip( self, *, ip_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> None: """ Delete an IP. Delete a flexible IP address from your account. This action is irreversible. :param ip_id: ID of the IP address to delete. :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated Usage: :: @@ -2039,7 +2093,7 @@ def refresh_ssh_keys( self, *, gateway_id: str, - zone: Optional[Zone] = None, + zone: Optional[ScwZone] = None, ) -> Gateway: """ Refresh a Public Gateway's SSH keys. @@ -2047,6 +2101,7 @@ def refresh_ssh_keys( :param gateway_id: ID of the gateway to refresh SSH keys on. :param zone: Zone to target. If none is passed will use default zone from the config. :return: :class:`Gateway ` + :deprecated Usage: :: @@ -2067,3 +2122,35 @@ def refresh_ssh_keys( self._throw_on_error(res) return unmarshal_Gateway(res.json()) + + def migrate_to_v2( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Put a Public Gateway in IPAM mode. + Put a Public Gateway in IPAM mode, so that it can be used with the Public Gateways API v2. This call is idempotent. + :param gateway_id: ID of the gateway to put into IPAM mode. + :param zone: Zone to target. If none is passed will use default zone from the config. + :deprecated + + Usage: + :: + + result = api.migrate_to_v2( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "POST", + f"/vpc-gw/v1/zones/{param_zone}/gateways/{param_gateway_id}/migrate-to-v2", + body={}, + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/vpcgw/v1/marshalling.py b/scaleway/scaleway/vpcgw/v1/marshalling.py index 80c04c1c..ef34334d 100644 --- a/scaleway/scaleway/vpcgw/v1/marshalling.py +++ b/scaleway/scaleway/vpcgw/v1/marshalling.py @@ -45,6 +45,7 @@ UpdateGatewayRequest, UpdateIPRequest, UpdatePATRuleRequest, + UpgradeGatewayRequest, ) @@ -83,10 +84,14 @@ def unmarshal_DHCP(data: Any) -> DHCP: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("pool_high", None) if field is not None: @@ -123,14 +128,20 @@ def unmarshal_DHCP(data: Any) -> DHCP: field = data.get("valid_lifetime", None) if field is not None: args["valid_lifetime"] = field + else: + args["valid_lifetime"] = None field = data.get("renew_timer", None) if field is not None: args["renew_timer"] = field + else: + args["renew_timer"] = None field = data.get("rebind_timer", None) if field is not None: args["rebind_timer"] = field + else: + args["rebind_timer"] = None return DHCP(**args) @@ -177,14 +188,20 @@ def unmarshal_GatewayNetwork(data: Any) -> GatewayNetwork: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("mac_address", None) if field is not None: args["mac_address"] = field + else: + args["mac_address"] = None field = data.get("enable_masquerade", None) if field is not None: @@ -205,14 +222,20 @@ def unmarshal_GatewayNetwork(data: Any) -> GatewayNetwork: field = data.get("dhcp", None) if field is not None: args["dhcp"] = unmarshal_DHCP(field) + else: + args["dhcp"] = None field = data.get("address", None) if field is not None: args["address"] = field + else: + args["address"] = None field = data.get("ipam_config", None) if field is not None: args["ipam_config"] = unmarshal_IpamConfig(field) + else: + args["ipam_config"] = None return GatewayNetwork(**args) @@ -252,18 +275,26 @@ def unmarshal_IP(data: Any) -> IP: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("reverse", None) if field is not None: args["reverse"] = field + else: + args["reverse"] = None field = data.get("gateway_id", None) if field is not None: args["gateway_id"] = field + else: + args["gateway_id"] = None return IP(**args) @@ -296,7 +327,7 @@ def unmarshal_DHCPEntry(data: Any) -> DHCPEntry: if field is not None: args["hostname"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -307,10 +338,14 @@ def unmarshal_DHCPEntry(data: Any) -> DHCPEntry: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return DHCPEntry(**args) @@ -361,14 +396,20 @@ def unmarshal_Gateway(data: Any) -> Gateway: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = unmarshal_GatewayType(field) + else: + args["type_"] = None field = data.get("status", None) if field is not None: @@ -399,14 +440,20 @@ def unmarshal_Gateway(data: Any) -> Gateway: field = data.get("ip", None) if field is not None: args["ip"] = unmarshal_IP(field) + else: + args["ip"] = None field = data.get("version", None) if field is not None: args["version"] = field + else: + args["version"] = None field = data.get("can_upgrade_to", None) if field is not None: args["can_upgrade_to"] = field + else: + args["can_upgrade_to"] = None field = data.get("bastion_port", None) if field is not None: @@ -470,10 +517,14 @@ def unmarshal_PATRule(data: Any) -> PATRule: field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None return PATRule(**args) @@ -1077,3 +1128,15 @@ def marshal_UpdatePATRuleRequest( output["protocol"] = str(request.protocol) return output + + +def marshal_UpgradeGatewayRequest( + request: UpgradeGatewayRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.type_ is not None: + output["type"] = request.type_ + + return output diff --git a/scaleway/scaleway/vpcgw/v1/types.py b/scaleway/scaleway/vpcgw/v1/types.py index 3fa4fd58..bb1c21bd 100644 --- a/scaleway/scaleway/vpcgw/v1/types.py +++ b/scaleway/scaleway/vpcgw/v1/types.py @@ -8,7 +8,7 @@ from typing import List, Optional from scaleway_core.bridge import ( - Zone, + Zone as ScwZone, ) from scaleway_core.utils import ( StrEnumMeta, @@ -208,7 +208,7 @@ class DHCP: TLD given to hostnames in the Private Networks. If an Instance with hostname `foo` gets a lease, and this is set to `bar`, `foo.bar` will resolve. """ - zone: Zone + zone: ScwZone """ Zone of this DHCP configuration. """ @@ -289,7 +289,7 @@ class GatewayNetwork: Defines whether DHCP is enabled on the connected Private Network. """ - zone: Zone + zone: ScwZone """ Zone of the GatewayNetwork connection. """ @@ -322,7 +322,7 @@ class GatewayType: Bandwidth, in bps, of the Public Gateway. This is the public bandwidth to the outer Internet, and the internal bandwidth to each connected Private Networks. """ - zone: Zone + zone: ScwZone """ Zone the Public Gateway type is available in. """ @@ -355,7 +355,7 @@ class IP: The IP address itself. """ - zone: Zone + zone: ScwZone """ Zone of the IP address. """ @@ -388,7 +388,7 @@ class CreateDHCPRequest: Subnet for the DHCP server. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -504,7 +504,7 @@ class DHCPEntry: Entry type, either static (DHCP reservation) or dynamic (DHCP lease). """ - zone: Zone + zone: ScwZone """ Zone of this DHCP entry. """ @@ -617,7 +617,7 @@ class Gateway: Defines whether the gateway uses routed IPs (IP mobility) instead of NAT IPs. """ - zone: Zone + zone: ScwZone """ Zone of the gateway. """ @@ -655,7 +655,7 @@ class PATRule: Protocol the rule applies to. """ - zone: Zone + zone: ScwZone """ Zone of the PAT rule. """ @@ -737,7 +737,7 @@ class CreateDHCPEntryRequest: IP address to give to the device. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -760,7 +760,7 @@ class CreateGatewayNetworkRequest: Note: this setting is ignored when passing `ipam_config`. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -797,7 +797,7 @@ class CreateGatewayRequest: Defines whether SSH bastion should be enabled the gateway. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -835,7 +835,7 @@ class CreateGatewayRequest: @dataclass class CreateIPRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -873,7 +873,7 @@ class CreatePATRuleRequest: Private port to translate to. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -891,7 +891,7 @@ class DeleteDHCPEntryRequest: ID of the DHCP entry to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -904,7 +904,7 @@ class DeleteDHCPRequest: DHCP configuration ID to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -922,7 +922,7 @@ class DeleteGatewayNetworkRequest: Defines whether to clean up attached DHCP configurations (if any, and if not attached to another Gateway Network). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -940,7 +940,7 @@ class DeleteGatewayRequest: Defines whether to clean up attached DHCP configurations (if any, and if not attached to another Gateway Network). """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -953,7 +953,7 @@ class DeleteIPRequest: ID of the IP address to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -966,7 +966,7 @@ class DeletePATRuleRequest: ID of the PAT rule to delete. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -979,7 +979,7 @@ class EnableIPMobilityRequest: ID of the gateway to upgrade to IP mobility. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -992,7 +992,7 @@ class GetDHCPEntryRequest: ID of the DHCP entry to fetch. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1005,7 +1005,7 @@ class GetDHCPRequest: ID of the DHCP configuration to fetch. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1018,7 +1018,7 @@ class GetGatewayNetworkRequest: ID of the GatewayNetwork to fetch. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1031,7 +1031,7 @@ class GetGatewayRequest: ID of the gateway to fetch. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1044,7 +1044,7 @@ class GetIPRequest: ID of the IP address to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1057,7 +1057,7 @@ class GetPATRuleRequest: ID of the PAT rule to get. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1065,7 +1065,7 @@ class GetPATRuleRequest: @dataclass class ListDHCPEntriesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1126,7 +1126,7 @@ class ListDHCPEntriesResponse: @dataclass class ListDHCPsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1182,7 +1182,7 @@ class ListDHCPsResponse: @dataclass class ListGatewayNetworksRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1243,7 +1243,7 @@ class ListGatewayNetworksResponse: @dataclass class ListGatewayTypesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1259,7 +1259,7 @@ class ListGatewayTypesResponse: @dataclass class ListGatewaysRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1330,7 +1330,7 @@ class ListGatewaysResponse: @dataclass class ListIPsRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1391,7 +1391,7 @@ class ListIPsResponse: @dataclass class ListPATRulesRequest: - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1440,6 +1440,19 @@ class ListPATRulesResponse: """ +@dataclass +class MigrateToV2Request: + gateway_id: str + """ + ID of the gateway to put into IPAM mode. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class RefreshSSHKeysRequest: gateway_id: str @@ -1447,7 +1460,7 @@ class RefreshSSHKeysRequest: ID of the gateway to refresh SSH keys on. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1460,7 +1473,7 @@ class SetDHCPEntriesRequest: ID of the Gateway Network on which to set DHCP reservation list. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1491,7 +1504,7 @@ class SetPATRulesRequest: New list of PAT rules. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1512,7 +1525,7 @@ class UpdateDHCPEntryRequest: ID of the DHCP entry to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1530,7 +1543,7 @@ class UpdateDHCPRequest: DHCP configuration to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1608,7 +1621,7 @@ class UpdateGatewayNetworkRequest: ID of the GatewayNetwork to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1638,7 +1651,7 @@ class UpdateGatewayRequest: ID of the gateway to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1681,7 +1694,7 @@ class UpdateIPRequest: ID of the IP address to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1709,7 +1722,7 @@ class UpdatePATRuleRequest: ID of the PAT rule to update. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ @@ -1742,7 +1755,12 @@ class UpgradeGatewayRequest: ID of the gateway to upgrade. """ - zone: Optional[Zone] + zone: Optional[ScwZone] """ Zone to target. If none is passed will use default zone from the config. """ + + type_: Optional[str] + """ + Gateway type (commercial offer). + """ diff --git a/scaleway/scaleway/vpcgw/v2/__init__.py b/scaleway/scaleway/vpcgw/v2/__init__.py new file mode 100644 index 00000000..8856eb50 --- /dev/null +++ b/scaleway/scaleway/vpcgw/v2/__init__.py @@ -0,0 +1,107 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import GatewayNetworkStatus +from .content import GATEWAY_NETWORK_TRANSIENT_STATUSES +from .types import GatewayStatus +from .content import GATEWAY_TRANSIENT_STATUSES +from .types import ListGatewayNetworksRequestOrderBy +from .types import ListGatewaysRequestOrderBy +from .types import ListIPsRequestOrderBy +from .types import ListPatRulesRequestOrderBy +from .types import PatRuleProtocol +from .types import GatewayNetwork +from .types import IP +from .types import GatewayType +from .types import Gateway +from .types import PatRule +from .types import SetPatRulesRequestRule +from .types import AddBastionAllowedIPsRequest +from .types import AddBastionAllowedIPsResponse +from .types import CreateGatewayNetworkRequest +from .types import CreateGatewayRequest +from .types import CreateIPRequest +from .types import CreatePatRuleRequest +from .types import DeleteBastionAllowedIPsRequest +from .types import DeleteGatewayNetworkRequest +from .types import DeleteGatewayRequest +from .types import DeleteIPRequest +from .types import DeletePatRuleRequest +from .types import GetGatewayNetworkRequest +from .types import GetGatewayRequest +from .types import GetIPRequest +from .types import GetPatRuleRequest +from .types import ListGatewayNetworksRequest +from .types import ListGatewayNetworksResponse +from .types import ListGatewayTypesRequest +from .types import ListGatewayTypesResponse +from .types import ListGatewaysRequest +from .types import ListGatewaysResponse +from .types import ListIPsRequest +from .types import ListIPsResponse +from .types import ListPatRulesRequest +from .types import ListPatRulesResponse +from .types import RefreshSSHKeysRequest +from .types import SetBastionAllowedIPsRequest +from .types import SetBastionAllowedIPsResponse +from .types import SetPatRulesRequest +from .types import SetPatRulesResponse +from .types import UpdateGatewayNetworkRequest +from .types import UpdateGatewayRequest +from .types import UpdateIPRequest +from .types import UpdatePatRuleRequest +from .types import UpgradeGatewayRequest +from .api import VpcgwV2API + +__all__ = [ + "GatewayNetworkStatus", + "GATEWAY_NETWORK_TRANSIENT_STATUSES", + "GatewayStatus", + "GATEWAY_TRANSIENT_STATUSES", + "ListGatewayNetworksRequestOrderBy", + "ListGatewaysRequestOrderBy", + "ListIPsRequestOrderBy", + "ListPatRulesRequestOrderBy", + "PatRuleProtocol", + "GatewayNetwork", + "IP", + "GatewayType", + "Gateway", + "PatRule", + "SetPatRulesRequestRule", + "AddBastionAllowedIPsRequest", + "AddBastionAllowedIPsResponse", + "CreateGatewayNetworkRequest", + "CreateGatewayRequest", + "CreateIPRequest", + "CreatePatRuleRequest", + "DeleteBastionAllowedIPsRequest", + "DeleteGatewayNetworkRequest", + "DeleteGatewayRequest", + "DeleteIPRequest", + "DeletePatRuleRequest", + "GetGatewayNetworkRequest", + "GetGatewayRequest", + "GetIPRequest", + "GetPatRuleRequest", + "ListGatewayNetworksRequest", + "ListGatewayNetworksResponse", + "ListGatewayTypesRequest", + "ListGatewayTypesResponse", + "ListGatewaysRequest", + "ListGatewaysResponse", + "ListIPsRequest", + "ListIPsResponse", + "ListPatRulesRequest", + "ListPatRulesResponse", + "RefreshSSHKeysRequest", + "SetBastionAllowedIPsRequest", + "SetBastionAllowedIPsResponse", + "SetPatRulesRequest", + "SetPatRulesResponse", + "UpdateGatewayNetworkRequest", + "UpdateGatewayRequest", + "UpdateIPRequest", + "UpdatePatRuleRequest", + "UpgradeGatewayRequest", + "VpcgwV2API", +] diff --git a/scaleway/scaleway/vpcgw/v2/api.py b/scaleway/scaleway/vpcgw/v2/api.py new file mode 100644 index 00000000..17b846a2 --- /dev/null +++ b/scaleway/scaleway/vpcgw/v2/api.py @@ -0,0 +1,1510 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + WaitForOptions, + random_name, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + GatewayNetworkStatus, + GatewayStatus, + ListGatewayNetworksRequestOrderBy, + ListGatewaysRequestOrderBy, + ListIPsRequestOrderBy, + ListPatRulesRequestOrderBy, + PatRuleProtocol, + AddBastionAllowedIPsRequest, + AddBastionAllowedIPsResponse, + CreateGatewayNetworkRequest, + CreateGatewayRequest, + CreateIPRequest, + CreatePatRuleRequest, + Gateway, + GatewayNetwork, + IP, + ListGatewayNetworksResponse, + ListGatewayTypesResponse, + ListGatewaysResponse, + ListIPsResponse, + ListPatRulesResponse, + PatRule, + SetBastionAllowedIPsRequest, + SetBastionAllowedIPsResponse, + SetPatRulesRequest, + SetPatRulesRequestRule, + SetPatRulesResponse, + UpdateGatewayNetworkRequest, + UpdateGatewayRequest, + UpdateIPRequest, + UpdatePatRuleRequest, + UpgradeGatewayRequest, +) +from .content import ( + GATEWAY_NETWORK_TRANSIENT_STATUSES, + GATEWAY_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_GatewayNetwork, + unmarshal_IP, + unmarshal_Gateway, + unmarshal_PatRule, + unmarshal_AddBastionAllowedIPsResponse, + unmarshal_ListGatewayNetworksResponse, + unmarshal_ListGatewayTypesResponse, + unmarshal_ListGatewaysResponse, + unmarshal_ListIPsResponse, + unmarshal_ListPatRulesResponse, + unmarshal_SetBastionAllowedIPsResponse, + unmarshal_SetPatRulesResponse, + marshal_AddBastionAllowedIPsRequest, + marshal_CreateGatewayNetworkRequest, + marshal_CreateGatewayRequest, + marshal_CreateIPRequest, + marshal_CreatePatRuleRequest, + marshal_SetBastionAllowedIPsRequest, + marshal_SetPatRulesRequest, + marshal_UpdateGatewayNetworkRequest, + marshal_UpdateGatewayRequest, + marshal_UpdateIPRequest, + marshal_UpdatePatRuleRequest, + marshal_UpgradeGatewayRequest, +) + + +class VpcgwV2API(API): + """ + This API allows you to manage your Public Gateways. + """ + + def list_gateways( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListGatewaysRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + types: Optional[List[str]] = None, + status: Optional[List[GatewayStatus]] = None, + private_network_ids: Optional[List[str]] = None, + include_legacy: Optional[bool] = None, + ) -> ListGatewaysResponse: + """ + List Public Gateways. + List Public Gateways in a given Scaleway Organization or Project. By default, results are displayed in ascending order of creation date. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Gateways per page. + :param organization_id: Include only gateways in this Organization. + :param project_id: Include only gateways in this Project. + :param name: Filter for gateways which have this search term in their name. + :param tags: Filter for gateways with these tags. + :param types: Filter for gateways of these types. + :param status: Filter for gateways with these status. Use `unknown` to include all statuses. + :param private_network_ids: Filter for gateways attached to these Private Networks. + :param include_legacy: Include also legacy gateways. + :return: :class:`ListGatewaysResponse ` + + Usage: + :: + + result = api.list_gateways() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/gateways", + params={ + "include_legacy": include_legacy, + "name": name, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "private_network_ids": private_network_ids, + "project_id": project_id or self.client.default_project_id, + "status": status, + "tags": tags, + "types": types, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListGatewaysResponse(res.json()) + + def list_gateways_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListGatewaysRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + types: Optional[List[str]] = None, + status: Optional[List[GatewayStatus]] = None, + private_network_ids: Optional[List[str]] = None, + include_legacy: Optional[bool] = None, + ) -> List[Gateway]: + """ + List Public Gateways. + List Public Gateways in a given Scaleway Organization or Project. By default, results are displayed in ascending order of creation date. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number to return. + :param page_size: Gateways per page. + :param organization_id: Include only gateways in this Organization. + :param project_id: Include only gateways in this Project. + :param name: Filter for gateways which have this search term in their name. + :param tags: Filter for gateways with these tags. + :param types: Filter for gateways of these types. + :param status: Filter for gateways with these status. Use `unknown` to include all statuses. + :param private_network_ids: Filter for gateways attached to these Private Networks. + :param include_legacy: Include also legacy gateways. + :return: :class:`List[Gateway] ` + + Usage: + :: + + result = api.list_gateways_all() + """ + + return fetch_all_pages( + type=ListGatewaysResponse, + key="gateways", + fetcher=self.list_gateways, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "name": name, + "tags": tags, + "types": types, + "status": status, + "private_network_ids": private_network_ids, + "include_legacy": include_legacy, + }, + ) + + def get_gateway( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + ) -> Gateway: + """ + Get a Public Gateway. + Get details of a Public Gateway, specified by its gateway ID. The response object contains full details of the gateway, including its **name**, **type**, **status** and more. + :param gateway_id: ID of the gateway to fetch. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Gateway ` + + Usage: + :: + + result = api.get_gateway( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}", + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + def wait_for_gateway( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[Gateway, bool]] = None, + ) -> Gateway: + """ + Get a Public Gateway. + Get details of a Public Gateway, specified by its gateway ID. The response object contains full details of the gateway, including its **name**, **type**, **status** and more. + :param gateway_id: ID of the gateway to fetch. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Gateway ` + + Usage: + :: + + result = api.get_gateway( + gateway_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in GATEWAY_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_gateway, + options=options, + args={ + "gateway_id": gateway_id, + "zone": zone, + }, + ) + + def create_gateway( + self, + *, + type_: str, + enable_smtp: bool, + enable_bastion: bool, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + ip_id: Optional[str] = None, + bastion_port: Optional[int] = None, + ) -> Gateway: + """ + Create a Public Gateway. + Create a new Public Gateway in the specified Scaleway Project, defining its **name**, **type** and other configuration details such as whether to enable SSH bastion. + :param type_: Gateway type (commercial offer type). + :param enable_smtp: Defines whether SMTP traffic should be allowed pass through the gateway. + :param enable_bastion: Defines whether SSH bastion should be enabled the gateway. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Scaleway Project to create the gateway in. + :param name: Name for the gateway. + :param tags: Tags for the gateway. + :param ip_id: Existing IP address to attach to the gateway. + :param bastion_port: Port of the SSH bastion. + :return: :class:`Gateway ` + + Usage: + :: + + result = api.create_gateway( + type="example", + enable_smtp=False, + enable_bastion=False, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/gateways", + body=marshal_CreateGatewayRequest( + CreateGatewayRequest( + type_=type_, + enable_smtp=enable_smtp, + enable_bastion=enable_bastion, + zone=zone, + project_id=project_id, + name=name or random_name(prefix="gw"), + tags=tags, + ip_id=ip_id, + bastion_port=bastion_port, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + def update_gateway( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + enable_bastion: Optional[bool] = None, + bastion_port: Optional[int] = None, + enable_smtp: Optional[bool] = None, + ) -> Gateway: + """ + Update a Public Gateway. + Update the parameters of an existing Public Gateway, for example, its **name**, **tags**, **SSH bastion configuration**, and **DNS servers**. + :param gateway_id: ID of the gateway to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param name: Name for the gateway. + :param tags: Tags for the gateway. + :param enable_bastion: Defines whether SSH bastion should be enabled the gateway. + :param bastion_port: Port of the SSH bastion. + :param enable_smtp: Defines whether SMTP traffic should be allowed to pass through the gateway. + :return: :class:`Gateway ` + + Usage: + :: + + result = api.update_gateway( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "PATCH", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}", + body=marshal_UpdateGatewayRequest( + UpdateGatewayRequest( + gateway_id=gateway_id, + zone=zone, + name=name, + tags=tags, + enable_bastion=enable_bastion, + bastion_port=bastion_port, + enable_smtp=enable_smtp, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + def delete_gateway( + self, + *, + gateway_id: str, + delete_ip: bool, + zone: Optional[ScwZone] = None, + ) -> Gateway: + """ + Delete a Public Gateway. + Delete an existing Public Gateway, specified by its gateway ID. This action is irreversible. + :param gateway_id: ID of the gateway to delete. + :param delete_ip: Defines whether the PGW's IP should be deleted. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Gateway ` + + Usage: + :: + + result = api.delete_gateway( + gateway_id="example", + delete_ip=False, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "DELETE", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}", + params={ + "delete_ip": delete_ip, + }, + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + def upgrade_gateway( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + type_: Optional[str] = None, + ) -> Gateway: + """ + Upgrade a Public Gateway to the latest version and/or to a different commercial offer type. + Upgrade a given Public Gateway to the newest software version or to a different commercial offer type. This applies the latest bugfixes and features to your Public Gateway. Note that gateway service will be interrupted during the update. + :param gateway_id: ID of the gateway to upgrade. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param type_: Gateway type (commercial offer). + :return: :class:`Gateway ` + + Usage: + :: + + result = api.upgrade_gateway( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}/upgrade", + body=marshal_UpgradeGatewayRequest( + UpgradeGatewayRequest( + gateway_id=gateway_id, + zone=zone, + type_=type_, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + def list_gateway_networks( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListGatewayNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + status: Optional[List[GatewayNetworkStatus]] = None, + gateway_ids: Optional[List[str]] = None, + private_network_ids: Optional[List[str]] = None, + masquerade_enabled: Optional[bool] = None, + ) -> ListGatewayNetworksResponse: + """ + List Public Gateway connections to Private Networks. + List the connections between Public Gateways and Private Networks (a connection = a GatewayNetwork). You can choose to filter by `gateway-id` to list all Private Networks attached to the specified Public Gateway, or by `private_network_id` to list all Public Gateways attached to the specified Private Network. Other query parameters are also available. The result is an array of GatewayNetwork objects, each giving details of the connection between a given Public Gateway and a given Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: GatewayNetworks per page. + :param status: Filter for GatewayNetworks with these status. Use `unknown` to include all statuses. + :param gateway_ids: Filter for GatewayNetworks connected to these gateways. + :param private_network_ids: Filter for GatewayNetworks connected to these Private Networks. + :param masquerade_enabled: Filter for GatewayNetworks with this `enable_masquerade` setting. + :return: :class:`ListGatewayNetworksResponse ` + + Usage: + :: + + result = api.list_gateway_networks() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/gateway-networks", + params={ + "gateway_ids": gateway_ids, + "masquerade_enabled": masquerade_enabled, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "private_network_ids": private_network_ids, + "status": status, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListGatewayNetworksResponse(res.json()) + + def list_gateway_networks_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListGatewayNetworksRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + status: Optional[List[GatewayNetworkStatus]] = None, + gateway_ids: Optional[List[str]] = None, + private_network_ids: Optional[List[str]] = None, + masquerade_enabled: Optional[bool] = None, + ) -> List[GatewayNetwork]: + """ + List Public Gateway connections to Private Networks. + List the connections between Public Gateways and Private Networks (a connection = a GatewayNetwork). You can choose to filter by `gateway-id` to list all Private Networks attached to the specified Public Gateway, or by `private_network_id` to list all Public Gateways attached to the specified Private Network. Other query parameters are also available. The result is an array of GatewayNetwork objects, each giving details of the connection between a given Public Gateway and a given Private Network. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: GatewayNetworks per page. + :param status: Filter for GatewayNetworks with these status. Use `unknown` to include all statuses. + :param gateway_ids: Filter for GatewayNetworks connected to these gateways. + :param private_network_ids: Filter for GatewayNetworks connected to these Private Networks. + :param masquerade_enabled: Filter for GatewayNetworks with this `enable_masquerade` setting. + :return: :class:`List[GatewayNetwork] ` + + Usage: + :: + + result = api.list_gateway_networks_all() + """ + + return fetch_all_pages( + type=ListGatewayNetworksResponse, + key="gateway_networks", + fetcher=self.list_gateway_networks, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "status": status, + "gateway_ids": gateway_ids, + "private_network_ids": private_network_ids, + "masquerade_enabled": masquerade_enabled, + }, + ) + + def get_gateway_network( + self, + *, + gateway_network_id: str, + zone: Optional[ScwZone] = None, + ) -> GatewayNetwork: + """ + Get a Public Gateway connection to a Private Network. + Get details of a given connection between a Public Gateway and a Private Network (this connection = a GatewayNetwork), specified by its `gateway_network_id`. The response object contains details of the connection including the IDs of the Public Gateway and Private Network, the dates the connection was created/updated and its configuration settings. + :param gateway_network_id: ID of the GatewayNetwork to fetch. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`GatewayNetwork ` + + Usage: + :: + + result = api.get_gateway_network( + gateway_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_network_id = validate_path_param( + "gateway_network_id", gateway_network_id + ) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/gateway-networks/{param_gateway_network_id}", + ) + + self._throw_on_error(res) + return unmarshal_GatewayNetwork(res.json()) + + def wait_for_gateway_network( + self, + *, + gateway_network_id: str, + zone: Optional[ScwZone] = None, + options: Optional[WaitForOptions[GatewayNetwork, bool]] = None, + ) -> GatewayNetwork: + """ + Get a Public Gateway connection to a Private Network. + Get details of a given connection between a Public Gateway and a Private Network (this connection = a GatewayNetwork), specified by its `gateway_network_id`. The response object contains details of the connection including the IDs of the Public Gateway and Private Network, the dates the connection was created/updated and its configuration settings. + :param gateway_network_id: ID of the GatewayNetwork to fetch. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`GatewayNetwork ` + + Usage: + :: + + result = api.get_gateway_network( + gateway_network_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = ( + lambda res: res.status not in GATEWAY_NETWORK_TRANSIENT_STATUSES + ) + + return wait_for_resource( + fetcher=self.get_gateway_network, + options=options, + args={ + "gateway_network_id": gateway_network_id, + "zone": zone, + }, + ) + + def create_gateway_network( + self, + *, + gateway_id: str, + private_network_id: str, + enable_masquerade: bool, + push_default_route: bool, + zone: Optional[ScwZone] = None, + ipam_ip_id: Optional[str] = None, + ) -> GatewayNetwork: + """ + Attach a Public Gateway to a Private Network. + Attach a specific Public Gateway to a specific Private Network (create a GatewayNetwork). You can configure parameters for the connection including whether to enable masquerade (dynamic NAT), and more. + :param gateway_id: Public Gateway to connect. + :param private_network_id: Private Network to connect. + :param enable_masquerade: Defines whether to enable masquerade (dynamic NAT) on the GatewayNetwork. + :param push_default_route: Enabling the default route also enables masquerading. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param ipam_ip_id: Use this IPAM-booked IP ID as the Gateway's IP in this Private Network. + :return: :class:`GatewayNetwork ` + + Usage: + :: + + result = api.create_gateway_network( + gateway_id="example", + private_network_id="example", + enable_masquerade=False, + push_default_route=False, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/gateway-networks", + body=marshal_CreateGatewayNetworkRequest( + CreateGatewayNetworkRequest( + gateway_id=gateway_id, + private_network_id=private_network_id, + enable_masquerade=enable_masquerade, + push_default_route=push_default_route, + zone=zone, + ipam_ip_id=ipam_ip_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_GatewayNetwork(res.json()) + + def update_gateway_network( + self, + *, + gateway_network_id: str, + zone: Optional[ScwZone] = None, + enable_masquerade: Optional[bool] = None, + push_default_route: Optional[bool] = None, + ipam_ip_id: Optional[str] = None, + ) -> GatewayNetwork: + """ + Update a Public Gateway's connection to a Private Network. + Update the configuration parameters of a connection between a given Public Gateway and Private Network (the connection = a GatewayNetwork). Updatable parameters include whether to enable traffic masquerade (dynamic NAT). + :param gateway_network_id: ID of the GatewayNetwork to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param enable_masquerade: Defines whether to enable masquerade (dynamic NAT) on the GatewayNetwork. + :param push_default_route: Enabling the default route also enables masquerading. + :param ipam_ip_id: Use this IPAM-booked IP ID as the Gateway's IP in this Private Network. + :return: :class:`GatewayNetwork ` + + Usage: + :: + + result = api.update_gateway_network( + gateway_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_network_id = validate_path_param( + "gateway_network_id", gateway_network_id + ) + + res = self._request( + "PATCH", + f"/vpc-gw/v2/zones/{param_zone}/gateway-networks/{param_gateway_network_id}", + body=marshal_UpdateGatewayNetworkRequest( + UpdateGatewayNetworkRequest( + gateway_network_id=gateway_network_id, + zone=zone, + enable_masquerade=enable_masquerade, + push_default_route=push_default_route, + ipam_ip_id=ipam_ip_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_GatewayNetwork(res.json()) + + def delete_gateway_network( + self, + *, + gateway_network_id: str, + zone: Optional[ScwZone] = None, + ) -> GatewayNetwork: + """ + Detach a Public Gateway from a Private Network. + Detach a given Public Gateway from a given Private Network, i.e. delete a GatewayNetwork specified by a gateway_network_id. + :param gateway_network_id: ID of the GatewayNetwork to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`GatewayNetwork ` + + Usage: + :: + + result = api.delete_gateway_network( + gateway_network_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_network_id = validate_path_param( + "gateway_network_id", gateway_network_id + ) + + res = self._request( + "DELETE", + f"/vpc-gw/v2/zones/{param_zone}/gateway-networks/{param_gateway_network_id}", + ) + + self._throw_on_error(res) + return unmarshal_GatewayNetwork(res.json()) + + def list_pat_rules( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListPatRulesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + gateway_ids: Optional[List[str]] = None, + private_ips: Optional[List[str]] = None, + protocol: Optional[PatRuleProtocol] = None, + ) -> ListPatRulesResponse: + """ + List PAT rules. + List PAT rules. You can filter by gateway ID to list all PAT rules for a particular gateway, or filter for PAT rules targeting a specific IP address or using a specific protocol. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: PAT rules per page. + :param gateway_ids: Filter for PAT rules on these gateways. + :param private_ips: Filter for PAT rules targeting these private ips. + :param protocol: Filter for PAT rules with this protocol. + :return: :class:`ListPatRulesResponse ` + + Usage: + :: + + result = api.list_pat_rules() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules", + params={ + "gateway_ids": gateway_ids, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + "private_ips": private_ips, + "protocol": protocol, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListPatRulesResponse(res.json()) + + def list_pat_rules_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListPatRulesRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + gateway_ids: Optional[List[str]] = None, + private_ips: Optional[List[str]] = None, + protocol: Optional[PatRuleProtocol] = None, + ) -> List[PatRule]: + """ + List PAT rules. + List PAT rules. You can filter by gateway ID to list all PAT rules for a particular gateway, or filter for PAT rules targeting a specific IP address or using a specific protocol. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: PAT rules per page. + :param gateway_ids: Filter for PAT rules on these gateways. + :param private_ips: Filter for PAT rules targeting these private ips. + :param protocol: Filter for PAT rules with this protocol. + :return: :class:`List[PatRule] ` + + Usage: + :: + + result = api.list_pat_rules_all() + """ + + return fetch_all_pages( + type=ListPatRulesResponse, + key="pat_rules", + fetcher=self.list_pat_rules, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "gateway_ids": gateway_ids, + "private_ips": private_ips, + "protocol": protocol, + }, + ) + + def get_pat_rule( + self, + *, + pat_rule_id: str, + zone: Optional[ScwZone] = None, + ) -> PatRule: + """ + Get a PAT rule. + Get a PAT rule, specified by its PAT rule ID. The response object gives full details of the PAT rule, including the Public Gateway it belongs to and the configuration settings in terms of public / private ports, private IP and protocol. + :param pat_rule_id: ID of the PAT rule to get. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`PatRule ` + + Usage: + :: + + result = api.get_pat_rule( + pat_rule_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_pat_rule_id = validate_path_param("pat_rule_id", pat_rule_id) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules/{param_pat_rule_id}", + ) + + self._throw_on_error(res) + return unmarshal_PatRule(res.json()) + + def create_pat_rule( + self, + *, + gateway_id: str, + public_port: int, + private_ip: str, + private_port: int, + zone: Optional[ScwZone] = None, + protocol: Optional[PatRuleProtocol] = None, + ) -> PatRule: + """ + Create a PAT rule. + Create a new PAT rule on a specified Public Gateway, defining the protocol to use, public port to listen on, and private port / IP address to map to. + :param gateway_id: ID of the Gateway on which to create the rule. + :param public_port: Public port to listen on. + :param private_ip: Private IP to forward data to. + :param private_port: Private port to translate to. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param protocol: Protocol the rule should apply to. + :return: :class:`PatRule ` + + Usage: + :: + + result = api.create_pat_rule( + gateway_id="example", + public_port=1, + private_ip="example", + private_port=1, + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules", + body=marshal_CreatePatRuleRequest( + CreatePatRuleRequest( + gateway_id=gateway_id, + public_port=public_port, + private_ip=private_ip, + private_port=private_port, + zone=zone, + protocol=protocol, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_PatRule(res.json()) + + def update_pat_rule( + self, + *, + pat_rule_id: str, + zone: Optional[ScwZone] = None, + public_port: Optional[int] = None, + private_ip: Optional[str] = None, + private_port: Optional[int] = None, + protocol: Optional[PatRuleProtocol] = None, + ) -> PatRule: + """ + Update a PAT rule. + Update a PAT rule, specified by its PAT rule ID. Configuration settings including private/public port, private IP address and protocol can all be updated. + :param pat_rule_id: ID of the PAT rule to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param public_port: Public port to listen on. + :param private_ip: Private IP to forward data to. + :param private_port: Private port to translate to. + :param protocol: Protocol the rule should apply to. + :return: :class:`PatRule ` + + Usage: + :: + + result = api.update_pat_rule( + pat_rule_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_pat_rule_id = validate_path_param("pat_rule_id", pat_rule_id) + + res = self._request( + "PATCH", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules/{param_pat_rule_id}", + body=marshal_UpdatePatRuleRequest( + UpdatePatRuleRequest( + pat_rule_id=pat_rule_id, + zone=zone, + public_port=public_port, + private_ip=private_ip, + private_port=private_port, + protocol=protocol, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_PatRule(res.json()) + + def set_pat_rules( + self, + *, + gateway_id: str, + pat_rules: List[SetPatRulesRequestRule], + zone: Optional[ScwZone] = None, + ) -> SetPatRulesResponse: + """ + Set all PAT rules. + Set a definitive list of PAT rules attached to a Public Gateway. Each rule is identified by its public port and protocol. This will sync the current PAT rule list on the gateway with the new list, creating, updating or deleting PAT rules accordingly. + :param gateway_id: ID of the gateway on which to set the PAT rules. + :param pat_rules: New list of PAT rules. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`SetPatRulesResponse ` + + Usage: + :: + + result = api.set_pat_rules( + gateway_id="example", + pat_rules=[], + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "PUT", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules", + body=marshal_SetPatRulesRequest( + SetPatRulesRequest( + gateway_id=gateway_id, + pat_rules=pat_rules, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetPatRulesResponse(res.json()) + + def delete_pat_rule( + self, + *, + pat_rule_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete a PAT rule. + Delete a PAT rule, identified by its PAT rule ID. This action is irreversible. + :param pat_rule_id: ID of the PAT rule to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_pat_rule( + pat_rule_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_pat_rule_id = validate_path_param("pat_rule_id", pat_rule_id) + + res = self._request( + "DELETE", + f"/vpc-gw/v2/zones/{param_zone}/pat-rules/{param_pat_rule_id}", + ) + + self._throw_on_error(res) + + def list_gateway_types( + self, + *, + zone: Optional[ScwZone] = None, + ) -> ListGatewayTypesResponse: + """ + List Public Gateway types. + List the different Public Gateway commercial offer types available at Scaleway. The response is an array of objects describing the name and technical details of each available gateway type. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`ListGatewayTypesResponse ` + + Usage: + :: + + result = api.list_gateway_types() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/gateway-types", + ) + + self._throw_on_error(res) + return unmarshal_ListGatewayTypesResponse(res.json()) + + def list_i_ps( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListIPsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + reverse: Optional[str] = None, + is_free: Optional[bool] = None, + ) -> ListIPsResponse: + """ + List IPs. + List Public Gateway flexible IP addresses. A number of filter options are available for limiting results in the response. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: IP addresses per page. + :param organization_id: Include only gateways in this Organization. + :param project_id: Filter for IP addresses in this Project. + :param tags: Filter for IP addresses with these tags. + :param reverse: Filter for IP addresses that have a reverse containing this string. + :param is_free: Filter based on whether the IP is attached to a gateway or not. + :return: :class:`ListIPsResponse ` + + Usage: + :: + + result = api.list_i_ps() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/ips", + params={ + "is_free": is_free, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "reverse": reverse, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListIPsResponse(res.json()) + + def list_i_ps_all( + self, + *, + zone: Optional[ScwZone] = None, + order_by: Optional[ListIPsRequestOrderBy] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + organization_id: Optional[str] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + reverse: Optional[str] = None, + is_free: Optional[bool] = None, + ) -> List[IP]: + """ + List IPs. + List Public Gateway flexible IP addresses. A number of filter options are available for limiting results in the response. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param order_by: Order in which to return results. + :param page: Page number. + :param page_size: IP addresses per page. + :param organization_id: Include only gateways in this Organization. + :param project_id: Filter for IP addresses in this Project. + :param tags: Filter for IP addresses with these tags. + :param reverse: Filter for IP addresses that have a reverse containing this string. + :param is_free: Filter based on whether the IP is attached to a gateway or not. + :return: :class:`List[IP] ` + + Usage: + :: + + result = api.list_i_ps_all() + """ + + return fetch_all_pages( + type=ListIPsResponse, + key="ips", + fetcher=self.list_i_ps, + args={ + "zone": zone, + "order_by": order_by, + "page": page, + "page_size": page_size, + "organization_id": organization_id, + "project_id": project_id, + "tags": tags, + "reverse": reverse, + "is_free": is_free, + }, + ) + + def get_ip( + self, + *, + ip_id: str, + zone: Optional[ScwZone] = None, + ) -> IP: + """ + Get an IP. + Get details of a Public Gateway flexible IP address, identified by its IP ID. The response object contains information including which (if any) Public Gateway using this IP address, the reverse and various other metadata. + :param ip_id: ID of the IP address to get. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`IP ` + + Usage: + :: + + result = api.get_ip( + ip_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "GET", + f"/vpc-gw/v2/zones/{param_zone}/ips/{param_ip_id}", + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + def create_ip( + self, + *, + zone: Optional[ScwZone] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + ) -> IP: + """ + Reserve an IP. + Create (reserve) a new flexible IP address that can be used for a Public Gateway in a specified Scaleway Project. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param project_id: Project to create the IP address in. + :param tags: Tags to give to the IP address. + :return: :class:`IP ` + + Usage: + :: + + result = api.create_ip() + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/ips", + body=marshal_CreateIPRequest( + CreateIPRequest( + zone=zone, + project_id=project_id, + tags=tags, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + def update_ip( + self, + *, + ip_id: str, + zone: Optional[ScwZone] = None, + tags: Optional[List[str]] = None, + reverse: Optional[str] = None, + gateway_id: Optional[str] = None, + ) -> IP: + """ + Update an IP. + Update details of an existing flexible IP address, including its tags, reverse and the Public Gateway it is assigned to. + :param ip_id: ID of the IP address to update. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param tags: Tags to give to the IP address. + :param reverse: Reverse to set on the address. Empty string to unset. + :param gateway_id: Gateway to attach the IP address to. Empty string to detach. + :return: :class:`IP ` + + Usage: + :: + + result = api.update_ip( + ip_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "PATCH", + f"/vpc-gw/v2/zones/{param_zone}/ips/{param_ip_id}", + body=marshal_UpdateIPRequest( + UpdateIPRequest( + ip_id=ip_id, + zone=zone, + tags=tags, + reverse=reverse, + gateway_id=gateway_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_IP(res.json()) + + def delete_ip( + self, + *, + ip_id: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete an IP. + Delete a flexible IP address from your account. This action is irreversible. + :param ip_id: ID of the IP address to delete. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_ip( + ip_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_ip_id = validate_path_param("ip_id", ip_id) + + res = self._request( + "DELETE", + f"/vpc-gw/v2/zones/{param_zone}/ips/{param_ip_id}", + ) + + self._throw_on_error(res) + + def refresh_ssh_keys( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + ) -> Gateway: + """ + Refresh a Public Gateway's SSH keys. + Refresh the SSH keys of a given Public Gateway, specified by its gateway ID. This adds any new SSH keys in the gateway's Scaleway Project to the gateway itself. + :param gateway_id: ID of the gateway to refresh SSH keys on. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Gateway ` + + Usage: + :: + + result = api.refresh_ssh_keys( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}/refresh-ssh-keys", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Gateway(res.json()) + + def add_bastion_allowed_i_ps( + self, + *, + gateway_id: str, + ip_range: str, + zone: Optional[ScwZone] = None, + ) -> AddBastionAllowedIPsResponse: + """ + Add allowed IP range to SSH bastion. + Add an IP range (in CIDR notation) to be allowed to connect to the SSH bastion. + :param gateway_id: ID of the gateway to add the allowed IP range to. + :param ip_range: IP range allowed to connect to the SSH bastion. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`AddBastionAllowedIPsResponse ` + + Usage: + :: + + result = api.add_bastion_allowed_i_ps( + gateway_id="example", + ip_range="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "POST", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}/bastion-allowed-ips", + body=marshal_AddBastionAllowedIPsRequest( + AddBastionAllowedIPsRequest( + gateway_id=gateway_id, + ip_range=ip_range, + zone=zone, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_AddBastionAllowedIPsResponse(res.json()) + + def set_bastion_allowed_i_ps( + self, + *, + gateway_id: str, + zone: Optional[ScwZone] = None, + ip_ranges: Optional[List[str]] = None, + ) -> SetBastionAllowedIPsResponse: + """ + Set all IP ranges allowed for SSH bastion. + Set a definitive list of IP ranges (in CIDR notation) allowed to connect to the SSH bastion. + :param gateway_id: ID of the gateway on which to set the allowed IP range. + :param zone: Zone to target. If none is passed will use default zone from the config. + :param ip_ranges: New list of IP ranges (each range in CIDR notation) allowed to connect to the SSH bastion. + :return: :class:`SetBastionAllowedIPsResponse ` + + Usage: + :: + + result = api.set_bastion_allowed_i_ps( + gateway_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + + res = self._request( + "PUT", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}/bastion-allowed-ips", + body=marshal_SetBastionAllowedIPsRequest( + SetBastionAllowedIPsRequest( + gateway_id=gateway_id, + zone=zone, + ip_ranges=ip_ranges, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_SetBastionAllowedIPsResponse(res.json()) + + def delete_bastion_allowed_i_ps( + self, + *, + gateway_id: str, + ip_range: str, + zone: Optional[ScwZone] = None, + ) -> None: + """ + Delete allowed IP range from SSH bastion. + Delete an IP range (defined in CIDR notation) from SSH bastion, so that it is no longer allowed to connect. + :param gateway_id: ID of the gateway on which to delete the allowed IP range. + :param ip_range: IP range to delete from SSH bastion's list of allowed IPs. + :param zone: Zone to target. If none is passed will use default zone from the config. + + Usage: + :: + + result = api.delete_bastion_allowed_i_ps( + gateway_id="example", + ip_range="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_gateway_id = validate_path_param("gateway_id", gateway_id) + param_ip_range = validate_path_param("ip_range", ip_range) + + res = self._request( + "DELETE", + f"/vpc-gw/v2/zones/{param_zone}/gateways/{param_gateway_id}/bastion-allowed-ips/{param_ip_range}", + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/vpcgw/v2/content.py b/scaleway/scaleway/vpcgw/v2/content.py new file mode 100644 index 00000000..a5b8a7ac --- /dev/null +++ b/scaleway/scaleway/vpcgw/v2/content.py @@ -0,0 +1,26 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + GatewayNetworkStatus, + GatewayStatus, +) + +GATEWAY_NETWORK_TRANSIENT_STATUSES: List[GatewayNetworkStatus] = [ + GatewayNetworkStatus.ATTACHING, + GatewayNetworkStatus.CONFIGURING, + GatewayNetworkStatus.DETACHING, +] +""" +Lists transient statutes of the enum :class:`GatewayNetworkStatus `. +""" +GATEWAY_TRANSIENT_STATUSES: List[GatewayStatus] = [ + GatewayStatus.ALLOCATING, + GatewayStatus.CONFIGURING, + GatewayStatus.STOPPING, + GatewayStatus.DELETING, +] +""" +Lists transient statutes of the enum :class:`GatewayStatus `. +""" diff --git a/scaleway/scaleway/vpcgw/v2/marshalling.py b/scaleway/scaleway/vpcgw/v2/marshalling.py new file mode 100644 index 00000000..2c01ee75 --- /dev/null +++ b/scaleway/scaleway/vpcgw/v2/marshalling.py @@ -0,0 +1,729 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from .types import ( + GatewayNetwork, + IP, + Gateway, + PatRule, + AddBastionAllowedIPsResponse, + ListGatewayNetworksResponse, + GatewayType, + ListGatewayTypesResponse, + ListGatewaysResponse, + ListIPsResponse, + ListPatRulesResponse, + SetBastionAllowedIPsResponse, + SetPatRulesResponse, + AddBastionAllowedIPsRequest, + CreateGatewayNetworkRequest, + CreateGatewayRequest, + CreateIPRequest, + CreatePatRuleRequest, + SetBastionAllowedIPsRequest, + SetPatRulesRequestRule, + SetPatRulesRequest, + UpdateGatewayNetworkRequest, + UpdateGatewayRequest, + UpdateIPRequest, + UpdatePatRuleRequest, + UpgradeGatewayRequest, +) + + +def unmarshal_GatewayNetwork(data: Any) -> GatewayNetwork: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GatewayNetwork' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("gateway_id", None) + if field is not None: + args["gateway_id"] = field + + field = data.get("private_network_id", None) + if field is not None: + args["private_network_id"] = field + + field = data.get("masquerade_enabled", None) + if field is not None: + args["masquerade_enabled"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("push_default_route", None) + if field is not None: + args["push_default_route"] = field + + field = data.get("ipam_ip_id", None) + if field is not None: + args["ipam_ip_id"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("mac_address", None) + if field is not None: + args["mac_address"] = field + else: + args["mac_address"] = None + + return GatewayNetwork(**args) + + +def unmarshal_IP(data: Any) -> IP: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'IP' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("address", None) + if field is not None: + args["address"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("reverse", None) + if field is not None: + args["reverse"] = field + else: + args["reverse"] = None + + field = data.get("gateway_id", None) + if field is not None: + args["gateway_id"] = field + else: + args["gateway_id"] = None + + return IP(**args) + + +def unmarshal_Gateway(data: Any) -> Gateway: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Gateway' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("bandwidth", None) + if field is not None: + args["bandwidth"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("gateway_networks", None) + if field is not None: + args["gateway_networks"] = ( + [unmarshal_GatewayNetwork(v) for v in field] if field is not None else None + ) + + field = data.get("bastion_enabled", None) + if field is not None: + args["bastion_enabled"] = field + + field = data.get("ipv4", None) + if field is not None: + args["ipv4"] = unmarshal_IP(field) + else: + args["ipv4"] = None + + field = data.get("version", None) + if field is not None: + args["version"] = field + else: + args["version"] = None + + field = data.get("can_upgrade_to", None) + if field is not None: + args["can_upgrade_to"] = field + else: + args["can_upgrade_to"] = None + + field = data.get("bastion_port", None) + if field is not None: + args["bastion_port"] = field + + field = data.get("smtp_enabled", None) + if field is not None: + args["smtp_enabled"] = field + + field = data.get("is_legacy", None) + if field is not None: + args["is_legacy"] = field + + field = data.get("bastion_allowed_ips", None) + if field is not None: + args["bastion_allowed_ips"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + return Gateway(**args) + + +def unmarshal_PatRule(data: Any) -> PatRule: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PatRule' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("gateway_id", None) + if field is not None: + args["gateway_id"] = field + + field = data.get("public_port", None) + if field is not None: + args["public_port"] = field + + field = data.get("private_ip", None) + if field is not None: + args["private_ip"] = field + + field = data.get("private_port", None) + if field is not None: + args["private_port"] = field + + field = data.get("protocol", None) + if field is not None: + args["protocol"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return PatRule(**args) + + +def unmarshal_AddBastionAllowedIPsResponse(data: Any) -> AddBastionAllowedIPsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AddBastionAllowedIPsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("ip_ranges", None) + if field is not None: + args["ip_ranges"] = field + + return AddBastionAllowedIPsResponse(**args) + + +def unmarshal_ListGatewayNetworksResponse(data: Any) -> ListGatewayNetworksResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGatewayNetworksResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("gateway_networks", None) + if field is not None: + args["gateway_networks"] = ( + [unmarshal_GatewayNetwork(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListGatewayNetworksResponse(**args) + + +def unmarshal_GatewayType(data: Any) -> GatewayType: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'GatewayType' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("bandwidth", None) + if field is not None: + args["bandwidth"] = field + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + + return GatewayType(**args) + + +def unmarshal_ListGatewayTypesResponse(data: Any) -> ListGatewayTypesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGatewayTypesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("types", None) + if field is not None: + args["types"] = ( + [unmarshal_GatewayType(v) for v in field] if field is not None else None + ) + + return ListGatewayTypesResponse(**args) + + +def unmarshal_ListGatewaysResponse(data: Any) -> ListGatewaysResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListGatewaysResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("gateways", None) + if field is not None: + args["gateways"] = ( + [unmarshal_Gateway(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListGatewaysResponse(**args) + + +def unmarshal_ListIPsResponse(data: Any) -> ListIPsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListIPsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("ips", None) + if field is not None: + args["ips"] = [unmarshal_IP(v) for v in field] if field is not None else None + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListIPsResponse(**args) + + +def unmarshal_ListPatRulesResponse(data: Any) -> ListPatRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListPatRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pat_rules", None) + if field is not None: + args["pat_rules"] = ( + [unmarshal_PatRule(v) for v in field] if field is not None else None + ) + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + return ListPatRulesResponse(**args) + + +def unmarshal_SetBastionAllowedIPsResponse(data: Any) -> SetBastionAllowedIPsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetBastionAllowedIPsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("ip_ranges", None) + if field is not None: + args["ip_ranges"] = field + + return SetBastionAllowedIPsResponse(**args) + + +def unmarshal_SetPatRulesResponse(data: Any) -> SetPatRulesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SetPatRulesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("pat_rules", None) + if field is not None: + args["pat_rules"] = ( + [unmarshal_PatRule(v) for v in field] if field is not None else None + ) + + return SetPatRulesResponse(**args) + + +def marshal_AddBastionAllowedIPsRequest( + request: AddBastionAllowedIPsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip_range is not None: + output["ip_range"] = request.ip_range + + return output + + +def marshal_CreateGatewayNetworkRequest( + request: CreateGatewayNetworkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.gateway_id is not None: + output["gateway_id"] = request.gateway_id + + if request.private_network_id is not None: + output["private_network_id"] = request.private_network_id + + if request.enable_masquerade is not None: + output["enable_masquerade"] = request.enable_masquerade + + if request.push_default_route is not None: + output["push_default_route"] = request.push_default_route + + if request.ipam_ip_id is not None: + output["ipam_ip_id"] = request.ipam_ip_id + + return output + + +def marshal_CreateGatewayRequest( + request: CreateGatewayRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.type_ is not None: + output["type"] = request.type_ + + if request.enable_smtp is not None: + output["enable_smtp"] = request.enable_smtp + + if request.enable_bastion is not None: + output["enable_bastion"] = request.enable_bastion + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.ip_id is not None: + output["ip_id"] = request.ip_id + + if request.bastion_port is not None: + output["bastion_port"] = request.bastion_port + + return output + + +def marshal_CreateIPRequest( + request: CreateIPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + return output + + +def marshal_CreatePatRuleRequest( + request: CreatePatRuleRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.gateway_id is not None: + output["gateway_id"] = request.gateway_id + + if request.public_port is not None: + output["public_port"] = request.public_port + + if request.private_ip is not None: + output["private_ip"] = request.private_ip + + if request.private_port is not None: + output["private_port"] = request.private_port + + if request.protocol is not None: + output["protocol"] = str(request.protocol) + + return output + + +def marshal_SetBastionAllowedIPsRequest( + request: SetBastionAllowedIPsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.ip_ranges is not None: + output["ip_ranges"] = request.ip_ranges + + return output + + +def marshal_SetPatRulesRequestRule( + request: SetPatRulesRequestRule, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.public_port is not None: + output["public_port"] = request.public_port + + if request.private_ip is not None: + output["private_ip"] = request.private_ip + + if request.private_port is not None: + output["private_port"] = request.private_port + + if request.protocol is not None: + output["protocol"] = str(request.protocol) + + return output + + +def marshal_SetPatRulesRequest( + request: SetPatRulesRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.gateway_id is not None: + output["gateway_id"] = request.gateway_id + + if request.pat_rules is not None: + output["pat_rules"] = [ + marshal_SetPatRulesRequestRule(item, defaults) for item in request.pat_rules + ] + + return output + + +def marshal_UpdateGatewayNetworkRequest( + request: UpdateGatewayNetworkRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.enable_masquerade is not None: + output["enable_masquerade"] = request.enable_masquerade + + if request.push_default_route is not None: + output["push_default_route"] = request.push_default_route + + if request.ipam_ip_id is not None: + output["ipam_ip_id"] = request.ipam_ip_id + + return output + + +def marshal_UpdateGatewayRequest( + request: UpdateGatewayRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.tags is not None: + output["tags"] = request.tags + + if request.enable_bastion is not None: + output["enable_bastion"] = request.enable_bastion + + if request.bastion_port is not None: + output["bastion_port"] = request.bastion_port + + if request.enable_smtp is not None: + output["enable_smtp"] = request.enable_smtp + + return output + + +def marshal_UpdateIPRequest( + request: UpdateIPRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.tags is not None: + output["tags"] = request.tags + + if request.reverse is not None: + output["reverse"] = request.reverse + + if request.gateway_id is not None: + output["gateway_id"] = request.gateway_id + + return output + + +def marshal_UpdatePatRuleRequest( + request: UpdatePatRuleRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.public_port is not None: + output["public_port"] = request.public_port + + if request.private_ip is not None: + output["private_ip"] = request.private_ip + + if request.private_port is not None: + output["private_port"] = request.private_port + + if request.protocol is not None: + output["protocol"] = str(request.protocol) + + return output + + +def marshal_UpgradeGatewayRequest( + request: UpgradeGatewayRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.type_ is not None: + output["type"] = request.type_ + + return output diff --git a/scaleway/scaleway/vpcgw/v2/types.py b/scaleway/scaleway/vpcgw/v2/types.py new file mode 100644 index 00000000..dfd76ccc --- /dev/null +++ b/scaleway/scaleway/vpcgw/v2/types.py @@ -0,0 +1,1156 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class GatewayNetworkStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + CREATED = "created" + ATTACHING = "attaching" + CONFIGURING = "configuring" + READY = "ready" + DETACHING = "detaching" + + def __str__(self) -> str: + return str(self.value) + + +class GatewayStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + STOPPED = "stopped" + ALLOCATING = "allocating" + CONFIGURING = "configuring" + RUNNING = "running" + STOPPING = "stopping" + FAILED = "failed" + DELETING = "deleting" + LOCKED = "locked" + + def __str__(self) -> str: + return str(self.value) + + +class ListGatewayNetworksRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListGatewaysRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + NAME_ASC = "name_asc" + NAME_DESC = "name_desc" + TYPE_ASC = "type_asc" + TYPE_DESC = "type_desc" + STATUS_ASC = "status_asc" + STATUS_DESC = "status_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListIPsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + ADDRESS_ASC = "address_asc" + ADDRESS_DESC = "address_desc" + REVERSE_ASC = "reverse_asc" + REVERSE_DESC = "reverse_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListPatRulesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + PUBLIC_PORT_ASC = "public_port_asc" + PUBLIC_PORT_DESC = "public_port_desc" + + def __str__(self) -> str: + return str(self.value) + + +class PatRuleProtocol(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PROTOCOL = "unknown_protocol" + BOTH = "both" + TCP = "tcp" + UDP = "udp" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class GatewayNetwork: + id: str + """ + ID of the Public Gateway-Private Network connection. + """ + + gateway_id: str + """ + ID of the connected Public Gateway. + """ + + private_network_id: str + """ + ID of the connected Private Network. + """ + + masquerade_enabled: bool + """ + Defines whether the gateway masquerades traffic for this Private Network (Dynamic NAT). + """ + + status: GatewayNetworkStatus + """ + Current status of the Public Gateway's connection to the Private Network. + """ + + push_default_route: bool + """ + Enabling the default route also enables masquerading. + """ + + ipam_ip_id: str + """ + Use this IPAM-booked IP ID as the Gateway's IP in this Private Network. + """ + + zone: ScwZone + """ + Zone of the GatewayNetwork connection. + """ + + created_at: Optional[datetime] + """ + Connection creation date. + """ + + updated_at: Optional[datetime] + """ + Connection last modification date. + """ + + mac_address: Optional[str] + """ + MAC address of the gateway in the Private Network (if the gateway is up and running). + """ + + +@dataclass +class IP: + id: str + """ + IP address ID. + """ + + organization_id: str + """ + Owning Organization. + """ + + project_id: str + """ + Owning Project. + """ + + tags: List[str] + """ + Tags associated with the IP address. + """ + + address: str + """ + The IP address itself. + """ + + zone: ScwZone + """ + Zone of the IP address. + """ + + created_at: Optional[datetime] + """ + IP address creation date. + """ + + updated_at: Optional[datetime] + """ + IP address last modification date. + """ + + reverse: Optional[str] + """ + Reverse domain name for the IP address. + """ + + gateway_id: Optional[str] + """ + Public Gateway associated with the IP address. + """ + + +@dataclass +class GatewayType: + name: str + """ + Public Gateway type name. + """ + + bandwidth: int + """ + Bandwidth, in bps, of the Public Gateway. This is the public bandwidth to the outer Internet, and the internal bandwidth to each connected Private Networks. + """ + + zone: ScwZone + """ + Zone the Public Gateway type is available in. + """ + + +@dataclass +class Gateway: + id: str + """ + ID of the gateway. + """ + + organization_id: str + """ + Owning Organization. + """ + + project_id: str + """ + Owning Project. + """ + + type_: str + """ + Gateway type name (commercial offer). + """ + + bandwidth: int + """ + Bandwidth available of the gateway. + """ + + status: GatewayStatus + """ + Current status of the gateway. + """ + + name: str + """ + Name of the gateway. + """ + + created_at: Optional[datetime] + """ + Gateway creation date. + """ + + updated_at: Optional[datetime] + """ + Gateway last modification date. + """ + + tags: List[str] + """ + Tags associated with the gateway. + """ + + gateway_networks: List[GatewayNetwork] + """ + GatewayNetwork objects attached to the gateway (each one represents a connection to a Private Network). + """ + + bastion_enabled: bool + """ + Defines whether SSH bastion is enabled on the gateway. + """ + + ipv4: Optional[IP] + """ + Public IPv4 address of the gateway. + """ + + version: Optional[str] + """ + Version of the running gateway software. + """ + + can_upgrade_to: Optional[str] + """ + Newly available gateway software version that can be updated to. + """ + + bastion_port: int + """ + Port of the SSH bastion. + """ + + smtp_enabled: bool + """ + Defines whether SMTP traffic is allowed to pass through the gateway. + """ + + is_legacy: bool + """ + Defines whether the gateway uses non-IPAM IP configurations. + """ + + bastion_allowed_ips: List[str] + """ + Ranges of IP addresses allowed to connect to the gateway's SSH bastion. + """ + + zone: ScwZone + """ + Zone of the gateway. + """ + + +@dataclass +class PatRule: + id: str + """ + PAT rule ID. + """ + + gateway_id: str + """ + Gateway the PAT rule applies to. + """ + + public_port: int + """ + Public port to listen on. + """ + + private_ip: str + """ + Private IP address to forward data to. + """ + + private_port: int + """ + Private port to translate to. + """ + + protocol: PatRuleProtocol + """ + Protocol the rule applies to. + """ + + zone: ScwZone + """ + Zone of the PAT rule. + """ + + created_at: Optional[datetime] + """ + PAT rule creation date. + """ + + updated_at: Optional[datetime] + """ + PAT rule last modification date. + """ + + +@dataclass +class SetPatRulesRequestRule: + public_port: int + """ + Public port to listen on. Uniquely identifies the rule, and a matching rule will be updated with the new parameters. + """ + + private_ip: str + """ + Private IP to forward data to. + """ + + private_port: int + """ + Private port to translate to. + """ + + protocol: PatRuleProtocol + """ + Protocol the rule should apply to. + """ + + +@dataclass +class AddBastionAllowedIPsRequest: + gateway_id: str + """ + ID of the gateway to add the allowed IP range to. + """ + + ip_range: str + """ + IP range allowed to connect to the SSH bastion. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class AddBastionAllowedIPsResponse: + ip_ranges: List[str] + """ + Ranges of IP addresses allowed to connect to the gateway's SSH bastion. + """ + + +@dataclass +class CreateGatewayNetworkRequest: + gateway_id: str + """ + Public Gateway to connect. + """ + + private_network_id: str + """ + Private Network to connect. + """ + + enable_masquerade: bool + """ + Defines whether to enable masquerade (dynamic NAT) on the GatewayNetwork. + """ + + push_default_route: bool + """ + Enabling the default route also enables masquerading. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + ipam_ip_id: Optional[str] + """ + Use this IPAM-booked IP ID as the Gateway's IP in this Private Network. + """ + + +@dataclass +class CreateGatewayRequest: + type_: str + """ + Gateway type (commercial offer type). + """ + + enable_smtp: bool + """ + Defines whether SMTP traffic should be allowed pass through the gateway. + """ + + enable_bastion: bool + """ + Defines whether SSH bastion should be enabled the gateway. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Scaleway Project to create the gateway in. + """ + + name: Optional[str] + """ + Name for the gateway. + """ + + tags: Optional[List[str]] + """ + Tags for the gateway. + """ + + ip_id: Optional[str] + """ + Existing IP address to attach to the gateway. + """ + + bastion_port: Optional[int] + """ + Port of the SSH bastion. + """ + + +@dataclass +class CreateIPRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + project_id: Optional[str] + """ + Project to create the IP address in. + """ + + tags: Optional[List[str]] + """ + Tags to give to the IP address. + """ + + +@dataclass +class CreatePatRuleRequest: + gateway_id: str + """ + ID of the Gateway on which to create the rule. + """ + + public_port: int + """ + Public port to listen on. + """ + + private_ip: str + """ + Private IP to forward data to. + """ + + private_port: int + """ + Private port to translate to. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + protocol: Optional[PatRuleProtocol] + """ + Protocol the rule should apply to. + """ + + +@dataclass +class DeleteBastionAllowedIPsRequest: + gateway_id: str + """ + ID of the gateway on which to delete the allowed IP range. + """ + + ip_range: str + """ + IP range to delete from SSH bastion's list of allowed IPs. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteGatewayNetworkRequest: + gateway_network_id: str + """ + ID of the GatewayNetwork to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteGatewayRequest: + gateway_id: str + """ + ID of the gateway to delete. + """ + + delete_ip: bool + """ + Defines whether the PGW's IP should be deleted. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeleteIPRequest: + ip_id: str + """ + ID of the IP address to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class DeletePatRuleRequest: + pat_rule_id: str + """ + ID of the PAT rule to delete. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetGatewayNetworkRequest: + gateway_network_id: str + """ + ID of the GatewayNetwork to fetch. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetGatewayRequest: + gateway_id: str + """ + ID of the gateway to fetch. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetIPRequest: + ip_id: str + """ + ID of the IP address to get. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class GetPatRuleRequest: + pat_rule_id: str + """ + ID of the PAT rule to get. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ListGatewayNetworksRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListGatewayNetworksRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + GatewayNetworks per page. + """ + + status: Optional[List[GatewayNetworkStatus]] + """ + Filter for GatewayNetworks with these status. Use `unknown` to include all statuses. + """ + + gateway_ids: Optional[List[str]] + """ + Filter for GatewayNetworks connected to these gateways. + """ + + private_network_ids: Optional[List[str]] + """ + Filter for GatewayNetworks connected to these Private Networks. + """ + + masquerade_enabled: Optional[bool] + """ + Filter for GatewayNetworks with this `enable_masquerade` setting. + """ + + +@dataclass +class ListGatewayNetworksResponse: + gateway_networks: List[GatewayNetwork] + """ + GatewayNetworks on this page. + """ + + total_count: int + """ + Total GatewayNetworks count matching the filter. + """ + + +@dataclass +class ListGatewayTypesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class ListGatewayTypesResponse: + types: List[GatewayType] + """ + Available types of Public Gateway. + """ + + +@dataclass +class ListGatewaysRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListGatewaysRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number to return. + """ + + page_size: Optional[int] + """ + Gateways per page. + """ + + organization_id: Optional[str] + """ + Include only gateways in this Organization. + """ + + project_id: Optional[str] + """ + Include only gateways in this Project. + """ + + name: Optional[str] + """ + Filter for gateways which have this search term in their name. + """ + + tags: Optional[List[str]] + """ + Filter for gateways with these tags. + """ + + types: Optional[List[str]] + """ + Filter for gateways of these types. + """ + + status: Optional[List[GatewayStatus]] + """ + Filter for gateways with these status. Use `unknown` to include all statuses. + """ + + private_network_ids: Optional[List[str]] + """ + Filter for gateways attached to these Private Networks. + """ + + include_legacy: Optional[bool] + """ + Include also legacy gateways. + """ + + +@dataclass +class ListGatewaysResponse: + gateways: List[Gateway] + """ + Gateways on this page. + """ + + total_count: int + """ + Total count of gateways matching the filter. + """ + + +@dataclass +class ListIPsRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListIPsRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + IP addresses per page. + """ + + organization_id: Optional[str] + """ + Include only gateways in this Organization. + """ + + project_id: Optional[str] + """ + Filter for IP addresses in this Project. + """ + + tags: Optional[List[str]] + """ + Filter for IP addresses with these tags. + """ + + reverse: Optional[str] + """ + Filter for IP addresses that have a reverse containing this string. + """ + + is_free: Optional[bool] + """ + Filter based on whether the IP is attached to a gateway or not. + """ + + +@dataclass +class ListIPsResponse: + ips: List[IP] + """ + IP addresses on this page. + """ + + total_count: int + """ + Total count of IP addresses matching the filter. + """ + + +@dataclass +class ListPatRulesRequest: + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + order_by: Optional[ListPatRulesRequestOrderBy] + """ + Order in which to return results. + """ + + page: Optional[int] + """ + Page number. + """ + + page_size: Optional[int] + """ + PAT rules per page. + """ + + gateway_ids: Optional[List[str]] + """ + Filter for PAT rules on these gateways. + """ + + private_ips: Optional[List[str]] + """ + Filter for PAT rules targeting these private ips. + """ + + protocol: Optional[PatRuleProtocol] + """ + Filter for PAT rules with this protocol. + """ + + +@dataclass +class ListPatRulesResponse: + pat_rules: List[PatRule] + """ + Array of PAT rules matching the filter. + """ + + total_count: int + """ + Total count of PAT rules matching the filter. + """ + + +@dataclass +class RefreshSSHKeysRequest: + gateway_id: str + """ + ID of the gateway to refresh SSH keys on. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SetBastionAllowedIPsRequest: + gateway_id: str + """ + ID of the gateway on which to set the allowed IP range. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + ip_ranges: Optional[List[str]] + """ + New list of IP ranges (each range in CIDR notation) allowed to connect to the SSH bastion. + """ + + +@dataclass +class SetBastionAllowedIPsResponse: + ip_ranges: List[str] + """ + Ranges of IP addresses allowed to connect to the gateway's SSH bastion. + """ + + +@dataclass +class SetPatRulesRequest: + gateway_id: str + """ + ID of the gateway on which to set the PAT rules. + """ + + pat_rules: List[SetPatRulesRequestRule] + """ + New list of PAT rules. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + +@dataclass +class SetPatRulesResponse: + pat_rules: List[PatRule] + """ + List of PAT rules. + """ + + +@dataclass +class UpdateGatewayNetworkRequest: + gateway_network_id: str + """ + ID of the GatewayNetwork to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + enable_masquerade: Optional[bool] + """ + Defines whether to enable masquerade (dynamic NAT) on the GatewayNetwork. + """ + + push_default_route: Optional[bool] + """ + Enabling the default route also enables masquerading. + """ + + ipam_ip_id: Optional[str] + """ + Use this IPAM-booked IP ID as the Gateway's IP in this Private Network. + """ + + +@dataclass +class UpdateGatewayRequest: + gateway_id: str + """ + ID of the gateway to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + name: Optional[str] + """ + Name for the gateway. + """ + + tags: Optional[List[str]] + """ + Tags for the gateway. + """ + + enable_bastion: Optional[bool] + """ + Defines whether SSH bastion should be enabled the gateway. + """ + + bastion_port: Optional[int] + """ + Port of the SSH bastion. + """ + + enable_smtp: Optional[bool] + """ + Defines whether SMTP traffic should be allowed to pass through the gateway. + """ + + +@dataclass +class UpdateIPRequest: + ip_id: str + """ + ID of the IP address to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + tags: Optional[List[str]] + """ + Tags to give to the IP address. + """ + + reverse: Optional[str] + """ + Reverse to set on the address. Empty string to unset. + """ + + gateway_id: Optional[str] + """ + Gateway to attach the IP address to. Empty string to detach. + """ + + +@dataclass +class UpdatePatRuleRequest: + pat_rule_id: str + """ + ID of the PAT rule to update. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + public_port: Optional[int] + """ + Public port to listen on. + """ + + private_ip: Optional[str] + """ + Private IP to forward data to. + """ + + private_port: Optional[int] + """ + Private port to translate to. + """ + + protocol: Optional[PatRuleProtocol] + """ + Protocol the rule should apply to. + """ + + +@dataclass +class UpgradeGatewayRequest: + gateway_id: str + """ + ID of the gateway to upgrade. + """ + + zone: Optional[ScwZone] + """ + Zone to target. If none is passed will use default zone from the config. + """ + + type_: Optional[str] + """ + Gateway type (commercial offer). + """ diff --git a/scaleway/scaleway/webhosting/v1/__init__.py b/scaleway/scaleway/webhosting/v1/__init__.py new file mode 100644 index 00000000..43df2e81 --- /dev/null +++ b/scaleway/scaleway/webhosting/v1/__init__.py @@ -0,0 +1,213 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import DnsRecordStatus +from .types import DnsRecordType +from .types import DnsRecordsStatus +from .types import DomainAction +from .types import DomainAvailabilityAction +from .types import DomainAvailabilityStatus +from .content import DOMAIN_AVAILABILITY_TRANSIENT_STATUSES +from .types import DomainDnsAction +from .types import DomainStatus +from .content import DOMAIN_TRANSIENT_STATUSES +from .types import DomainZoneOwner +from .types import HostingStatus +from .content import HOSTING_TRANSIENT_STATUSES +from .types import ListDatabaseUsersRequestOrderBy +from .types import ListDatabasesRequestOrderBy +from .types import ListFtpAccountsRequestOrderBy +from .types import ListHostingsRequestOrderBy +from .types import ListMailAccountsRequestOrderBy +from .types import ListOffersRequestOrderBy +from .types import ListWebsitesRequestOrderBy +from .types import NameserverStatus +from .types import OfferOptionName +from .types import OfferOptionWarning +from .types import PlatformPlatformGroup +from .types import PlatformControlPanelUrls +from .types import OfferOption +from .types import PlatformControlPanel +from .types import CreateDatabaseRequestUser +from .types import AutoConfigDomainDns +from .types import CreateHostingRequestDomainConfiguration +from .types import OfferOptionRequest +from .types import SyncDomainDnsRecordsRequestRecord +from .types import DnsRecord +from .types import Nameserver +from .types import HostingUser +from .types import Offer +from .types import Platform +from .types import ControlPanel +from .types import DatabaseUser +from .types import Database +from .types import FtpAccount +from .types import HostingSummary +from .types import MailAccount +from .types import Website +from .types import DomainAvailability +from .types import CheckUserOwnsDomainResponse +from .types import ControlPanelApiListControlPanelsRequest +from .types import DatabaseApiAssignDatabaseUserRequest +from .types import DatabaseApiChangeDatabaseUserPasswordRequest +from .types import DatabaseApiCreateDatabaseRequest +from .types import DatabaseApiCreateDatabaseUserRequest +from .types import DatabaseApiDeleteDatabaseRequest +from .types import DatabaseApiDeleteDatabaseUserRequest +from .types import DatabaseApiGetDatabaseRequest +from .types import DatabaseApiGetDatabaseUserRequest +from .types import DatabaseApiListDatabaseUsersRequest +from .types import DatabaseApiListDatabasesRequest +from .types import DatabaseApiUnassignDatabaseUserRequest +from .types import DnsApiCheckUserOwnsDomainRequest +from .types import DnsApiGetDomainDnsRecordsRequest +from .types import DnsApiGetDomainRequest +from .types import DnsApiSearchDomainsRequest +from .types import DnsApiSyncDomainDnsRecordsRequest +from .types import DnsRecords +from .types import Domain +from .types import FtpAccountApiChangeFtpAccountPasswordRequest +from .types import FtpAccountApiCreateFtpAccountRequest +from .types import FtpAccountApiListFtpAccountsRequest +from .types import FtpAccountApiRemoveFtpAccountRequest +from .types import Hosting +from .types import HostingApiCreateHostingRequest +from .types import HostingApiCreateSessionRequest +from .types import HostingApiDeleteHostingRequest +from .types import HostingApiGetHostingRequest +from .types import HostingApiGetResourceSummaryRequest +from .types import HostingApiListHostingsRequest +from .types import HostingApiResetHostingPasswordRequest +from .types import HostingApiUpdateHostingRequest +from .types import ListControlPanelsResponse +from .types import ListDatabaseUsersResponse +from .types import ListDatabasesResponse +from .types import ListFtpAccountsResponse +from .types import ListHostingsResponse +from .types import ListMailAccountsResponse +from .types import ListOffersResponse +from .types import ListWebsitesResponse +from .types import MailAccountApiChangeMailAccountPasswordRequest +from .types import MailAccountApiCreateMailAccountRequest +from .types import MailAccountApiListMailAccountsRequest +from .types import MailAccountApiRemoveMailAccountRequest +from .types import OfferApiListOffersRequest +from .types import ResetHostingPasswordResponse +from .types import ResourceSummary +from .types import SearchDomainsResponse +from .types import Session +from .types import WebsiteApiListWebsitesRequest +from .api import WebhostingV1ControlPanelAPI +from .api import WebhostingV1DatabaseAPI +from .api import WebhostingV1DnsAPI +from .api import WebhostingV1OfferAPI +from .api import WebhostingV1HostingAPI +from .api import WebhostingV1FtpAccountAPI +from .api import WebhostingV1MailAccountAPI +from .api import WebhostingV1WebsiteAPI + +__all__ = [ + "DnsRecordStatus", + "DnsRecordType", + "DnsRecordsStatus", + "DomainAction", + "DomainAvailabilityAction", + "DomainAvailabilityStatus", + "DOMAIN_AVAILABILITY_TRANSIENT_STATUSES", + "DomainDnsAction", + "DomainStatus", + "DOMAIN_TRANSIENT_STATUSES", + "DomainZoneOwner", + "HostingStatus", + "HOSTING_TRANSIENT_STATUSES", + "ListDatabaseUsersRequestOrderBy", + "ListDatabasesRequestOrderBy", + "ListFtpAccountsRequestOrderBy", + "ListHostingsRequestOrderBy", + "ListMailAccountsRequestOrderBy", + "ListOffersRequestOrderBy", + "ListWebsitesRequestOrderBy", + "NameserverStatus", + "OfferOptionName", + "OfferOptionWarning", + "PlatformPlatformGroup", + "PlatformControlPanelUrls", + "OfferOption", + "PlatformControlPanel", + "CreateDatabaseRequestUser", + "AutoConfigDomainDns", + "CreateHostingRequestDomainConfiguration", + "OfferOptionRequest", + "SyncDomainDnsRecordsRequestRecord", + "DnsRecord", + "Nameserver", + "HostingUser", + "Offer", + "Platform", + "ControlPanel", + "DatabaseUser", + "Database", + "FtpAccount", + "HostingSummary", + "MailAccount", + "Website", + "DomainAvailability", + "CheckUserOwnsDomainResponse", + "ControlPanelApiListControlPanelsRequest", + "DatabaseApiAssignDatabaseUserRequest", + "DatabaseApiChangeDatabaseUserPasswordRequest", + "DatabaseApiCreateDatabaseRequest", + "DatabaseApiCreateDatabaseUserRequest", + "DatabaseApiDeleteDatabaseRequest", + "DatabaseApiDeleteDatabaseUserRequest", + "DatabaseApiGetDatabaseRequest", + "DatabaseApiGetDatabaseUserRequest", + "DatabaseApiListDatabaseUsersRequest", + "DatabaseApiListDatabasesRequest", + "DatabaseApiUnassignDatabaseUserRequest", + "DnsApiCheckUserOwnsDomainRequest", + "DnsApiGetDomainDnsRecordsRequest", + "DnsApiGetDomainRequest", + "DnsApiSearchDomainsRequest", + "DnsApiSyncDomainDnsRecordsRequest", + "DnsRecords", + "Domain", + "FtpAccountApiChangeFtpAccountPasswordRequest", + "FtpAccountApiCreateFtpAccountRequest", + "FtpAccountApiListFtpAccountsRequest", + "FtpAccountApiRemoveFtpAccountRequest", + "Hosting", + "HostingApiCreateHostingRequest", + "HostingApiCreateSessionRequest", + "HostingApiDeleteHostingRequest", + "HostingApiGetHostingRequest", + "HostingApiGetResourceSummaryRequest", + "HostingApiListHostingsRequest", + "HostingApiResetHostingPasswordRequest", + "HostingApiUpdateHostingRequest", + "ListControlPanelsResponse", + "ListDatabaseUsersResponse", + "ListDatabasesResponse", + "ListFtpAccountsResponse", + "ListHostingsResponse", + "ListMailAccountsResponse", + "ListOffersResponse", + "ListWebsitesResponse", + "MailAccountApiChangeMailAccountPasswordRequest", + "MailAccountApiCreateMailAccountRequest", + "MailAccountApiListMailAccountsRequest", + "MailAccountApiRemoveMailAccountRequest", + "OfferApiListOffersRequest", + "ResetHostingPasswordResponse", + "ResourceSummary", + "SearchDomainsResponse", + "Session", + "WebsiteApiListWebsitesRequest", + "WebhostingV1ControlPanelAPI", + "WebhostingV1DatabaseAPI", + "WebhostingV1DnsAPI", + "WebhostingV1OfferAPI", + "WebhostingV1HostingAPI", + "WebhostingV1FtpAccountAPI", + "WebhostingV1MailAccountAPI", + "WebhostingV1WebsiteAPI", +] diff --git a/scaleway/scaleway/webhosting/v1/api.py b/scaleway/scaleway/webhosting/v1/api.py new file mode 100644 index 00000000..7c925ee6 --- /dev/null +++ b/scaleway/scaleway/webhosting/v1/api.py @@ -0,0 +1,2115 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import List, Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + Region as ScwRegion, +) +from scaleway_core.utils import ( + WaitForOptions, + validate_path_param, + fetch_all_pages, + wait_for_resource, +) +from .types import ( + HostingStatus, + ListDatabaseUsersRequestOrderBy, + ListDatabasesRequestOrderBy, + ListFtpAccountsRequestOrderBy, + ListHostingsRequestOrderBy, + ListMailAccountsRequestOrderBy, + ListOffersRequestOrderBy, + ListWebsitesRequestOrderBy, + AutoConfigDomainDns, + CheckUserOwnsDomainResponse, + ControlPanel, + CreateDatabaseRequestUser, + CreateHostingRequestDomainConfiguration, + Database, + DatabaseApiAssignDatabaseUserRequest, + DatabaseApiChangeDatabaseUserPasswordRequest, + DatabaseApiCreateDatabaseRequest, + DatabaseApiCreateDatabaseUserRequest, + DatabaseApiUnassignDatabaseUserRequest, + DatabaseUser, + DnsApiCheckUserOwnsDomainRequest, + DnsApiSyncDomainDnsRecordsRequest, + DnsRecords, + Domain, + FtpAccount, + FtpAccountApiChangeFtpAccountPasswordRequest, + FtpAccountApiCreateFtpAccountRequest, + Hosting, + HostingApiCreateHostingRequest, + HostingApiUpdateHostingRequest, + HostingSummary, + ListControlPanelsResponse, + ListDatabaseUsersResponse, + ListDatabasesResponse, + ListFtpAccountsResponse, + ListHostingsResponse, + ListMailAccountsResponse, + ListOffersResponse, + ListWebsitesResponse, + MailAccount, + MailAccountApiChangeMailAccountPasswordRequest, + MailAccountApiCreateMailAccountRequest, + MailAccountApiRemoveMailAccountRequest, + Offer, + OfferOptionRequest, + ResetHostingPasswordResponse, + ResourceSummary, + SearchDomainsResponse, + Session, + SyncDomainDnsRecordsRequestRecord, + Website, +) +from .content import ( + DOMAIN_TRANSIENT_STATUSES, + HOSTING_TRANSIENT_STATUSES, +) +from .marshalling import ( + unmarshal_DatabaseUser, + unmarshal_Database, + unmarshal_FtpAccount, + unmarshal_MailAccount, + unmarshal_CheckUserOwnsDomainResponse, + unmarshal_DnsRecords, + unmarshal_Domain, + unmarshal_Hosting, + unmarshal_ListControlPanelsResponse, + unmarshal_ListDatabaseUsersResponse, + unmarshal_ListDatabasesResponse, + unmarshal_ListFtpAccountsResponse, + unmarshal_ListHostingsResponse, + unmarshal_ListMailAccountsResponse, + unmarshal_ListOffersResponse, + unmarshal_ListWebsitesResponse, + unmarshal_ResetHostingPasswordResponse, + unmarshal_ResourceSummary, + unmarshal_SearchDomainsResponse, + unmarshal_Session, + marshal_DatabaseApiAssignDatabaseUserRequest, + marshal_DatabaseApiChangeDatabaseUserPasswordRequest, + marshal_DatabaseApiCreateDatabaseRequest, + marshal_DatabaseApiCreateDatabaseUserRequest, + marshal_DatabaseApiUnassignDatabaseUserRequest, + marshal_DnsApiCheckUserOwnsDomainRequest, + marshal_DnsApiSyncDomainDnsRecordsRequest, + marshal_FtpAccountApiChangeFtpAccountPasswordRequest, + marshal_FtpAccountApiCreateFtpAccountRequest, + marshal_HostingApiCreateHostingRequest, + marshal_HostingApiUpdateHostingRequest, + marshal_MailAccountApiChangeMailAccountPasswordRequest, + marshal_MailAccountApiCreateMailAccountRequest, + marshal_MailAccountApiRemoveMailAccountRequest, +) +from ...std.types import ( + LanguageCode as StdLanguageCode, +) + + +class WebhostingV1ControlPanelAPI(API): + """ + This API allows you to manage your Web Hosting services. + """ + + def list_control_panels( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> ListControlPanelsResponse: + """ + "List the control panels type: cpanel or plesk.". + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of control panels to return (must be a positive integer lower or equal to 100). + :return: :class:`ListControlPanelsResponse ` + + Usage: + :: + + result = api.list_control_panels() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/control-panels", + params={ + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListControlPanelsResponse(res.json()) + + def list_control_panels_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + ) -> List[ControlPanel]: + """ + "List the control panels type: cpanel or plesk.". + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of control panels to return (must be a positive integer lower or equal to 100). + :return: :class:`List[ControlPanel] ` + + Usage: + :: + + result = api.list_control_panels_all() + """ + + return fetch_all_pages( + type=ListControlPanelsResponse, + key="control_panels", + fetcher=self.list_control_panels, + args={ + "region": region, + "page": page, + "page_size": page_size, + }, + ) + + +class WebhostingV1DatabaseAPI(API): + """ + This API allows you to manage your databases and database users for your Web Hosting services. + """ + + def create_database( + self, + *, + hosting_id: str, + database_name: str, + region: Optional[ScwRegion] = None, + new_user: Optional[CreateDatabaseRequestUser] = None, + existing_username: Optional[str] = None, + ) -> Database: + """ + "Create a new database within your hosting plan". + :param hosting_id: UUID of the hosting plan where the database will be created. + :param database_name: Name of the database to be created. + :param region: Region to target. If none is passed will use default region from the config. + :param new_user: (Optional) Username and password to create a user and link to the database. + One-Of ('user'): at most one of 'new_user', 'existing_username' could be set. + :param existing_username: (Optional) Username to link an existing user to the database. + One-Of ('user'): at most one of 'new_user', 'existing_username' could be set. + :return: :class:`Database ` + + Usage: + :: + + result = api.create_database( + hosting_id="example", + database_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases", + body=marshal_DatabaseApiCreateDatabaseRequest( + DatabaseApiCreateDatabaseRequest( + hosting_id=hosting_id, + database_name=database_name, + region=region, + new_user=new_user, + existing_username=existing_username, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Database(res.json()) + + def list_databases( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDatabasesRequestOrderBy] = None, + ) -> ListDatabasesResponse: + """ + "List all databases within your hosting plan". + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of databases to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of databases in the response. + :return: :class:`ListDatabasesResponse ` + + Usage: + :: + + result = api.list_databases( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDatabasesResponse(res.json()) + + def list_databases_all( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDatabasesRequestOrderBy] = None, + ) -> List[Database]: + """ + "List all databases within your hosting plan". + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of databases to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of databases in the response. + :return: :class:`List[Database] ` + + Usage: + :: + + result = api.list_databases_all( + hosting_id="example", + ) + """ + + return fetch_all_pages( + type=ListDatabasesResponse, + key="databases", + fetcher=self.list_databases, + args={ + "hosting_id": hosting_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + def get_database( + self, + *, + hosting_id: str, + database_name: str, + region: Optional[ScwRegion] = None, + ) -> Database: + """ + "Get details of a database within your hosting plan". + :param hosting_id: UUID of the hosting plan. + :param database_name: Name of the database. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Database ` + + Usage: + :: + + result = api.get_database( + hosting_id="example", + database_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_database_name = validate_path_param("database_name", database_name) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases/{param_database_name}", + ) + + self._throw_on_error(res) + return unmarshal_Database(res.json()) + + def delete_database( + self, + *, + hosting_id: str, + database_name: str, + region: Optional[ScwRegion] = None, + ) -> Database: + """ + "Delete a database within your hosting plan". + :param hosting_id: UUID of the hosting plan. + :param database_name: Name of the database to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Database ` + + Usage: + :: + + result = api.delete_database( + hosting_id="example", + database_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_database_name = validate_path_param("database_name", database_name) + + res = self._request( + "DELETE", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases/{param_database_name}", + ) + + self._throw_on_error(res) + return unmarshal_Database(res.json()) + + def create_database_user( + self, + *, + hosting_id: str, + username: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Create a new database user". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the user to create. + :param password: Password of the user to create. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = api.create_database_user( + hosting_id="example", + username="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases-users", + body=marshal_DatabaseApiCreateDatabaseUserRequest( + DatabaseApiCreateDatabaseUserRequest( + hosting_id=hosting_id, + username=username, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + def list_database_users( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDatabaseUsersRequestOrderBy] = None, + ) -> ListDatabaseUsersResponse: + """ + "List all database users". + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of database users to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of database users in the response. + :return: :class:`ListDatabaseUsersResponse ` + + Usage: + :: + + result = api.list_database_users( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/database-users", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListDatabaseUsersResponse(res.json()) + + def list_database_users_all( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListDatabaseUsersRequestOrderBy] = None, + ) -> List[DatabaseUser]: + """ + "List all database users". + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of database users to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of database users in the response. + :return: :class:`List[DatabaseUser] ` + + Usage: + :: + + result = api.list_database_users_all( + hosting_id="example", + ) + """ + + return fetch_all_pages( + type=ListDatabaseUsersResponse, + key="users", + fetcher=self.list_database_users, + args={ + "hosting_id": hosting_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) + + def get_database_user( + self, + *, + hosting_id: str, + username: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Get details of a database user". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the database user to retrieve details. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = api.get_database_user( + hosting_id="example", + username="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_username = validate_path_param("username", username) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases-users/{param_username}", + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + def delete_database_user( + self, + *, + hosting_id: str, + username: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Delete a database user". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the database user to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = api.delete_database_user( + hosting_id="example", + username="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_username = validate_path_param("username", username) + + res = self._request( + "DELETE", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/database-users/{param_username}", + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + def change_database_user_password( + self, + *, + hosting_id: str, + username: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Change the password of a database user". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the user to update. + :param password: New password. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = api.change_database_user_password( + hosting_id="example", + username="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_username = validate_path_param("username", username) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases-users/{param_username}/change-password", + body=marshal_DatabaseApiChangeDatabaseUserPasswordRequest( + DatabaseApiChangeDatabaseUserPasswordRequest( + hosting_id=hosting_id, + username=username, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + def assign_database_user( + self, + *, + hosting_id: str, + username: str, + database_name: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Assign a database user to a database". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the user to assign. + :param database_name: Name of the database to be assigned. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = api.assign_database_user( + hosting_id="example", + username="example", + database_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_database_name = validate_path_param("database_name", database_name) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases/{param_database_name}/assign-user", + body=marshal_DatabaseApiAssignDatabaseUserRequest( + DatabaseApiAssignDatabaseUserRequest( + hosting_id=hosting_id, + username=username, + database_name=database_name, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + def unassign_database_user( + self, + *, + hosting_id: str, + username: str, + database_name: str, + region: Optional[ScwRegion] = None, + ) -> DatabaseUser: + """ + "Unassign a database user from a database". + :param hosting_id: UUID of the hosting plan. + :param username: Name of the user to unassign. + :param database_name: Name of the database to be unassigned. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DatabaseUser ` + + Usage: + :: + + result = api.unassign_database_user( + hosting_id="example", + username="example", + database_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_database_name = validate_path_param("database_name", database_name) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/databases/{param_database_name}/unassign-user", + body=marshal_DatabaseApiUnassignDatabaseUserRequest( + DatabaseApiUnassignDatabaseUserRequest( + hosting_id=hosting_id, + username=username, + database_name=database_name, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DatabaseUser(res.json()) + + +class WebhostingV1DnsAPI(API): + """ + This API allows you to manage your Web Hosting services. + """ + + def get_domain_dns_records( + self, + *, + domain: str, + region: Optional[ScwRegion] = None, + ) -> DnsRecords: + """ + Get DNS records. + Get the set of DNS records of a specified domain associated with a Web Hosting plan's domain. + :param domain: Domain associated with the DNS records. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`DnsRecords ` + + Usage: + :: + + result = api.get_domain_dns_records( + domain="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain = validate_path_param("domain", domain) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/domains/{param_domain}/dns-records", + ) + + self._throw_on_error(res) + return unmarshal_DnsRecords(res.json()) + + def check_user_owns_domain( + self, + *, + domain: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> CheckUserOwnsDomainResponse: + """ + Check whether you own this domain or not. + :param domain: Domain for which ownership is to be verified. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project currently in use. + :return: :class:`CheckUserOwnsDomainResponse ` + + Usage: + :: + + result = api.check_user_owns_domain( + domain="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain = validate_path_param("domain", domain) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/domains/{param_domain}/check-ownership", + body=marshal_DnsApiCheckUserOwnsDomainRequest( + DnsApiCheckUserOwnsDomainRequest( + domain=domain, + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckUserOwnsDomainResponse(res.json()) + + def sync_domain_dns_records( + self, + *, + domain: str, + region: Optional[ScwRegion] = None, + update_web_records: Optional[bool] = None, + update_mail_records: Optional[bool] = None, + update_all_records: Optional[bool] = None, + update_nameservers: Optional[bool] = None, + custom_records: Optional[List[SyncDomainDnsRecordsRequestRecord]] = None, + auto_config_domain_dns: Optional[AutoConfigDomainDns] = None, + ) -> DnsRecords: + """ + Synchronize your DNS records on the Elements Console and on cPanel. + :param domain: Domain for which the DNS records will be synchronized. + :param region: Region to target. If none is passed will use default region from the config. + :param update_web_records: Whether or not to synchronize the web records (deprecated, use auto_config_domain_dns). + :param update_mail_records: Whether or not to synchronize the mail records (deprecated, use auto_config_domain_dns). + :param update_all_records: Whether or not to synchronize all types of records. This one has priority (deprecated, use auto_config_domain_dns). + :param update_nameservers: Whether or not to synchronize domain nameservers (deprecated, use auto_config_domain_dns). + :param custom_records: Custom records to synchronize. + :param auto_config_domain_dns: Whether or not to synchronize each types of records. + :return: :class:`DnsRecords ` + + Usage: + :: + + result = api.sync_domain_dns_records( + domain="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain = validate_path_param("domain", domain) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/domains/{param_domain}/sync-domain-dns-records", + body=marshal_DnsApiSyncDomainDnsRecordsRequest( + DnsApiSyncDomainDnsRecordsRequest( + domain=domain, + region=region, + update_web_records=update_web_records, + update_mail_records=update_mail_records, + update_all_records=update_all_records, + update_nameservers=update_nameservers, + custom_records=custom_records, + auto_config_domain_dns=auto_config_domain_dns, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_DnsRecords(res.json()) + + def search_domains( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> SearchDomainsResponse: + """ + Search for available domains based on domain name. + :param domain_name: Domain name to search. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to search the domain to create the Web Hosting plan. + :return: :class:`SearchDomainsResponse ` + + Usage: + :: + + result = api.search_domains( + domain_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/search-domains", + params={ + "domain_name": domain_name, + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_SearchDomainsResponse(res.json()) + + def get_domain( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> Domain: + """ + Retrieve detailed information about a specific domain, including its status, DNS configuration, and ownership. + :param domain_name: Domain name to get. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + :return: :class:`Domain ` + + Usage: + :: + + result = api.get_domain( + domain_name="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain_name = validate_path_param("domain_name", domain_name) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/domains/{param_domain_name}", + params={ + "project_id": project_id or self.client.default_project_id, + }, + ) + + self._throw_on_error(res) + return unmarshal_Domain(res.json()) + + def wait_for_domain( + self, + *, + domain_name: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + options: Optional[WaitForOptions[Domain, bool]] = None, + ) -> Domain: + """ + Retrieve detailed information about a specific domain, including its status, DNS configuration, and ownership. + :param domain_name: Domain name to get. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + :return: :class:`Domain ` + + Usage: + :: + + result = api.get_domain( + domain_name="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in DOMAIN_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_domain, + options=options, + args={ + "domain_name": domain_name, + "region": region, + "project_id": project_id, + }, + ) + + +class WebhostingV1OfferAPI(API): + """ + This API allows you to manage your offer for your Web Hosting services. + """ + + def list_offers( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOffersRequestOrderBy] = None, + hosting_id: Optional[str] = None, + control_panels: Optional[List[str]] = None, + ) -> ListOffersResponse: + """ + List all available hosting offers along with their specific options. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of websites to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting offers in the response. + :param hosting_id: UUID of the hosting plan. + :param control_panels: Name of the control panel(s) to filter for. + :return: :class:`ListOffersResponse ` + + Usage: + :: + + result = api.list_offers() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/offers", + params={ + "control_panels": control_panels, + "hosting_id": hosting_id, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListOffersResponse(res.json()) + + def list_offers_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListOffersRequestOrderBy] = None, + hosting_id: Optional[str] = None, + control_panels: Optional[List[str]] = None, + ) -> List[Offer]: + """ + List all available hosting offers along with their specific options. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of websites to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting offers in the response. + :param hosting_id: UUID of the hosting plan. + :param control_panels: Name of the control panel(s) to filter for. + :return: :class:`List[Offer] ` + + Usage: + :: + + result = api.list_offers_all() + """ + + return fetch_all_pages( + type=ListOffersResponse, + key="offers", + fetcher=self.list_offers, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "hosting_id": hosting_id, + "control_panels": control_panels, + }, + ) + + +class WebhostingV1HostingAPI(API): + """ + This API allows you to manage your Web Hosting services. + """ + + def create_hosting( + self, + *, + offer_id: str, + email: str, + domain: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + tags: Optional[List[str]] = None, + offer_options: Optional[List[OfferOptionRequest]] = None, + language: Optional[StdLanguageCode] = None, + domain_configuration: Optional[CreateHostingRequestDomainConfiguration] = None, + skip_welcome_email: Optional[bool] = None, + auto_config_domain_dns: Optional[AutoConfigDomainDns] = None, + ) -> Hosting: + """ + Order a Web Hosting plan. + Order a Web Hosting plan, specifying the offer type required via the `offer_id` parameter. + :param offer_id: ID of the selected offer for the Web Hosting plan. + :param email: Contact email for the Web Hosting client. + :param domain: Domain name to link to the Web Hosting plan. You must already own this domain name, and have completed the DNS validation process beforehand. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the Scaleway Project in which to create the Web Hosting plan. + :param tags: List of tags for the Web Hosting plan. + :param offer_options: List of the Web Hosting plan options IDs with their quantities. + :param language: Default language for the control panel interface. + :param domain_configuration: Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_config_domain_dns instead). + :param skip_welcome_email: Indicates whether to skip a welcome email to the contact email containing hosting info. + :param auto_config_domain_dns: Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_update_* fields instead). + :return: :class:`Hosting ` + + Usage: + :: + + result = api.create_hosting( + offer_id="example", + email="example", + domain="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings", + body=marshal_HostingApiCreateHostingRequest( + HostingApiCreateHostingRequest( + offer_id=offer_id, + email=email, + domain=domain, + region=region, + project_id=project_id, + tags=tags, + offer_options=offer_options, + language=language, + domain_configuration=domain_configuration, + skip_welcome_email=skip_welcome_email, + auto_config_domain_dns=auto_config_domain_dns, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Hosting(res.json()) + + def list_hostings( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListHostingsRequestOrderBy] = None, + tags: Optional[List[str]] = None, + statuses: Optional[List[HostingStatus]] = None, + domain: Optional[str] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + control_panels: Optional[List[str]] = None, + ) -> ListHostingsResponse: + """ + List all Web Hosting plans. + List all of your existing Web Hosting plans. Various filters are available to limit the results, including filtering by domain, status, tag and Project ID. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results (must be a positive integer). + :param page_size: Number of Web Hosting plans to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting plans in the response. + :param tags: Tags to filter for, only Web Hosting plans with matching tags will be returned. + :param statuses: Statuses to filter for, only Web Hosting plans with matching statuses will be returned. + :param domain: Domain to filter for, only Web Hosting plans associated with this domain will be returned. + :param project_id: Project ID to filter for, only Web Hosting plans from this Project will be returned. + :param organization_id: Organization ID to filter for, only Web Hosting plans from this Organization will be returned. + :param control_panels: Name of the control panel to filter for, only Web Hosting plans from this control panel will be returned. + :return: :class:`ListHostingsResponse ` + + Usage: + :: + + result = api.list_hostings() + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings", + params={ + "control_panels": control_panels, + "domain": domain, + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "project_id": project_id or self.client.default_project_id, + "statuses": statuses, + "tags": tags, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListHostingsResponse(res.json()) + + def list_hostings_all( + self, + *, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListHostingsRequestOrderBy] = None, + tags: Optional[List[str]] = None, + statuses: Optional[List[HostingStatus]] = None, + domain: Optional[str] = None, + project_id: Optional[str] = None, + organization_id: Optional[str] = None, + control_panels: Optional[List[str]] = None, + ) -> List[HostingSummary]: + """ + List all Web Hosting plans. + List all of your existing Web Hosting plans. Various filters are available to limit the results, including filtering by domain, status, tag and Project ID. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number to return, from the paginated results (must be a positive integer). + :param page_size: Number of Web Hosting plans to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting plans in the response. + :param tags: Tags to filter for, only Web Hosting plans with matching tags will be returned. + :param statuses: Statuses to filter for, only Web Hosting plans with matching statuses will be returned. + :param domain: Domain to filter for, only Web Hosting plans associated with this domain will be returned. + :param project_id: Project ID to filter for, only Web Hosting plans from this Project will be returned. + :param organization_id: Organization ID to filter for, only Web Hosting plans from this Organization will be returned. + :param control_panels: Name of the control panel to filter for, only Web Hosting plans from this control panel will be returned. + :return: :class:`List[HostingSummary] ` + + Usage: + :: + + result = api.list_hostings_all() + """ + + return fetch_all_pages( + type=ListHostingsResponse, + key="hostings", + fetcher=self.list_hostings, + args={ + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "tags": tags, + "statuses": statuses, + "domain": domain, + "project_id": project_id, + "organization_id": organization_id, + "control_panels": control_panels, + }, + ) + + def get_hosting( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> Hosting: + """ + Get a Web Hosting plan. + Get the details of one of your existing Web Hosting plans, specified by its `hosting_id`. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Hosting ` + + Usage: + :: + + result = api.get_hosting( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}", + ) + + self._throw_on_error(res) + return unmarshal_Hosting(res.json()) + + def wait_for_hosting( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + options: Optional[WaitForOptions[Hosting, bool]] = None, + ) -> Hosting: + """ + Get a Web Hosting plan. + Get the details of one of your existing Web Hosting plans, specified by its `hosting_id`. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Hosting ` + + Usage: + :: + + result = api.get_hosting( + hosting_id="example", + ) + """ + + if not options: + options = WaitForOptions() + + if not options.stop: + options.stop = lambda res: res.status not in HOSTING_TRANSIENT_STATUSES + + return wait_for_resource( + fetcher=self.get_hosting, + options=options, + args={ + "hosting_id": hosting_id, + "region": region, + }, + ) + + def update_hosting( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + email: Optional[str] = None, + tags: Optional[List[str]] = None, + offer_options: Optional[List[OfferOptionRequest]] = None, + offer_id: Optional[str] = None, + protected: Optional[bool] = None, + ) -> Hosting: + """ + Update a Web Hosting plan. + Update the details of one of your existing Web Hosting plans, specified by its `hosting_id`. You can update parameters including the contact email address, tags, options and offer. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :param email: New contact email for the Web Hosting plan. + :param tags: New tags for the Web Hosting plan. + :param offer_options: List of the Web Hosting plan options IDs with their quantities. + :param offer_id: ID of the new offer for the Web Hosting plan. + :param protected: Whether the hosting is protected or not. + :return: :class:`Hosting ` + + Usage: + :: + + result = api.update_hosting( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "PATCH", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}", + body=marshal_HostingApiUpdateHostingRequest( + HostingApiUpdateHostingRequest( + hosting_id=hosting_id, + region=region, + email=email, + tags=tags, + offer_options=offer_options, + offer_id=offer_id, + protected=protected, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Hosting(res.json()) + + def delete_hosting( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> Hosting: + """ + Delete a Web Hosting plan. + Delete a Web Hosting plan, specified by its `hosting_id`. Note that deletion is not immediate: it will take place at the end of the calendar month, after which time your Web Hosting plan and all its data (files and emails) will be irreversibly lost. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Hosting ` + + Usage: + :: + + result = api.delete_hosting( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "DELETE", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}", + ) + + self._throw_on_error(res) + return unmarshal_Hosting(res.json()) + + def create_session( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> Session: + """ + Create a user session. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Session ` + + Usage: + :: + + result = api.create_session( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/sessions", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Session(res.json()) + + def reset_hosting_password( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> ResetHostingPasswordResponse: + """ + Reset a Web Hosting plan password. + :param hosting_id: UUID of the hosting. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ResetHostingPasswordResponse ` + + Usage: + :: + + result = api.reset_hosting_password( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/reset-password", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_ResetHostingPasswordResponse(res.json()) + + def get_resource_summary( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> ResourceSummary: + """ + Get the total counts of websites, databases, email accounts, and FTP accounts of a Web Hosting plan. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ResourceSummary ` + + Usage: + :: + + result = api.get_resource_summary( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/resource-summary", + ) + + self._throw_on_error(res) + return unmarshal_ResourceSummary(res.json()) + + +class WebhostingV1FtpAccountAPI(API): + """ + This API allows you to manage your FTP accounts for your Web Hosting services. + """ + + def create_ftp_account( + self, + *, + hosting_id: str, + username: str, + path: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> FtpAccount: + """ + Create a new FTP account within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param username: Username for the new FTP account. + :param path: Path for the new FTP account. + :param password: Password for the new FTP account. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`FtpAccount ` + + Usage: + :: + + result = api.create_ftp_account( + hosting_id="example", + username="example", + path="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/ftp-accounts", + body=marshal_FtpAccountApiCreateFtpAccountRequest( + FtpAccountApiCreateFtpAccountRequest( + hosting_id=hosting_id, + username=username, + path=path, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_FtpAccount(res.json()) + + def list_ftp_accounts( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListFtpAccountsRequestOrderBy] = None, + domain: Optional[str] = None, + ) -> ListFtpAccountsResponse: + """ + List all FTP accounts within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of FTP accounts to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of FTP accounts in the response. + :param domain: Domain to filter the FTP accounts. + :return: :class:`ListFtpAccountsResponse ` + + Usage: + :: + + result = api.list_ftp_accounts( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/ftp-accounts", + params={ + "domain": domain, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListFtpAccountsResponse(res.json()) + + def list_ftp_accounts_all( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListFtpAccountsRequestOrderBy] = None, + domain: Optional[str] = None, + ) -> List[FtpAccount]: + """ + List all FTP accounts within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of FTP accounts to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of FTP accounts in the response. + :param domain: Domain to filter the FTP accounts. + :return: :class:`List[FtpAccount] ` + + Usage: + :: + + result = api.list_ftp_accounts_all( + hosting_id="example", + ) + """ + + return fetch_all_pages( + type=ListFtpAccountsResponse, + key="ftp_accounts", + fetcher=self.list_ftp_accounts, + args={ + "hosting_id": hosting_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "domain": domain, + }, + ) + + def remove_ftp_account( + self, + *, + hosting_id: str, + username: str, + region: Optional[ScwRegion] = None, + ) -> FtpAccount: + """ + Delete a specific FTP account within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param username: Username of the FTP account to be deleted. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`FtpAccount ` + + Usage: + :: + + result = api.remove_ftp_account( + hosting_id="example", + username="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_username = validate_path_param("username", username) + + res = self._request( + "DELETE", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/ftp-accounts/{param_username}", + ) + + self._throw_on_error(res) + return unmarshal_FtpAccount(res.json()) + + def change_ftp_account_password( + self, + *, + hosting_id: str, + username: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> FtpAccount: + """ + :param hosting_id: UUID of the hosting plan. + :param username: Username of the FTP account. + :param password: New password for the FTP account. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`FtpAccount ` + + Usage: + :: + + result = api.change_ftp_account_password( + hosting_id="example", + username="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + param_username = validate_path_param("username", username) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/ftp-accounts/{param_username}/change-password", + body=marshal_FtpAccountApiChangeFtpAccountPasswordRequest( + FtpAccountApiChangeFtpAccountPasswordRequest( + hosting_id=hosting_id, + username=username, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_FtpAccount(res.json()) + + +class WebhostingV1MailAccountAPI(API): + """ + This API allows you to manage your mail accounts for your Web Hosting services. + """ + + def create_mail_account( + self, + *, + hosting_id: str, + domain: str, + username: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> MailAccount: + """ + Create a new mail account within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param domain: Domain part of the mail account address. + :param username: Username part address of the mail account address. + :param password: Password for the new mail account. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`MailAccount ` + + Usage: + :: + + result = api.create_mail_account( + hosting_id="example", + domain="example", + username="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/mail-accounts", + body=marshal_MailAccountApiCreateMailAccountRequest( + MailAccountApiCreateMailAccountRequest( + hosting_id=hosting_id, + domain=domain, + username=username, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_MailAccount(res.json()) + + def list_mail_accounts( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListMailAccountsRequestOrderBy] = None, + domain: Optional[str] = None, + ) -> ListMailAccountsResponse: + """ + List all mail accounts within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of mail accounts to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of mail accounts in the response. + :param domain: Domain to filter the mail accounts. + :return: :class:`ListMailAccountsResponse ` + + Usage: + :: + + result = api.list_mail_accounts( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/mail-accounts", + params={ + "domain": domain, + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListMailAccountsResponse(res.json()) + + def list_mail_accounts_all( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListMailAccountsRequestOrderBy] = None, + domain: Optional[str] = None, + ) -> List[MailAccount]: + """ + List all mail accounts within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of mail accounts to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order of mail accounts in the response. + :param domain: Domain to filter the mail accounts. + :return: :class:`List[MailAccount] ` + + Usage: + :: + + result = api.list_mail_accounts_all( + hosting_id="example", + ) + """ + + return fetch_all_pages( + type=ListMailAccountsResponse, + key="mail_accounts", + fetcher=self.list_mail_accounts, + args={ + "hosting_id": hosting_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + "domain": domain, + }, + ) + + def remove_mail_account( + self, + *, + hosting_id: str, + domain: str, + username: str, + region: Optional[ScwRegion] = None, + ) -> MailAccount: + """ + Delete a mail account within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param domain: Domain part of the mail account address. + :param username: Username part of the mail account address. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`MailAccount ` + + Usage: + :: + + result = api.remove_mail_account( + hosting_id="example", + domain="example", + username="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/remove-mail-account", + body=marshal_MailAccountApiRemoveMailAccountRequest( + MailAccountApiRemoveMailAccountRequest( + hosting_id=hosting_id, + domain=domain, + username=username, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_MailAccount(res.json()) + + def change_mail_account_password( + self, + *, + hosting_id: str, + domain: str, + username: str, + password: str, + region: Optional[ScwRegion] = None, + ) -> MailAccount: + """ + Update the password of a mail account within your hosting plan. + :param hosting_id: UUID of the hosting plan. + :param domain: Domain part of the mail account address. + :param username: Username part of the mail account address. + :param password: New password for the mail account. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`MailAccount ` + + Usage: + :: + + result = api.change_mail_account_password( + hosting_id="example", + domain="example", + username="example", + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/change-mail-password", + body=marshal_MailAccountApiChangeMailAccountPasswordRequest( + MailAccountApiChangeMailAccountPasswordRequest( + hosting_id=hosting_id, + domain=domain, + username=username, + password=password, + region=region, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_MailAccount(res.json()) + + +class WebhostingV1WebsiteAPI(API): + """ + This API allows you to manage your websites for your Web Hosting services. + """ + + def list_websites( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListWebsitesRequestOrderBy] = None, + ) -> ListWebsitesResponse: + """ + List all websites for a specific hosting. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of websites to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting websites in the response. + :return: :class:`ListWebsitesResponse ` + + Usage: + :: + + result = api.list_websites( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "GET", + f"/webhosting/v1/regions/{param_region}/hostings/{param_hosting_id}/websites", + params={ + "order_by": order_by, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListWebsitesResponse(res.json()) + + def list_websites_all( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListWebsitesRequestOrderBy] = None, + ) -> List[Website]: + """ + List all websites for a specific hosting. + :param hosting_id: UUID of the hosting plan. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of websites to return (must be a positive integer lower or equal to 100). + :param order_by: Sort order for Web Hosting websites in the response. + :return: :class:`List[Website] ` + + Usage: + :: + + result = api.list_websites_all( + hosting_id="example", + ) + """ + + return fetch_all_pages( + type=ListWebsitesResponse, + key="websites", + fetcher=self.list_websites, + args={ + "hosting_id": hosting_id, + "region": region, + "page": page, + "page_size": page_size, + "order_by": order_by, + }, + ) diff --git a/scaleway/scaleway/webhosting/v1/content.py b/scaleway/scaleway/webhosting/v1/content.py new file mode 100644 index 00000000..9c1b79cf --- /dev/null +++ b/scaleway/scaleway/webhosting/v1/content.py @@ -0,0 +1,30 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from typing import List + +from .types import ( + DomainAvailabilityStatus, + DomainStatus, + HostingStatus, +) + +DOMAIN_AVAILABILITY_TRANSIENT_STATUSES: List[DomainAvailabilityStatus] = [ + DomainAvailabilityStatus.VALIDATING, +] +""" +Lists transient statutes of the enum :class:`DomainAvailabilityStatus `. +""" +DOMAIN_TRANSIENT_STATUSES: List[DomainStatus] = [ + DomainStatus.VALIDATING, +] +""" +Lists transient statutes of the enum :class:`DomainStatus `. +""" +HOSTING_TRANSIENT_STATUSES: List[HostingStatus] = [ + HostingStatus.DELIVERING, + HostingStatus.DELETING, + HostingStatus.MIGRATING, +] +""" +Lists transient statutes of the enum :class:`HostingStatus `. +""" diff --git a/scaleway/scaleway/webhosting/v1/marshalling.py b/scaleway/scaleway/webhosting/v1/marshalling.py new file mode 100644 index 00000000..20e51fb2 --- /dev/null +++ b/scaleway/scaleway/webhosting/v1/marshalling.py @@ -0,0 +1,1391 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any, Dict +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from scaleway_core.bridge import ( + unmarshal_Money, +) +from scaleway_core.utils import ( + OneOfPossibility, + resolve_one_of, +) +from .types import ( + DomainAction, + DomainAvailabilityAction, + DomainDnsAction, + DatabaseUser, + Database, + FtpAccount, + MailAccount, + CheckUserOwnsDomainResponse, + AutoConfigDomainDns, + DnsRecord, + Nameserver, + DnsRecords, + Domain, + PlatformControlPanelUrls, + OfferOption, + PlatformControlPanel, + HostingUser, + Offer, + Platform, + Hosting, + ControlPanel, + ListControlPanelsResponse, + ListDatabaseUsersResponse, + ListDatabasesResponse, + ListFtpAccountsResponse, + HostingSummary, + ListHostingsResponse, + ListMailAccountsResponse, + ListOffersResponse, + Website, + ListWebsitesResponse, + ResetHostingPasswordResponse, + ResourceSummary, + DomainAvailability, + SearchDomainsResponse, + Session, + DatabaseApiAssignDatabaseUserRequest, + DatabaseApiChangeDatabaseUserPasswordRequest, + CreateDatabaseRequestUser, + DatabaseApiCreateDatabaseRequest, + DatabaseApiCreateDatabaseUserRequest, + DatabaseApiUnassignDatabaseUserRequest, + DnsApiCheckUserOwnsDomainRequest, + SyncDomainDnsRecordsRequestRecord, + DnsApiSyncDomainDnsRecordsRequest, + FtpAccountApiChangeFtpAccountPasswordRequest, + FtpAccountApiCreateFtpAccountRequest, + CreateHostingRequestDomainConfiguration, + OfferOptionRequest, + HostingApiCreateHostingRequest, + HostingApiUpdateHostingRequest, + MailAccountApiChangeMailAccountPasswordRequest, + MailAccountApiCreateMailAccountRequest, + MailAccountApiRemoveMailAccountRequest, +) +from ...std.types import ( + LanguageCode as StdLanguageCode, +) + + +def unmarshal_DatabaseUser(data: Any) -> DatabaseUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DatabaseUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("databases", None) + if field is not None: + args["databases"] = field + + return DatabaseUser(**args) + + +def unmarshal_Database(data: Any) -> Database: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Database' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("database_name", None) + if field is not None: + args["database_name"] = field + + field = data.get("users", None) + if field is not None: + args["users"] = field + + return Database(**args) + + +def unmarshal_FtpAccount(data: Any) -> FtpAccount: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'FtpAccount' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("path", None) + if field is not None: + args["path"] = field + + return FtpAccount(**args) + + +def unmarshal_MailAccount(data: Any) -> MailAccount: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'MailAccount' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("username", None) + if field is not None: + args["username"] = field + + return MailAccount(**args) + + +def unmarshal_CheckUserOwnsDomainResponse(data: Any) -> CheckUserOwnsDomainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckUserOwnsDomainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("owns_domain", None) + if field is not None: + args["owns_domain"] = field + + return CheckUserOwnsDomainResponse(**args) + + +def unmarshal_AutoConfigDomainDns(data: Any) -> AutoConfigDomainDns: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'AutoConfigDomainDns' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("nameservers", None) + if field is not None: + args["nameservers"] = field + + field = data.get("web_records", None) + if field is not None: + args["web_records"] = field + + field = data.get("mail_records", None) + if field is not None: + args["mail_records"] = field + + field = data.get("all_records", None) + if field is not None: + args["all_records"] = field + + field = data.get("none", None) + if field is not None: + args["none"] = field + + return AutoConfigDomainDns(**args) + + +def unmarshal_DnsRecord(data: Any) -> DnsRecord: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DnsRecord' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("type", None) + if field is not None: + args["type_"] = field + + field = data.get("ttl", None) + if field is not None: + args["ttl"] = field + + field = data.get("value", None) + if field is not None: + args["value"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("raw_data", None) + if field is not None: + args["raw_data"] = field + + field = data.get("priority", None) + if field is not None: + args["priority"] = field + else: + args["priority"] = None + + return DnsRecord(**args) + + +def unmarshal_Nameserver(data: Any) -> Nameserver: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Nameserver' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("is_default", None) + if field is not None: + args["is_default"] = field + + return Nameserver(**args) + + +def unmarshal_DnsRecords(data: Any) -> DnsRecords: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DnsRecords' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("records", None) + if field is not None: + args["records"] = ( + [unmarshal_DnsRecord(v) for v in field] if field is not None else None + ) + + field = data.get("name_servers", None) + if field is not None: + args["name_servers"] = ( + [unmarshal_Nameserver(v) for v in field] if field is not None else None + ) + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("dns_config", None) + if field is not None: + args["dns_config"] = ( + [DomainDnsAction(v) for v in field] if field is not None else None + ) + else: + args["dns_config"] = None + + field = data.get("auto_config_domain_dns", None) + if field is not None: + args["auto_config_domain_dns"] = unmarshal_AutoConfigDomainDns(field) + else: + args["auto_config_domain_dns"] = None + + return DnsRecords(**args) + + +def unmarshal_Domain(data: Any) -> Domain: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Domain' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("owner", None) + if field is not None: + args["owner"] = field + + field = data.get("available_actions", None) + if field is not None: + args["available_actions"] = ( + [DomainAction(v) for v in field] if field is not None else None + ) + + field = data.get("available_dns_actions", None) + if field is not None: + args["available_dns_actions"] = ( + [DomainDnsAction(v) for v in field] if field is not None else None + ) + else: + args["available_dns_actions"] = None + + field = data.get("auto_config_domain_dns", None) + if field is not None: + args["auto_config_domain_dns"] = unmarshal_AutoConfigDomainDns(field) + else: + args["auto_config_domain_dns"] = None + + return Domain(**args) + + +def unmarshal_PlatformControlPanelUrls(data: Any) -> PlatformControlPanelUrls: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlatformControlPanelUrls' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("dashboard", None) + if field is not None: + args["dashboard"] = field + + field = data.get("webmail", None) + if field is not None: + args["webmail"] = field + + return PlatformControlPanelUrls(**args) + + +def unmarshal_OfferOption(data: Any) -> OfferOption: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'OfferOption' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("billing_operation_path", None) + if field is not None: + args["billing_operation_path"] = field + + field = data.get("min_value", None) + if field is not None: + args["min_value"] = field + + field = data.get("current_value", None) + if field is not None: + args["current_value"] = field + + field = data.get("max_value", None) + if field is not None: + args["max_value"] = field + + field = data.get("quota_warning", None) + if field is not None: + args["quota_warning"] = field + + field = data.get("price", None) + if field is not None: + args["price"] = unmarshal_Money(field) + else: + args["price"] = None + + return OfferOption(**args) + + +def unmarshal_PlatformControlPanel(data: Any) -> PlatformControlPanel: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'PlatformControlPanel' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("urls", None) + if field is not None: + args["urls"] = unmarshal_PlatformControlPanelUrls(field) + else: + args["urls"] = None + + return PlatformControlPanel(**args) + + +def unmarshal_HostingUser(data: Any) -> HostingUser: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HostingUser' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("username", None) + if field is not None: + args["username"] = field + + field = data.get("contact_email", None) + if field is not None: + args["contact_email"] = field + + field = data.get("one_time_password", None) + if field is not None: + args["one_time_password"] = field + else: + args["one_time_password"] = None + + field = data.get("one_time_password_b64", None) + if field is not None: + args["one_time_password_b64"] = field + else: + args["one_time_password_b64"] = None + + return HostingUser(**args) + + +def unmarshal_Offer(data: Any) -> Offer: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Offer' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("billing_operation_path", None) + if field is not None: + args["billing_operation_path"] = field + + field = data.get("options", None) + if field is not None: + args["options"] = ( + [unmarshal_OfferOption(v) for v in field] if field is not None else None + ) + + field = data.get("available", None) + if field is not None: + args["available"] = field + + field = data.get("control_panel_name", None) + if field is not None: + args["control_panel_name"] = field + + field = data.get("end_of_life", None) + if field is not None: + args["end_of_life"] = field + + field = data.get("quota_warning", None) + if field is not None: + args["quota_warning"] = field + + field = data.get("price", None) + if field is not None: + args["price"] = unmarshal_Money(field) + else: + args["price"] = None + + return Offer(**args) + + +def unmarshal_Platform(data: Any) -> Platform: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Platform' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("hostname", None) + if field is not None: + args["hostname"] = field + + field = data.get("number", None) + if field is not None: + args["number"] = field + + field = data.get("group_name", None) + if field is not None: + args["group_name"] = field + + field = data.get("ipv4", None) + if field is not None: + args["ipv4"] = field + + field = data.get("ipv6", None) + if field is not None: + args["ipv6"] = field + + field = data.get("control_panel", None) + if field is not None: + args["control_panel"] = unmarshal_PlatformControlPanel(field) + else: + args["control_panel"] = None + + return Platform(**args) + + +def unmarshal_Hosting(data: Any) -> Hosting: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Hosting' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + + field = data.get("ipv4", None) + if field is not None: + args["ipv4"] = field + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("protected", None) + if field is not None: + args["protected"] = field + + field = data.get("domain_status", None) + if field is not None: + args["domain_status"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("offer", None) + if field is not None: + args["offer"] = unmarshal_Offer(field) + else: + args["offer"] = None + + field = data.get("platform", None) + if field is not None: + args["platform"] = unmarshal_Platform(field) + else: + args["platform"] = None + + field = data.get("dns_status", None) + if field is not None: + args["dns_status"] = field + else: + args["dns_status"] = None + + field = data.get("user", None) + if field is not None: + args["user"] = unmarshal_HostingUser(field) + else: + args["user"] = None + + return Hosting(**args) + + +def unmarshal_ControlPanel(data: Any) -> ControlPanel: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ControlPanel' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("available", None) + if field is not None: + args["available"] = field + + field = data.get("logo_url", None) + if field is not None: + args["logo_url"] = field + + field = data.get("available_languages", None) + if field is not None: + args["available_languages"] = ( + [StdLanguageCode(v) for v in field] if field is not None else None + ) + + return ControlPanel(**args) + + +def unmarshal_ListControlPanelsResponse(data: Any) -> ListControlPanelsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListControlPanelsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("control_panels", None) + if field is not None: + args["control_panels"] = ( + [unmarshal_ControlPanel(v) for v in field] if field is not None else None + ) + + return ListControlPanelsResponse(**args) + + +def unmarshal_ListDatabaseUsersResponse(data: Any) -> ListDatabaseUsersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDatabaseUsersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("users", None) + if field is not None: + args["users"] = ( + [unmarshal_DatabaseUser(v) for v in field] if field is not None else None + ) + + return ListDatabaseUsersResponse(**args) + + +def unmarshal_ListDatabasesResponse(data: Any) -> ListDatabasesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListDatabasesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("databases", None) + if field is not None: + args["databases"] = ( + [unmarshal_Database(v) for v in field] if field is not None else None + ) + + return ListDatabasesResponse(**args) + + +def unmarshal_ListFtpAccountsResponse(data: Any) -> ListFtpAccountsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListFtpAccountsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("ftp_accounts", None) + if field is not None: + args["ftp_accounts"] = ( + [unmarshal_FtpAccount(v) for v in field] if field is not None else None + ) + + return ListFtpAccountsResponse(**args) + + +def unmarshal_HostingSummary(data: Any) -> HostingSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'HostingSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("protected", None) + if field is not None: + args["protected"] = field + + field = data.get("offer_name", None) + if field is not None: + args["offer_name"] = field + + field = data.get("domain_status", None) + if field is not None: + args["domain_status"] = field + + field = data.get("region", None) + if field is not None: + args["region"] = field + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + field = data.get("dns_status", None) + if field is not None: + args["dns_status"] = field + else: + args["dns_status"] = None + + return HostingSummary(**args) + + +def unmarshal_ListHostingsResponse(data: Any) -> ListHostingsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListHostingsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("hostings", None) + if field is not None: + args["hostings"] = ( + [unmarshal_HostingSummary(v) for v in field] if field is not None else None + ) + + return ListHostingsResponse(**args) + + +def unmarshal_ListMailAccountsResponse(data: Any) -> ListMailAccountsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListMailAccountsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("mail_accounts", None) + if field is not None: + args["mail_accounts"] = ( + [unmarshal_MailAccount(v) for v in field] if field is not None else None + ) + + return ListMailAccountsResponse(**args) + + +def unmarshal_ListOffersResponse(data: Any) -> ListOffersResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListOffersResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("offers", None) + if field is not None: + args["offers"] = ( + [unmarshal_Offer(v) for v in field] if field is not None else None + ) + + return ListOffersResponse(**args) + + +def unmarshal_Website(data: Any) -> Website: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Website' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("path", None) + if field is not None: + args["path"] = field + + field = data.get("ssl_status", None) + if field is not None: + args["ssl_status"] = field + + return Website(**args) + + +def unmarshal_ListWebsitesResponse(data: Any) -> ListWebsitesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListWebsitesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("websites", None) + if field is not None: + args["websites"] = ( + [unmarshal_Website(v) for v in field] if field is not None else None + ) + + return ListWebsitesResponse(**args) + + +def unmarshal_ResetHostingPasswordResponse(data: Any) -> ResetHostingPasswordResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ResetHostingPasswordResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("one_time_password_b64", None) + if field is not None: + args["one_time_password_b64"] = field + + field = data.get("one_time_password", None) + if field is not None: + args["one_time_password"] = field + else: + args["one_time_password"] = None + + return ResetHostingPasswordResponse(**args) + + +def unmarshal_ResourceSummary(data: Any) -> ResourceSummary: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ResourceSummary' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("databases_count", None) + if field is not None: + args["databases_count"] = field + + field = data.get("mail_accounts_count", None) + if field is not None: + args["mail_accounts_count"] = field + + field = data.get("ftp_accounts_count", None) + if field is not None: + args["ftp_accounts_count"] = field + + field = data.get("websites_count", None) + if field is not None: + args["websites_count"] = field + + return ResourceSummary(**args) + + +def unmarshal_DomainAvailability(data: Any) -> DomainAvailability: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'DomainAvailability' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("name", None) + if field is not None: + args["name"] = field + + field = data.get("zone_name", None) + if field is not None: + args["zone_name"] = field + + field = data.get("status", None) + if field is not None: + args["status"] = field + + field = data.get("available_actions", None) + if field is not None: + args["available_actions"] = ( + [DomainAvailabilityAction(v) for v in field] if field is not None else None + ) + + field = data.get("can_create_hosting", None) + if field is not None: + args["can_create_hosting"] = field + + field = data.get("price", None) + if field is not None: + args["price"] = unmarshal_Money(field) + else: + args["price"] = None + + return DomainAvailability(**args) + + +def unmarshal_SearchDomainsResponse(data: Any) -> SearchDomainsResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SearchDomainsResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("domains_available", None) + if field is not None: + args["domains_available"] = ( + [unmarshal_DomainAvailability(v) for v in field] + if field is not None + else None + ) + + return SearchDomainsResponse(**args) + + +def unmarshal_Session(data: Any) -> Session: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Session' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("url", None) + if field is not None: + args["url"] = field + + return Session(**args) + + +def marshal_DatabaseApiAssignDatabaseUserRequest( + request: DatabaseApiAssignDatabaseUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + return output + + +def marshal_DatabaseApiChangeDatabaseUserPasswordRequest( + request: DatabaseApiChangeDatabaseUserPasswordRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_CreateDatabaseRequestUser( + request: CreateDatabaseRequestUser, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_DatabaseApiCreateDatabaseRequest( + request: DatabaseApiCreateDatabaseRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + output.update( + resolve_one_of( + [ + OneOfPossibility("new_user", request.new_user), + OneOfPossibility("existing_username", request.existing_username), + ] + ), + ) + + if request.database_name is not None: + output["database_name"] = request.database_name + + return output + + +def marshal_DatabaseApiCreateDatabaseUserRequest( + request: DatabaseApiCreateDatabaseUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_DatabaseApiUnassignDatabaseUserRequest( + request: DatabaseApiUnassignDatabaseUserRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + return output + + +def marshal_DnsApiCheckUserOwnsDomainRequest( + request: DnsApiCheckUserOwnsDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_AutoConfigDomainDns( + request: AutoConfigDomainDns, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.nameservers is not None: + output["nameservers"] = request.nameservers + + if request.web_records is not None: + output["web_records"] = request.web_records + + if request.mail_records is not None: + output["mail_records"] = request.mail_records + + if request.all_records is not None: + output["all_records"] = request.all_records + + if request.none is not None: + output["none"] = request.none + + return output + + +def marshal_SyncDomainDnsRecordsRequestRecord( + request: SyncDomainDnsRecordsRequestRecord, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.name is not None: + output["name"] = request.name + + if request.type_ is not None: + output["type"] = str(request.type_) + + return output + + +def marshal_DnsApiSyncDomainDnsRecordsRequest( + request: DnsApiSyncDomainDnsRecordsRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.update_web_records is not None: + output["update_web_records"] = request.update_web_records + + if request.update_mail_records is not None: + output["update_mail_records"] = request.update_mail_records + + if request.update_all_records is not None: + output["update_all_records"] = request.update_all_records + + if request.update_nameservers is not None: + output["update_nameservers"] = request.update_nameservers + + if request.custom_records is not None: + output["custom_records"] = [ + marshal_SyncDomainDnsRecordsRequestRecord(item, defaults) + for item in request.custom_records + ] + + if request.auto_config_domain_dns is not None: + output["auto_config_domain_dns"] = marshal_AutoConfigDomainDns( + request.auto_config_domain_dns, defaults + ) + + return output + + +def marshal_FtpAccountApiChangeFtpAccountPasswordRequest( + request: FtpAccountApiChangeFtpAccountPasswordRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_FtpAccountApiCreateFtpAccountRequest( + request: FtpAccountApiCreateFtpAccountRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.username is not None: + output["username"] = request.username + + if request.path is not None: + output["path"] = request.path + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_CreateHostingRequestDomainConfiguration( + request: CreateHostingRequestDomainConfiguration, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.update_nameservers is not None: + output["update_nameservers"] = request.update_nameservers + + if request.update_web_record is not None: + output["update_web_record"] = request.update_web_record + + if request.update_mail_record is not None: + output["update_mail_record"] = request.update_mail_record + + if request.update_all_records is not None: + output["update_all_records"] = request.update_all_records + + return output + + +def marshal_OfferOptionRequest( + request: OfferOptionRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.id is not None: + output["id"] = request.id + + if request.quantity is not None: + output["quantity"] = request.quantity + + return output + + +def marshal_HostingApiCreateHostingRequest( + request: HostingApiCreateHostingRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.email is not None: + output["email"] = request.email + + if request.domain is not None: + output["domain"] = request.domain + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + if request.tags is not None: + output["tags"] = request.tags + + if request.offer_options is not None: + output["offer_options"] = [ + marshal_OfferOptionRequest(item, defaults) for item in request.offer_options + ] + + if request.language is not None: + output["language"] = str(request.language) + + if request.domain_configuration is not None: + output["domain_configuration"] = ( + marshal_CreateHostingRequestDomainConfiguration( + request.domain_configuration, defaults + ) + ) + + if request.skip_welcome_email is not None: + output["skip_welcome_email"] = request.skip_welcome_email + + if request.auto_config_domain_dns is not None: + output["auto_config_domain_dns"] = marshal_AutoConfigDomainDns( + request.auto_config_domain_dns, defaults + ) + + return output + + +def marshal_HostingApiUpdateHostingRequest( + request: HostingApiUpdateHostingRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.email is not None: + output["email"] = request.email + + if request.tags is not None: + output["tags"] = request.tags + + if request.offer_options is not None: + output["offer_options"] = [ + marshal_OfferOptionRequest(item, defaults) for item in request.offer_options + ] + + if request.offer_id is not None: + output["offer_id"] = request.offer_id + + if request.protected is not None: + output["protected"] = request.protected + + return output + + +def marshal_MailAccountApiChangeMailAccountPasswordRequest( + request: MailAccountApiChangeMailAccountPasswordRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain is not None: + output["domain"] = request.domain + + if request.username is not None: + output["username"] = request.username + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_MailAccountApiCreateMailAccountRequest( + request: MailAccountApiCreateMailAccountRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain is not None: + output["domain"] = request.domain + + if request.username is not None: + output["username"] = request.username + + if request.password is not None: + output["password"] = request.password + + return output + + +def marshal_MailAccountApiRemoveMailAccountRequest( + request: MailAccountApiRemoveMailAccountRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain is not None: + output["domain"] = request.domain + + if request.username is not None: + output["username"] = request.username + + return output diff --git a/scaleway/scaleway/webhosting/v1/types.py b/scaleway/scaleway/webhosting/v1/types.py new file mode 100644 index 00000000..8abd971c --- /dev/null +++ b/scaleway/scaleway/webhosting/v1/types.py @@ -0,0 +1,1872 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import List, Optional + +from scaleway_core.bridge import ( + Money, + Region as ScwRegion, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + +from ...std.types import ( + LanguageCode as StdLanguageCode, +) + + +class DnsRecordStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + VALID = "valid" + INVALID = "invalid" + + def __str__(self) -> str: + return str(self.value) + + +class DnsRecordType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_TYPE = "unknown_type" + A = "a" + CNAME = "cname" + MX = "mx" + TXT = "txt" + NS = "ns" + AAAA = "aaaa" + + def __str__(self) -> str: + return str(self.value) + + +class DnsRecordsStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + VALID = "valid" + INVALID = "invalid" + + def __str__(self) -> str: + return str(self.value) + + +class DomainAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + TRANSFER = "transfer" + MANAGE_EXTERNAL = "manage_external" + RENEW = "renew" + + def __str__(self) -> str: + return str(self.value) + + +class DomainAvailabilityAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ACTION = "unknown_action" + REGISTER = "register" + TRANSFER = "transfer" + MANAGE_EXTERNAL = "manage_external" + + def __str__(self) -> str: + return str(self.value) + + +class DomainAvailabilityStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + AVAILABLE = "available" + NOT_AVAILABLE = "not_available" + OWNED = "owned" + VALIDATING = "validating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class DomainDnsAction(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_DNS_ACTION = "unknown_dns_action" + AUTO_CONFIG_ALL_RECORDS = "auto_config_all_records" + AUTO_CONFIG_WEB_RECORDS = "auto_config_web_records" + AUTO_CONFIG_MAIL_RECORDS = "auto_config_mail_records" + AUTO_CONFIG_NAMESERVERS = "auto_config_nameservers" + AUTO_CONFIG_NONE = "auto_config_none" + + def __str__(self) -> str: + return str(self.value) + + +class DomainStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + VALID = "valid" + INVALID = "invalid" + VALIDATING = "validating" + ERROR = "error" + + def __str__(self) -> str: + return str(self.value) + + +class DomainZoneOwner(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_ZONE_OWNER = "unknown_zone_owner" + EXTERNAL = "external" + SCALEWAY = "scaleway" + ONLINE = "online" + WEBHOSTING = "webhosting" + + def __str__(self) -> str: + return str(self.value) + + +class HostingStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + DELIVERING = "delivering" + READY = "ready" + DELETING = "deleting" + ERROR = "error" + LOCKED = "locked" + MIGRATING = "migrating" + + def __str__(self) -> str: + return str(self.value) + + +class ListDatabaseUsersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + USERNAME_ASC = "username_asc" + USERNAME_DESC = "username_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListDatabasesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + DATABASE_NAME_ASC = "database_name_asc" + DATABASE_NAME_DESC = "database_name_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListFtpAccountsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + USERNAME_ASC = "username_asc" + USERNAME_DESC = "username_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListHostingsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + CREATED_AT_ASC = "created_at_asc" + CREATED_AT_DESC = "created_at_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListMailAccountsRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + USERNAME_ASC = "username_asc" + USERNAME_DESC = "username_desc" + DOMAIN_ASC = "domain_asc" + DOMAIN_DESC = "domain_desc" + + def __str__(self) -> str: + return str(self.value) + + +class ListOffersRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + PRICE_ASC = "price_asc" + + def __str__(self) -> str: + return str(self.value) + + +class ListWebsitesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + DOMAIN_ASC = "domain_asc" + DOMAIN_DESC = "domain_desc" + + def __str__(self) -> str: + return str(self.value) + + +class NameserverStatus(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_STATUS = "unknown_status" + VALID = "valid" + INVALID = "invalid" + + def __str__(self) -> str: + return str(self.value) + + +class OfferOptionName(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_NAME = "unknown_name" + DOMAIN_COUNT = "domain_count" + EMAIL_COUNT = "email_count" + STORAGE_GB = "storage_gb" + VCPU_COUNT = "vcpu_count" + RAM_GB = "ram_gb" + BACKUP = "backup" + DEDICATED_IP = "dedicated_ip" + EMAIL_STORAGE_GB = "email_storage_gb" + DATABASE_COUNT = "database_count" + SUPPORT = "support" + + def __str__(self) -> str: + return str(self.value) + + +class OfferOptionWarning(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_WARNING = "unknown_warning" + QUOTA_EXCEEDED_WARNING = "quota_exceeded_warning" + USAGE_LOW_WARNING = "usage_low_warning" + + def __str__(self) -> str: + return str(self.value) + + +class PlatformPlatformGroup(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_GROUP = "unknown_group" + DEFAULT = "default" + PREMIUM = "premium" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class PlatformControlPanelUrls: + dashboard: str + """ + URL to connect to the hosting control panel dashboard. + """ + + webmail: str + """ + URL to connect to the hosting Webmail interface. + """ + + +@dataclass +class OfferOption: + id: str + """ + Option ID. + """ + + name: OfferOptionName + """ + Name of the option. + """ + + billing_operation_path: str + """ + Unique identifier used for billing. + """ + + min_value: int + """ + Minimum value for the option in the offer. + """ + + current_value: int + """ + If a hosting_id was specified in the call, defines the current value of the option in the hosting. + """ + + max_value: int + """ + Maximum value for the option in the offer. + """ + + quota_warning: OfferOptionWarning + """ + Defines a warning if the maximum value for the option has been reached. + """ + + price: Optional[Money] + """ + Price of the option for 1 value. + """ + + +@dataclass +class PlatformControlPanel: + name: str + """ + Name of the control panel. + """ + + urls: Optional[PlatformControlPanelUrls] + """ + URL to connect to control panel dashboard and to Webmail interface. + """ + + +@dataclass +class CreateDatabaseRequestUser: + username: str + + password: str + + +@dataclass +class AutoConfigDomainDns: + nameservers: bool + """ + Whether or not to synchronize domain nameservers. + """ + + web_records: bool + """ + Whether or not to synchronize web records. + """ + + mail_records: bool + """ + Whether or not to synchronize mail records. + """ + + all_records: bool + """ + Whether or not to synchronize all types of records. Takes priority over the other fields. + """ + + none: bool + """ + No automatic domain configuration. Users must configure their domain for the Web Hosting to work. + """ + + +@dataclass +class CreateHostingRequestDomainConfiguration: + update_nameservers: bool + + update_web_record: bool + + update_mail_record: bool + + update_all_records: bool + + +@dataclass +class OfferOptionRequest: + id: str + """ + Offer option ID. + """ + + quantity: int + """ + The option requested quantity to set for the Web Hosting plan. + """ + + +@dataclass +class SyncDomainDnsRecordsRequestRecord: + name: str + + type_: DnsRecordType + + +@dataclass +class DnsRecord: + name: str + """ + Record name. + """ + + type_: DnsRecordType + """ + Record type. + """ + + ttl: int + """ + Record time-to-live. + """ + + value: str + """ + Record value. + """ + + status: DnsRecordStatus + """ + Record status. + """ + + raw_data: str + """ + Record representation as it appears in the zone file or DNS management system. + """ + + priority: Optional[int] + """ + Record priority level. + """ + + +@dataclass +class Nameserver: + hostname: str + """ + Hostname of the nameserver. + """ + + status: NameserverStatus + """ + Status of the nameserver. + """ + + is_default: bool + """ + Defines whether the nameserver is the default one. + """ + + +@dataclass +class HostingUser: + username: str + """ + Main Web Hosting control panel username. + """ + + contact_email: str + """ + Contact email used for the hosting. + """ + + one_time_password: Optional[str] + """ + One-time-password used for the first login to the control panel, cleared after first use (deprecated, use password_b64 instead). + """ + + one_time_password_b64: Optional[str] + """ + One-time-password used for the first login to the control panel, cleared after first use, encoded in base64. + """ + + +@dataclass +class Offer: + id: str + """ + Offer ID. + """ + + name: str + """ + Offer name. + """ + + billing_operation_path: str + """ + Unique identifier used for billing. + """ + + options: List[OfferOption] + """ + Options available for the offer. + """ + + available: bool + """ + If a hosting_id was specified in the call, defines whether the offer is available for a specified hosting plan to migrate (update) to. + """ + + control_panel_name: str + """ + Name of the control panel. + """ + + end_of_life: bool + """ + Indicates if the offer has reached its end of life. + """ + + quota_warning: OfferOptionWarning + """ + Defines a warning if the maximum value for an option in the offer is exceeded. + """ + + price: Optional[Money] + """ + Price of the offer. + """ + + +@dataclass +class Platform: + hostname: str + """ + Hostname of the host platform. + """ + + number: int + """ + Number of the host platform. + """ + + group_name: PlatformPlatformGroup + """ + Group name of the hosting's host platform. + """ + + ipv4: str + """ + IPv4 address of the hosting's host platform. + """ + + ipv6: str + """ + IPv6 address of the hosting's host platform. + """ + + control_panel: Optional[PlatformControlPanel] + """ + Details of the platform control panel. + """ + + +@dataclass +class ControlPanel: + name: str + """ + Control panel name. + """ + + available: bool + """ + Define if the control panel type is available to order. + """ + + logo_url: str + """ + URL of the control panel's logo. + """ + + available_languages: List[StdLanguageCode] + """ + List of available languages for the control panel. + """ + + +@dataclass +class DatabaseUser: + username: str + """ + Name of the database user. + """ + + databases: List[str] + """ + List of databases accessible by the user. + """ + + +@dataclass +class Database: + database_name: str + """ + Name of the database. + """ + + users: List[str] + """ + List of users who have access to the database. + """ + + +@dataclass +class FtpAccount: + username: str + """ + The username of the FTP account. + """ + + path: str + """ + The path associated with the FTP account. + """ + + +@dataclass +class HostingSummary: + id: str + """ + ID of the Web Hosting plan. + """ + + project_id: str + """ + ID of the Scaleway Project the Web Hosting plan belongs to. + """ + + status: HostingStatus + """ + Status of the Web Hosting plan. + """ + + domain: str + """ + Main domain associated with the Web Hosting plan. + """ + + protected: bool + """ + Whether the hosting is protected or not. + """ + + offer_name: str + """ + Name of the active offer for the Web Hosting plan. + """ + + domain_status: DomainStatus + """ + Main domain status of the Web Hosting plan. + """ + + region: ScwRegion + """ + Region where the Web Hosting plan is hosted. + """ + + created_at: Optional[datetime] + """ + Date on which the Web Hosting plan was created. + """ + + updated_at: Optional[datetime] + """ + Date on which the Web Hosting plan was last updated. + """ + + dns_status: Optional[DnsRecordsStatus] + """ + DNS status of the Web Hosting plan. + """ + + +@dataclass +class MailAccount: + domain: str + """ + Domain part of the mail account address. + """ + + username: str + """ + Username part address of the mail account address. + """ + + +@dataclass +class Website: + domain: str + """ + The domain of the website. + """ + + path: str + """ + The directory path of the website. + """ + + ssl_status: bool + """ + The SSL status of the website. + """ + + +@dataclass +class DomainAvailability: + name: str + """ + Fully qualified domain name (FQDN). + """ + + zone_name: str + """ + DNS zone associated with the domain. + """ + + status: DomainAvailabilityStatus + """ + Availability status of the domain. + """ + + available_actions: List[DomainAvailabilityAction] + """ + A list of actions that can be performed on the domain. + """ + + can_create_hosting: bool + """ + Whether a hosting can be created for this domain. + """ + + price: Optional[Money] + """ + Price for registering the domain. + """ + + +@dataclass +class CheckUserOwnsDomainResponse: + owns_domain: bool + """ + Indicates whether the specified project owns the domain. + """ + + +@dataclass +class ControlPanelApiListControlPanelsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of control panels to return (must be a positive integer lower or equal to 100). + """ + + +@dataclass +class DatabaseApiAssignDatabaseUserRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the user to assign. + """ + + database_name: str + """ + Name of the database to be assigned. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiChangeDatabaseUserPasswordRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the user to update. + """ + + password: str + """ + New password. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiCreateDatabaseRequest: + hosting_id: str + """ + UUID of the hosting plan where the database will be created. + """ + + database_name: str + """ + Name of the database to be created. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + new_user: Optional[CreateDatabaseRequestUser] + + existing_username: Optional[str] + + +@dataclass +class DatabaseApiCreateDatabaseUserRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the user to create. + """ + + password: str + """ + Password of the user to create. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiDeleteDatabaseRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + database_name: str + """ + Name of the database to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiDeleteDatabaseUserRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the database user to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiGetDatabaseRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + database_name: str + """ + Name of the database. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiGetDatabaseUserRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the database user to retrieve details. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DatabaseApiListDatabaseUsersRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of database users to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListDatabaseUsersRequestOrderBy] + """ + Sort order of database users in the response. + """ + + +@dataclass +class DatabaseApiListDatabasesRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of databases to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListDatabasesRequestOrderBy] + """ + Sort order of databases in the response. + """ + + +@dataclass +class DatabaseApiUnassignDatabaseUserRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Name of the user to unassign. + """ + + database_name: str + """ + Name of the database to be unassigned. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DnsApiCheckUserOwnsDomainRequest: + domain: str + """ + Domain for which ownership is to be verified. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project currently in use. + """ + + +@dataclass +class DnsApiGetDomainDnsRecordsRequest: + domain: str + """ + Domain associated with the DNS records. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class DnsApiGetDomainRequest: + domain_name: str + """ + Domain name to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Scaleway Project in which to get the domain to create the Web Hosting plan. + """ + + +@dataclass +class DnsApiSearchDomainsRequest: + domain_name: str + """ + Domain name to search. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Scaleway Project in which to search the domain to create the Web Hosting plan. + """ + + +@dataclass +class DnsApiSyncDomainDnsRecordsRequest: + domain: str + """ + Domain for which the DNS records will be synchronized. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + update_web_records: Optional[bool] + """ + Whether or not to synchronize the web records (deprecated, use auto_config_domain_dns). + """ + + update_mail_records: Optional[bool] + """ + Whether or not to synchronize the mail records (deprecated, use auto_config_domain_dns). + """ + + update_all_records: Optional[bool] + """ + Whether or not to synchronize all types of records. This one has priority (deprecated, use auto_config_domain_dns). + """ + + update_nameservers: Optional[bool] + """ + Whether or not to synchronize domain nameservers (deprecated, use auto_config_domain_dns). + """ + + custom_records: Optional[List[SyncDomainDnsRecordsRequestRecord]] + """ + Custom records to synchronize. + """ + + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Whether or not to synchronize each types of records. + """ + + +@dataclass +class DnsRecords: + records: List[DnsRecord] + """ + List of DNS records. + """ + + name_servers: List[Nameserver] + """ + List of nameservers. + """ + + status: DnsRecordsStatus + """ + Status of the records. + """ + + dns_config: Optional[List[DomainDnsAction]] + """ + Records dns auto configuration settings (deprecated, use auto_config_domain_dns). + """ + + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Whether or not to synchronize each types of records. + """ + + +@dataclass +class Domain: + name: str + """ + Name of the domain. + """ + + status: DomainStatus + """ + Current status of the domain. + """ + + owner: DomainZoneOwner + """ + Zone owner of the domain. + """ + + available_actions: List[DomainAction] + """ + A list of actions that can be performed on the domain. + """ + + available_dns_actions: Optional[List[DomainDnsAction]] + """ + A list of DNS-related actions that can be auto configured for the domain (deprecated, use auto_config_domain_dns instead). + """ + + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Whether or not to synchronize each type of record. + """ + + +@dataclass +class FtpAccountApiChangeFtpAccountPasswordRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Username of the FTP account. + """ + + password: str + """ + New password for the FTP account. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class FtpAccountApiCreateFtpAccountRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Username for the new FTP account. + """ + + path: str + """ + Path for the new FTP account. + """ + + password: str + """ + Password for the new FTP account. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class FtpAccountApiListFtpAccountsRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of FTP accounts to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListFtpAccountsRequestOrderBy] + """ + Sort order of FTP accounts in the response. + """ + + domain: Optional[str] + """ + Domain to filter the FTP accounts. + """ + + +@dataclass +class FtpAccountApiRemoveFtpAccountRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + username: str + """ + Username of the FTP account to be deleted. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class Hosting: + id: str + """ + ID of the Web Hosting plan. + """ + + project_id: str + """ + ID of the Scaleway Project the Web Hosting plan belongs to. + """ + + status: HostingStatus + """ + Status of the Web Hosting plan. + """ + + domain: str + """ + Main domain associated with the Web Hosting plan. + """ + + tags: List[str] + """ + List of tags associated with the Web Hosting plan. + """ + + ipv4: str + """ + Current IPv4 address of the hosting. + """ + + updated_at: Optional[datetime] + """ + Date on which the Web Hosting plan was last updated. + """ + + created_at: Optional[datetime] + """ + Date on which the Web Hosting plan was created. + """ + + protected: bool + """ + Whether the hosting is protected or not. + """ + + domain_status: DomainStatus + """ + Main domain status of the Web Hosting plan. + """ + + region: ScwRegion + """ + Region where the Web Hosting plan is hosted. + """ + + offer: Optional[Offer] + """ + Details of the Web Hosting plan offer and options. + """ + + platform: Optional[Platform] + """ + Details of the hosting platform. + """ + + dns_status: Optional[DnsRecordsStatus] + """ + DNS status of the Web Hosting plan. + """ + + user: Optional[HostingUser] + """ + Details of the hosting user. + """ + + +@dataclass +class HostingApiCreateHostingRequest: + offer_id: str + """ + ID of the selected offer for the Web Hosting plan. + """ + + email: str + """ + Contact email for the Web Hosting client. + """ + + domain: str + """ + Domain name to link to the Web Hosting plan. You must already own this domain name, and have completed the DNS validation process beforehand. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the Scaleway Project in which to create the Web Hosting plan. + """ + + tags: Optional[List[str]] + """ + List of tags for the Web Hosting plan. + """ + + offer_options: Optional[List[OfferOptionRequest]] + """ + List of the Web Hosting plan options IDs with their quantities. + """ + + language: Optional[StdLanguageCode] + """ + Default language for the control panel interface. + """ + + domain_configuration: Optional[CreateHostingRequestDomainConfiguration] + """ + Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_config_domain_dns instead). + """ + + skip_welcome_email: Optional[bool] + """ + Indicates whether to skip a welcome email to the contact email containing hosting info. + """ + + auto_config_domain_dns: Optional[AutoConfigDomainDns] + """ + Indicates whether to update hosting domain name servers and DNS records for domains managed by Scaleway Elements (deprecated, use auto_update_* fields instead). + """ + + +@dataclass +class HostingApiCreateSessionRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class HostingApiDeleteHostingRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class HostingApiGetHostingRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class HostingApiGetResourceSummaryRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class HostingApiListHostingsRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number to return, from the paginated results (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of Web Hosting plans to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListHostingsRequestOrderBy] + """ + Sort order for Web Hosting plans in the response. + """ + + tags: Optional[List[str]] + """ + Tags to filter for, only Web Hosting plans with matching tags will be returned. + """ + + statuses: Optional[List[HostingStatus]] + """ + Statuses to filter for, only Web Hosting plans with matching statuses will be returned. + """ + + domain: Optional[str] + """ + Domain to filter for, only Web Hosting plans associated with this domain will be returned. + """ + + project_id: Optional[str] + """ + Project ID to filter for, only Web Hosting plans from this Project will be returned. + """ + + organization_id: Optional[str] + """ + Organization ID to filter for, only Web Hosting plans from this Organization will be returned. + """ + + control_panels: Optional[List[str]] + """ + Name of the control panel to filter for, only Web Hosting plans from this control panel will be returned. + """ + + +@dataclass +class HostingApiResetHostingPasswordRequest: + hosting_id: str + """ + UUID of the hosting. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class HostingApiUpdateHostingRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + email: Optional[str] + """ + New contact email for the Web Hosting plan. + """ + + tags: Optional[List[str]] + """ + New tags for the Web Hosting plan. + """ + + offer_options: Optional[List[OfferOptionRequest]] + """ + List of the Web Hosting plan options IDs with their quantities. + """ + + offer_id: Optional[str] + """ + ID of the new offer for the Web Hosting plan. + """ + + protected: Optional[bool] + """ + Whether the hosting is protected or not. + """ + + +@dataclass +class ListControlPanelsResponse: + total_count: int + """ + Number of control panels returned. + """ + + control_panels: List[ControlPanel] + """ + List of control panels. + """ + + +@dataclass +class ListDatabaseUsersResponse: + total_count: int + """ + Total number of database users. + """ + + users: List[DatabaseUser] + """ + List of database users. + """ + + +@dataclass +class ListDatabasesResponse: + total_count: int + """ + Total number of databases. + """ + + databases: List[Database] + """ + List of databases. + """ + + +@dataclass +class ListFtpAccountsResponse: + total_count: int + """ + Total number of FTP accounts. + """ + + ftp_accounts: List[FtpAccount] + """ + List of FTP accounts. + """ + + +@dataclass +class ListHostingsResponse: + total_count: int + """ + Number of Web Hosting plans returned. + """ + + hostings: List[HostingSummary] + """ + List of Web Hosting plans. + """ + + +@dataclass +class ListMailAccountsResponse: + total_count: int + """ + Total number of mail accounts. + """ + + mail_accounts: List[MailAccount] + """ + List of mail accounts. + """ + + +@dataclass +class ListOffersResponse: + total_count: int + """ + Total number of offers. + """ + + offers: List[Offer] + """ + List of offers. + """ + + +@dataclass +class ListWebsitesResponse: + total_count: int + """ + Total number of websites. + """ + + websites: List[Website] + """ + List of websites. + """ + + +@dataclass +class MailAccountApiChangeMailAccountPasswordRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + domain: str + """ + Domain part of the mail account address. + """ + + username: str + """ + Username part of the mail account address. + """ + + password: str + """ + New password for the mail account. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class MailAccountApiCreateMailAccountRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + domain: str + """ + Domain part of the mail account address. + """ + + username: str + """ + Username part address of the mail account address. + """ + + password: str + """ + Password for the new mail account. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class MailAccountApiListMailAccountsRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of mail accounts to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListMailAccountsRequestOrderBy] + """ + Sort order of mail accounts in the response. + """ + + domain: Optional[str] + """ + Domain to filter the mail accounts. + """ + + +@dataclass +class MailAccountApiRemoveMailAccountRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + domain: str + """ + Domain part of the mail account address. + """ + + username: str + """ + Username part of the mail account address. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class OfferApiListOffersRequest: + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of websites to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListOffersRequestOrderBy] + """ + Sort order for Web Hosting offers in the response. + """ + + hosting_id: Optional[str] + """ + UUID of the hosting plan. + """ + + control_panels: Optional[List[str]] + """ + Name of the control panel(s) to filter for. + """ + + +@dataclass +class ResetHostingPasswordResponse: + one_time_password_b64: str + """ + New temporary password, encoded in base64. + """ + + one_time_password: Optional[str] + """ + New temporary password (deprecated, use password_b64 instead). + """ + + +@dataclass +class ResourceSummary: + databases_count: int + """ + Total number of active databases in the Web Hosting plan. + """ + + mail_accounts_count: int + """ + Total number of active email accounts in the Web Hosting plan. + """ + + ftp_accounts_count: int + """ + Total number of active FTP accounts in the Web Hosting plan. + """ + + websites_count: int + """ + Total number of active domains in the Web Hosting plan. + """ + + +@dataclass +class SearchDomainsResponse: + domains_available: List[DomainAvailability] + """ + List of domains availability. + """ + + +@dataclass +class Session: + url: str + """ + Logged user's session URL. + """ + + +@dataclass +class WebsiteApiListWebsitesRequest: + hosting_id: str + """ + UUID of the hosting plan. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of websites to return (must be a positive integer lower or equal to 100). + """ + + order_by: Optional[ListWebsitesRequestOrderBy] + """ + Sort order for Web Hosting websites in the response. + """ diff --git a/scaleway/scaleway/webhosting/v1alpha1/__init__.py b/scaleway/scaleway/webhosting/v1alpha1/__init__.py index 09a3260e..2384d374 100644 --- a/scaleway/scaleway/webhosting/v1alpha1/__init__.py +++ b/scaleway/scaleway/webhosting/v1alpha1/__init__.py @@ -12,14 +12,24 @@ from .types import OfferQuotaWarning from .types import HostingCpanelUrls from .types import HostingOption +from .types import EmailAddress from .types import OfferProduct from .types import CreateHostingRequestDomainConfiguration from .types import DnsRecord from .types import Nameserver from .types import ControlPanel from .types import Hosting +from .types import Mailbox from .types import Offer +from .types import CheckUserOwnsDomainRequest +from .types import CheckUserOwnsDomainResponse +from .types import ClassicMailApiCreateMailboxRequest +from .types import ClassicMailApiDeleteMailboxRequest +from .types import ClassicMailApiGetMailboxRequest +from .types import ClassicMailApiListMailboxesRequest +from .types import ClassicMailApiUpdateMailboxRequest from .types import CreateHostingRequest +from .types import CreateSessionRequest from .types import DeleteHostingRequest from .types import DnsRecords from .types import GetDomainDnsRecordsRequest @@ -28,11 +38,16 @@ from .types import ListControlPanelsResponse from .types import ListHostingsRequest from .types import ListHostingsResponse +from .types import ListMailboxesResponse from .types import ListOffersRequest from .types import ListOffersResponse +from .types import ResetHostingPasswordRequest +from .types import ResetHostingPasswordResponse from .types import RestoreHostingRequest +from .types import Session from .types import UpdateHostingRequest from .api import WebhostingV1Alpha1API +from .api import WebhostingV1Alpha1ClassicMailAPI __all__ = [ "DnsRecordStatus", @@ -47,14 +62,24 @@ "OfferQuotaWarning", "HostingCpanelUrls", "HostingOption", + "EmailAddress", "OfferProduct", "CreateHostingRequestDomainConfiguration", "DnsRecord", "Nameserver", "ControlPanel", "Hosting", + "Mailbox", "Offer", + "CheckUserOwnsDomainRequest", + "CheckUserOwnsDomainResponse", + "ClassicMailApiCreateMailboxRequest", + "ClassicMailApiDeleteMailboxRequest", + "ClassicMailApiGetMailboxRequest", + "ClassicMailApiListMailboxesRequest", + "ClassicMailApiUpdateMailboxRequest", "CreateHostingRequest", + "CreateSessionRequest", "DeleteHostingRequest", "DnsRecords", "GetDomainDnsRecordsRequest", @@ -63,9 +88,14 @@ "ListControlPanelsResponse", "ListHostingsRequest", "ListHostingsResponse", + "ListMailboxesResponse", "ListOffersRequest", "ListOffersResponse", + "ResetHostingPasswordRequest", + "ResetHostingPasswordResponse", "RestoreHostingRequest", + "Session", "UpdateHostingRequest", "WebhostingV1Alpha1API", + "WebhostingV1Alpha1ClassicMailAPI", ] diff --git a/scaleway/scaleway/webhosting/v1alpha1/api.py b/scaleway/scaleway/webhosting/v1alpha1/api.py index 0c5915c2..afcb9702 100644 --- a/scaleway/scaleway/webhosting/v1alpha1/api.py +++ b/scaleway/scaleway/webhosting/v1alpha1/api.py @@ -5,7 +5,7 @@ from scaleway_core.api import API from scaleway_core.bridge import ( - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( WaitForOptions, @@ -17,14 +17,23 @@ HostingStatus, ListHostingsRequestOrderBy, ListOffersRequestOrderBy, + CheckUserOwnsDomainRequest, + CheckUserOwnsDomainResponse, + ClassicMailApiCreateMailboxRequest, + ClassicMailApiUpdateMailboxRequest, ControlPanel, CreateHostingRequest, CreateHostingRequestDomainConfiguration, DnsRecords, + EmailAddress, Hosting, ListControlPanelsResponse, ListHostingsResponse, + ListMailboxesResponse, ListOffersResponse, + Mailbox, + ResetHostingPasswordResponse, + Session, UpdateHostingRequest, ) from .content import ( @@ -32,10 +41,18 @@ ) from .marshalling import ( unmarshal_Hosting, + unmarshal_Mailbox, + unmarshal_CheckUserOwnsDomainResponse, unmarshal_DnsRecords, unmarshal_ListControlPanelsResponse, unmarshal_ListHostingsResponse, + unmarshal_ListMailboxesResponse, unmarshal_ListOffersResponse, + unmarshal_ResetHostingPasswordResponse, + unmarshal_Session, + marshal_CheckUserOwnsDomainRequest, + marshal_ClassicMailApiCreateMailboxRequest, + marshal_ClassicMailApiUpdateMailboxRequest, marshal_CreateHostingRequest, marshal_UpdateHostingRequest, ) @@ -46,7 +63,7 @@ class WebhostingV1Alpha1API(API): """ - Web Hosting API. + This API allows you to manage your Web Hosting services. """ def create_hosting( @@ -54,7 +71,7 @@ def create_hosting( *, offer_id: str, domain: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, project_id: Optional[str] = None, email: Optional[str] = None, tags: Optional[List[str]] = None, @@ -114,7 +131,7 @@ def create_hosting( def list_hostings( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListHostingsRequestOrderBy] = None, @@ -173,7 +190,7 @@ def list_hostings( def list_hostings_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, order_by: Optional[ListHostingsRequestOrderBy] = None, @@ -227,7 +244,7 @@ def get_hosting( self, *, hosting_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hosting: """ Get a Web Hosting plan. @@ -261,7 +278,7 @@ def wait_for_hosting( self, *, hosting_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, options: Optional[WaitForOptions[Hosting, bool]] = None, ) -> Hosting: """ @@ -298,7 +315,7 @@ def update_hosting( self, *, hosting_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, email: Optional[str] = None, tags: Optional[List[str]] = None, option_ids: Optional[List[str]] = None, @@ -354,7 +371,7 @@ def delete_hosting( self, *, hosting_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hosting: """ Delete a Web Hosting plan. @@ -388,7 +405,7 @@ def restore_hosting( self, *, hosting_id: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> Hosting: """ Restore a Web Hosting plan. @@ -423,7 +440,7 @@ def get_domain_dns_records( self, *, domain: str, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, ) -> DnsRecords: """ Get DNS records. @@ -453,12 +470,55 @@ def get_domain_dns_records( self._throw_on_error(res) return unmarshal_DnsRecords(res.json()) + def check_user_owns_domain( + self, + *, + domain: str, + region: Optional[ScwRegion] = None, + project_id: Optional[str] = None, + ) -> CheckUserOwnsDomainResponse: + """ + "Check whether you own this domain or not.". + :param domain: Domain for which ownership is to be verified. + :param region: Region to target. If none is passed will use default region from the config. + :param project_id: ID of the project currently in use. + :return: :class:`CheckUserOwnsDomainResponse ` + + Usage: + :: + + result = api.check_user_owns_domain( + domain="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_domain = validate_path_param("domain", domain) + + res = self._request( + "POST", + f"/webhosting/v1alpha1/regions/{param_region}/domains/{param_domain}/check-ownership", + body=marshal_CheckUserOwnsDomainRequest( + CheckUserOwnsDomainRequest( + domain=domain, + region=region, + project_id=project_id, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_CheckUserOwnsDomainResponse(res.json()) + def list_offers( self, *, without_options: bool, only_options: bool, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, order_by: Optional[ListOffersRequestOrderBy] = None, hosting_id: Optional[str] = None, control_panels: Optional[List[str]] = None, @@ -505,13 +565,12 @@ def list_offers( def list_control_panels( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> ListControlPanelsResponse: """ - List all control panels type. - List the control panels type: cpanel or plesk. + "List the control panels type: cpanel or plesk.". :param region: Region to target. If none is passed will use default region from the config. :param page: Page number to return, from the paginated results (must be a positive integer). :param page_size: Number of control panels to return (must be a positive integer lower or equal to 100). @@ -542,13 +601,12 @@ def list_control_panels( def list_control_panels_all( self, *, - region: Optional[Region] = None, + region: Optional[ScwRegion] = None, page: Optional[int] = None, page_size: Optional[int] = None, ) -> List[ControlPanel]: """ - List all control panels type. - List the control panels type: cpanel or plesk. + "List the control panels type: cpanel or plesk.". :param region: Region to target. If none is passed will use default region from the config. :param page: Page number to return, from the paginated results (must be a positive integer). :param page_size: Number of control panels to return (must be a positive integer lower or equal to 100). @@ -570,3 +628,327 @@ def list_control_panels_all( "page_size": page_size, }, ) + + def create_session( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> Session: + """ + Create a user session. + :param hosting_id: Hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Session ` + + Usage: + :: + + result = api.create_session( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1alpha1/regions/{param_region}/hostings/{param_hosting_id}/sessions", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Session(res.json()) + + def reset_hosting_password( + self, + *, + hosting_id: str, + region: Optional[ScwRegion] = None, + ) -> ResetHostingPasswordResponse: + """ + :param hosting_id: UUID of the hosting. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`ResetHostingPasswordResponse ` + + Usage: + :: + + result = api.reset_hosting_password( + hosting_id="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_hosting_id = validate_path_param("hosting_id", hosting_id) + + res = self._request( + "POST", + f"/webhosting/v1alpha1/regions/{param_region}/hostings/{param_hosting_id}/reset-password", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_ResetHostingPasswordResponse(res.json()) + + +class WebhostingV1Alpha1ClassicMailAPI(API): + """ + This API allows you to manage your mailboxes for your Web Hosting services. + """ + + def create_mailbox( + self, + *, + online_id: int, + password: str, + region: Optional[ScwRegion] = None, + email: Optional[EmailAddress] = None, + ) -> Mailbox: + """ + Create a new mailbox within your hosting plan. + :param online_id: The Online hosting ID. + :param password: Password for the new mailbox. + :param region: Region to target. If none is passed will use default region from the config. + :param email: The email address of the mailbox. + :return: :class:`Mailbox ` + + Usage: + :: + + result = api.create_mailbox( + online_id=1, + password="example", + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_online_id = validate_path_param("online_id", online_id) + + res = self._request( + "POST", + f"/webhosting/v1alpha1/regions/{param_region}/classic-hostings/{param_online_id}/mailboxes", + body=marshal_ClassicMailApiCreateMailboxRequest( + ClassicMailApiCreateMailboxRequest( + online_id=online_id, + password=password, + region=region, + email=email, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Mailbox(res.json()) + + def get_mailbox( + self, + *, + online_id: int, + mailbox_id: int, + region: Optional[ScwRegion] = None, + ) -> Mailbox: + """ + Get a mailbox by id within your hosting plan. + :param online_id: The Online hosting ID. + :param mailbox_id: The ID of the mailbox to get. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Mailbox ` + + Usage: + :: + + result = api.get_mailbox( + online_id=1, + mailbox_id=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_online_id = validate_path_param("online_id", online_id) + param_mailbox_id = validate_path_param("mailbox_id", mailbox_id) + + res = self._request( + "GET", + f"/webhosting/v1alpha1/regions/{param_region}/classic-hostings/{param_online_id}/mailboxes/{param_mailbox_id}", + ) + + self._throw_on_error(res) + return unmarshal_Mailbox(res.json()) + + def list_mailboxes( + self, + *, + online_id: int, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + domain: Optional[str] = None, + ) -> ListMailboxesResponse: + """ + List all mailboxes within your hosting plan. + :param online_id: The Online hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of mailboxes to return (must be a positive integer lower or equal to 100). + :param domain: Domain to filter the mailboxes. + :return: :class:`ListMailboxesResponse ` + + Usage: + :: + + result = api.list_mailboxes( + online_id=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_online_id = validate_path_param("online_id", online_id) + + res = self._request( + "GET", + f"/webhosting/v1alpha1/regions/{param_region}/classic-hostings/{param_online_id}/mailboxes", + params={ + "domain": domain, + "page": page, + "page_size": page_size or self.client.default_page_size, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListMailboxesResponse(res.json()) + + def list_mailboxes_all( + self, + *, + online_id: int, + region: Optional[ScwRegion] = None, + page: Optional[int] = None, + page_size: Optional[int] = None, + domain: Optional[str] = None, + ) -> List[Mailbox]: + """ + List all mailboxes within your hosting plan. + :param online_id: The Online hosting ID. + :param region: Region to target. If none is passed will use default region from the config. + :param page: Page number (must be a positive integer). + :param page_size: Number of mailboxes to return (must be a positive integer lower or equal to 100). + :param domain: Domain to filter the mailboxes. + :return: :class:`List[Mailbox] ` + + Usage: + :: + + result = api.list_mailboxes_all( + online_id=1, + ) + """ + + return fetch_all_pages( + type=ListMailboxesResponse, + key="mailboxes", + fetcher=self.list_mailboxes, + args={ + "online_id": online_id, + "region": region, + "page": page, + "page_size": page_size, + "domain": domain, + }, + ) + + def delete_mailbox( + self, + *, + online_id: int, + mailbox_id: int, + region: Optional[ScwRegion] = None, + ) -> Mailbox: + """ + :param online_id: The Online hosting ID. + :param mailbox_id: The ID of the mailbox to delete. + :param region: Region to target. If none is passed will use default region from the config. + :return: :class:`Mailbox ` + + Usage: + :: + + result = api.delete_mailbox( + online_id=1, + mailbox_id=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_online_id = validate_path_param("online_id", online_id) + param_mailbox_id = validate_path_param("mailbox_id", mailbox_id) + + res = self._request( + "DELETE", + f"/webhosting/v1alpha1/regions/{param_region}/classic-hostings/{param_online_id}/mailboxes/{param_mailbox_id}", + ) + + self._throw_on_error(res) + return unmarshal_Mailbox(res.json()) + + def update_mailbox( + self, + *, + online_id: int, + mailbox_id: int, + region: Optional[ScwRegion] = None, + password: Optional[str] = None, + ) -> Mailbox: + """ + Update the mailbox within your hosting plan. + :param online_id: The Online hosting ID. + :param mailbox_id: The ID of the mailbox to update. + :param region: Region to target. If none is passed will use default region from the config. + :param password: New password for the mailbox. + :return: :class:`Mailbox ` + + Usage: + :: + + result = api.update_mailbox( + online_id=1, + mailbox_id=1, + ) + """ + + param_region = validate_path_param( + "region", region or self.client.default_region + ) + param_online_id = validate_path_param("online_id", online_id) + param_mailbox_id = validate_path_param("mailbox_id", mailbox_id) + + res = self._request( + "PATCH", + f"/webhosting/v1alpha1/regions/{param_region}/classic-hostings/{param_online_id}/mailboxes/{param_mailbox_id}", + body=marshal_ClassicMailApiUpdateMailboxRequest( + ClassicMailApiUpdateMailboxRequest( + online_id=online_id, + mailbox_id=mailbox_id, + region=region, + password=password, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_Mailbox(res.json()) diff --git a/scaleway/scaleway/webhosting/v1alpha1/marshalling.py b/scaleway/scaleway/webhosting/v1alpha1/marshalling.py index 108fd7db..2b574c20 100644 --- a/scaleway/scaleway/webhosting/v1alpha1/marshalling.py +++ b/scaleway/scaleway/webhosting/v1alpha1/marshalling.py @@ -13,19 +13,31 @@ HostingCpanelUrls, HostingOption, Hosting, + EmailAddress, + Mailbox, + CheckUserOwnsDomainResponse, DnsRecord, Nameserver, DnsRecords, ControlPanel, ListControlPanelsResponse, ListHostingsResponse, + ListMailboxesResponse, OfferProduct, Offer, ListOffersResponse, + ResetHostingPasswordResponse, + Session, + CheckUserOwnsDomainRequest, + ClassicMailApiCreateMailboxRequest, + ClassicMailApiUpdateMailboxRequest, CreateHostingRequestDomainConfiguration, CreateHostingRequest, UpdateHostingRequest, ) +from ...std.types import ( + LanguageCode as StdLanguageCode, +) def unmarshal_HostingCpanelUrls(data: Any) -> HostingCpanelUrls: @@ -102,25 +114,31 @@ def unmarshal_Hosting(data: Any) -> Hosting: if field is not None: args["offer_name"] = field + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("tags", None) + if field is not None: + args["tags"] = field + field = data.get("updated_at", None) if field is not None: args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None field = data.get("created_at", None) if field is not None: args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None field = data.get("platform_number", None) if field is not None: args["platform_number"] = field - - field = data.get("domain", None) - if field is not None: - args["domain"] = field - - field = data.get("tags", None) - if field is not None: - args["tags"] = field + else: + args["platform_number"] = None field = data.get("options", None) if field is not None: @@ -160,6 +178,10 @@ def unmarshal_Hosting(data: Any) -> Hosting: if field is not None: args["protected"] = field + field = data.get("one_time_password", None) + if field is not None: + args["one_time_password"] = field + field = data.get("region", None) if field is not None: args["region"] = field @@ -167,10 +189,67 @@ def unmarshal_Hosting(data: Any) -> Hosting: field = data.get("cpanel_urls", None) if field is not None: args["cpanel_urls"] = unmarshal_HostingCpanelUrls(field) + else: + args["cpanel_urls"] = None return Hosting(**args) +def unmarshal_EmailAddress(data: Any) -> EmailAddress: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'EmailAddress' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("domain", None) + if field is not None: + args["domain"] = field + + field = data.get("login", None) + if field is not None: + args["login"] = field + + return EmailAddress(**args) + + +def unmarshal_Mailbox(data: Any) -> Mailbox: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Mailbox' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("mailbox_id", None) + if field is not None: + args["mailbox_id"] = field + + field = data.get("email", None) + if field is not None: + args["email"] = unmarshal_EmailAddress(field) + else: + args["email"] = None + + return Mailbox(**args) + + +def unmarshal_CheckUserOwnsDomainResponse(data: Any) -> CheckUserOwnsDomainResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'CheckUserOwnsDomainResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("owns_domain", None) + if field is not None: + args["owns_domain"] = field + + return CheckUserOwnsDomainResponse(**args) + + def unmarshal_DnsRecord(data: Any) -> DnsRecord: if not isinstance(data, dict): raise TypeError( @@ -183,7 +262,7 @@ def unmarshal_DnsRecord(data: Any) -> DnsRecord: if field is not None: args["name"] = field - field = data.get("type_", None) + field = data.get("type", None) if field is not None: args["type_"] = field @@ -202,6 +281,8 @@ def unmarshal_DnsRecord(data: Any) -> DnsRecord: field = data.get("priority", None) if field is not None: args["priority"] = field + else: + args["priority"] = None return DnsRecord(**args) @@ -276,6 +357,12 @@ def unmarshal_ControlPanel(data: Any) -> ControlPanel: if field is not None: args["logo_url"] = field + field = data.get("available_languages", None) + if field is not None: + args["available_languages"] = ( + [StdLanguageCode(v) for v in field] if field is not None else None + ) + return ControlPanel(**args) @@ -321,6 +408,27 @@ def unmarshal_ListHostingsResponse(data: Any) -> ListHostingsResponse: return ListHostingsResponse(**args) +def unmarshal_ListMailboxesResponse(data: Any) -> ListMailboxesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListMailboxesResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + + field = data.get("mailboxes", None) + if field is not None: + args["mailboxes"] = ( + [unmarshal_Mailbox(v) for v in field] if field is not None else None + ) + + return ListMailboxesResponse(**args) + + def unmarshal_OfferProduct(data: Any) -> OfferProduct: if not isinstance(data, dict): raise TypeError( @@ -409,10 +517,14 @@ def unmarshal_Offer(data: Any) -> Offer: field = data.get("product", None) if field is not None: args["product"] = unmarshal_OfferProduct(field) + else: + args["product"] = None field = data.get("price", None) if field is not None: args["price"] = unmarshal_Money(field) + else: + args["price"] = None return Offer(**args) @@ -434,6 +546,90 @@ def unmarshal_ListOffersResponse(data: Any) -> ListOffersResponse: return ListOffersResponse(**args) +def unmarshal_ResetHostingPasswordResponse(data: Any) -> ResetHostingPasswordResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ResetHostingPasswordResponse' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("password", None) + if field is not None: + args["password"] = field + + return ResetHostingPasswordResponse(**args) + + +def unmarshal_Session(data: Any) -> Session: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Session' failed as data isn't a dictionary." + ) + + args: Dict[str, Any] = {} + + field = data.get("url", None) + if field is not None: + args["url"] = field + + return Session(**args) + + +def marshal_CheckUserOwnsDomainRequest( + request: CheckUserOwnsDomainRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.project_id is not None: + output["project_id"] = request.project_id or defaults.default_project_id + + return output + + +def marshal_EmailAddress( + request: EmailAddress, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.domain is not None: + output["domain"] = request.domain + + if request.login is not None: + output["login"] = request.login + + return output + + +def marshal_ClassicMailApiCreateMailboxRequest( + request: ClassicMailApiCreateMailboxRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + if request.email is not None: + output["email"] = marshal_EmailAddress(request.email, defaults) + + return output + + +def marshal_ClassicMailApiUpdateMailboxRequest( + request: ClassicMailApiUpdateMailboxRequest, + defaults: ProfileDefaults, +) -> Dict[str, Any]: + output: Dict[str, Any] = {} + + if request.password is not None: + output["password"] = request.password + + return output + + def marshal_CreateHostingRequestDomainConfiguration( request: CreateHostingRequestDomainConfiguration, defaults: ProfileDefaults, @@ -486,7 +682,7 @@ def marshal_CreateHostingRequest( output["domain_configuration"] = ( marshal_CreateHostingRequestDomainConfiguration( request.domain_configuration, defaults - ), + ) ) return output diff --git a/scaleway/scaleway/webhosting/v1alpha1/types.py b/scaleway/scaleway/webhosting/v1alpha1/types.py index b9650921..ef600c2f 100644 --- a/scaleway/scaleway/webhosting/v1alpha1/types.py +++ b/scaleway/scaleway/webhosting/v1alpha1/types.py @@ -9,7 +9,7 @@ from scaleway_core.bridge import ( Money, - Region, + Region as ScwRegion, ) from scaleway_core.utils import ( StrEnumMeta, @@ -102,6 +102,7 @@ class OfferQuotaWarning(str, Enum, metaclass=StrEnumMeta): EMAIL_COUNT_EXCEEDED = "email_count_exceeded" DATABASE_COUNT_EXCEEDED = "database_count_exceeded" DISK_USAGE_EXCEEDED = "disk_usage_exceeded" + ADDON_DOMAIN_COUNT_EXCEEDED = "addon_domain_count_exceeded" def __str__(self) -> str: return str(self.value) @@ -127,6 +128,19 @@ class HostingOption: """ +@dataclass +class EmailAddress: + domain: str + """ + Domain part of the mailbox address. + """ + + login: str + """ + Username part address of the mailbox address. + """ + + @dataclass class OfferProduct: name: str @@ -259,6 +273,11 @@ class ControlPanel: URL of this control panel's logo. """ + available_languages: List[StdLanguageCode] + """ + List of available languages for the control panel. + """ + @dataclass class Hosting: @@ -297,29 +316,29 @@ class Hosting: Name of the active offer for the Web Hosting plan. """ - updated_at: Optional[datetime] + domain: str """ - Date on which the Web Hosting plan was last updated. + Main domain associated with the Web Hosting plan. """ - created_at: Optional[datetime] + tags: List[str] """ - Date on which the Web Hosting plan was created. + List of tags associated with the Web Hosting plan. """ - platform_number: Optional[int] + updated_at: Optional[datetime] """ - Number of the host platform. + Date on which the Web Hosting plan was last updated. """ - domain: str + created_at: Optional[datetime] """ - Main domain associated with the Web Hosting plan. + Date on which the Web Hosting plan was created. """ - tags: List[str] + platform_number: Optional[int] """ - List of tags associated with the Web Hosting plan. + Number of the host platform. """ options: List[HostingOption] @@ -367,7 +386,12 @@ class Hosting: Whether the hosting is protected or not. """ - region: Region + one_time_password: str + """ + One-time-password used for the first login or reset password, empty after first use. + """ + + region: ScwRegion """ Region where the Web Hosting plan is hosted. """ @@ -378,6 +402,19 @@ class Hosting: """ +@dataclass +class Mailbox: + mailbox_id: int + """ + The ID of the mailbox. + """ + + email: Optional[EmailAddress] + """ + The email address of the mailbox. + """ + + @dataclass class Offer: id: str @@ -421,6 +458,142 @@ class Offer: """ +@dataclass +class CheckUserOwnsDomainRequest: + domain: str + """ + Domain for which ownership is to be verified. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + project_id: Optional[str] + """ + ID of the project currently in use. + """ + + +@dataclass +class CheckUserOwnsDomainResponse: + owns_domain: bool + """ + Indicates whether the specified project owns the domain. + """ + + +@dataclass +class ClassicMailApiCreateMailboxRequest: + online_id: int + """ + The Online hosting ID. + """ + + password: str + """ + Password for the new mailbox. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + email: Optional[EmailAddress] + """ + The email address of the mailbox. + """ + + +@dataclass +class ClassicMailApiDeleteMailboxRequest: + online_id: int + """ + The Online hosting ID. + """ + + mailbox_id: int + """ + The ID of the mailbox to delete. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ClassicMailApiGetMailboxRequest: + online_id: int + """ + The Online hosting ID. + """ + + mailbox_id: int + """ + The ID of the mailbox to get. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ClassicMailApiListMailboxesRequest: + online_id: int + """ + The Online hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + page: Optional[int] + """ + Page number (must be a positive integer). + """ + + page_size: Optional[int] + """ + Number of mailboxes to return (must be a positive integer lower or equal to 100). + """ + + domain: Optional[str] + """ + Domain to filter the mailboxes. + """ + + +@dataclass +class ClassicMailApiUpdateMailboxRequest: + online_id: int + """ + The Online hosting ID. + """ + + mailbox_id: int + """ + The ID of the mailbox to update. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + password: Optional[str] + """ + New password for the mailbox. + """ + + @dataclass class CreateHostingRequest: offer_id: str @@ -433,7 +606,7 @@ class CreateHostingRequest: Domain name to link to the Web Hosting plan. You must already own this domain name, and have completed the DNS validation process beforehand. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -469,6 +642,19 @@ class CreateHostingRequest: """ +@dataclass +class CreateSessionRequest: + hosting_id: str + """ + Hosting ID. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + @dataclass class DeleteHostingRequest: hosting_id: str @@ -476,7 +662,7 @@ class DeleteHostingRequest: Hosting ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -507,7 +693,7 @@ class GetDomainDnsRecordsRequest: Domain associated with the DNS records. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -520,7 +706,7 @@ class GetHostingRequest: Hosting ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -528,7 +714,7 @@ class GetHostingRequest: @dataclass class ListControlPanelsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -559,7 +745,7 @@ class ListControlPanelsResponse: @dataclass class ListHostingsRequest: - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -623,6 +809,19 @@ class ListHostingsResponse: """ +@dataclass +class ListMailboxesResponse: + total_count: int + """ + Total number of mailboxes. + """ + + mailboxes: List[Mailbox] + """ + List of mailboxes. + """ + + @dataclass class ListOffersRequest: without_options: bool @@ -635,7 +834,7 @@ class ListOffersRequest: Defines whether the response should consist of options only, without offers. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ @@ -664,6 +863,27 @@ class ListOffersResponse: """ +@dataclass +class ResetHostingPasswordRequest: + hosting_id: str + """ + UUID of the hosting. + """ + + region: Optional[ScwRegion] + """ + Region to target. If none is passed will use default region from the config. + """ + + +@dataclass +class ResetHostingPasswordResponse: + password: str + """ + New password. + """ + + @dataclass class RestoreHostingRequest: hosting_id: str @@ -671,12 +891,20 @@ class RestoreHostingRequest: Hosting ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ +@dataclass +class Session: + url: str + """ + Logged user's session URL. + """ + + @dataclass class UpdateHostingRequest: hosting_id: str @@ -684,7 +912,7 @@ class UpdateHostingRequest: Hosting ID. """ - region: Optional[Region] + region: Optional[ScwRegion] """ Region to target. If none is passed will use default region from the config. """ diff --git a/scaleway/tests/test_total_count_legacy.py b/scaleway/tests/test_total_count_legacy.py new file mode 100644 index 00000000..c49f025f --- /dev/null +++ b/scaleway/tests/test_total_count_legacy.py @@ -0,0 +1,20 @@ +import logging +import sys +import unittest +from scaleway_core.client import Client +from scaleway.instance.v1 import InstanceV1API + +logger = logging.getLogger() +logger.level = logging.DEBUG +stream_handler = logging.StreamHandler(sys.stdout) +logger.addHandler(stream_handler) + + +class TestTotalCountLegacy(unittest.TestCase): + def setUp(self) -> None: + self.client = Client() + self.instance_api = InstanceV1API(self.client, bypass_validation=True) + + def test_list_servers_type(self): + list_server_type = self.instance_api.list_servers_types(zone="fr-par-1") + self.assertIsNotNone(list_server_type.total_count)