Foundry Flow SDK Documentation

Flow programmatic SDK and libraries. Pythonic interface to interact with the Foundry API.

Note: the Flow Task SDK and CLI are currently in preview. Please message us in your dedicated Foundry Slack channel to request access, and we will send right away.

Welcome to the Foundry Flow SDK, a Python library designed to streamline the configuration, orchestration, and management of resources on the Foundry Cloud Platform (FCP). This SDK provides:

• Simple authentication to the Foundry API

Programmatic management of projects, SSH keys, spot-bids, instances, and storage

• High-level, modular, and extensible abstractions to simplify key workflows, such as setting thresholds for spot-instances and managing persistent storage

With the Foundry Flow SDK, you can build robust Python applications that automate complex resource provisioning and lifecycle operations, while maintaining control over user-defined configurations and budgets.

Overview of Core Components

The Foundry Flow SDK comprises multiple pieces that work together to simplify your interactions with the Foundry Cloud Platform. Below is a brief overview of the foundational components.

FoundryClient

FoundryClient is the core interface to the Foundry platform. It handles:

  • Authentication

  • User management (e.g., retrieving user info)

  • Project management (e.g., listing projects and retrieving project IDs)

  • Instance operations (e.g., retrieving instance details)

  • Bid submission and management (e.g., placing or canceling bids)

  • Disk and storage operations (e.g., creating, listing, and deleting disks)

Example:

from flow.clients.foundry_client import FoundryClient

# Replace with your Foundry email and password, pulled from os or your .env
email = 'your-email@example.com'
password = 'your-secure-password'
foundry_client = FoundryClient(email=email, password=password)

user = foundry_client.get_user()
print("Authenticated User:", user)

BidManager

BidManager offers higher-level functionality on top of FoundryClient for:

  • Preparing bid payloads with prepare_bid_payload()

  • Submitting bids with submit_bid()

  • Listing and canceling existing bids

This abstraction lets you more simply define and execute spot bids in Foundry.

InstanceManager

InstanceManager manages instances created from successful bids. Key features include:

  • Retrieving a list of instances in a particular project

  • Filtering instances by name, status, or other criteria

StorageManager

StorageManager simplifies managing ephemeral or persistent storage for your Foundry tasks:

  • Creating new disks

  • Retrieving existing disks

  • Attaching or detaching persistent storage to your instances

AuctionFinder

AuctionFinder helps retrieve auctions that match specific resource requirements (e.g., GPU type).

It can:

  • Fetch available auctions for a project

  • Filter them based on user-defined specifications (e.g., number of GPUs, GPU type)

FlowTaskManager

The FlowTaskManager is the centerpiece for orchestrating a higher-level Flow “task.”

It coordinates parsing user configurations, preparing startup scripts (including optional compression when scripts get large), and submitting a spot bid to provision an instance. Specifically, it:

  1. Parses task configurations (e.g., from a ConfigParser) that might include resource specs, ephemeral/persistent storage needs, ports configs, etc.

  2. Builds a combined startup script:

    • Injects ephemeral storage configuration

    • Adds persistent storage attachments

    • Sets up port forwards (optional)

    • Incorporates user-provided scripts

  3. Authenticates the user and retrieves relevant Foundry project, user, and SSH key IDs.

  4. Finds matching auctions (using AuctionFinder) that meet the user’s resource specs.

  5. Creates a final bid payload (via BidManager) and submits it to Foundry.

Using the FlowTaskManager abstracts away a large portion of the boilerplate. Under the hood, it calls multiple managers (BidManager, StorageManager, etc.) so you don’t have to.

Key Methods in FlowTaskManager

  • run()

The entry point that encapsulates the entire flow: parse configs, build scripts, find auctions, prepare and submit bids, and handle success notifications.

  • cancel_bid(name)

Cancels a submitted bid by name. After authenticating and looking up the project ID, it retrieves a list of bids and cancels the matching one.

  • check_status(task_name=None, show_all=False)

Retrieves the status of bids and instances, optionally filtered by the provided task_name. If show_all is True, it includes incomplete or partial data as well.

Getting Started

Installation

pdm install # from the project root

Authentication

All interactions with the Foundry Cloud Platform require authentication. You can authenticate by creating a FoundryClient instance with your credentials:

from flow.clients.foundry_client import FoundryClient

foundry_client = FoundryClient(
    email='your-email@example.com',
    password='your-password'
)

Usage Examples

4.1 Submitting a Bid with FlowTaskManager

Below is a minimal example of using the FlowTaskManager to parse a configuration, build the startup script, and place a spot bid.

import logging

from flow.clients.foundry_client import FoundryClient
from flow.managers.auction_finder import AuctionFinder
from flow.managers.bid_manager import BidManager
from flow.task_config.config_parser import ConfigParser
from flow.managers.task_manager import FlowTaskManager

# Initialize logging
logging.basicConfig(level=logging.INFO)


# Prepare FoundryClient and default manager instances
foundry_client = FoundryClient(email="your-email", password="your-password")
auction_finder = AuctionFinder(foundry_client=foundry_client)
bid_manager = BidManager(foundry_client=foundry_client)


# Assume we loaded user YAML or JSON config into config_parser
config_parser = ConfigParser(path="path/to/config.yaml")


# Create the FlowTaskManager
task_manager = FlowTaskManager(
    config_parser=config_parser,
    foundry_client=foundry_client,
    auction_finder=auction_finder,
    bid_manager=bid_manager,
)

# Execute the flow: parse, authenticate, find auctions, and submit the bid
task_manager.run()
print("FlowTask executed successfully!")

4.2 Managing Disks with StorageManager

Below is an example of how you can create and delete a disk programmatically:

import uuid
from flow.clients.foundry_client import FoundryClient
from flow.managers.storage_manager import StorageManager
from flow.models.disk_attachment import DiskAttachment


# Initialize FoundryClient
foundry_client = FoundryClient(
    email='your-email@example.com',
    password='your-password'
)


# Create StorageManager
storage_manager = StorageManager(foundry_client=foundry_client)


project_id = 'your-project-id'
disk_id = str(uuid.uuid4())
disk_name = f"testdisk-{uuid.uuid4().hex}"


disk_attachment = DiskAttachment(
    disk_id=disk_id,
    name=disk_name,
    volume_name='my-disk-volume',
    disk_interface='Block',
    region_id=storage_manager.get_default_region_id(),
    size=10,      # Size in GB
    size_unit='gb'
)


# Create the disk
disk_response = foundry_client.create_disk(
    project_id=project_id,
    disk_attachment=disk_attachment
)
print("Disk created:", disk_response)


# List disks
disks = foundry_client.get_disks(project_id=project_id)
print("All disks:", disks)


# Delete the disk
if 'id' in disk_response:
    foundry_client.delete_disk(project_id=project_id, disk_id=disk_response['id'])
    print(f"Disk {disk_response['id']} deleted successfully.")

Filtering Instances with InstanceManager

from flow.clients.foundry_client import FoundryClient
from flow.managers.instance_manager import InstanceManager


foundry_client = FoundryClient(email='your-email', password='your-password')
instance_manager = InstanceManager(foundry_client=foundry_client)


project_id = 'your-project-id'
instances = instance_manager.get_instances(project_id=project_id)
print("All instances in project:", instances)


# Filter by name
filtered = instance_manager.filter_instances(instances, name='my-task')
print("Filtered instances:", filtered)

Advanced Topics

Handling Large Ephemeral/Persistent Storage

FlowTaskManager and StorageManager can handle ephemeral storage for short-lived tasks or persistent storage for tasks that require data to persist across restarts. Both ephemeral and persistent storage sections can be injected into your final startup script automatically, making it easy to spin up tasks with pre-formatted storage volumes.

Conclusion

The Foundry Flow SDK is a modular and extensible toolkit for developers looking to automate provisioning, bidding, instance lifecycle management, and storage operations on the Foundry Cloud Platform. By leveraging convenient abstractions like FlowTaskManager, you can drastically reduce boilerplate code and speed up your development.

Feel free to explore and/or extend each undergirding manager (like BidManager, StorageManager, etc.) to fit your application’s unique workflow. As this SDK evolves, we aim to provide even more utility and deeper integrations with FCPs platform offerings.

Happy coding!

Need Help?

For feedback, suggestions, or issues, please open a discussion or file a ticket on our GitHub repository

Appendix of SDK Snippets

from flow.clients.foundry_client import FoundryClient

# Replace with your Foundry email and password
email = 'your-email@example.com'
password = 'your-password'

foundry_client = FoundryClient(email=email, password=password)

FoundryClient

The FoundryClient is a high-level client that encapsulates interactions with the Foundry Cloud Platform (FCP) compute and storage services. It handles authentication and provides methods to manage users, projects, instances, bids, and storage resources.

Methods

User and Project Management

  • get_user()

    Retrieves authenticated user information.

    user_info = foundry_client.get_user()
    print(user_info)
  • get_projects()

    Retrieves all projects associated with the authenticated user.

    projects = foundry_client.get_projects()
    print(projects)
  • get_project_by_name(project_name)

    Retrieves a project_id by its name.

    project_id = foundry_client.get_project_by_name('core_project')
    print(project_id)

Instance Management

  • get_instances(project_id)

    Retrieves instances associated with a project.

    instances = foundry_client.get_instances(project_id='project_id')
    print(instances)

Auction and Bid Management

  • get_auctions(project_id)

    Retrieves available auctions for the specified project.

    auctions = foundry_client.get_auctions(project_id='project_id')
    print(auctions)
  • get_bids(project_id)

    Retrieves all bids for the specified project.

    bids = foundry_client.get_bids(project_id='project_id')
    print(bids)
  • place_bid(project_id, bid_payload)

    Places a bid on an auction.

    • Parameters:

      • project_id: The unique identifier of the project.

      • bid_payload: Dictionary containing bid details including price, instance specifications, etc.

    bid_payload = {
        'cluster_id': 'cluster-id',
        'instance_quantity': 1,
        'instance_type_id': 'instance-type-id',
        'limit_price_cents': 10000,
        'order_name': 'my-bid',
        'ssh_key_ids': ['ssh-key-id'],
        'startup_script': '#!/bin/bash\necho Hello World',
        'user_id': 'user-id',
    }
    
    bid_response = foundry_client.place_bid(project_id='project-id', bid_payload=bid_payload)
    print(bid_response)
  • cancel_bid(project_id, bid_id)

    Cancels a bid.

    foundry_client.cancel_bid(project_id='project-id', bid_id='bid-id')

SSH Keys Management

  • get_ssh_keys(project_id)

    Retrieves SSH keys for the specified project.

    ssh_keys = foundry_client.get_ssh_keys(project_id='project-id')
    print(ssh_keys)

Storage Management

  • create_disk(project_id, disk_attachment)

    Creates a new disk in the specified project.

    • Parameters:

      • disk_attachment: An instance of DiskAttachment containing disk details.

    from flow.models.disk_attachment import DiskAttachment
    
    disk_attachment = DiskAttachment(
        disk_id='disk-id',
        name='my-disk',
        volume_name='my-disk-volume',
        disk_interface='Block',
        region_id='region-id',
        size=10,
        size_unit='gb',
    )
    
    disk_response = foundry_client.create_disk(project_id='project-id', disk_attachment=disk_attachment)
    print(disk_response)
  • get_disks(project_id)

    Retrieves existing disks for the specified project.

    disks = foundry_client.get_disks(project_id='project-id')
    print(disks)
  • delete_disk(project_id, disk_id)

    Deletes a disk from the specified project.

    foundry_client.delete_disk(project_id='project-id', disk_id='disk-id')
  • get_storage_quota(project_id)

    Retrieves storage quota information for the specified project.

    quota = foundry_client.get_storage_quota(project_id='project-id')
    print(quota)
  • get_regions()

    Retrieves the list of available regions.

    regions = foundry_client.get_regions()
    print(regions)

Managers

Managers provide higher-level abstractions over the FoundryClient methods, offering convenient interfaces for common tasks.

BidManager

The BidManager handles bid preparation and submission.

  • prepare_bid_payload(**kwargs)

    Prepares and validates the bid payload.

    • Parameters:

      • cluster_id: The ID of the cluster.

      • instance_quantity: The number of instances.

      • instance_type_id: The type ID of the instance.

      • limit_price_cents: The limit price in cents.

      • order_name: The name of the bid.

      • project_id: The ID of the project.

      • ssh_key_id: The SSH key ID.

      • user_id: The user ID.

      • startup_script: Optional startup script.

      • disk_attachments: Optional list of DiskAttachment instances.

    from flow.managers.bid_manager import BidManager
    
    bid_manager = BidManager(foundry_client=foundry_client)
    
    bid_payload = bid_manager.prepare_bid_payload(
        cluster_id='cluster-id',
        instance_quantity=1,
        instance_type_id='instance-type-id',
        limit_price_cents=10000,
        order_name='my-bid',
        project_id='project-id',
        ssh_key_id='ssh-key-id',
        user_id='user-id',
        startup_script='#!/bin/bash\necho Hello World',
    )
  • submit_bid(project_id, bid_payload)

    Submits a bid using the FoundryClient.

    bid_response = bid_manager.submit_bid(project_id='project-id', bid_payload=bid_payload)
    print(bid_response)
  • get_bids(project_id)

    Retrieves all bids for the specified project.

    bids = bid_manager.get_bids(project_id='project-id')
    print(bids)
  • cancel_bid(project_id, bid_id)

    Cancels a bid based on the bid ID.

    bid_manager.cancel_bid(project_id='project-id', bid_id='bid-id')

InstanceManager

The InstanceManager handles retrieval and filtering of instances.

  • get_instances(project_id)

    Retrieves all instances for the specified project.

    from flow.managers.instance_manager import InstanceManager
    
    instance_manager = InstanceManager(foundry_client=foundry_client)
    
    instances = instance_manager.get_instances(project_id='project-id')
    print(instances)
  • filter_instances(instances, name=None, status=None)

    Filters instances based on name and status.

    filtered_instances = instance_manager.filter_instances(instances, name='my-instance', status='running')
    print(filtered_instances)

StorageManager

The StorageManager manages storage creation and attachment.

  • handle_persistent_storage(project_id, persistent_storage)

    Handles creating or attaching storage as per the configuration.

    • Parameters:

      • persistent_storage: An instance of PersistentStorage containing storage configuration.

    from flow.managers.storage_manager import StorageManager
    from flow.config.config_parser import PersistentStorage
    
    storage_manager = StorageManager(foundry_client=foundry_client)
    
    persistent_storage = PersistentStorage(
        create={
            'volume_name': 'my-volume',
            'disk_interface': 'Block',
            'size': 10,
            'size_unit': 'gb',
        }
    )
    
    disk_attachment = storage_manager.handle_persistent_storage(
        project_id='project-id',
        persistent_storage=persistent_storage,
    )
    print(disk_attachment)
  • get_default_region_id()

    Retrieves the default region ID.

    default_region_id = storage_manager.get_default_region_id()
    print(default_region_id)

AuctionFinder

The AuctionFinder provides methods to find auctions matching specified criteria.

  • fetch_auctions(project_id)

    Fetches auctions for a given project ID.

    from flow.managers.auction_finder import AuctionFinder
    
    auction_finder = AuctionFinder(foundry_client=foundry_client)
    
    auctions = auction_finder.fetch_auctions(project_id='project-id')
    print(auctions)
  • find_matching_auctions(auctions, criteria)

    Finds auctions matching the specified criteria.

    • Parameters:

      • auctions: A list of Auction instances to search.

      • criteria: An instance of ResourcesSpecification containing matching criteria.

    from flow.config.config_parser import ResourcesSpecification
    
    criteria = ResourcesSpecification(
        gpu_type='A100',
        num_gpus=1,
    )
    
    matching_auctions = auction_finder.find_matching_auctions(auctions, criteria)
    print(matching_auctions)

Usage Examples

Managing Disks with StorageManager

Here's how you can create a disk, retrieve it, and then delete it using the StorageManager and FoundryClient.

import uuid
from flow.clients.foundry_client import FoundryClient
from flow.managers.storage_manager import StorageManager
from flow.models.disk_attachment import DiskAttachment

# Initialize FoundryClient
email = 'your-email@example.com'
password = 'your-password'
foundry_client = FoundryClient(email=email, password=password)

# Initialize StorageManager
storage_manager = StorageManager(foundry_client=foundry_client)

# Retrieve project ID (assuming you have a method or know your project ID)
project_id = 'your-project-id'

# Create a unique disk
disk_id = str(uuid.uuid4())
disk_name = f"testdisk-{uuid.uuid4().hex}"
disk_attachment = DiskAttachment(
    name=disk_name,
    disk_id=disk_id,
    disk_interface='Block',
    region_id=storage_manager.get_default_region_id(),
    size=10,  # Size in GB
    size_unit='gb',
)

# Create the disk
disk_response = foundry_client.create_disk(project_id=project_id, disk_attachment=disk_attachment)
print(f"Disk created: {disk_response}")

# Retrieve all disks
disks = foundry_client.get_disks(project_id=project_id)
print(f"Disks: {disks}")

# Delete the disk
foundry_client.delete_disk(project_id=project_id, disk_id=disk_response.get('id'))
print("Disk deleted.")

Submitting Bids with BidManager

This example demonstrates how to prepare and submit a bid using the BidManager.

from flow.clients.foundry_client import FoundryClient
from flow.managers.bid_manager import BidManager
from flow.models.bid_payload import BidPayload

# Initialize FoundryClient
email = 'your-email@example.com'
password = 'your-password'
foundry_client = FoundryClient(email=email, password=password)

# Initialize BidManager
bid_manager = BidManager(foundry_client=foundry_client)

# Retrieve necessary IDs
project_id = 'your-project-id'
user_id = foundry_client.get_user().get('id')
ssh_key_id = 'your-ssh-key-id'

# Retrieve auctions to get valid cluster_id and instance_type_id
auctions = foundry_client.get_auctions(project_id=project_id)
if not auctions:
    raise Exception("No auctions available.")

auction = auctions[0]  # grab the first auction for this test example
cluster_id = auction.get('cluster_id')  # grab the cluster associated with the auction
instance_type_id = auction.get('instance_type_id')

# Prepare bid payload
bid_payload = bid_manager.prepare_bid_payload(
    cluster_id=cluster_id,
    instance_quantity=1,
    instance_type_id=instance_type_id,
    limit_price_cents=500,  # Limit price in cents
    order_name='my-bid',
    project_id=project_id,
    ssh_key_id=ssh_key_id,
    user_id=user_id,
    startup_script='#!/bin/bash\necho Hello World',
)

# Submit the bid
bid_response = bid_manager.submit_bid(project_id=project_id, bid_payload=bid_payload)
print(f"Bid submitted successfully: {bid_response}")

# Optionally, cancel the bid to clear
bid_manager.cancel_bid(project_id=project_id, bid_id=bid_response.id)
print("Bid canceled.")

Last updated