all:
  children:
    zuul_unreachable:
      hosts: {}
  hosts:
    debian-bookworm:
      ansible_connection: ssh
      ansible_host: 2a13:1a81:8000:3124:f816:3eff:fea7:7db7
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      nodepool:
        az: nova
        cloud: regiocloud-a-ci
        external_id: ec42e11a-a22c-4853-9cd7-a40ac008fec8
        host_id: 82101243836454d7401d5893feae9e2c5df7cc291646d8a99b33b53b
        interface_ip: 2a13:1a81:8000:3124:f816:3eff:fea7:7db7
        label: debian-bookworm
        node_properties: {}
        private_ipv4: 10.128.7.80
        private_ipv6: null
        provider: regiocloud-a
        public_ipv4: 81.163.193.91
        public_ipv6: 2a13:1a81:8000:3124:f816:3eff:fea7:7db7
        region: null
        slot: null
  vars:
    zuul:
      _inheritance_path:
      - '<Job base explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-config/zuul.d/jobs.yaml@main#2>'
      - '<Job flake8 explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-jobs/.zuul.yaml@main#32>'
      - '<Job flake8 explicit: None implied: None source: osism/netbox-manager/.zuul.yaml@main#32>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: 2cc067c5685145c9a7d402d7c265086f
      build_refs:
      - branch: main
        change: '245'
        change_message: "Disambiguate duplicate interface labels on multi-homed nodes
          (#243)\n\n## Problem\n\n`netbox-manager autoconf` propagates a switch's
          `device_interface_label` custom field (e.g. `data1`) onto every connected
          node interface. The label value comes from the **switch**, not the port,
          so it is applied identically to all node interfaces connected to that switch.\n\nWhen
          a single server has **more than one link to the same switch**, both node
          interfaces receive the identical label `data1`, producing duplicate, ambiguous
          interface labels on that node.\n\n## Fix\n\nDetect duplicates per `(node
          device, label)` and disambiguate them by appending suffixes: `data1a`, `data1b`,
          ...\n\n- **Ordering**: suffixes are assigned by natural sort of the node
          interface name (e.g. `Ethernet3` \u2192 `data1a`, `Ethernet5` \u2192 `data1b`).\n-
          **Scope**: any two interfaces on the same node with the same label are disambiguated,
          regardless of source switch.\n- Labels occurring only once are left unchanged
          (backward compatible \u2014 existing `leaf1`/`leaf2` topologies are untouched).\n-
          Tasks without a label pass through untouched.\n\n### Changes\n\n- `netbox_manager/main.py`:
          three pure, side-effect-free helpers above `_generate_device_interface_labels()`:\n
          \ - `_natural_sort_key()` \u2014 numeric-aware sort (`Ethernet2` < `Ethernet10`)\n
          \ - `_label_suffix()` \u2014 index \u2192 `a, b, \u2026, z, aa, ab, \u2026`
          (robust beyond 26 links)\n  - `_disambiguate_interface_labels()` \u2014
          groups by `(device, label)`, renames duplicates, logs each renamed group\n-
          `tests/unit/netbox_manager/test_interface_labels.py`: 11 unit tests for
          the pure helpers (no NetBox mocking required)\n\n## Verification\n\n- `flake8`:
          clean\n- `mypy netbox_manager/`: no new errors\n- `pytest tests/unit`: 14
          passed\n\nCloses #243\n\n\U0001F916 Generated with [Claude Code](https://claude.com/claude-code)"
        change_url: https://github.com/osism/netbox-manager/pull/245
        commit_id: c6a8ebfd0b05e3686ce9e62359a364feb991b4dd
        patchset: c6a8ebfd0b05e3686ce9e62359a364feb991b4dd
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/netbox-manager
          name: osism/netbox-manager
          short_name: netbox-manager
        src_dir: src/github.com/osism/netbox-manager
        topic: null
      buildset: 32736565e26243ec9e080a3eaf0ca62a
      buildset_refs:
      - branch: main
        change: '245'
        change_message: "Disambiguate duplicate interface labels on multi-homed nodes
          (#243)\n\n## Problem\n\n`netbox-manager autoconf` propagates a switch's
          `device_interface_label` custom field (e.g. `data1`) onto every connected
          node interface. The label value comes from the **switch**, not the port,
          so it is applied identically to all node interfaces connected to that switch.\n\nWhen
          a single server has **more than one link to the same switch**, both node
          interfaces receive the identical label `data1`, producing duplicate, ambiguous
          interface labels on that node.\n\n## Fix\n\nDetect duplicates per `(node
          device, label)` and disambiguate them by appending suffixes: `data1a`, `data1b`,
          ...\n\n- **Ordering**: suffixes are assigned by natural sort of the node
          interface name (e.g. `Ethernet3` \u2192 `data1a`, `Ethernet5` \u2192 `data1b`).\n-
          **Scope**: any two interfaces on the same node with the same label are disambiguated,
          regardless of source switch.\n- Labels occurring only once are left unchanged
          (backward compatible \u2014 existing `leaf1`/`leaf2` topologies are untouched).\n-
          Tasks without a label pass through untouched.\n\n### Changes\n\n- `netbox_manager/main.py`:
          three pure, side-effect-free helpers above `_generate_device_interface_labels()`:\n
          \ - `_natural_sort_key()` \u2014 numeric-aware sort (`Ethernet2` < `Ethernet10`)\n
          \ - `_label_suffix()` \u2014 index \u2192 `a, b, \u2026, z, aa, ab, \u2026`
          (robust beyond 26 links)\n  - `_disambiguate_interface_labels()` \u2014
          groups by `(device, label)`, renames duplicates, logs each renamed group\n-
          `tests/unit/netbox_manager/test_interface_labels.py`: 11 unit tests for
          the pure helpers (no NetBox mocking required)\n\n## Verification\n\n- `flake8`:
          clean\n- `mypy netbox_manager/`: no new errors\n- `pytest tests/unit`: 14
          passed\n\nCloses #243\n\n\U0001F916 Generated with [Claude Code](https://claude.com/claude-code)"
        change_url: https://github.com/osism/netbox-manager/pull/245
        commit_id: c6a8ebfd0b05e3686ce9e62359a364feb991b4dd
        patchset: c6a8ebfd0b05e3686ce9e62359a364feb991b4dd
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/netbox-manager
          name: osism/netbox-manager
          short_name: netbox-manager
        src_dir: src/github.com/osism/netbox-manager
        topic: null
      change: '245'
      change_message: "Disambiguate duplicate interface labels on multi-homed nodes
        (#243)\n\n## Problem\n\n`netbox-manager autoconf` propagates a switch's `device_interface_label`
        custom field (e.g. `data1`) onto every connected node interface. The label
        value comes from the **switch**, not the port, so it is applied identically
        to all node interfaces connected to that switch.\n\nWhen a single server has
        **more than one link to the same switch**, both node interfaces receive the
        identical label `data1`, producing duplicate, ambiguous interface labels on
        that node.\n\n## Fix\n\nDetect duplicates per `(node device, label)` and disambiguate
        them by appending suffixes: `data1a`, `data1b`, ...\n\n- **Ordering**: suffixes
        are assigned by natural sort of the node interface name (e.g. `Ethernet3`
        \u2192 `data1a`, `Ethernet5` \u2192 `data1b`).\n- **Scope**: any two interfaces
        on the same node with the same label are disambiguated, regardless of source
        switch.\n- Labels occurring only once are left unchanged (backward compatible
        \u2014 existing `leaf1`/`leaf2` topologies are untouched).\n- Tasks without
        a label pass through untouched.\n\n### Changes\n\n- `netbox_manager/main.py`:
        three pure, side-effect-free helpers above `_generate_device_interface_labels()`:\n
        \ - `_natural_sort_key()` \u2014 numeric-aware sort (`Ethernet2` < `Ethernet10`)\n
        \ - `_label_suffix()` \u2014 index \u2192 `a, b, \u2026, z, aa, ab, \u2026`
        (robust beyond 26 links)\n  - `_disambiguate_interface_labels()` \u2014 groups
        by `(device, label)`, renames duplicates, logs each renamed group\n- `tests/unit/netbox_manager/test_interface_labels.py`:
        11 unit tests for the pure helpers (no NetBox mocking required)\n\n## Verification\n\n-
        `flake8`: clean\n- `mypy netbox_manager/`: no new errors\n- `pytest tests/unit`:
        14 passed\n\nCloses #243\n\n\U0001F916 Generated with [Claude Code](https://claude.com/claude-code)"
      change_url: https://github.com/osism/netbox-manager/pull/245
      child_jobs: []
      commit_id: c6a8ebfd0b05e3686ce9e62359a364feb991b4dd
      event_id: 8cbed2e0-63e6-11f1-89c9-bd0fd181b653
      executor:
        hostname: 521e9411259a
        inventory_file: /var/lib/zuul/builds/2cc067c5685145c9a7d402d7c265086f/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/2cc067c5685145c9a7d402d7c265086f/work/logs
        result_data_file: /var/lib/zuul/builds/2cc067c5685145c9a7d402d7c265086f/work/results.json
        src_root: /var/lib/zuul/builds/2cc067c5685145c9a7d402d7c265086f/work/src
        work_root: /var/lib/zuul/builds/2cc067c5685145c9a7d402d7c265086f/work
      include_vars: []
      items:
      - branch: main
        change: '245'
        change_message: "Disambiguate duplicate interface labels on multi-homed nodes
          (#243)\n\n## Problem\n\n`netbox-manager autoconf` propagates a switch's
          `device_interface_label` custom field (e.g. `data1`) onto every connected
          node interface. The label value comes from the **switch**, not the port,
          so it is applied identically to all node interfaces connected to that switch.\n\nWhen
          a single server has **more than one link to the same switch**, both node
          interfaces receive the identical label `data1`, producing duplicate, ambiguous
          interface labels on that node.\n\n## Fix\n\nDetect duplicates per `(node
          device, label)` and disambiguate them by appending suffixes: `data1a`, `data1b`,
          ...\n\n- **Ordering**: suffixes are assigned by natural sort of the node
          interface name (e.g. `Ethernet3` \u2192 `data1a`, `Ethernet5` \u2192 `data1b`).\n-
          **Scope**: any two interfaces on the same node with the same label are disambiguated,
          regardless of source switch.\n- Labels occurring only once are left unchanged
          (backward compatible \u2014 existing `leaf1`/`leaf2` topologies are untouched).\n-
          Tasks without a label pass through untouched.\n\n### Changes\n\n- `netbox_manager/main.py`:
          three pure, side-effect-free helpers above `_generate_device_interface_labels()`:\n
          \ - `_natural_sort_key()` \u2014 numeric-aware sort (`Ethernet2` < `Ethernet10`)\n
          \ - `_label_suffix()` \u2014 index \u2192 `a, b, \u2026, z, aa, ab, \u2026`
          (robust beyond 26 links)\n  - `_disambiguate_interface_labels()` \u2014
          groups by `(device, label)`, renames duplicates, logs each renamed group\n-
          `tests/unit/netbox_manager/test_interface_labels.py`: 11 unit tests for
          the pure helpers (no NetBox mocking required)\n\n## Verification\n\n- `flake8`:
          clean\n- `mypy netbox_manager/`: no new errors\n- `pytest tests/unit`: 14
          passed\n\nCloses #243\n\n\U0001F916 Generated with [Claude Code](https://claude.com/claude-code)"
        change_url: https://github.com/osism/netbox-manager/pull/245
        commit_id: c6a8ebfd0b05e3686ce9e62359a364feb991b4dd
        patchset: c6a8ebfd0b05e3686ce9e62359a364feb991b4dd
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/netbox-manager
          name: osism/netbox-manager
          short_name: netbox-manager
          src_dir: src/github.com/osism/netbox-manager
        topic: null
      job: flake8
      jobtags: []
      max_attempts: 3
      message: RGlzYW1iaWd1YXRlIGR1cGxpY2F0ZSBpbnRlcmZhY2UgbGFiZWxzIG9uIG11bHRpLWhvbWVkIG5vZGVzICgjMjQzKQoKIyMgUHJvYmxlbQoKYG5ldGJveC1tYW5hZ2VyIGF1dG9jb25mYCBwcm9wYWdhdGVzIGEgc3dpdGNoJ3MgYGRldmljZV9pbnRlcmZhY2VfbGFiZWxgIGN1c3RvbSBmaWVsZCAoZS5nLiBgZGF0YTFgKSBvbnRvIGV2ZXJ5IGNvbm5lY3RlZCBub2RlIGludGVyZmFjZS4gVGhlIGxhYmVsIHZhbHVlIGNvbWVzIGZyb20gdGhlICoqc3dpdGNoKiosIG5vdCB0aGUgcG9ydCwgc28gaXQgaXMgYXBwbGllZCBpZGVudGljYWxseSB0byBhbGwgbm9kZSBpbnRlcmZhY2VzIGNvbm5lY3RlZCB0byB0aGF0IHN3aXRjaC4KCldoZW4gYSBzaW5nbGUgc2VydmVyIGhhcyAqKm1vcmUgdGhhbiBvbmUgbGluayB0byB0aGUgc2FtZSBzd2l0Y2gqKiwgYm90aCBub2RlIGludGVyZmFjZXMgcmVjZWl2ZSB0aGUgaWRlbnRpY2FsIGxhYmVsIGBkYXRhMWAsIHByb2R1Y2luZyBkdXBsaWNhdGUsIGFtYmlndW91cyBpbnRlcmZhY2UgbGFiZWxzIG9uIHRoYXQgbm9kZS4KCiMjIEZpeAoKRGV0ZWN0IGR1cGxpY2F0ZXMgcGVyIGAobm9kZSBkZXZpY2UsIGxhYmVsKWAgYW5kIGRpc2FtYmlndWF0ZSB0aGVtIGJ5IGFwcGVuZGluZyBzdWZmaXhlczogYGRhdGExYWAsIGBkYXRhMWJgLCAuLi4KCi0gKipPcmRlcmluZyoqOiBzdWZmaXhlcyBhcmUgYXNzaWduZWQgYnkgbmF0dXJhbCBzb3J0IG9mIHRoZSBub2RlIGludGVyZmFjZSBuYW1lIChlLmcuIGBFdGhlcm5ldDNgIOKGkiBgZGF0YTFhYCwgYEV0aGVybmV0NWAg4oaSIGBkYXRhMWJgKS4KLSAqKlNjb3BlKio6IGFueSB0d28gaW50ZXJmYWNlcyBvbiB0aGUgc2FtZSBub2RlIHdpdGggdGhlIHNhbWUgbGFiZWwgYXJlIGRpc2FtYmlndWF0ZWQsIHJlZ2FyZGxlc3Mgb2Ygc291cmNlIHN3aXRjaC4KLSBMYWJlbHMgb2NjdXJyaW5nIG9ubHkgb25jZSBhcmUgbGVmdCB1bmNoYW5nZWQgKGJhY2t3YXJkIGNvbXBhdGlibGUg4oCUIGV4aXN0aW5nIGBsZWFmMWAvYGxlYWYyYCB0b3BvbG9naWVzIGFyZSB1bnRvdWNoZWQpLgotIFRhc2tzIHdpdGhvdXQgYSBsYWJlbCBwYXNzIHRocm91Z2ggdW50b3VjaGVkLgoKIyMjIENoYW5nZXMKCi0gYG5ldGJveF9tYW5hZ2VyL21haW4ucHlgOiB0aHJlZSBwdXJlLCBzaWRlLWVmZmVjdC1mcmVlIGhlbHBlcnMgYWJvdmUgYF9nZW5lcmF0ZV9kZXZpY2VfaW50ZXJmYWNlX2xhYmVscygpYDoKICAtIGBfbmF0dXJhbF9zb3J0X2tleSgpYCDigJQgbnVtZXJpYy1hd2FyZSBzb3J0IChgRXRoZXJuZXQyYCA8IGBFdGhlcm5ldDEwYCkKICAtIGBfbGFiZWxfc3VmZml4KClgIOKAlCBpbmRleCDihpIgYGEsIGIsIOKApiwgeiwgYWEsIGFiLCDigKZgIChyb2J1c3QgYmV5b25kIDI2IGxpbmtzKQogIC0gYF9kaXNhbWJpZ3VhdGVfaW50ZXJmYWNlX2xhYmVscygpYCDigJQgZ3JvdXBzIGJ5IGAoZGV2aWNlLCBsYWJlbClgLCByZW5hbWVzIGR1cGxpY2F0ZXMsIGxvZ3MgZWFjaCByZW5hbWVkIGdyb3VwCi0gYHRlc3RzL3VuaXQvbmV0Ym94X21hbmFnZXIvdGVzdF9pbnRlcmZhY2VfbGFiZWxzLnB5YDogMTEgdW5pdCB0ZXN0cyBmb3IgdGhlIHB1cmUgaGVscGVycyAobm8gTmV0Qm94IG1vY2tpbmcgcmVxdWlyZWQpCgojIyBWZXJpZmljYXRpb24KCi0gYGZsYWtlOGA6IGNsZWFuCi0gYG15cHkgbmV0Ym94X21hbmFnZXIvYDogbm8gbmV3IGVycm9ycwotIGBweXRlc3QgdGVzdHMvdW5pdGA6IDE0IHBhc3NlZAoKQ2xvc2VzICMyNDMKCvCfpJYgR2VuZXJhdGVkIHdpdGggW0NsYXVkZSBDb2RlXShodHRwczovL2NsYXVkZS5jb20vY2xhdWRlLWNvZGUp
      patchset: c6a8ebfd0b05e3686ce9e62359a364feb991b4dd
      pipeline: check
      playbook_context:
        playbook_projects:
          trusted/project_0/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 019f0261a526db7d8989ff1abefc2299a8c0ffbc
          trusted/project_1/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 038dd8b856c62af4433c8477c5cb3d0480847059
          trusted/project_2/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: 0c74c57cedff2b36bb37ca68a5338d1c49991496
          untrusted/project_0/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: 0c74c57cedff2b36bb37ca68a5338d1c49991496
          untrusted/project_1/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 019f0261a526db7d8989ff1abefc2299a8c0ffbc
          untrusted/project_2/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 038dd8b856c62af4433c8477c5cb3d0480847059
        playbooks:
        - path: untrusted/project_0/github.com/osism/zuul-jobs/playbooks/flake8/run.yaml
          roles:
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/playbook_0/role_0/zuul-config
            link_target: untrusted/project_1/github.com/osism/zuul-config
            role_path: ansible/playbook_0/role_0/zuul-config/roles
          - checkout: master
            checkout_description: project default branch
            link_name: ansible/playbook_0/role_1/openinfra-zuul-jobs
            link_target: untrusted/project_2/github.com/osism/openinfra-zuul-jobs
            role_path: ansible/playbook_0/role_1/openinfra-zuul-jobs/roles
          - checkout: main
            checkout_description: playbook branch
            link_name: ansible/playbook_0/role_2/zuul-jobs
            link_target: untrusted/project_0/github.com/osism/zuul-jobs
            role_path: ansible/playbook_0/role_2/zuul-jobs/roles
      post_review: false
      post_timeout: null
      pre_timeout: null
      project:
        canonical_hostname: github.com
        canonical_name: github.com/osism/netbox-manager
        name: osism/netbox-manager
        short_name: netbox-manager
        src_dir: src/github.com/osism/netbox-manager
      projects:
        github.com/osism/netbox-manager:
          canonical_hostname: github.com
          canonical_name: github.com/osism/netbox-manager
          checkout: main
          checkout_description: zuul branch
          commit: e4b499863308dc7aceeac2da9764cab6c55fc37d
          name: osism/netbox-manager
          required: false
          short_name: netbox-manager
          src_dir: src/github.com/osism/netbox-manager
      ref: refs/pull/245/head
      resources: {}
      tenant: osism
      timeout: 1800
      topic: null
      voting: true
