Skip to main content

Resource Hierarchy

Last updated on

When creating flexible templates there may be resources you want to create that could exist at multiple scopes: Account, Organization, or Project.

To do this, you must do three things:

  • Have the user specify the location where the template should be placed
  • Place the resource [using the terraform code] at the target location
  • Dynamically give the users links to the created resources

This can be achieved using the following pattern in your catalog and terraform code.

Specify location

You can use the following template section in your catalog to ask the user where the resource should be placed.

parameters:
- title: Template Location
description: Where should this be placed?
required:
- template_location
properties:
template_location:
title: Template Location
type: string
description: Where should we place the template?
enum:
- Account
- Organization
- Project
dependencies:
template_location:
oneOf:
- properties:
template_location:
enum:
- Account
- properties:
template_location:
enum:
- Organization
org_id:
title: Org Identifier
description: Harness Organization Identifier
type: string
ui:field: HarnessOrgPicker
required:
- org_id
- properties:
template_location:
enum:
- Project
project_id:
title: Project Identifier
description: Harness Project Identifier
type: string
ui:field: HarnessProjectPicker
org_id:
title: Org Identifier
description: Harness Organization Identifier
type: string
ui:field: HarnessOrgPicker
required:
- project_id
- org_id

You can then pass the org and project IDs to your terraform based on the values selected:

RESOURCE_VARS:
organization_id: ${{ parameters.org_id if parameters.project_id else ( parameters.org_id if parameters.org_id else "") }}
project_id: ${{ parameters.project_id if parameters.project_id else "" }}

Use location

Now in your terraform, you need to define variables for the org and project IDs, and use them in your resource definition.

variable "organization_id" {
type = string
description = "[Optional] The organization where the step template will live, leave blank for account level. Provide an existing organization reference ID. Must exist before execution"
default = null
}

variable "project_id" {
type = string
description = "[Optional] The project where the step template will live, leave blank for organization or account level. Provide an existing project reference ID. Must exist before execution"
default = null
}

Data sources validate that the locations exist before Terraform tries to create them, turning a confusing apply failure into a clear plan failure.

data "harness_platform_organization" "this" {
count = var.organization_id == null ? 0 : 1
identifier = var.organization_id
}

data "harness_platform_project" "this" {
count = var.project_id == null ? 0 : 1
identifier = var.project_id
org_id = data.harness_platform_organization.template[0].id
}

The data sources can then be used to place the resources being created at whatever level the user specified.

resource "harness_platform_template" "this" {
org_id = var.template_organization_id == null ? null : data.harness_platform_organization.template[0].id
project_id = var.template_project_id == null ? null : data.harness_platform_project.template[0].id
}

Finally, give the user handy links in their template so they can easily navigate to the created resource. The resource URL is crafted based on the org or project specified. This may change based on the resource you are linking to; the following is an example for some of the common resources.

output:
links:
- title: Created Resource
url: ${{ parameters.solutions_factory_details.harness_account_url }}/ng/account/${{ parameters.solutions_factory_details.harness_account_id }}/all${{ ("/orgs/" + parameters.org_id) if parameters.org_id else "" }}${{ ("/projects/" + parameters.project_id) if parameters.project_id else "" }}/settings/templates/${{ template_id }}