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
126 changes: 126 additions & 0 deletions examples/reserved_tag_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/usr/bin/env python3
"""Reserved Tag Keys Example Script.

This script demonstrates how to use the Reserved Tag Keys API to:
1. List all reserved tag keys for an organization
2. Create a new reserved tag key
3. Update a reserved tag key
4. Delete a reserved tag key

Before running this script:
1. Set TFE_TOKEN environment variable with your Terraform Cloud API token
2. Set TFE_ORG environment variable with your organization name
"""

import os
import sys

# Add the source directory to the path for direct execution
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))

from tfe import TFEClient, TFEConfig
from tfe.errors import TFEError
from tfe.models import (
ReservedTagKeyCreateOptions,
ReservedTagKeyListOptions,
ReservedTagKeyUpdateOptions,
)

# Configuration
TFE_TOKEN = os.getenv("TFE_TOKEN")
TFE_ORG = os.getenv("TFE_ORG")


def main():
"""Main function demonstrating Reserved Tag Keys API usage."""

# Validate environment variables
if not TFE_TOKEN:
print("❌ Error: TFE_TOKEN environment variable is required")
sys.exit(1)

if not TFE_ORG:
print("❌ Error: TFE_ORG environment variable is required")
sys.exit(1)

# Initialize the TFE client
config = TFEConfig(token=TFE_TOKEN)
client = TFEClient(config)

print(f"Reserved Tag Keys API Example for organization: {TFE_ORG}")
print("=" * 60)

try:
# 1. List existing reserved tag keys
print("\n1. Listing reserved tag keys...")
reserved_tag_keys = client.reserved_tag_key.list(TFE_ORG)
print(f"✅ Found {len(reserved_tag_keys.items)} reserved tag keys:")
for rtk in reserved_tag_keys.items:
print(
f" - ID: {rtk.id}, Key: {rtk.key}, Disable Overrides: {rtk.disable_overrides}"
)

# 2. Create a new reserved tag key
print("\n2. Creating a new reserved tag key...")
create_options = ReservedTagKeyCreateOptions(
key="python-tfe-example", disable_overrides=False
)

new_rtk = client.reserved_tag_key.create(TFE_ORG, create_options)
print(f"✅ Created reserved tag key: {new_rtk.id} - {new_rtk.key}")
print(f" Disable Overrides: {new_rtk.disable_overrides}")

# 3. Update the reserved tag key
print("\n3. Updating the reserved tag key...")
update_options = ReservedTagKeyUpdateOptions(
key="python-tfe-example-updated", disable_overrides=True
)

updated_rtk = client.reserved_tag_key.update(new_rtk.id, update_options)
print(f"✅ Updated reserved tag key: {updated_rtk.id} - {updated_rtk.key}")
print(f" Disable Overrides: {updated_rtk.disable_overrides}")

# 4. Delete the reserved tag key
print("\n4. Deleting the reserved tag key...")
client.reserved_tag_key.delete(new_rtk.id)
print(f"✅ Deleted reserved tag key: {new_rtk.id}")

# 5. Verify deletion by listing again
print("\n5. Verifying deletion...")
reserved_tag_keys_after = client.reserved_tag_key.list(TFE_ORG)
print(
f"✅ Reserved tag keys after deletion: {len(reserved_tag_keys_after.items)}"
)

# 6. Demonstrate pagination with options
print("\n6. Demonstrating pagination options...")
list_options = ReservedTagKeyListOptions(page_size=5, page_number=1)
paginated_rtks = client.reserved_tag_key.list(TFE_ORG, list_options)
print(f"✅ Page 1 with page size 5: {len(paginated_rtks.items)} keys")
print(f" Total pages: {paginated_rtks.total_pages}")
print(f" Total count: {paginated_rtks.total_count}")

print("\n🎉 Reserved Tag Keys API example completed successfully!")

except NotImplementedError as e:
print(f"\n⚠️ Note: {e}")
print("This is expected - the read operation is not supported by the API.")

except TFEError as e:
print(f"\n❌ TFE API Error: {e}")
if hasattr(e, "status"):
if e.status == 403:
print("💡 Permission denied - check token permissions")
elif e.status == 401:
print("💡 Authentication failed - check token validity")
elif e.status == 422:
print("💡 Validation error - check reserved tag key format")
sys.exit(1)

except Exception as e:
print(f"\n❌ Unexpected error: {e}")
sys.exit(1)


if __name__ == "__main__":
main()
4 changes: 4 additions & 0 deletions src/tfe/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .resources.query_run import QueryRuns
from .resources.registry_module import RegistryModules
from .resources.registry_provider import RegistryProviders
from .resources.reserved_tag_key import ReservedTagKey
from .resources.run import Runs
from .resources.run_event import RunEvents
from .resources.run_task import RunTasks
Expand Down Expand Up @@ -73,5 +74,8 @@ def __init__(self, config: TFEConfig | None = None):
# SSH Keys
self.ssh_keys = SSHKeys(self._transport)

# Reserved Tag Key
self.reserved_tag_key = ReservedTagKey(self._transport)

def close(self) -> None:
pass
5 changes: 5 additions & 0 deletions src/tfe/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ class ErrStateVersionUploadNotSupported(TFEError): ...
# SSH Key Error Constants
ERR_INVALID_SSH_KEY_ID = "invalid SSH key ID"

# Reserved Tag Key Error Constants
ERR_INVALID_RESERVED_TAG_KEY_ID = "invalid reserved tag key ID"
ERR_REQUIRED_TAG_KEY = "tag key is required"
ERR_INVALID_TAG_KEY = "invalid tag key"


class WorkspaceNotFound(NotFound): ...

Expand Down
15 changes: 15 additions & 0 deletions src/tfe/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@
RegistryProviderReadOptions,
)

# Re-export all reserved tag key types
from .reserved_tag_key import (
ReservedTagKey,
ReservedTagKeyCreateOptions,
ReservedTagKeyList,
ReservedTagKeyListOptions,
ReservedTagKeyUpdateOptions,
)

# Re-export all SSH key types
from .ssh_key import (
SSHKey,
Expand Down Expand Up @@ -139,6 +148,12 @@
"SSHKeyList",
"SSHKeyListOptions",
"SSHKeyUpdateOptions",
# Reserved tag key types
"ReservedTagKey",
"ReservedTagKeyCreateOptions",
"ReservedTagKeyList",
"ReservedTagKeyListOptions",
"ReservedTagKeyUpdateOptions",
# Agent and agent pool types
"Agent",
"AgentPool",
Expand Down
88 changes: 88 additions & 0 deletions src/tfe/models/reserved_tag_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from __future__ import annotations

from datetime import datetime

from pydantic import BaseModel, ConfigDict, Field


class ReservedTagKey(BaseModel):
"""Represents a reserved tag key in Terraform Enterprise."""

model_config = ConfigDict(populate_by_name=True)

id: str = Field(..., description="The unique identifier for this reserved tag key")
type: str = Field(
default="reserved-tag-keys", description="The type of this resource"
)
key: str = Field(..., description="The key targeted by this reserved tag key")
disable_overrides: bool = Field(
...,
alias="disable-overrides",
description="If true, disables overriding inherited tags with the specified key at the workspace level",
)
created_at: datetime | None = Field(
None,
alias="created-at",
description="The time when the reserved tag key was created",
)
updated_at: datetime | None = Field(
None,
alias="updated-at",
description="The time when the reserved tag key was last updated",
)


class ReservedTagKeyCreateOptions(BaseModel):
"""Options for creating a new reserved tag key."""

model_config = ConfigDict(populate_by_name=True)

key: str = Field(..., description="The key targeted by this reserved tag key")
disable_overrides: bool = Field(
...,
alias="disable-overrides",
description="If true, disables overriding inherited tags with the specified key at the workspace level",
)


class ReservedTagKeyUpdateOptions(BaseModel):
"""Options for updating a reserved tag key."""

model_config = ConfigDict(populate_by_name=True)

key: str | None = Field(
None, description="The key targeted by this reserved tag key"
)
disable_overrides: bool | None = Field(
None,
alias="disable-overrides",
description="If true, disables overriding inherited tags with the specified key at the workspace level",
)


class ReservedTagKeyListOptions(BaseModel):
"""Options for listing reserved tag keys."""

model_config = ConfigDict(populate_by_name=True)

page_number: int | None = Field(
None, alias="page[number]", description="Page number to retrieve", ge=1
)
page_size: int | None = Field(
None, alias="page[size]", description="Number of items per page", ge=1, le=100
)


class ReservedTagKeyList(BaseModel):
"""Represents a paginated list of reserved tag keys."""

model_config = ConfigDict(populate_by_name=True)

items: list[ReservedTagKey] = Field(
default_factory=list, description="List of reserved tag keys"
)
current_page: int | None = Field(None, description="Current page number")
total_pages: int | None = Field(None, description="Total number of pages")
prev_page: str | None = Field(None, description="URL of the previous page")
next_page: str | None = Field(None, description="URL of the next page")
total_count: int | None = Field(None, description="Total number of items")
Loading
Loading