acl: add Roles, Auth Methods, Binding Rules, bootstrap/login/logout; connect: add Intentions#120
Merged
Merged
Conversation
added 8 commits
July 2, 2026 09:37
Adds full CRUD for /v1/acl/role and /v1/acl/roles, matching the CB.json()/CB.boolean() + prepare_headers() pattern used by the existing ACL resources. Response shapes are typed via TypedDict (AclRole, AclServiceIdentity, AclNodeIdentity), not a new runtime dependency.
Adds full CRUD for /v1/acl/auth-method and /v1/acl/auth-methods. Tests configure an offline "jwt" auth method with a static RSA public key so CRUD can be exercised without a real OIDC/Kubernetes backend.
Adds full CRUD for /v1/acl/binding-rule and /v1/acl/binding-rules, including the "authmethod" list filter. bind_type is constrained to the current valid enum via typing.Literal.
Adds ACL.bootstrap(), ACL.login(), ACL.logout() (top-level ACL operations, not tied to a specific resource) and Token.read_self() for GET /v1/acl/token/self. Also adds an AclToken TypedDict and typed return values across the rest of token.py while the file was already being touched for this change.
Adds Connect.Intentions (upsert/read/delete/list/check/match) using the current exact-match intentions API introduced in Consul 1.9. The deprecated pre-1.9 UUID-based CRUD model is intentionally not implemented.
The mypy pre-commit hook ran with --non-interactive --install-types, which makes mypy shell out to `python -m pip install <stub-pkgs>` whenever it hits an import with missing type stubs. CI's tox-uv environments are created via `uv venv`, which does not include pip, so that subprocess fails; depending on how pre-commit batches the file list across invocations, this crashes mypy with an unhandled INTERNAL ERROR instead of just skipping the stub suggestion. Removing both flags (--non-interactive only has meaning paired with --install-types) lets mypy fall back to Any for the handful of transitively-imported, stub-less third-party modules instead of trying to self-heal an environment that has no pip. Verified via `pre-commit run --all-files` locally: ruff / ruff format / pylint / mypy all pass.
The previous fix (dropping --install-types) didn't resolve CI's mypy INTERNAL ERROR crashes, and they're not reproducible locally across several attempts (directory mode, explicit file-list mode, full pre-commit run). Adding --show-traceback so the next CI run surfaces the actual Python exception instead of just "please use --show-traceback to print a traceback when reporting a bug".
The --show-traceback diagnostic commit revealed the actual crash: File "mypy/metastore.py", line 174, in connect_db sqlite3.OperationalError: database is locked mypy 2.x uses a sqlite-backed cache metastore, which is failing to acquire its lock in CI's runner environment. This wasn't reproducible locally (tried directory mode, explicit file-list mode, full `pre-commit run --all-files`) since a single-writer, unconstrained local filesystem doesn't hit whatever CI's runner does (sandboxed/overlay filesystem locking semantics, or genuine concurrent cache writers). --no-sqlite-cache forces mypy back to its plain JSON-file cache, which has no OS-level file-locking requirement and sidesteps the issue regardless of root cause. Verified locally via a full `pre-commit run --all-files`: ruff / ruff format / pylint / mypy all pass.
4 tasks
mougams
approved these changes
Jul 3, 2026
mbrulatout
added a commit
that referenced
this pull request
Jul 3, 2026
* api: add generic Config Entries CRUD (/v1/config) Adds consul.config for the generic Kind/Name-based config entry endpoint (PUT/GET/GET-list/DELETE /v1/config), covering all config entry kinds (service-defaults, service-router, proxy-defaults, mesh, ingress-gateway, etc.) through one implementation rather than modeling each kind's schema individually. cas (check-and-set) support included on both set() and delete(). Note: DELETE /v1/config/:kind/:name returns an empty object when no cas is given, but a real JSON boolean when cas is passed -- callback choice (CB.boolean vs CB.json) branches on that. * api: add Discovery Chain endpoint (/v1/discovery-chain) Adds consul.discovery_chain.get(), covering both the plain GET (no overrides) and the POST variant Consul requires when passing OverrideConnectTimeout/OverrideProtocol/OverrideMeshGateway. * ci: carry over mypy --no-sqlite-cache fix from PR #120 master doesn't have this fix yet (PR #120 is still pending review), so any branch cut from master right now hits the same sqlite3.OperationalError: database is locked INTERNAL ERROR in CI. Carrying the fix here too so this PR's CI is green independently. Trivial to reconcile on rebase once #120 merges. --------- Co-authored-by: Mathias Brulatout <m.brulatout@criteo.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes several of the gaps tracked in
ENDPOINT_STATUS.mdunder the ACL and Connect sections. Adds the following, each as its own commit:consul/api/acl/role.py)consul/api/acl/auth_method.py)consul/api/acl/binding_rule.py)ACL.bootstrap()/ACL.login()/ACL.logout()andToken.read_self()Connect.Intentions— the current exact-match intentions model (Consul 1.9+). The deprecated pre-1.9 UUID-based CRUD model is intentionally not implemented.Response shapes are typed via
TypedDict(e.g.AclRole,AclAuthMethod,AclBindingRule,AclToken,Intention) rather than a new runtime dependency like pydantic — this keeps the library dependency-free for consumers while still giving mypy/IDE support.Explicitly out of scope: anything Enterprise-only (Namespaces, Admin Partitions, and the Enterprise-only slices of Operator).
Test plan
mypy consul/— cleanruff check ./ruff format --diff .— cleantests/api/test_acl.pyandtests/api/test_connect.py, run against real dockerized Consul (1.20.6/1.21.5/1.22.0) via the existingacl_consulfixture — 60/60 passingjwt-type auth method, so they don't require a live OIDC/Kubernetes backend