{"id":1725,"date":"2025-02-12T17:15:48","date_gmt":"2025-02-12T17:15:48","guid":{"rendered":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2025\/02\/12\/a-smoother-hcp-terraform-workspace-experience\/"},"modified":"2025-02-12T17:15:48","modified_gmt":"2025-02-12T17:15:48","slug":"a-smoother-hcp-terraform-workspace-experience","status":"publish","type":"post","link":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2025\/02\/12\/a-smoother-hcp-terraform-workspace-experience\/","title":{"rendered":"A smoother HCP Terraform workspace experience"},"content":{"rendered":"<p>HCP Terraform allows organizations to scale the management of their cloud infrastructure. However, onboarding multiple teams with unique requirements and workflows introduces its own set of challenges. This blog post will demonstrate how you can automate your HCP Terraform workspace setup by using the TFE provider and building an onboarding module.<\/p>\n<h2>A common scenario<\/h2>\n<p>To illustrate a common scenario, imagine a tech company. We\u2019ll call them \u201cHashiCups\u201d. Their <a href=\"https:\/\/www.hashicorp.com\/resources\/what-is-a-platform-team-and-why-do-we-need-them\">platform team<\/a> has successfully built their initial cloud landing zones using HCP Terraform. <\/p>\n<p><strong>Cloud landing zone:<\/strong> A pre-configured, secure, and scalable environment that serves as a foundation for deploying and managing cloud resources.<\/p>\n<p>Now they\u2019re ready to make their first attempt at on-boarding an application team to HCP Terraform, with many more teams to follow. They realize that manually creating and configuring workspaces for each team is time-consuming and prone to errors. They need an automated onboarding process that&#8217;s not only efficient but also scalable and consistent.<\/p>\n<p>They\u2019ve decided they\u2019re going to add another abstraction layer to codify and automate the onboarding setup for HCP Terraform workspaces, teams and processes. They\u2019ll do this using Terraform as the engine once again, with the <a href=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/tfe\/latest\">TFE provider<\/a>.<\/p>\n<p>With this provider they can build a reusable Terraform module (we\u2019ll call it the \u201cworkspace onboarding module\u201d) that encapsulates best practices for workspace creation, permission management, and team onboarding. This approach should allow HashiCups to scale effortlessly as they bring more teams into their infrastructure as code ecosystem.<\/p>\n<h2>Onboarding the first team<\/h2>\n<p>The HashiCups platform team will start their onboarding process by having a meeting with the application team. To prepare for this meeting, they\u2019ll review their objectives.<\/p>\n<p>The platform team has two main objectives here:<\/p>\n<p>Get the application team up and running as quickly as possible.<br \/>\nCreate and test their reusable onboarding pattern (which is codified in a Terraform module) so that they can iron out any issues before they offer it to other teams.<\/p>\n<p>Based on these objectives, in their first meeting, they will ask:<\/p>\n<p>If the team is familiar with workspaces in HCP Terraform and provide an overview if necessary.<br \/>\nWhat their environment landscape looks like (the promotion path i.e. path from dev&gt;test&gt;prod).<br \/>\nWho should be permitted to change infrastructure configuration, and if those permissions depend on the environment.<\/p>\n<h3>What is an HCP Terraform workspace?<\/h3>\n<p>In HCP Terraform, a <a href=\"https:\/\/developer.hashicorp.com\/terraform\/cloud-docs\/workspaces\">workspace<\/a> is a fundamental concept that is used to organize infrastructure as code, so it makes sense to start the meeting reviewing what workspaces are and what\u2019s the impact on the team\u2019s IaC code.<\/p>\n<p>An HCP Terraform workspace is an isolated environment where a specific team or working group can manage a specific set of infrastructure resources. Each workspace maintains its own state file, which is important for tracking the current state of your infrastructure and ensuring that Terraform can accurately plan and apply changes to it. It provides a collaborative space for teams to manage infrastructure as code, with capabilities such as version control integration, secure state management, and role-based access control.<\/p>\n<h3>Workspace scoping recommendations<\/h3>\n<p>Our recommended practice is that you structure your HCP Terraform setup so that each workspace corresponds to a specific: <\/p>\n<p>Business unit<br \/>\nApplication name<br \/>\nInfrastructure layer<br \/>\nPromotion path environment (i.e. dev&gt;test&gt;prod)<br \/>\nand\/or region <\/p>\n<p>Some example workspace names for a simple application following this recommendation could include:<\/p>\n<p>bu1-billing-prod-us-east<br \/>\nbu1-billing-staging-us-east<\/p>\n<p>For more complex scenarios, teams will need to divide their workspaces into even smaller scopes. If they have a large number of resources to deploy that becomes harder to manage and decipher. For example:<\/p>\n<p>bu2-orders-networking-prod-us-east<br \/>\nbu2-orders-compute-prod-us-east<br \/>\nbu2-orders-db-prod-us-east<br \/>\nbu2-orders-networking-staging-us-east<br \/>\nbu2-orders-compute-staging-us-east<br \/>\nbu2-orders-db-staging-us-east<\/p>\n<p>The main takeaway here is you can delineate your workspace scopes according to how you think you should isolate each environment to ensure three things: <\/p>\n<p>Adequately limiting the potential impact or &#8216;blast radius&#8217; of any change-related failures<br \/>\nPreventing performance degradations from affecting other workspaces<br \/>\nAccommodating different infrastructure sizing and configuration needs for development, testing, and production scenarios<\/p>\n<h3>The requirements<\/h3>\n<p>After asking the questions listed earlier and building a general understanding of workspaces and how they can be scoped, the HashiCups platform team has gotten a set of requirements from the application team. <\/p>\n<p>The application team explained that they use a 3-environment landscape (development, staging and production), which will translate into three workspaces. Through meetings with other stakeholders, such as security, operations leadership, and platform team leadership (sometimes these best-practice-building groups are called a \u201ccenter of cloud excellence (CCoE)\u201d), the platform team has an additional set of requirements for HCP Terraform workspace default settings:<\/p>\n<p>Each application team should have a group that is responsible for workspace administration and another group that has the necessary permissions to use the workspaces.<br \/>\nPowerful data removal commands like terraform destroy should not be allowed for production. Only development and staging environments.<br \/>\nTechnical leadership has decided on workspace naming conventions. Each name will have only two pieces of information: An application identifier, followed by an environment identifier (&lt;application&gt;-&lt;environment&gt;), and the workspace name must be in lowercase.<br \/>\nGenerally the environment used by the end users must use the prod environment identifier.<\/p>\n<p>After completing the discovery process,the platform team can now create the first version of the  workspace onboarding module.<\/p>\n<h2>Making the onboarding pattern reusable<\/h2>\n<p>The workspace onboarding module will generate the workspaces needed for the first application team. Rather than hardcoding their team-specific requirements into the workspace, the onboarding module will have empty variable fields so that any team in the organization can use the same module to customize workspaces for their own specific needs. For example, while the first team had 3 environments, some teams have 2 environments, and some teams have more than 3 environments. The number of environments generated will need to be a variable field in the module.<\/p>\n<h3>Create the variable definitions<\/h3>\n<p>The first file we\u2019ll create is the variables.tf file, where we\u2019ll define four <a href=\"https:\/\/developer.hashicorp.com\/terraform\/language\/values\/variables\">variables<\/a>:<\/p>\n<p>application_id, to hold the application (unique) identifier.<br \/>\nadmin_team_name, to hold the name of the (pre-existing) HCP Terraform team representing the application administrators.<br \/>\nuser_team_name, to hold the name of the (pre-existing) HCP Terraform team representing the application infrastructure engineers (or developers).<br \/>\nenvironment_names, to hold the list of environment names (dev, prod, etc.) in this application\u2019s environment landscape.<\/p>\n<p>The environment_names variable also needs a validation block to ensure that there is an environment named prod, as per the organization\u2019s requirements.<\/p>\n<p>variable &#8220;environment_names&#8221; {<br \/>\n  description = &#8220;A list of environment names&#8221;<br \/>\n  type        = list(string)<\/p>\n<p>  validation {<br \/>\n    condition     = contains([for env in var.environment_names : lower(env)], &#8220;prod&#8221;)<br \/>\n    error_message = &#8220;The list of environment names must contain &#8216;prod&#8217;.&#8221;<br \/>\n  }<br \/>\n}<\/p>\n<p>variable &#8220;admin_team_name&#8221; {<br \/>\n  description = &#8220;The name of the team for the workspace administrators&#8221;<br \/>\n  type        = string<br \/>\n}<\/p>\n<p>variable &#8220;user_team_name&#8221; {<br \/>\n  description = &#8220;The name of the team for the workspace users&#8221;<br \/>\n  type        = string<br \/>\n}<\/p>\n<p>variable &#8220;application_id&#8221; {<br \/>\n  description = &#8220;The identifier of the application&#8221;<br \/>\n  type        = string<br \/>\n}<\/p>\n<h3>Create the workspaces<\/h3>\n<p>The next step is creating the main.tf file, where admins will define the workspaces and team permissions. When creating the workspace for the prod environment, the team configures it so that destroy plans aren\u2019t allowed, as per the organization\u2019s requirements. They\u2019ll also use string interpolation to name the workspace according to the organization\u2019s naming convention. See how this looks in the configuration below.<\/p>\n<p>resource &#8220;tfe_workspace&#8221; &#8220;workspace&#8221; {<br \/>\n  for_each = toset(var.environment_names)<\/p>\n<p>  name               = &#8220;${lower(var.application_id)}-${lower(each.value)}&#8221;<br \/>\n  description        = &#8220;Workspace for the ${each.value} environment of application ${var.application_id}&#8221;<br \/>\n  allow_destroy_plan = each.value == &#8220;prod&#8221; ? false : true<\/p>\n<p>}<\/p>\n<p>data &#8220;tfe_team&#8221; &#8220;admin_team&#8221; {<br \/>\n  name = var.admin_team_name<br \/>\n}<\/p>\n<p>data &#8220;tfe_team&#8221; &#8220;user_team&#8221; {<br \/>\n  name = var.user_team_name<br \/>\n}<\/p>\n<p>resource &#8220;tfe_team_access&#8221; &#8220;admin_team_access&#8221; {<br \/>\n  for_each = toset(var.environment_names)<\/p>\n<p>  workspace_id = tfe_workspace.workspace[each.value].id<br \/>\n  team_id      = data.tfe_team.admin_team.id<br \/>\n  access       = &#8220;admin&#8221;<br \/>\n}<\/p>\n<p>resource &#8220;tfe_team_access&#8221; &#8220;user_team_access&#8221; {<br \/>\n  for_each = toset(var.environment_names)<\/p>\n<p>  workspace_id = tfe_workspace.workspace[each.value].id<br \/>\n  team_id      = data.tfe_team.user_team.id<br \/>\n  access       = &#8220;write&#8221;<br \/>\n}<\/p>\n<p>Note that this example is using data sources to fetch information about the admin_team and the user_team. An alternative would be to accept the team ID instead of the team name as an input variable. Using the team ID as an input variable can simplify the code and make it more efficient in terms of data processing. However, it may also make it less intuitive for a human to understand the input at a glance.<\/p>\n<h3>Make outputs available<\/h3>\n<p>One of the key principles in infrastructure as code is composition. Composition in the context of IaC and Terraform refers to the practice of building complex configurations by combining smaller, reusable components. This approach enables modular, scalable, and maintainable infrastructure definitions.<\/p>\n<p>To enable composition with modules, the team needs to share information using <a href=\"https:\/\/developer.hashicorp.com\/terraform\/language\/values\/outputs\">outputs<\/a>. In this case, they made the IDs of the workspaces created for the application team available, as well as the IDs of the admin and user teams in the outputs.tf file:<\/p>\n<p>output &#8220;workspace_ids&#8221; {<br \/>\n  description = &#8220;The IDs of the created workspaces&#8221;<br \/>\n  value       = { for k, v in tfe_workspace.workspace : k =&gt; v.id }<br \/>\n}<\/p>\n<p>output &#8220;admin_team_ids&#8221; {<br \/>\n  description = &#8220;The IDs of the admin teams&#8221;<br \/>\n  value       = data.tfe_team.admin_team.id<br \/>\n}<\/p>\n<p>output &#8220;user_team_ids&#8221; {<br \/>\n  description = &#8220;The IDs of the user teams&#8221;<br \/>\n  value       = data.tfe_team.user_team.id<br \/>\n}<\/p>\n<p>For a more in-depth discussion about outputs in Terraform, have a look at this discussion from HashiConf 2024: <a href=\"https:\/\/youtu.be\/BKtvWiggY7Q?si=KTF_-C1u-OSB_M5v&amp;t=779\">Meet the experts: Terraform module design<\/a>. <\/p>\n<h3>Module tests<\/h3>\n<p>At this point, the team has a working module, but it\u2019s still missing an important component: <a href=\"https:\/\/developer.hashicorp.com\/terraform\/language\/tests\">Terraform tests<\/a>. These tests are necessary to ensure that as engineers improve the module they do not introduce bugs or break existing functionality.<\/p>\n<p>Terraform tests live under the tests directory in the module code repository.<\/p>\n<h4>Test setup<\/h4>\n<p>The first step when writing a test suite is to ensure that the prerequisites are available. In this case, the prerequisites are the HCP Terraform teams for the workspace administrators and the workspace users.<\/p>\n<p>To define the prerequisites, the platform team will create the file tests\/testing\/setup\/main.tf with the following content:<\/p>\n<p>resource &#8220;tfe_team&#8221; &#8220;admin_team&#8221; {<br \/>\n  name = &#8220;admins-test&#8221;<br \/>\n}<\/p>\n<p>resource &#8220;tfe_team&#8221; &#8220;user_team&#8221; {<br \/>\n  name = &#8220;users-test&#8221;<br \/>\n}<\/p>\n<h4>Test suite<\/h4>\n<p>The next step is to write the test suite. The platform team will create tests that ensure that the validation code on the environment_names variable works as expected.<\/p>\n<p>To define the test suite, they\u2019ll create the file tests\/environment_landscape_validation.tftest.hcl with the following content:<\/p>\n<p>provider &#8220;tfe&#8221; {<br \/>\n  organization = &#8220;&#8221;<br \/>\n}<\/p>\n<p>variables {<br \/>\n  admin_team_name = &#8220;admins-test&#8221;<br \/>\n  user_team_name  = &#8220;users-test&#8221;<br \/>\n  application_id  = &#8220;my-app&#8221;<br \/>\n}<\/p>\n<p>run &#8220;setup&#8221; {<\/p>\n<p>  module {<br \/>\n    source = &#8220;.\/tests\/testing\/setup&#8221;<br \/>\n  }<br \/>\n}<\/p>\n<p>run &#8220;invalid_environment_landscape_missing_prod_name&#8221; {<\/p>\n<p>  command = plan<\/p>\n<p>  variables {<br \/>\n    environment_names = [&#8220;dev&#8221;, &#8220;staging&#8221;]<br \/>\n    admin_team_name   = var.admin_team_name<br \/>\n    user_team_name    = var.user_team_name<br \/>\n    application_id    = var.application_id<br \/>\n  }<\/p>\n<p>  expect_failures = [var.environment_names]<\/p>\n<p>}<\/p>\n<p>run &#8220;invalid_environment_landscape_incorrect_prod_name&#8221; {<\/p>\n<p>  command = plan<\/p>\n<p>  variables {<br \/>\n    environment_names = [&#8220;dev&#8221;, &#8220;staging&#8221;, &#8220;production&#8221;]<br \/>\n    admin_team_name   = var.admin_team_name<br \/>\n    user_team_name    = var.user_team_name<br \/>\n    application_id    = var.application_id<br \/>\n  }<\/p>\n<p>  expect_failures = [var.environment_names]<\/p>\n<p>}<\/p>\n<p>run &#8220;valid_environment_landscape&#8221; {<\/p>\n<p>  command = plan<\/p>\n<p>  variables {<br \/>\n    environment_names = [&#8220;dev&#8221;, &#8220;staging&#8221;, &#8220;prod&#8221;]<br \/>\n    admin_team_name   = var.admin_team_name<br \/>\n    user_team_name    = var.user_team_name<br \/>\n    application_id    = var.application_id<br \/>\n  }<\/p>\n<p>}<\/p>\n<p>run &#8220;workspace_name_in_lowercase&#8221; {<\/p>\n<p>  command = plan<\/p>\n<p>  variables {<br \/>\n    environment_names = [&#8220;Dev&#8221;, &#8220;Staging&#8221;, &#8220;Prod&#8221;]<br \/>\n    admin_team_name   = var.admin_team_name<br \/>\n    user_team_name    = var.user_team_name<br \/>\n    application_id    = &#8220;My-App&#8221;<br \/>\n  }<\/p>\n<p>  assert {<br \/>\n    condition     = alltrue([for ws in tfe_workspace.workspace : lower(ws.name) == ws.name])<br \/>\n    error_message = &#8220;All workspace names must be in lowercase.&#8221;<br \/>\n  }<br \/>\n}<\/p>\n<p>The test suite above does the following:<\/p>\n<p>Provides a valid TFE provider configuration to use.<br \/>\nEnsures that the test prerequisites are present.<br \/>\nValidates that passing an invalid environment landscape is detected and fails the plan operation. An invalid environment landscape is either missing the prod environment or is using an incorrect name such as production.<br \/>\nValidates that passing a valid environment landscape is successful.<br \/>\nValidates that passing an application ID and\/or environment names with capitalized letters still result in the workspace name being in all lowercase.<br \/>\nTears down the test prerequisites.<\/p>\n<h4>Running the test suite<\/h4>\n<p>Executing the test suite requires access to HCP Terraform. Prior to running the test suite, the platform team will need to generate an API token with permissions to create teams and make it available to their execution environment. Here is an example of how to do this on Linux:<\/p>\n<p>export TFE_TOKEN=&lt;replace with the API token&gt;<\/p>\n<p>Executing the test suite is easy from the command line:<\/p>\n<p>terraform test<\/p>\n<p>Terraform will discover the available tests and execute them, reporting on the results:<\/p>\n<p>tests\/invalid_environment_landscape.tftest.hcl&#8230; in progress<br \/>\n  run &#8220;setup&#8221;&#8230; pass<br \/>\n  run &#8220;invalid_environment_landscape_missing_prod_name&#8221;&#8230; pass<br \/>\n  run &#8220;invalid_environment_landscape_incorrect_prod_name&#8221;&#8230; pass<br \/>\n  run &#8220;valid_environment_landscape&#8221;&#8230; pass<br \/>\n  run &#8220;workspace_name_in_lowercase&#8221;&#8230; pass<br \/>\ntests\/invalid_environment_landscape.tftest.hcl&#8230; tearing down<br \/>\ntests\/invalid_environment_landscape.tftest.hcl&#8230; pass<\/p>\n<p>Success! 5 passed, 0 failed.<\/p>\n<h4>Provide documentation and examples<\/h4>\n<p>When developing a Terraform module, it is highly recommended to include two essential files: a comprehensive documentation file and a detailed changelog.<\/p>\n<p>The documentation file, named README.md, serves as a valuable resource for users of the module, providing clear instructions on its purpose, usage, input variables, outputs, and any specific requirements or dependencies. This documentation ensures that other team members or future maintainers can quickly understand and effectively utilize the module without extensive reverse engineering.<\/p>\n<p>Equally important is the changelog file, named CHANGELOG.md, which records all notable changes and version increments for the module over time. The changelog acts as a historical record, allowing users to track modifications, understand the evolution of the module, and make informed decisions about upgrades. Together, these files significantly enhance the module&#8217;s usability, maintainability, and overall quality, fostering better collaboration and reducing potential issues arising from lack of information or miscommunication.<\/p>\n<p>Example README.md file:<\/p>\n<p># Terraform Workspaces Module<\/p>\n<p>## Description<\/p>\n<p>This module configures one or more workspaces for an application team, with one workspace corresponding to one SDLC environment. It uses the TFE provider to create workspaces in HCP Terraform.<\/p>\n<p>## Usage<\/p>\n<p>&#8220;`hcl<br \/>\nmodule &#8220;workspaces&#8221; {<br \/>\n  source            = &#8220;path\/to\/your\/module&#8221;<br \/>\n  environment_names = [&#8220;dev&#8221;, &#8220;staging&#8221;, &#8220;prod&#8221;]<br \/>\n  admin_team_name   = &#8220;admin-team&#8221;<br \/>\n  user_team_name    = &#8220;user-team&#8221;<br \/>\n  application_id    = &#8220;my-app&#8221;<br \/>\n}<br \/>\n&#8220;`<\/p>\n<p>## Inputs<\/p>\n<p>| Name              | Description                                      | Type        | Default     | Required |<br \/>\n|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;|&#8212;&#8212;&#8212;&#8212;-|&#8212;&#8212;&#8212;&#8212;-|&#8212;&#8212;&#8212;-|<br \/>\n| environment_names | A list of environment names                      | list(string)| n\/a         | yes      |<br \/>\n| admin_team_name   | The name of the team for the workspace administrators | string      | n\/a         | yes      |<br \/>\n| user_team_name    | The name of the team for the workspace users     | string      | n\/a         | yes      |<br \/>\n| application_id    | The identifier of the application                | string      | n\/a         | yes      |<\/p>\n<p>## Outputs<\/p>\n<p>| Name                | Description                              |<br \/>\n|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;|<br \/>\n| workspace_ids       | The IDs of the created workspaces        |<br \/>\n| admin_team_ids      | The IDs of the admin teams               |<br \/>\n| user_team_ids       | The IDs of the user teams                |<\/p>\n<p>Example CHANGELOG.md file:<\/p>\n<p># Changelog<\/p>\n<p>## [1.0.0] &#8211; 2025-01-XX<br \/>\n### Added<br \/>\n&#8211; Initial version of the Terraform module.<br \/>\n&#8211; Added support for creating workspaces in Terraform Cloud using the TFE provider.<br \/>\n&#8211; Added variables for environment names, admin team name, user team name and application ID.<br \/>\n&#8211; Added validation to ensure the environment names list contains &#8220;prod&#8221;.<br \/>\n&#8211; Added outputs for workspace IDs, admin team IDs, and user team IDs.<br \/>\n&#8211; Added tests to validate the environment names and workspace name formatting.<\/p>\n<h2>Recap and possible enhancements<\/h2>\n<p>Using an example scenario and company, this blog post has shown how to gather requirements to automate the creation of workspaces for an application team and translate those requirements into a reusable Terraform module, complete with code, documentation, and automated tests. Once created, the module should be published and used by future teams adopting HCP Terraform. You can learn more about publishing your module in this tutorial: <a href=\"https:\/\/developer.hashicorp.com\/terraform\/tutorials\/modules\/module-private-registry-share\">Share modules in the private registry<\/a>.<\/p>\n<p>We intentionally used a simplified scenario to keep the post to a reasonable length and easy to understand, but some readers may argue that certain important aspects were omitted, and they\u2019d be right. Let\u2019s cover those aspects and flag them as potential enhancements to the example solution:<\/p>\n<p>Introduce <a href=\"https:\/\/developer.hashicorp.com\/terraform\/cloud-docs\/projects\">HCP Terraform projects<\/a><br \/>\nConfigure <a href=\"https:\/\/developer.hashicorp.com\/terraform\/cloud-docs\/workspaces\/settings\/notifications\">workspace notifications<\/a><br \/>\nUse <a href=\"https:\/\/developer.hashicorp.com\/terraform\/cloud-docs\/workspaces\/dynamic-provider-credentials\">dynamic provider credentials<\/a><br \/>\n<a href=\"https:\/\/www.youtube.com\/watch?v=-dmzfQndOtk\">Module lifecycle management<\/a><\/p>\n<p><strong>HCP Terraform projects<\/strong> are used to group together multiple related workspaces and simplify configuration by allowing RBAC, variable sets, policy sets to be configured at the project level, rather than at the workspace level, easing the management burden.<\/p>\n<p>It generally makes sense to create an HCP Terraform project per application team, and in our scenario, we could update the module to create a project and register all workspaces under it.<\/p>\n<p>You can learn more about using HCP Terraform projects in this tutorial: <a href=\"https:\/\/developer.hashicorp.com\/terraform\/tutorials\/cloud\/projects\">Organize workspaces with projects<\/a>.<\/p>\n<p><strong>Workspace notifications<\/strong> enable HCP Terraform to send notifications about run progress and other significant events to external systems, such as Slack, Microsoft Teams, or via email. Each workspace can have its own notification settings, allowing up to 20 different notification destinations per workspace.<\/p>\n<p>In our scenario, the platform team could update the module to configure workspace notifications that trigger on the following events:<\/p>\n<p>Workspace events<\/p>\n<p>Drift (HCP Terraform detected a configuration drift)<br \/>\nCheck failure (HCP Terraform detected one or more failed continuous validation checks), if your code includes checks.<\/p>\n<p>Run events<\/p>\n<p>Needs attention (a plan has changes and HCP Terraform requires user input to continue).<br \/>\nErrored (a run terminated early due to an error or cancellation)<\/p>\n<p><strong>Dynamic provider credentials<\/strong> in HCP Terraform represent a significant advancement in security and access management. This feature allows Terraform to automatically generate short-lived credentials for cloud providers on-demand, rather than relying on long-term, static access keys. When a Terraform operation is initiated, HCP Terraform requests temporary credentials from the cloud provider that are valid only for the duration of the specific task.<\/p>\n<p>This approach substantially improves the security posture by minimizing the exposure window of access credentials, reducing the risk of unauthorized access if credentials are compromised. Additionally, it eliminates the need to manage and manually rotate long-term access keys, decreasing administrative overhead and the potential for human error in credential management.<\/p>\n<p>You can learn more about using dynamic provider credentials in this tutorial: <a href=\"https:\/\/developer.hashicorp.com\/terraform\/tutorials\/cloud\/dynamic-credentials\">Authenticate providers with dynamic credentials<\/a>. <\/p>\n<p><strong>Module lifecycle management<\/strong> is a systematic approach to control and maintain Terraform modules from rollout to retirement, provide module status visibility, and improve communication across teams. Key aspects of module lifecycle management include:<\/p>\n<p><strong>Version control<\/strong>: Modules are tracked in version control systems to maintain history and allow collaboration between modules maintainers.<br \/>\n<strong>Testing<\/strong>: Writing and executing tests for your module code lets you check if everything works correctly before publishing a new version.<br \/>\n<strong>Publishing new versions<\/strong>: Releasing an updated copy of your module in a <a href=\"https:\/\/developer.hashicorp.com\/terraform\/registry\/private\">private registry<\/a> with new features or fixes, similar to releasing a new version of an application.<br \/>\n<strong>Deprecation handling<\/strong>: The ability to mark modules as deprecated and communicate when modules should no longer be used.<\/p>\n<p>The module in this post is designed to onboard a new application team, but it could, with minor changes, also apply to shared services maintained by a platform team: The application_id variable could be renamed shared_service_id and this would be the start of a good foundation for shared services. As a platform team engineer, you can create a module to not only speed up the onboarding of new teams but also solve onboarding for shared services that your team manages.<\/p>\n<h2>Additional resources<\/h2>\n<p><a href=\"https:\/\/developer.hashicorp.com\/terraform\/tutorials\/automation\/tfe-provider-run-triggers\">Automate HCP Terraform workflows<\/a><br \/>\nTry <a href=\"https:\/\/www.hashicorp.com\/en\/products\/terraform?utm_source=hashicorp.com&amp;utm_medium=referral&amp;utm_campaign=26Q1_WW_hcp-signups-from-blogs&amp;utm_content=a-smoother-hcp-terraform-workspace-experience&amp;utm_offer=signup\">HCP Terraform\u2019s free tier<\/a> which includes up to 500 resources per month.<\/p>","protected":false},"excerpt":{"rendered":"<p>HCP Terraform allows organizations to scale the management of their cloud infrastructure. However, onboarding multiple teams with unique requirements and [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[6],"tags":[],"class_list":["post-1725","post","type-post","status-publish","format-standard","hentry","category-terraform"],"_links":{"self":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/1725","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/comments?post=1725"}],"version-history":[{"count":0,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/1725\/revisions"}],"wp:attachment":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media?parent=1725"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/categories?post=1725"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/tags?post=1725"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}