Skip to content

Initial OpenFaaS Python SDK#1

Open
welteki wants to merge 13 commits intoopenfaas:masterfrom
welteki:initial-sdk
Open

Initial OpenFaaS Python SDK#1
welteki wants to merge 13 commits intoopenfaas:masterfrom
welteki:initial-sdk

Conversation

@welteki
Copy link
Copy Markdown
Member

@welteki welteki commented Apr 22, 2026

Description

Implements the initial Python SDK for OpenFaaS.

Provides a synchronous Client backed by requests, covering the full OpenFaaS REST API:

  • System info
  • Namespaces (list, get, create, update, delete)
  • Functions (list, get, deploy, update, scale, delete)
  • Secrets (list, create, update, delete)
  • Logs (streaming via iterator)
  • Function invocation (sync and async/queued, with optional per-function IAM scoped tokens)

Pydantic v2 models are used for all request and response types. FAAS_DEBUG=1 enables request/response logging with auth headers redacted.

Authentication

All standard OpenFaaS auth strategies are included:

  • BasicAuth — HTTP Basic
  • TokenAuth — OpenFaaS IAM token exchange (RFC 8693); caches and auto-refreshes the gateway JWT with a 10-second expiry buffer matching the Go SDK
  • ServiceAccountTokenSource — Reads a Kubernetes projected service account token from disk, re-read on every call so token rotation is transparent
  • ClientCredentialsTokenSource — Fetches tokens from an external IdP via OAuth 2.0 client_credentials, with internal caching
  • ClientCredentialsAuthrequests.auth.AuthBase wrapper around any TokenSource
  • MemoryTokenCache — Thread-safe in-memory cache for per-function scoped tokens (used by get_function_token())

TokenAuth also implements the TokenSource protocol, enabling automatic wiring as function_token_source for per-function scoped token exchange.

Tests

100 tests covering models, all client endpoints, all auth strategies, token exchange, the memory token cache, and function invocation.

Motivation and Context

  • I have raised an issue to propose this change (required)

@welteki welteki force-pushed the initial-sdk branch 2 times, most recently from 1c3d49e to bc90ad9 Compare April 22, 2026 17:43
@reviewfn

This comment has been minimized.

@reviewfn

This comment has been minimized.

@reviewfn

This comment has been minimized.

@reviewfn

This comment has been minimized.

welteki added 11 commits April 23, 2026 17:03
… coverage

Synchronous client backed by requests.Session, covering the full OpenFaaS
REST API: system info, namespaces, functions (deploy/update/scale/delete),
secrets, and streaming logs.

- requests.Session transport with FAAS_DEBUG hook-based logging
- requests.auth.AuthBase auth classes: BasicAuth, TokenAuth,
  ClientCredentialsAuth
- OpenFaaS IAM: ServiceAccountTokenSource, ClientCredentialsTokenSource,
  exchange_id_token, MemoryTokenCache, get_function_token()
- Pydantic v2 models for all request and response types
- Tests use requests-mock

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
- Add _parse_function_name_namespace helper to extract name/namespace
  from /function/<name>.<ns> and /async-function/<name>.<ns> paths
- Add _FunctionAuth(requests.auth.AuthBase) compound auth that applies
  gateway auth then overrides Authorization with a per-function Bearer token
- Add Client.invoke_function() supporting bytes/str payload, custom
  method/headers/query params, async invocation, callback URL, and
  use_function_auth for IAM-scoped per-function token exchange
- Add echo handler and 18 new tests covering all invoke_function params
- Update README with invoke_function API reference section

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
…ng to function invocations

- Remove _FunctionAuth compound auth class
- Add _BearerAuth for static Bearer token auth on function invocations
- invoke_function with use_function_auth=True uses _BearerAuth(fn_token)
- invoke_function with use_function_auth=False passes auth=None
- Remove unused _parse_function_name_namespace helper and its tests

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
…dules

- Rename _parse_token_response -> parse_token_response to fix reportPrivateUsage
  across auth.py and exchange.py
- Add explicit cast in BasicAuth.__call__ to silence Unknown return from requests stubs
- Remove unused _on_request hook from _transport.py (requests has no request hook;
  request-side debug logging to be revisited)
- Remove or{} fallback on r.headers in _transport.py (headers is never None)
- Fix bare dict return annotations on to_api_dict() methods in models.py to dict[str, Any]

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
…d ClientCredentialsTokenSource

- exchange_id_token: add timeout kwarg (default 30s) passed to session.post()
- ClientCredentialsTokenSource: add timeout and http_client kwargs matching
  the exchange_id_token pattern; _fetch() uses _owns_session to avoid closing
  caller-provided sessions

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
Remove the unnecessary delegation to HTTPBasicAuth via composition.
Subclassing eliminates __init__, __call__, and the cast() workaround,
keeping only the __repr__ override to avoid leaking the password.

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
Reuses the client's existing connection pool and inherits any proxy,
SSL, or other session-level configuration for gateway token exchange.

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
Implements the builder package without secret sealing:
- BuildConfig / BuildResult models with wire-format serialisation
- make_tar: packs a build context dir + BuildConfig into a tar archive
- create_build_context: assembles an on-disk context from a template and
  handler directory, skipping build/ and template/ handler subdirs
- FunctionBuilder.build: blocking POST, returns a single BuildResult
- FunctionBuilder.build_stream: streaming POST, yields BuildResult per NDJSON line
- Optional HMAC-SHA256 request signing via hmac_secret (X-Build-Signature header)
- 33 tests covering models, tar helpers, context assembly, and the HTTP client

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
@reviewfn

This comment has been minimized.

@reviewfn

This comment has been minimized.

@welteki welteki marked this pull request as ready for review April 23, 2026 16:25
@alexellis
Copy link
Copy Markdown
Member

However, a critical bug in function invocation authentication could cause failures in protected environments, and the lack of thread safety may limit concurrent usage. These issues must be resolved, and testing should verify the auth bug fix.

What were your thoughts about this?

…thod

Async and sync invocation have different semantics — async queues work
and always uses POST, sync invokes directly and supports any HTTP method.
Conflating them behind an async_invoke flag made the API harder to use
and required awkward validation. Two dedicated methods make the intent
clear at the call site.

- invoke_function: synchonous invocation, method is required and explicit
- invoke_function_async: queued invocation via /async-function/, always
  POSTs internally, accepts an optional callback_url

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
@reviewfn

This comment has been minimized.

The gateway requires the openfaas label to be present in the request
body to identify the namespace as OpenFaaS-managed. Without it the
gateway returned 401.

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
@reviewfn
Copy link
Copy Markdown

reviewfn Bot commented Apr 24, 2026

AI Pull Request Overview

Summary

This pull request introduces the initial OpenFaaS Python SDK, providing a synchronous client backed by requests that covers the full OpenFaaS REST API. Key features include system info retrieval, namespace and function management, secrets handling, streaming logs, function invocation with support for both synchronous and asynchronous modes, and comprehensive authentication strategies including Basic Auth, OpenFaaS IAM token exchange, Kubernetes service account tokens, and OAuth2 client credentials. The SDK uses Pydantic v2 for type-safe models, includes extensive test coverage, and supports debug logging with auth header redaction. The implementation is well-structured with proper error handling, thread safety, and context manager support.

Approval rating (1-10)

9

Summary per file

Summary per file
File path Summary
openfaas/init.py Module initialization and public API exports
openfaas/_transport.py HTTP session configuration with timeouts and retries
openfaas/_version.py Version information for the SDK
openfaas/auth.py Authentication implementations including BasicAuth, TokenAuth, and token sources
openfaas/builder/init.py Builder module exports
openfaas/builder/client.py Function builder client for OpenFaaS Pro build API
openfaas/builder/models.py Pydantic models for build requests and responses
openfaas/builder/tar.py Tar archive creation utilities for build contexts
openfaas/client.py Main synchronous client implementation
openfaas/exceptions.py Custom exception hierarchy for API errors
openfaas/exchange.py OAuth 2.0 token exchange implementation
openfaas/models.py Pydantic models for API requests and responses
openfaas/token.py Token representation and parsing utilities
openfaas/token_cache.py Thread-safe in-memory token caching
openfaas/init.py Module initialization (duplicate entry)
pyproject.toml Python project configuration and dependencies
tests/test_auth.py Authentication-related tests
tests/test_builder.py Function builder tests
tests/test_client.py Main client functionality tests
tests/test_iam.py IAM-specific tests
tests/test_models.py Model validation tests
uv.lock Dependency lock file

Overall Assessment

The OpenFaaS Python SDK implementation is comprehensive and well-engineered, providing a robust interface to the OpenFaaS API with strong typing, comprehensive error handling, and support for multiple authentication mechanisms. The use of Pydantic v2 ensures type safety and validation, while the thread-safe token caching and authentication implementations demonstrate attention to concurrency concerns. The test suite appears extensive, covering models, client operations, and authentication flows.

However, there are several areas that warrant attention: error handling in log parsing could be more robust, potential race conditions in token caching under high concurrency, and some inconsistencies in model field types that may cause confusion. The implementation correctly handles the OpenFaaS API specification but could benefit from additional validation in edge cases.

Detailed Review

Detailed Review

openfaas/models.py

  • Positive: Excellent use of Pydantic v2 with proper field aliases for camelCase API fields. The to_api_dict() methods correctly handle serialization with exclude_none.
  • Issue: invocation_count is typed as float but represents a count. While OpenFaaS may return floating-point values, this could be misleading. Consider typing as int with runtime validation if possible.
  • Suggestion: Add validation to ensure invocation_count and replicas are non-negative integers.

openfaas/client.py

  • Positive: Clean separation of concerns with proper context manager implementation. The _raise_for_status helper correctly maps HTTP status codes to specific exceptions.
  • Issue: In get_logs(), the JSON parsing catches generic Exception, which may mask unexpected errors. Consider catching ValueError or pydantic.ValidationError specifically.
  • Risk: The streaming log implementation uses iter_lines() which is appropriate, but ensure the finally block properly closes the response even if iteration is interrupted.
  • Issue: In _inject_openfaas_labels, both "labels" and "annotations" are set with the same "openfaas": "1" value. Verify this matches OpenFaaS requirements.
  • Suggestion: Add input validation for namespace and function names to prevent injection attacks, though the underlying requests library handles URL encoding.

openfaas/auth.py

  • Positive: Thread-safe implementations with proper locking. The TokenAuth class correctly implements both AuthBase and TokenSource protocols.
  • Issue: ClientCredentialsTokenSource._fetch() creates a new session if none provided, but doesn't configure it with the same settings (timeouts, proxies) as the main client. This could lead to inconsistent behavior.
  • Risk: Token expiry checking uses datetime.now(tz=timezone.utc) which assumes system clock is accurate. In distributed systems, this could cause issues if clocks are skewed.
  • Suggestion: Consider allowing injection of a time provider for testing and clock-skew handling.

openfaas/token_cache.py

  • Positive: Abstract base class allows for different cache implementations. The MemoryTokenCache properly evicts expired tokens on access.
  • Risk: The use of threading.RLock() is appropriate, but under extreme concurrency with many threads, there could be contention. Consider if this needs optimization for high-throughput scenarios.

openfaas/exchange.py

  • Positive: Proper OAuth 2.0 token exchange implementation with RFC 8693 compliance. Debug logging with auth redaction is security-conscious.
  • Issue: The _redact_auth regex uses re.IGNORECASE but only matches "Basic" and "Bearer". Consider expanding to cover other auth schemes if needed.
  • Suggestion: The error handling for 400 responses assumes JSON format, but falls back gracefully. This is appropriate.

openfaas/exceptions.py

  • Positive: Clean exception hierarchy inheriting from a common base. APIStatusError properly exposes status code and response for debugging.
  • Suggestion: Consider adding more specific exceptions for common API errors (e.g., conflict on resource creation).

Tests

  • Positive: Extensive test coverage using requests-mock for isolation. Tests cover success and error paths.
  • Issue: Some tests may not cover concurrent access scenarios for thread-safe components like TokenAuth and MemoryTokenCache.
  • Suggestion: Add integration tests that exercise the full client lifecycle, including connection cleanup and context manager behavior.

pyproject.toml

  • Positive: Proper dependency specification with Pydantic v2 requirement.
  • Suggestion: Consider specifying minimum Python version (3.10+) explicitly if not already handled.

Security Considerations

  • Positive: Auth headers are redacted in debug logging. Tokens are cached securely with expiry checking.
  • Risk: ServiceAccountTokenSource reads tokens from disk without verifying file permissions. In Kubernetes environments, ensure the token mount is properly secured.
  • Issue: The SDK allows arbitrary headers in function invocation, which could potentially be used for header injection if not validated. However, requests handles this safely.

Performance

  • Positive: Connection reuse via requests.Session. Token caching reduces redundant exchanges.
  • Suggestion: Consider connection pooling configuration for high-throughput applications.

Consistency

  • Positive: Consistent use of type hints throughout. Naming conventions follow Python standards.
  • Issue: Some methods return HTTP status codes as integers (e.g., deploy), while others don't. Consider standardizing return values or providing more structured responses.

AI agent details.

Agent processing time: 55.246s
Environment preparation time: 3.659s
Total time from webhook: 1m1.127s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants