Skip to main content

llamazure.azrest : A REST client for the Azure API

Usage

llamazure.azrest has 3 primary components:

  1. an Engine for running requests
  2. an OpenAPI Generator for creating bindings for Azure services
  3. the Bindings created by the Generator and submitted to the Engine

The general workflow is:

  1. use the Generator to codegen Bindings
  2. create an Engine
  3. use the Bindings to create requests
  4. run those requests with the Engine

You only need to run regenrate the bindings to upgrade the version of llamazure or to change the version of the Azure API you're targeting. If you're using the shell, you can use:

python3 llamazure-azrest-openapi 'https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/' 'specification/authorization/resource-manager/Microsoft.Authorization/stable/2022-04-01/authorization-RoleAssignmentsCalls.json' 'my/module/role_asn.py' 

If you're using the Pants build system, try something like:

adhoc_tool(
	name="role_asn",
	runnable="//llamazure/azrest/openapi.py",  # TODO: adapt for out-of-tree
	args=[
		"https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/",
		"specification/authorization/resource-manager/Microsoft.Authorization/stable/2022-04-01/authorization-RoleAssignmentsCalls.json",
		"my/module/az",
	],
	output_directories=["my/module/az"],
	root_output_directory=".",
)

experimental_wrap_as_python_sources(
	name="azgen",
	inputs=[
		":role_asn",
        ...
	],
)

And then in your code:

from azure.identity import DefaultAzureCredential
from llamazure.azrest.azrest import AzRest

from my.module.role_asn import AzRoleAssignments
# create the Engine
az = AzRest.from_credential(DefaultAzureCredential())

# use the Bindings to create the request
req = AzRoleAssignments.ListForScope(scope="/")

# run the request
role_assignments = az.call(req)

Some Azure datatypes are subsets of others. For example, a FooResource might also have FooResourceUpdateParams, which is mostly the same. You can use the cast_as function for this:

from llamazure.azrest.models import cast_as

d = Dashboard(...)
cast_as(d, PatchableDashboard)

Using the secret batching API

Azure lets you batch several requests into one request. This can save you round-trip time.

from azure.identity import DefaultAzureCredential
from llamazure.azrest.azrest import AzRest
from llamazure.azrest.models import BatchReq

from my.module.role_asn import AzRoleAssignments

az = AzRest.from_credential(DefaultAzureCredential())
query_subscriptions: list[str] = [...]

# use the bindings to create multiple requests
reqs = [AzRoleAssignments.ListForSubscription(sub) for sub in query_subscriptions]
# gather those into a batch
# the `BatchReq.gather` method automatically assigns them IDs
batch_req = BatchReq.gather(reqs)
# you can also name them explicitly
named_reqs = {sub: AzRoleAssignments.ListForSubscription(sub) for sub in query_subscriptions}
batch_req = BatchReq(named_reqs)

az.call_batch(batch_req)

Services with other domain

Some services need different hosts. For example, keyvaults use https://myvault.vault.azure.net. Using these services requires creating a separate AzRest instance to execute those requests:

from azure.identity import DefaultAzureCredential
from llamazure.azrest.azrest import AzRest

a = AzRest.from_credential(DefaultAzureCredential(), token_scope="https://vault.azure.net/.default", base_url="https://myvault.vault.azure.net")

Manually constructing requests

You can build requests yourself

from llamazure.azrest.models import Req

req = Req.get(
    name="List my spacecraft",  # this is a meaningful name for you. It will appear in logs
    path="/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/spaaaaaaaace/providers/Microsoft.Orbital/spacecrafts/potato",
    apiv="2022-11-01",
    ret_t=dict, # This is the return type you expect. You can use a Pydantic BaseModel. A Pydantic TypeAdapter is used to deserialise the return. 
)

For requests that expect a body, use a Pydantic BaseModel.

You can also modify existing requests. There are even some builtin helpers:

from my.module.role_asn import AzRoleAssignments

secure_rg = "secure-rg"

my_req = AzRoleAssignments.ListForResourceGroup(my_subscription, secure_rg).named("list role assignments on secure rg")

TODO

  1. Odata parameters (x-ms-odata) (I'd have to think through the common elements with llamazure.msgraph)
  2. Better retries of Batch elements
  3. Enums (x-ms-enum)
  4. Nullable (x-nullable)
  5. Support path-level parameters

Known Issues

  • Pagination doesn't work if the nextLinkName is not "nextLink"

X-MS Support

support extension comments
no x-ms-skip-url-encoding priority:low really, supporting url encoding is the priority
no x-ms-enum priority:hig
no x-ms-parameter-grouping priority:low
no x-ms-parameter-location priority:low
yes x-ms-paths
no x-ms-client-name priority:med will cause breaking changes in object names
no x-ms-external priority:low
no x-ms-discriminator-value priority:low The resources that require this are not priorities for me
never x-ms-client-flatten In all my experience with the API, this makes it harder to use in any context
mostly x-ms-parameterized-host supported, requires a separate AzRest instance
no x-ms-mutability priority:low
never x-ms-examples No need for examples in code
yes x-ms-error-response General error support
no x-ms-text priority:low (only in file and blob operations)
no x-ms-client-default priority:low You can do this with filters
mostly x-ms-pageable
no x-ms-long-running-operation priority:mid
no x-ms-long-running-operation-options priority:mid
no x-nullable priority:hig
never x-ms-header-collection-prefix I think this isn't for me
never x-ms-internal Rude (although it's not used... in the public api)
no x-ms-odata priority:hig actually useful
never x-ms-azure-resource I'm not generating Terraform providers... yet
no x-ms-request-id priority:low I think this might be necessary for some long operations
no x-ms-client-request-id priority:low I think this might be necessary for some long operations
no x-ms-arm-id-details priority:mid Might be nice to accept/convert the real resource
no x-ms-secret priority:low seems more design-by-contract
no x-ms-identifiers priority:low
never x-ms-azure-rbac-permissions-required Not for me

Metadata

Release files for llamazure.azrest 0.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for llamazure.azrest 0.4.1
File Size Uploaded Provenance Actions
llamazure_azrest-0.4.1.tar.gz 25.6 kB Without provenance Details for llamazure_azrest-0.4.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for llamazure.azrest 0.4.1
File Interpreter ABI Platform Actions
llamazure_azrest-0.4.1-py3-none-any.whl Python 3 none any Details for llamazure_azrest-0.4.1-py3-none-any.whl

Total release size: 50.6 kB

Release files / llamazure_azrest-0.4.1.tar.gz

Download URL llamazure_azrest-0.4.1.tar.gz
Size 25.6 kB
Tags Source
SHA-256 checksum
How to use checksums
a3775d450cb9ab7ea134315efc07112bd57a7395dfec240cb4af51683addf2bd
BLAKE2b-256 checksum
How to use checksums
5210b2b4db72ef690cf9b8f1d380fa0f3c290a325e649689cb8365892567034c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / llamazure_azrest-0.4.1-py3-none-any.whl

Download URL llamazure_azrest-0.4.1-py3-none-any.whl
Size 24.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6b87c0e7ac6d1db91218d45b0a27ccf1e7919b879a7e0ea9784aacfe8fd21b9e
BLAKE2b-256 checksum
How to use checksums
b50691a33ee59f0926dcd7e5ae99d9f7d799e494add9f41b9a9df51e6a748cb6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Security for llamazure.azrest 0.4.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page