Meraki Dashboard API Python Library

repository·main·Indexed 43 days ago

https://github.com/meraki/dashboard-api-python

A client library for interacting with the Cisco Meraki Dashboard API, supporting both synchronous and asynchronous (AsyncIO) workflows. Version 4.5.0 requires Python 3.10 or later and provides the DashboardAPI and AsyncDashboardAPI clients for managing networks and organizations.

Tokens
17.2K
Snippets
48
Records
78
Agent score
56%

What's inside Meraki

  1. Understand the Meraki Dashboard API Python Library versioning rules

    main

    The library follows specific versioning rules based on the target branch and the underlying Meraki API releases. The source of truth for the current minor version is the pyproject.toml file on the respective branch.

    Branch-specific versioning

    • GA (General Availability) on main branch: When a new API release is detected, the library minor version is bumped and the patch is reset (e.g., X.Y.Z becomes X.(Y+1).0). GA releases always bump the minor version, even after manual patches.
    • Beta releases on beta branch: The library patch and beta number mirror the API release.
      • Library patch = API patch (e.g., API 1.81.2-beta.0 $\rightarrow$ library patch 2).
      • Library beta number = API beta number (e.g., API 1.81.2-beta.3 $\rightarrow$ b3).
      • A new API minor version bumps the library minor version.
    • Dev releases on httpx branch: Follows the same logic as Beta releases but is generated using the -b httpx flag and a specific test organization ID.

    Key Rules

    • API Version Mapping: The API version is the OpenAPI tag with the v prefix stripped (e.g., v1.71.0-beta.2 becomes 1.71.0-beta.2).
    • Manual Releases: Patches or fixes can be released manually at any time by updating pyproject.toml. The next automated release will use this manual version as its baseline.
    • No Version Reuse: If a manual release occupies the next expected version, the automated release will skip to the following version.
    |
    | Event | API Version | Library Version | Branch |
    | --- | --- | --- | --- |
    | `v1.71.0-beta.0` detected | `1.71.0-beta.0` | `3.2.0b0` | `beta` |
    | (same trigger) | `1.71.0-beta.0` | `4.1.0b0` | `httpx` |
    | `v1.71.1-beta.0` detected | `1.71.1-beta.0` | `3.2.1b0` | `beta` |
    | (same trigger) | `1.71.1-beta.0` | `4.1.1b0` | `httpx` |
    | Manual bugfix (no API change) | `1.70.0` | `3.1.1` | `main` |
    | `v1.71.0` detected (GA) | `1.71.0` | `3.2.0` | `main` |
    |
  2. Understand the OASv3 Migration Plan

    main

    The Meraki Dashboard API supports both OASv2 and OASv3 specifications. The library is transitioning from a v2-only generator to a modular OASv3 generator. Key differences in the v3 specification that affect the generated Python library include:

    • requestBody: Unlike v2 where body parameters were part of parameters with "in": "body", v3 uses a dedicated requestBody object. The generator parses this into the same dictionary format used by v2 to maintain compatibility.
    • $ref References: v3 uses $ref to point to reusable schemas in #/components/schemas/.... The generator resolves these at parse time.
    • oneOf Query Parameters: Allows a parameter to be a string OR an object (e.g., for date ranges like startDate being a string or an object with lt/gt). These are handled as optional **kwargs in the Python methods.
    • nullable: true: Properties marked as nullable in OASv3 will result in type hints like name: str | None in the generated Python code.
    • Parameter Schema: v3 uses a more consistent parameter.schema.type structure for path and query parameters.
    • Servers: v3 uses a servers array with URLs, whereas v2 used host, basePath, and schemes.
  3. Understand the Meraki SDK versioning scheme

    main

    The SDK follows a MAJOR.MINOR.PATCH[bN] versioning scheme:

    • MAJOR: Bumped for SDK-only breaking changes (e.g., new HTTP backend, changes to generated code structure, or changes in supported Python versions).
    • MINOR: Bumped when a new upstream Meraki Dashboard API release is released (tracks API minor versions).
    • PATCH: Bumped for SDK bug fixes or upstream API patch releases.
    • bN: A pre-release beta suffix (e.g., 4.1.0b1) used for unreleased major/minor tracks or to include beta API operations.
  4. Implementation details of the OASv3 Generator

    main

    The OASv3 generator is designed to be modular and follows these core parsing and generation logic patterns:

    Core Parsing

    • resolve_ref: Follows JSON pointers (e.g., #/components/schemas/...) and includes circular reference protection by tracking visited refs. It uses a cache (spec["_ref_cache"]) to avoid redundant traversals.
    • parse_request_body: Handles application/json, multipart/form-data (marking file fields with format: binary), and application/octet-stream (single binary body param).
    • parse_params: A unified function that collects path-level parameters, merges them with operation-level parameters (where operation wins on name/location collisions), and parses query/path params using parameter.schema.type.

    Code Generation Improvements

    • Explicit Parameter Construction: Unlike the v2 generator which used kwargs.update(locals()), the v3 generator uses explicit dictionary construction to make code type-safe and compatible with static analysis:
    # Target (v3) - explicit, type-safe
    def getOrganizationNetworks(self, organizationId, total_pages=1, direction="next", **kwargs):
        params = {k: v for k, v in kwargs.items() if k in query_params}
        body = {k: v for k, v in kwargs.items() if k in body_params}
        # ...
    • Type Stubs: The generator can produce .pyi stub files (via a --stubs flag) to enable downstream type checking. OAS3 types map as follows:
      • string -> str
      • integer -> int
      • boolean -> bool
      • array -> list
      • object -> dict
      • oneOf -> Union[str, dict]
      • nullable: true -> | None
  5. How write-operation query parameters are handled

    main

    The Meraki Dashboard API Python Library preserves OpenAPI query parameters (where in == "query") during write operations (POST, PUT, and PATCH).

    There are two primary transport mechanisms depending on the client type:

    1. Standard and Asynchronous Methods: Query parameters are passed through trailing-compatible session helper arguments. The generated methods include a params argument which is passed to the underlying RestSession or AioRestSession.
    2. Action-Batch Methods: Query parameters are encoded directly into the action resource using httpx.QueryParams to ensure they are part of the URL string during batch execution.

    This ensures that even when sending a request body (payload), query-based filters or validation flags (e.g., ?validate=true) are correctly transmitted to the Meraki dashboard.

  6. Understand the Token Bucket algorithm and rate floor

    main

    The rate limiter uses a token bucket primitive to manage request bursts and steady-state throughput.

    Key behaviors for developers to note:

    • Unconditional Deduction: Tokens are deducted from the bucket regardless of whether the current count is positive. Tokens can go negative; a negative value represents a 'reservation' or deficit that must be recovered before the next request can proceed without waiting.
    • Wait Calculation: If the token count is negative, the system calculates a wait time (the time required for the bucket to refill enough to cover the deficit) and sleeps the thread.
    • Rate Floor: To prevent the AIMD algorithm from accidentally stalling a bucket to zero throughput, the rate has a hard floor of 0.5 tokens/sec. Any attempt to set or decrease the rate below this value will clamp it to 0.5.
    # Conceptual logic of the acquire() operation
    now      = monotonic()
    elapsed  = now - last
    tokens   = min(capacity, tokens + elapsed * rate)   # refill
    last     = now
    tokens   = tokens - 1                                # deduct unconditionally
    wait     = (-tokens / rate) if tokens < 0 else 0     # deficit -> sleep
    if wait > 0: sleep(wait)
  7. Understand the HTTPX Migration Plan and Risk Mitigation

    main

    The Meraki Dashboard API Python Library is undergoing a migration from requests to httpx to unify the sync and async implementation paths. This migration aims to reduce code duplication and complexity by moving shared logic (retry loops, rate limiting, error handling, and logging) into a unified session base class, while keeping the sync and async layers thin.

    Key Technical Behaviors Post-Migration

    • Sync Responses: httpx sync responses are fully buffered, maintaining parity with requests behavior.
    • Async Responses: The response body is read immediately after await client.request(), simplifying async logic.
    • Connection Pooling: Client (sync) and AsyncClient (async) maintain connection pools similar to requests.Session.
    • Timeouts: While httpx defaults to 5s, the SDK explicitly sets a 60s timeout.
    • Certificate Verification: The verify parameter (e.g., verify="/path/to/cert.pem") remains identical.
    • Proxy Configuration: Proxies are passed as strings (e.g., proxy="http://host:port").
  8. Understand the HTTPX migration changes

    main

    The Meraki SDK is migrating from requests (sync) and aiohttp (async) to httpx to unify the underlying HTTP transport. This migration changes how certain attributes and methods are accessed on response objects.

    Sync Session Changes (requests -> httpx)

    • Client Initialization: Use httpx.Client(headers=..., verify=..., proxy=..., timeout=..., follow_redirects=False).
    • Request Method: session.request(method, url, allow_redirects=False, **kwargs) becomes self._client.request(method, url, **kwargs).
    • Exception Type: requests.exceptions.RequestException is replaced by httpx.HTTPError.
    • Response Attributes: response.reason is now response.reason_phrase.
    • Proxy Configuration: proxies={"https": url} is now proxy=url.

    Async Session Changes (aiohttp -> httpx)

    • Client Initialization: Use httpx.AsyncClient(headers=..., verify=..., proxy=..., timeout=..., follow_redirects=False).
    • Response Status: response.status is now response.status_code.
    • JSON Parsing: await response.json() becomes response.json() (the body is already buffered after the request is awaited).
    • Context Management: The pattern async with await self.request(...) as response: is replaced by simple assignment: response = await self.request(...).
    • Resource Management: response.release() is no longer needed as httpx buffers the body automatically.
  9. Use query parameters in POST, PUT, and PATCH operations

    main
    The Meraki Dashboard API Python library supports passing query parameters alongside request bodies for POST, PUT, and PATCH operations. When calling these methods, you can provide both params (for URL query parameters) and json or payload (for the request body). The library ensures that both are correctly serialized and sent to the Meraki Dashboard API.
  10. How AIMD rate adaptation handles 429 errors

    main

    The Smart Flow limiter uses Additive-Increase / Multiplicative-Decrease (AIMD) to adapt to network conditions. This ensures that if you hit a rate limit, the SDK automatically slows down to match the server's capacity.

    On 429 (Rate Limited)

    When a 429 is encountered, the rate is reduced multiplicatively:

    • Per-org bucket: rate *= 0.7
    • Global bucket: rate *= 0.7 (only if the URL is not an 'unresolved scoped URL')
    • Note: An 'unresolved scoped URL' is a URL containing a network or device ID but no explicit /organizations/<id>. These do not penalize the global bucket to avoid punishing all organizations for one unknown organization's limit.

    On 2xx (Success)

    When a request succeeds, the rate is increased additively:

    • Per-org bucket: rate = min(configured_org_rate, rate + 0.2)
    • Global bucket: rate = min(configured_global_rate, rate + 0.5)
  11. Identify your application in API requests

    main

    Application developers and ecosystem partners should identify their application in every API request. This is done by passing a specific identifier via the session keyword argument following the format defined in config.py.

    The identifier key is: MERAKI_PYTHON_SDK_CALLER

    Note: This is optional unless you are an official ecosystem partner.

    # Example of passing the identifier via session kwarg
    # (Note: exact implementation details depend on config.py formatting)
    MERAKI_PYTHON_SDK_CALLER