hashicorp / terraform-provider-tfe

Official HCP Terraform and Terraform Enterprise provider, maintained by HashiCorp. Provision HCP Terraform or Terraform Enterprise - with Terraform!
https://registry.terraform.io/providers/hashicorp/tfe
Mozilla Public License 2.0
161 stars 151 forks source link

Get Project name in addition to ID with tfe_workspace_ids and tfe_workspace data sources #778

Open lucymhdavies opened 1 year ago

lucymhdavies commented 1 year ago

Use-cases

I want to find all workspaces that match a certain tag. That's easily doable already.

# Find all Workspaces with specific tags
data "tfe_workspace_ids" "tagged" {
  tag_names    = var.tag_names
  organization = var.tfc_organization_name
}

output "tagged_workspace_ids" {
  value = data.tfe_workspace_ids.tagged
}

# Get full info on those workspaces (including Project ID)
data "tfe_workspace" "tagged" {
  for_each = data.tfe_workspace_ids.tagged.ids

  name         = each.key
  organization = var.tfc_organization_name
}

output "tagged_workspaces" {
  value = data.tfe_workspace.tagged
}

however, by doing so, I can only find out the Project ID

Changes to Outputs:
  + tagged_workspace_ids = {
      + exclude_tags = null
      + full_names   = {
          + "ami-cleanup" = "hashi_strawb_testing/ami-cleanup"
        }
      + id           = "hashi_strawb_testing/1686291893"
      + ids          = {
          + "ami-cleanup" = "ws-3h9fjhTAkAaoS6td"
        }
      + names        = null
      + organization = "hashi_strawb_testing"
      + tag_names    = [
          + "creds:dynamic-aws",
          + "aws-account:sandbox",
        ]
    }
  + tagged_workspaces    = {
      + ami-cleanup = {
          + allow_destroy_plan            = true
          + assessments_enabled           = true
          + auto_apply                    = false
          + description                   = ""
          + file_triggers_enabled         = false
          + global_remote_state           = false
          + id                            = "ws-3h9fjhTAkAaoS6td"
          + name                          = "ami-cleanup"
          + operations                    = true
          + organization                  = "hashi_strawb_testing"
          + policy_check_failures         = 0
          + project_id                    = "prj-GiZbB7qAkHnMUkdf"
          + queue_all_runs                = false
          + remote_state_consumer_ids     = []
          + resource_count                = 23
          + run_failures                  = 18
          + runs_count                    = 30
          + speculative_enabled           = true
          + ssh_key_id                    = null
          + structured_run_output_enabled = true
          + tag_names                     = [
              + "aws-account:sandbox",
              + "creds:dynamic-aws",
            ]
          + terraform_version             = "1.3.2"
          + trigger_patterns              = []
          + trigger_prefixes              = []
          + vcs_repo                      = []
          + working_directory             = ""
        }
    }

That's useful, but... in this case, I actually do want to know the name of the project, not just the ID.

Attempted Solutions

A potential workaround would be to pipe those project IDs into a for_each on a tfe_project data source... but we don't have one of those in the provider yet.

Proposal

A few things:

rhughes1 commented 1 year ago

Would be really nice if the API supported wildcard searching of projects similar to workspaces. Once you have that, then you could create a tfe_project_ids data source similar to the workspace_ids data source which can return a map of names to IDs of projects.

Also noticed that the API doesn't support getting a project by it's name (Similar to getting a workspace). I'm thinking we'd want to have that?

nfagerlund commented 1 year ago

Yeah, this could stand to be more ergonomic.

We just added a ticket to prioritize for adding a tfe_project data source — I've extended that ticket's description to note that we should consider how to make project ID/name conversions more ergonomic at the same time, since it might influence the design.

lucymhdavies commented 1 year ago

The tfe_project data source does now exist, which is great :) https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/data-sources/project

However, the data source currently requires you to pass in the project name.

For my use-case, where I'm getting workspace details from the tfe_workspace_ids and tfe_workspace data sources, I know the ID but I don't yet know the name.

My initial thought was that we could update that so that it takes either a name or an ID. (although... doing that for just tfe_project feels unnecessary. If we're gonna do that sort of thing, then it's the sort of thing we'd want to do for all the data sources, not just one or two)

My next thought was similar to my initial thinking, i.e. update tfe_workspace. Looks like that would either require an update to the API (which does not currently return project name: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/workspaces#show-workspace), or a second API call (which wouldn't necessarily be needed for everybody)

lucymhdavies commented 1 year ago

In my case, the reason why I'm looking to get the project name is so I can setup AWS Dynamic Creds: https://developer.hashicorp.com/terraform/tutorials/cloud/dynamic-credentials

So I do have a workaround in this case (which is to just use * in place of the project name). But for other use-cases, it may be more important.

lucymhdavies commented 1 year ago

My current workaround...

The tfe_workspace includes project_id in the attributes.

So a terracurl to https://developer.hashicorp.com/terraform/cloud-docs/api-docs/projects#show-project with the Project ID is good enough for now

data "terracurl_request" "project_name_for_workspace" {
  for_each = data.tfe_workspace.tagged

  name   = "project_name_for_workspace"
  url    = "https://app.terraform.io/api/v2/projects/${each.value.project_id}"
  method = "GET"

  headers = {
    Authorization = "Bearer ${local.tfe_token}"
    Content-Type  = "application/vnd.api+json"
  }
  response_codes = [200]
}