Marketplace Demos

View as Markdown
# Imports (run once)
from typing import Iterator
from air_sdk import AirApi
from air_sdk.endpoints import MarketplaceDemo, MarketplaceDemoTag
from air_sdk.endpoints.simulations import Simulation
# Authentication (run once)
api = AirApi.with_ngc_config()
# OR api = AirApi.with_api_key(api_key="...")
# OR api = AirApi.with_device_login(email="...", org_num="...")
# ^ use in terminal only — not supported in Jupyter notebooks

Create

A marketplace demo is created from an existing simulation, which becomes the template that gets cloned each time someone provisions the demo. By default the latest COMPLETE checkpoint of that simulation is used; pass checkpoint to pin a specific one.

simulation_id = '...' # replace with an actual simulation ID to use as the template
demo: MarketplaceDemo = api.marketplace_demos.create(
name='My Marketplace Demo',
simulation=simulation_id,
description='A short, catalog-friendly description of the demo.',
documentation='https://example.com/docs',
repo='https://github.com/example/repo',
tags=['networking', 'sonic'],
)
demo.dict()

Get

Retrieve a single marketplace demo by ID. The model exposes several fields worth calling out:

  • demo — foreign key to the template Simulation (lazily resolved).
  • demo_simulation_state — state of that template simulation (DEMO, CLONING, INVALID).
  • published / publicly_published — whether the demo is published, and whether it is published catalog-wide vs. restricted to an allow-list.
  • publish_access_record_id — the active publish access record, if any.
  • featured / order — control default catalog ordering (see Featuring & ordering).
  • provision_count — how many clones have been provisioned from this demo.
demo_id = '...' # replace with an actual marketplace demo ID
demo: MarketplaceDemo = api.marketplace_demos.get(demo_id)
print(f'{demo.name} ({demo.id})')
print(f' published={demo.published} publicly_published={demo.publicly_published}')
print(f' demo_simulation_state={demo.demo_simulation_state!r}')
print(f' publish_access_record_id={demo.publish_access_record_id}')
print(f' featured={demo.featured} order={demo.order}')
print(f' provision_count={demo.provision_count}')
# `demo` is a foreign key to the template Simulation (resolved on access).
template: Simulation = demo.demo
print(f' template simulation: {template.name} ({template.id}) state={template.state}')

list() returns an iterator of MarketplaceDemo objects (paginated automatically). Pass query parameters to filter, order, or search. Convert to a list to work with all results at once, or iterate lazily.

# All marketplace demos
demos: Iterator[MarketplaceDemo] = api.marketplace_demos.list()
for demo in demos:
print(f'{demo.name:40} published={demo.published} state={demo.demo_simulation_state}')
# Filter by creator, tags, and published status
mine = list(
api.marketplace_demos.list(
creator='me@example.com',
tags=['networking'],
published=True,
)
)
# Filter by the template simulation state and order the results
demo_state = list(
api.marketplace_demos.list(demo_simulation_state='DEMO', ordering='order')
)
# Free-text search
search_results = list(api.marketplace_demos.list(search='sonic'))

Update

Update the editable metadata on a demo: name, description, documentation, repo, tags, and icon. Fields like creator, demo, and published are read-only. You can update via the model instance or via the endpoint API.

demo_id = '...' # replace with an actual marketplace demo ID
demo: MarketplaceDemo = api.marketplace_demos.get(demo_id)
# Update via the model instance
demo.update(
description='An updated description.',
documentation='https://example.com/docs/v2',
tags=['networking', 'evpn'],
)
print(demo.description, demo.tags)
# Or patch via the endpoint API using the demo's primary key
api.marketplace_demos.patch(demo.id, name='My Renamed Demo')

Provision

Provisioning clones the demo’s template simulation into a brand-new Simulation that belongs to you. Each successful provision increments the demo’s provision_count.

demo_id = '...' # replace with an actual marketplace demo ID
demo: MarketplaceDemo = api.marketplace_demos.get(demo_id)
# Provision via the model instance...
simulation: Simulation = demo.provision()
print(f'Provisioned simulation {simulation.name} ({simulation.id})')
# ...or via the endpoint API using the demo (object or ID)
simulation = api.marketplace_demos.provision(marketplace_demo=demo.id)

Tags

Tags are managed through api.marketplace_demo_tags. Each MarketplaceDemoTag has an is_public flag indicating whether the tag is visible catalog-wide. A tag also exposes a marketplace_demos property that reverse-lists the demos assigned that tag.

# List all tags and show the is_public flag
tags: Iterator[MarketplaceDemoTag] = api.marketplace_demo_tags.list()
for tag in tags:
print(f'{tag.name:30} is_public={tag.is_public}')
# Retrieve a single tag by ID
tag_id = '...' # replace with an actual tag ID
tag: MarketplaceDemoTag = api.marketplace_demo_tags.get(tag_id)
# The `marketplace_demos` property reverse-lists demos assigned this tag
for demo in tag.marketplace_demos.list():
print(f' {demo.name} ({demo.id})')

Featuring & Ordering (Privileged)

These management actions require elevated (SRE/ADMIN) privileges.

  • manage(featured=..., order=...) sets whether a demo is featured and its ordering value. Featured demos sort before non-featured ones, and lower order values sort first. Pass order=None to clear a demo’s order.
  • tighten_order() is a collection-level action that re-numbers the populated order values to be consecutive starting at 1 (e.g. [1, 5, 20] -> [1, 2, 3]), preserving relative ordering. Demos with order=None are left untouched.
demo_id = '...' # replace with an actual marketplace demo ID
demo: MarketplaceDemo = api.marketplace_demos.get(demo_id)
# Feature the demo and place it first
demo.manage(featured=True, order=1)
print(f'featured={demo.featured} order={demo.order}')
# Or via the endpoint API
api.marketplace_demos.manage(marketplace_demo=demo.id, featured=False, order=None)
# Recompact ordering across all demos so `order` values are consecutive from 1
api.marketplace_demos.tighten_order()

Delete

Delete a marketplace demo. This removes the demo entry; it does not delete the underlying template simulation.

demo_id = '...' # replace with an actual marketplace demo ID
demo: MarketplaceDemo = api.marketplace_demos.get(demo_id)
# Delete via the model instance...
demo.delete()
assert demo.id is None
# ...or via the endpoint API by ID
api.marketplace_demos.delete('marketplace-demo-id')