Repository: canonical/cloud-init (branch: main)
Commit date: 2024-01-05T08:18:36Z

Workflow file: .github/workflows/check_format.yml (Lint Tests)
name: Lint Tests
on:
  pull_request:
  push:
    branches:
      - main

concurrency:
  group: 'ci-${{ github.workflow }}-${{ github.ref }}'
  cancel-in-progress: true
defaults:
  run:
    shell: sh -ex {0}

jobs:
  check_format:
    strategy:
      fail-fast: false
      matrix:
        env: [ruff, mypy, pylint, black, isort]
        lint-with:
          - {tip-versions: false, os: ubuntu-20.04}
          - {tip-versions: true, os: ubuntu-latest}
    name: Check ${{ matrix.lint-with.tip-versions && 'tip-' || '' }}${{ matrix.env }}
    runs-on: ${{ matrix.lint-with.os }}
    services:
      pypi_wayback:
        image: ghcr.io/waleko/pypi-wayback
        ports:
          - 8629:8080
    steps:
      - name: "Checkout #1"
        uses: actions/checkout@v3.0.0

      - name: "Checkout #2 (for tools/read-version)"
        run: |
          git fetch --unshallow
          git remote add upstream https://git.launchpad.net/cloud-init

      - name: Dependencies
        run: |
          sudo DEBIAN_FRONTEND=noninteractive apt-get -qy update
          sudo DEBIAN_FRONTEND=noninteractive apt-get -qy install tox

      - name: Print version
        run: python3 --version

      - name: Test
        if: ${{ !matrix.lint-with.tip-versions }}
        env:
          # matrix env: not to be confused w/environment variables or testenv
          TOXENV: ${{ matrix.env }}
        run: tox
      - name: Test (tip versions)
        if: matrix.lint-with.tip-versions
        continue-on-error: true
        env:
          TOXENV: tip-${{ matrix.env }}
        run: tox
  schema-format:
    strategy:
      fail-fast: false
    name: Check json format
    runs-on: ubuntu-22.04
    services:
      pypi_wayback:
        image: ghcr.io/waleko/pypi-wayback
        ports:
          - 8629:8080
    steps:
      - name: "Checkout #1"
        uses: actions/checkout@v3.0.0

      - name: "Test format"
        run: |
          tools/check_json_format.sh cloudinit/config/schemas/schema-cloud-config-v1.json
          tools/check_json_format.sh cloudinit/config/schemas/schema-network-config-v1.json
          tools/check_json_format.sh cloudinit/config/schemas/versions.schema.cloud-config.json

  doc:
    strategy:
      fail-fast: false
    name: Check docs
    runs-on: ubuntu-22.04
    services:
      pypi_wayback:
        image: ghcr.io/waleko/pypi-wayback
        ports:
          - 8629:8080
    steps:
      - name: "Checkout #1"
        uses: actions/checkout@v3.0.0

      - name: "Checkout #2 (for tools/read-version)"
        run: |
          git fetch --unshallow
          git remote add upstream https://git.launchpad.net/cloud-init
      - name: "Install Python 3.10"
        uses: actions/setup-python@v4
        with:
          python-version: '3.10.8'
      - name: "Install dependencies"
        run: |
          sudo DEBIAN_FRONTEND=noninteractive apt-get -qy update
          sudo DEBIAN_FRONTEND=noninteractive apt-get -qy install tox
      - name: "Spellcheck"
        run: |
          tox
        env:
          TOXENV: doc-spelling
      - name: "Build docs"
        env:
          TOXENV: doc
        run: |
          tox

  shell-lint:
    name: Shell Lint
    runs-on: ubuntu-22.04
    services:
      pypi_wayback:
        image: ghcr.io/waleko/pypi-wayback
        ports:
          - 8629:8080
    steps:
      - name: Checkout
        uses: actions/checkout@v3.0.0

      - name: Install ShellCheck
        run: |
          sudo apt-get update
          sudo apt install shellcheck

      - name: Run ShellCheck
        run: |
          shellcheck ./tools/ds-identify

  check-cla-signers:
    runs-on: ubuntu-22.04
    services:
      pypi_wayback:
        image: ghcr.io/waleko/pypi-wayback
        ports:
          - 8629:8080
    steps:
      - uses: actions/checkout@v3.0.0

      - name: Check CLA signers file
        run: tools/check-cla-signers

env:
  PIP_INDEX_URL: http://localhost:8629/2024-01-05
  UV_INDEX_URL: http://localhost:8629/2024-01-05


Failed build logs:
step_name: Check mypy/6_Test.txt
log: ##[group]Run tox
[36;1mtox[0m
shell: /usr/bin/sh -ex {0}
env:
  TOXENV: mypy
##[endgroup]
+ tox
GLOB sdist-make: /home/runner/work/cloud-init/cloud-init/setup.py
mypy create: /home/runner/work/cloud-init/cloud-init/.tox/mypy
mypy installdeps: hypothesis===6.31.6, hypothesis_jsonschema===0.20.1, mypy===0.950, pytest===7.0.1, types-jsonschema===4.4.2, types-passlib===1.7.7.12, types-pyyaml===6.0.4, types-oauthlib===3.1.6, types-requests===2.27.8, types-setuptools===57.4.9, typing-extensions===4.1.1
mypy inst: /home/runner/work/cloud-init/cloud-init/.tox/.tmp/package/1/cloud-init-23.4+73.g786216e0.zip
mypy installed: attrs==23.2.0,certifi==2023.11.17,charset-normalizer==3.3.2,cloud-init==23.4+73.g786216e0,configobj==5.0.8,hypothesis==6.31.6,hypothesis-jsonschema==0.20.1,idna==3.6,importlib-resources==6.1.1,iniconfig==2.0.0,Jinja2==3.1.2,jsonpatch==1.33,jsonpointer==2.4,jsonschema==4.20.0,jsonschema-specifications==2023.12.1,MarkupSafe==2.1.3,mypy==0.950,mypy-extensions==1.0.0,netifaces==0.11.0,oauthlib==3.2.2,packaging==23.2,pkgutil-resolve-name==1.3.10,pluggy==1.3.0,py==1.11.0,pyserial==3.5,pytest==7.0.1,PyYAML==6.0.1,referencing==0.32.0,requests==2.31.0,rpds-py==0.16.2,six==1.16.0,sortedcontainers==2.4.0,tomli==2.0.1,types-jsonschema==4.4.2,types-oauthlib==3.1.6,types-passlib==1.7.7.12,types-PyYAML==6.0.4,types-requests==2.27.8,types-setuptools==57.4.9,types-urllib3==1.26.25.14,typing-extensions==4.1.1,urllib3==2.1.0,zipp==3.17.0
mypy run-test-pre: PYTHONHASHSEED='2984288895'
mypy run-test: commands[0] | /home/runner/work/cloud-init/cloud-init/.tox/mypy/bin/python -m mypy cloudinit/ tests/ tools/
cloudinit/distros/__init__.py:154: error: X | Y syntax for unions requires Python 3.10
cloudinit/distros/__init__.py:158: error: X | Y syntax for unions requires Python 3.10
Found 2 errors in 1 file (checked 543 source files)
ERROR: InvocationError for command /home/runner/work/cloud-init/cloud-init/.tox/mypy/bin/python -m mypy cloudinit/ tests/ tools/ (exited with code 1)
___________________________________ summary ____________________________________
ERROR:   mypy: commands failed
##[error]Process completed with exit code 1.

step_name: Check pylint/6_Test.txt
log: ##[group]Run tox
[36;1mtox[0m
shell: /usr/bin/sh -ex {0}
env:
  TOXENV: pylint
##[endgroup]
+ tox
GLOB sdist-make: /home/runner/work/cloud-init/cloud-init/setup.py
pylint create: /home/runner/work/cloud-init/cloud-init/.tox/pylint
pylint installdeps: pylint===2.13.9, -r/home/runner/work/cloud-init/cloud-init/test-requirements.txt, -r/home/runner/work/cloud-init/cloud-init/integration-requirements.txt
pylint inst: /home/runner/work/cloud-init/cloud-init/.tox/.tmp/package/1/cloud-init-23.4+73.g786216e0.zip
pylint installed: adal==1.2.7,anyio==4.2.0,appdirs==1.4.4,applicationinsights==0.11.10,argcomplete==3.1.6,astroid==2.11.7,attrs==23.2.0,autopage==0.5.2,azure-cli-core==2.55.0,azure-cli-telemetry==1.1.0,azure-common==1.1.28,azure-core==1.29.6,azure-identity==1.15.0,azure-mgmt-compute==30.4.0,azure-mgmt-core==1.4.0,azure-mgmt-network==25.2.0,azure-mgmt-resource==23.0.1,bcrypt==4.1.2,boto3==1.34.13,botocore==1.34.13,cachetools==5.3.2,certifi==2023.11.17,cffi==1.16.0,charset-normalizer==3.3.2,circuitbreaker==1.4.0,cliff==4.4.0,cloud-init==23.4+73.g786216e0,cmd2==2.4.3,configobj==5.0.8,coverage==7.4.0,cryptography==41.0.7,debtcollector==2.5.0,decorator==5.1.1,dill==0.3.7,distro==1.9.0,dogpile.cache==1.3.0,exceptiongroup==1.2.0,google-api-core==2.15.0,google-api-python-client==2.112.0,google-auth==2.26.1,google-auth-httplib2==0.2.0,googleapis-common-protos==1.62.0,httplib2==0.22.0,humanfriendly==10.0,ibm-cloud-sdk-core==3.18.2,ibm-platform-services==0.48.1,ibm-vpc==0.20.0,idna==3.6,importlib-metadata==7.0.1,importlib-resources==6.1.1,iniconfig==2.0.0,iso8601==2.1.0,isodate==0.6.1,isort==5.13.2,Jinja2==3.1.2,jmespath==1.0.1,jsonpatch==1.33,jsonpointer==2.4,jsonschema==4.20.0,jsonschema-specifications==2023.12.1,keystoneauth1==5.4.0,knack==0.11.0,lazy-object-proxy==1.10.0,MarkupSafe==2.1.3,mccabe==0.7.0,msal==1.24.0b2,msal-extensions==1.0.0,msgpack==1.0.7,msrest==0.7.1,msrestazure==0.6.4,netaddr==0.10.1,netifaces==0.11.0,oauthlib==3.2.2,oci==2.118.0,openstacksdk==1.4.0,os-service-types==1.7.0,osc-lib==2.9.0,oslo.config==9.2.0,oslo.i18n==6.2.0,oslo.serialization==5.2.0,oslo.utils==6.3.0,packaging==23.2,paramiko==3.4.0,passlib==1.7.4,pbr==6.0.0,pkginfo==1.9.6,pkgutil-resolve-name==1.3.10,platformdirs==4.1.0,pluggy==1.3.0,portalocker==2.8.2,prettytable==3.9.0,protobuf==3.19.6,psutil==5.9.7,pyasn1==0.5.1,pyasn1-modules==0.3.0,pycloudlib==1!5.12.1,pycparser==2.21,pygments==2.17.2,PyJWT==2.8.0,pylint==2.13.9,PyNaCl==1.5.0,pyOpenSSL==23.3.0,pyparsing==2.4.7,pyperclip==1.8.2,pyserial==3.5,pytest==7.4.4,pytest-cov==4.1.0,pytest-mock==3.12.0,python-cinderclient==9.4.0,python-dateutil==2.8.2,python-keystoneclient==5.2.0,python-novaclient==18.4.0,python-openstackclient==6.4.0,pytz==2023.3.post1,PyYAML==6.0.1,qemu.qmp==0.0.3,referencing==0.32.0,requests==2.31.0,requests-oauthlib==1.3.1,requestsexceptions==1.4.0,responses==0.24.1,rfc3986==2.0.0,rpds-py==0.16.2,rsa==4.9,s3transfer==0.10.0,simplejson==3.19.2,six==1.16.0,sniffio==1.3.0,stevedore==5.1.0,tabulate==0.9.0,toml==0.10.0,tomli==2.0.1,typing-extensions==4.9.0,tzdata==2023.4,uritemplate==4.1.1,urllib3==2.1.0,wcwidth==0.2.12,wrapt==1.16.0,zipp==3.17.0
pylint run-test-pre: PYTHONHASHSEED='2754439474'
pylint run-test: commands[0] | /home/runner/work/cloud-init/cloud-init/.tox/pylint/bin/python -m pylint cloudinit/ tests/ tools/ conftest.py setup.py
************* Module cloudinit.distros
cloudinit/distros/__init__.py:154: [E1131(unsupported-binary-operation), Distro] unsupported operand type(s) for |
cloudinit/distros/__init__.py:158: [E1131(unsupported-binary-operation), Distro] unsupported operand type(s) for |

------------------------------------
Your code has been rated at 10.00/10

ERROR: InvocationError for command /home/runner/work/cloud-init/cloud-init/.tox/pylint/bin/python -m pylint cloudinit/ tests/ tools/ conftest.py setup.py (exited with code 2)
___________________________________ summary ____________________________________
ERROR:   pylint: commands failed
##[error]Process completed with exit code 1.


Changed files:
cloudinit/distros/__init__.py
cloudinit/sources/DataSourceCloudStack.py

Fix diff:
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
index 9a073742c..c857a8737 100644
--- a/cloudinit/distros/__init__.py
+++ b/cloudinit/distros/__init__.py
@@ -151,11 +151,11 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta):
     # Directory where the distro stores their DHCP leases.
     # The children classes should override this with their dhcp leases
     # directory
-    dhclient_lease_directory: str | None = None
+    dhclient_lease_directory: Optional[str] = None
     # A regex to match DHCP lease file(s)
     # The children classes should override this with a regex matching
     # their lease file name format
-    dhclient_lease_file_regex: str | None = None
+    dhclient_lease_file_regex: Optional[str] = None
 
     def __init__(self, name, cfg, paths):
         self._paths = paths
diff --git a/cloudinit/sources/DataSourceCloudStack.py b/cloudinit/sources/DataSourceCloudStack.py
index e4b4d39b2..98078554e 100644
--- a/cloudinit/sources/DataSourceCloudStack.py
+++ b/cloudinit/sources/DataSourceCloudStack.py
@@ -299,16 +299,16 @@ def get_vr_address(distro=None):
     else:
         LOG.debug("Distro object is not defined, skipping leasefile search")
 
-    if not lease_file:
-        LOG.debug("No lease file found, using default gateway")
-        return get_default_gateway()
-
-    lease_file = dhcp.IscDhclient.parse_dhcp_server_from_lease_file(lease_file)
-    if not latest_address:
-        # No virtual router found, fallback on default gateway
-        LOG.debug("No DHCP found, using default gateway")
-        return get_default_gateway()
-    return latest_address
+    if lease_file:
+        latest_address = dhcp.IscDhclient.parse_dhcp_server_from_lease_file(
+            lease_file
+        )
+        if latest_address:
+            return latest_address
+
+    # No virtual router found, fallback to default gateway
+    LOG.debug("No DHCP found, using default gateway")
+    return get_default_gateway()
 
 
 # Used to match classes to dependencies