Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions examples/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""Simple Individual Agent operations example with the TFE Python SDK.

This example demonstrates:
1. Listing agents within agent pools
2. Reading individual agent details
3. Agent status monitoring
4. Using the organization SDK client

Note: Individual agents are created by running the agent binary, not through the API.
This example shows how to manage agents that have already connected to agent pools.

Make sure to set the following environment variables:
- TFE_TOKEN: Your Terraform Cloud/Enterprise API token
- TFE_ADDRESS: Your Terraform Cloud/Enterprise URL (optional, defaults to https://app.terraform.io)
- TFE_ORG: Your organization name

Usage:
export TFE_TOKEN="your-token-here"
export TFE_ORG="your-organization"
python examples/agent_simple.py
"""

import os

from tfe.client import TFEClient
from tfe.config import TFEConfig
from tfe.errors import NotFound
from tfe.models.agent import AgentListOptions


def main():
"""Main function demonstrating agent operations."""
# Get environment variables
token = os.environ.get("TFE_TOKEN")
org = os.environ.get("TFE_ORG")
address = os.environ.get("TFE_ADDRESS", "https://app.terraform.io")

if not token:
print("❌ TFE_TOKEN environment variable is required")
return 1

if not org:
print("❌ TFE_ORG environment variable is required")
return 1

# Create TFE client
config = TFEConfig(token=token, address=address)
client = TFEClient(config=config)

print(f"🔗 Connected to: {address}")
print(f"🏢 Organization: {org}")

try:
# Example 1: Find agent pools to demonstrate agent operations
print("\n📋 Finding agent pools...")
agent_pools = client.agent_pools.list(org)

# Convert to list to check if empty and get count
pool_list = list(agent_pools)
if not pool_list:
print("⚠️ No agent pools found. Create an agent pool first.")
return 1

print(f"Found {len(pool_list)} agent pools:")
for pool in pool_list:
print(f" - {pool.name} (ID: {pool.id}, Agents: {pool.agent_count})")

# Example 2: List agents in each pool
print("\n🤖 Listing agents in each pool...")
total_agents = 0

for pool in pool_list:
print(f"\n📂 Agents in pool '{pool.name}':")

# Use optional parameters for listing
list_options = AgentListOptions(page_size=10) # Optional parameter
agents = client.agents.list(pool.id, options=list_options)

# Convert to list to check if empty and iterate
agent_list = list(agents)
if agent_list:
total_agents += len(agent_list)
for agent in agent_list:
print(f" - Agent {agent.id}")
print(f" Name: {agent.name or 'Unnamed'}")
print(f" Status: {agent.status}")
print(f" Version: {agent.version or 'Unknown'}")
print(f" IP: {agent.ip_address or 'Unknown'}")
print(f" Last Ping: {agent.last_ping_at or 'Never'}")

# Example 3: Read detailed agent information
try:
agent_details = client.agents.read(agent.id)
print(" ✅ Agent details retrieved successfully")
print(f" Full name: {agent_details.name or 'Unnamed'}")
print(f" Current status: {agent_details.status}")
except NotFound:
print(" ⚠️ Agent details not accessible")
except Exception as e:
print(f" ❌ Error reading agent details: {e}")

print("")
else:
print(" No agents found in this pool")

if total_agents == 0:
print("\n⚠️ No agents found in any pools.")
print("To see agents in action:")
print("1. Create an agent pool")
print("2. Run a Terraform Enterprise agent binary connected to the pool")
print("3. Run this example again")
else:
print(f"\n📊 Total agents found across all pools: {total_agents}")

print("\n🎉 Agent operations completed successfully!")
return 0

except NotFound as e:
print(f"❌ Resource not found: {e}")
return 1
except Exception as e:
print(f"❌ Error: {e}")
return 1


if __name__ == "__main__":
exit(main())
140 changes: 140 additions & 0 deletions examples/agent_pool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"""Simple Agent Pool operations example with the TFE Python SDK.

This example demonstrates:
1. Agent Pool CRUD operations (Create, Read, Update, Delete)
2. Agent token creation and management
3. Using the organization SDK client
4. Proper error handling

Make sure to set the following environment variables:
- TFE_TOKEN: Your Terraform Cloud/Enterprise API token
- TFE_ADDRESS: Your Terraform Cloud/Enterprise URL (optional, defaults to https://app.terraform.io)
- TFE_ORG: Your organization name

Usage:
export TFE_TOKEN="your-token-here"
export TFE_ORG="your-organization"
python examples/agent_pool_simple.py
"""

import os
import uuid

from tfe import TFEClient, TFEConfig
from tfe.errors import NotFound
from tfe.models.agent import (
AgentPoolAllowedWorkspacePolicy,
AgentPoolCreateOptions,
AgentPoolListOptions,
AgentPoolUpdateOptions,
AgentTokenCreateOptions,
)


def main():
"""Main function demonstrating agent pool operations."""
# Get environment variables
token = os.environ.get("TFE_TOKEN")
org = os.environ.get("TFE_ORG")
address = os.environ.get("TFE_ADDRESS", "https://app.terraform.io")

if not token:
print("❌ TFE_TOKEN environment variable is required")
return 1

if not org:
print("❌ TFE_ORG environment variable is required")
return 1

# Create TFE client
config = TFEConfig(token=token, address=address)
client = TFEClient(config=config)

print(f"🔗 Connected to: {address}")
print(f"🏢 Organization: {org}")

try:
# Example 1: List existing agent pools
print("\n📋 Listing existing agent pools...")
list_options = AgentPoolListOptions(page_size=10) # Optional parameters
agent_pools = client.agent_pools.list(org, options=list_options)

# Convert to list to get count and iterate
pool_list = list(agent_pools)
print(f"Found {len(pool_list)} agent pools:")
for pool in pool_list:
print(f" - {pool.name} (ID: {pool.id}, Agents: {pool.agent_count})")

# Example 2: Create a new agent pool
print("\n🆕 Creating a new agent pool...")
unique_name = f"sdk-example-pool-{uuid.uuid4().hex[:8]}"

create_options = AgentPoolCreateOptions(
name=unique_name,
organization_scoped=True, # Optional parameter
allowed_workspace_policy=AgentPoolAllowedWorkspacePolicy.ALL_WORKSPACES, # Optional
)

new_pool = client.agent_pools.create(org, create_options)
print(f"✅ Created agent pool: {new_pool.name} (ID: {new_pool.id})")

# Example 3: Read the agent pool
print("\n📖 Reading agent pool details...")
pool_details = client.agent_pools.read(new_pool.id)
print(f" Name: {pool_details.name}")
print(f" Organization Scoped: {pool_details.organization_scoped}")
print(f" Policy: {pool_details.allowed_workspace_policy}")
print(f" Agent Count: {pool_details.agent_count}")

# Example 4: Update the agent pool
print("\n✏️ Updating agent pool...")
update_options = AgentPoolUpdateOptions(
name=f"{unique_name}-updated",
organization_scoped=False, # Making this optional parameter different
)

updated_pool = client.agent_pools.update(new_pool.id, update_options)
print(f"✅ Updated agent pool name to: {updated_pool.name}")

# Example 5: Create an agent token
print("\n🔑 Creating agent token...")
token_options = AgentTokenCreateOptions(
description="SDK example token" # Optional description
)

agent_token = client.agent_tokens.create(new_pool.id, token_options)
print(f"✅ Created agent token: {agent_token.id}")
if agent_token.token:
print(f" Token (first 10 chars): {agent_token.token[:10]}...")

# Example 6: List agent tokens
print("\n📝 Listing agent tokens...")
tokens = client.agent_tokens.list(new_pool.id)

# Convert to list to get count and iterate
token_list = list(tokens)
print(f"Found {len(token_list)} tokens:")
for token in token_list:
print(f" - {token.description or 'No description'} (ID: {token.id})")

# Example 7: Clean up - delete the token and pool
print("\n🧹 Cleaning up...")
client.agent_tokens.delete(agent_token.id)
print("✅ Deleted agent token")

client.agent_pools.delete(new_pool.id)
print("✅ Deleted agent pool")

print("\n🎉 Agent pool operations completed successfully!")
return 0

except NotFound as e:
print(f"❌ Resource not found: {e}")
return 1
except Exception as e:
print(f"❌ Error: {e}")
return 1


if __name__ == "__main__":
exit(main())
9 changes: 9 additions & 0 deletions src/tfe/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from ._http import HTTPTransport
from .config import TFEConfig
from .resources.agent_pools import AgentPools
from .resources.agents import Agents, AgentTokens
from .resources.apply import Applies
from .resources.configuration_version import ConfigurationVersions
from .resources.organizations import Organizations
Expand Down Expand Up @@ -36,6 +38,12 @@ def __init__(self, config: TFEConfig | None = None):
proxies=cfg.proxies,
ca_bundle=cfg.ca_bundle,
)
# Agent resources
self.agent_pools = AgentPools(self._transport)
self.agents = Agents(self._transport)
self.agent_tokens = AgentTokens(self._transport)

# Core resources
self.configuration_versions = ConfigurationVersions(self._transport)
self.applies = Applies(self._transport)
self.plans = Plans(self._transport)
Expand All @@ -48,6 +56,7 @@ def __init__(self, config: TFEConfig | None = None):
self.registry_modules = RegistryModules(self._transport)
self.registry_providers = RegistryProviders(self._transport)

# State and execution resources
self.state_versions = StateVersions(self._transport)
self.state_version_outputs = StateVersionOutputs(self._transport)
self.run_tasks = RunTasks(self._transport)
Expand Down
35 changes: 35 additions & 0 deletions src/tfe/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@
import importlib.util
import os

# Re-export all agent and agent pool types
from .agent import (
Agent,
AgentListOptions,
AgentPool,
AgentPoolAllowedWorkspacePolicy,
AgentPoolAssignToWorkspacesOptions,
AgentPoolCreateOptions,
AgentPoolListOptions,
AgentPoolReadOptions,
AgentPoolRemoveFromWorkspacesOptions,
AgentPoolUpdateOptions,
AgentReadOptions,
AgentStatus,
AgentToken,
AgentTokenCreateOptions,
AgentTokenListOptions,
)

# Re-export all configuration version types
from .configuration_version_types import (
ConfigurationSource,
Expand Down Expand Up @@ -65,6 +84,22 @@

# Define what should be available when importing with *
__all__ = [
# Agent and agent pool types
"Agent",
"AgentPool",
"AgentPoolAllowedWorkspacePolicy",
"AgentPoolAssignToWorkspacesOptions",
"AgentPoolCreateOptions",
"AgentPoolListOptions",
"AgentPoolReadOptions",
"AgentPoolRemoveFromWorkspacesOptions",
"AgentPoolUpdateOptions",
"AgentStatus",
"AgentListOptions",
"AgentReadOptions",
"AgentToken",
"AgentTokenCreateOptions",
"AgentTokenListOptions",
# Configuration version types
"ConfigurationSource",
"ConfigurationStatus",
Expand Down
Loading
Loading