From 131e6d1c8e20721cc9d3a3f1bac40636da210711 Mon Sep 17 00:00:00 2001 From: Sivaselvan32 Date: Mon, 27 Apr 2026 15:13:34 +0530 Subject: [PATCH 1/3] fix(sshKey & stateVersion): Updated id as only mandatory option for sshkey and state_version models --- src/pytfe/models/ssh_key.py | 2 +- src/pytfe/models/state_version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pytfe/models/ssh_key.py b/src/pytfe/models/ssh_key.py index 4df3d0a0..52423fb8 100644 --- a/src/pytfe/models/ssh_key.py +++ b/src/pytfe/models/ssh_key.py @@ -13,7 +13,7 @@ class SSHKey(BaseModel): id: str = Field(..., description="The unique identifier for this SSH key") type: str = Field(default="ssh-keys", description="The type of this resource") - name: str = Field(..., description="A name to identify the SSH key") + name: str = Field(default="", description="A name to identify the SSH key") class SSHKeyCreateOptions(BaseModel): diff --git a/src/pytfe/models/state_version.py b/src/pytfe/models/state_version.py index 4d8607dd..dab42619 100644 --- a/src/pytfe/models/state_version.py +++ b/src/pytfe/models/state_version.py @@ -32,7 +32,7 @@ class StateVersion(BaseModel): model_config = ConfigDict(populate_by_name=True, validate_by_name=True) id: str = Field(..., alias="id") - created_at: datetime = Field(..., alias="created-at") + created_at: datetime | None = Field(None, alias="created-at") hosted_state_download_url: str | None = Field( None, alias="hosted-state-download-url" ) From a563a0ff7c44c6de9bceceab63d53f9acee3b153 Mon Sep 17 00:00:00 2001 From: Sivaselvan32 Date: Mon, 27 Apr 2026 15:14:41 +0530 Subject: [PATCH 2/3] fix(workspace): Updated workspace model with right relationship models and resource with additional relationship mapper --- src/pytfe/models/workspace.py | 14 +++++++++---- src/pytfe/resources/workspaces.py | 34 ++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/pytfe/models/workspace.py b/src/pytfe/models/workspace.py index d24ab35d..38949b3b 100644 --- a/src/pytfe/models/workspace.py +++ b/src/pytfe/models/workspace.py @@ -23,9 +23,13 @@ from ..utils import has_tags_regex_defined, is_valid_workspace_name, valid_string from .agent import AgentPool from .common import EffectiveTagBinding, Tag, TagBinding +from .configuration_version import ConfigurationVersion from .data_retention_policy import DataRetentionPolicyChoice from .organization import ExecutionMode, Organization from .project import Project +from .ssh_key import SSHKey +from .variable import Variable +from .state_version import StateVersion if TYPE_CHECKING: from .run import Run @@ -168,15 +172,17 @@ class Workspace(BaseModel): # Relations agent_pool: AgentPool | None = None # AgentPool object current_run: Run | None = None # Run object - current_state_version: Any | None = None # StateVersion object + current_state_version: StateVersion | None = None # StateVersion object organization: Organization | None = None project: Project | None = None - ssh_key: Any | None = None # SSHKey object + ssh_key: SSHKey | None = None # SSHKey object outputs: list[WorkspaceOutputs] = Field(default_factory=list) tags: list[Tag] = Field(default_factory=list) - current_configuration_version: Any | None = None # ConfigurationVersion object + current_configuration_version: ConfigurationVersion | None = ( + None # ConfigurationVersion object + ) locked_by: LockedByChoice | None = None - variables: list[Any] = Field(default_factory=list) # Variable objects + variables: list[Variable] = Field(default_factory=list) # Variable objects tag_bindings: list[TagBinding] = Field(default_factory=list) effective_tag_bindings: list[EffectiveTagBinding] = Field(default_factory=list) diff --git a/src/pytfe/resources/workspaces.py b/src/pytfe/resources/workspaces.py index 2bd2d9b3..a8bcfd31 100644 --- a/src/pytfe/resources/workspaces.py +++ b/src/pytfe/resources/workspaces.py @@ -7,6 +7,8 @@ from collections.abc import Iterator from typing import Any +from pytfe.models.ssh_key import SSHKey + from ..errors import ( InvalidOrgError, InvalidSSHKeyIDError, @@ -19,11 +21,13 @@ WorkspaceMinimumLimitError, WorkspaceRequiredError, ) +from ..models.agent import AgentPool from ..models.common import ( EffectiveTagBinding, Tag, TagBinding, ) +from ..models.configuration_version import ConfigurationVersion from ..models.data_retention_policy import ( DataRetentionPolicy, DataRetentionPolicyChoice, @@ -34,6 +38,9 @@ ) from ..models.organization import Organization from ..models.project import Project +from ..models.run import Run +from ..models.variable import Variable +from ..models.state_version import StateVersion from ..models.workspace import ( ExecutionMode, LockedByChoice, @@ -181,7 +188,32 @@ def _ws_from(d: dict[str, Any]) -> Workspace: {"id": relationships["project"]["data"].get("id")} ) if relationships.get("ssh-key", {}).get("data"): - attr["ssh_key"] = relationships["ssh-key"]["data"].get("id") + attr["ssh_key"] = SSHKey.model_validate( + {"id": relationships["ssh-key"]["data"].get("id")} + ) + if relationships.get("agent-pool", {}).get("data"): + attr["agent_pools"] = AgentPool.model_validate( + {"id": relationships["agent-pool"]["data"].get("id")} + ) + if relationships.get("current-run", {}).get("data"): + attr["current_run"] = Run.model_validate( + {"id": relationships["current-run"]["data"].get("id")} + ) + if relationships.get("current-configuration-version", {}).get("data"): + attr["current_configuration_version"] = ConfigurationVersion.model_validate( + {"id": relationships["current-configuration-version"]["data"].get("id")} + ) + if relationships.get("vars", {}).get("data"): + attr["variables"] = [ + Variable.model_validate({"id": item.get("id")}) + for item in relationships["vars"]["data"] + if item.get("id") + ] + if relationships.get("current-state-version", {}).get("data"): + attr["current_state_version"] = StateVersion.model_validate( + {"id": relationships["current-state-version"]["data"].get("id")} + ) + attr["outputs"] = outputs attr["locked_by"] = locked_by attr["data_retention_policy_choice"] = data_retention_policy_choice From f01a2af3f7170d306069418ad017444d659cbc7a Mon Sep 17 00:00:00 2001 From: Sivaselvan32 Date: Mon, 27 Apr 2026 15:19:54 +0530 Subject: [PATCH 3/3] Updated changelog --- CHANGELOG.md | 2 ++ src/pytfe/models/workspace.py | 2 +- src/pytfe/resources/workspaces.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad638af3..55e5164c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ # v0.1.5 * `pytfe.__version__` added in src/pytfe/init.py via importlib.metadata.version("pytfe"). This will resolve to the version from pyproject.toml. +* Updated comments, sshkey, stateversion and cost-estimate models to have id as mandatory attribute by @isivaselvan [#137](https://github.com/hashicorp/python-tfe/pull/137) +* Updated workspace resource to include additional relationship models include AgentPool, Configuration-version, Run, Variables and State-version by @isivaselvan [#138](https://github.com/hashicorp/python-tfe/pull/138) ## Bug Fixes * Run.read / Run.create fail with pydantic ValidationError when response has a `cost-estimate` and `comments` relationship. diff --git a/src/pytfe/models/workspace.py b/src/pytfe/models/workspace.py index 38949b3b..e0be77a7 100644 --- a/src/pytfe/models/workspace.py +++ b/src/pytfe/models/workspace.py @@ -28,8 +28,8 @@ from .organization import ExecutionMode, Organization from .project import Project from .ssh_key import SSHKey -from .variable import Variable from .state_version import StateVersion +from .variable import Variable if TYPE_CHECKING: from .run import Run diff --git a/src/pytfe/resources/workspaces.py b/src/pytfe/resources/workspaces.py index a8bcfd31..1a6ac6cb 100644 --- a/src/pytfe/resources/workspaces.py +++ b/src/pytfe/resources/workspaces.py @@ -39,8 +39,8 @@ from ..models.organization import Organization from ..models.project import Project from ..models.run import Run -from ..models.variable import Variable from ..models.state_version import StateVersion +from ..models.variable import Variable from ..models.workspace import ( ExecutionMode, LockedByChoice,