Skip to content
Open
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
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,8 @@ dist
.terraform/
terraform.tfstate
terraform.tfstate.backup
*.tfvars
*.tfvars

# Example secrets and lock files
examples/scope-definition/terraform.tfvars.json
examples/scope-definition/.terraform.lock.hcl
56 changes: 56 additions & 0 deletions examples/scope-definition/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
terraform {
required_providers {
nullplatform = {
source = "nullplatform/nullplatform"
}
http = {
source = "hashicorp/http"
}
}
}

provider "nullplatform" {
api_key = var.np_api_key
}

################################################################################
# Example: scope-definition module
#
# This example shows how to use the scope-definition module to create a scope
# type, service specification, and action specifications from templates stored
# in a GitHub repository.
#
# Set create_scope_configuration = true when the scope repository contains a
# /specs/scope-configuration.json.tpl file. This will also create a
# nullplatform_provider_specification resource from the template.
################################################################################

module "scope_definition" {
source = "../../modules/nullplatform/scope-definition"

nrn = var.nrn
organization_nrn = var.organization_nrn

github_repo_url = var.github_repo_url
github_ref = var.github_ref
github_scope_path = var.github_scope_path

scope_name = var.scope_name
scope_description = var.scope_description

create_scope_configuration = var.create_scope_configuration

np_api_key = var.np_api_key
}

output "service_specification_id" {
value = module.scope_definition.service_specification_id
}

output "scope_type_id" {
value = module.scope_definition.scope_type_id
}

output "provider_specification_id" {
value = module.scope_definition.provider_specification_id
}
11 changes: 11 additions & 0 deletions examples/scope-definition/terraform.tfvars.json.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"np_api_key": "your-nullplatform-api-key",
"nrn": "organization=1234567890:account=987654321",
"organization_nrn": "organization=1234567890",
"github_repo_url": "https://github.com/nullplatform/scopes-static-files",
"github_ref": "main",
"github_scope_path": "static-files",
"scope_name": "my-scope",
"scope_description": "My custom scope type",
"create_scope_configuration": false
}
43 changes: 43 additions & 0 deletions examples/scope-definition/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
variable "np_api_key" {
type = string
sensitive = true
}

variable "nrn" {
type = string
description = "Nullplatform Resource Name (organization:account format)"
}

variable "organization_nrn" {
type = string
description = "Organization NRN used when create_scope_configuration is true"
default = ""
}

variable "github_repo_url" {
type = string
default = "https://github.com/nullplatform/scopes-static-files"
}

variable "github_ref" {
type = string
default = "main"
}

variable "github_scope_path" {
type = string
default = "static-files"
}

variable "scope_name" {
type = string
}

variable "scope_description" {
type = string
}

variable "create_scope_configuration" {
type = bool
default = false
}
8 changes: 4 additions & 4 deletions modules/nullplatform/scope-definition/backend.tf
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
terraform {
required_providers {
nullplatform = {
source = "nullplatform/nullplatform"
source = "nullplatform/nullplatform"
}
http = {
source = "hashicorp/http"
source = "hashicorp/http"
}
external = {
source = "hashicorp/external"
source = "hashicorp/external"
}
null = {
source = "hashicorp/null"
source = "hashicorp/null"
}
}
}
61 changes: 47 additions & 14 deletions modules/nullplatform/scope-definition/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ data "http" "service_spec_template" {
url = "${var.github_repo_url}/raw/${var.github_ref}/${var.github_scope_path}/specs/service-spec.json.tpl"
}

# Fetch scope configuration template (optional - may not exist for all scopes)
data "http" "scope_configuration_template" {
count = var.create_scope_configuration ? 1 : 0
url = "${var.github_repo_url}/raw/${var.github_ref}/${var.github_scope_path}/specs/scope-configuration.json.tpl"
}

# Fetch action specification templates
data "http" "action_templates" {
for_each = toset(var.action_spec_names)
Expand All @@ -18,22 +24,22 @@ data "http" "action_templates" {
################################################################################

locals {
# Process the template by replacing the template variables
# replace is done because some old templates contain gomplate placeholders
service_spec_rendered = replace(
data.http.service_spec_template.response_body,
"/\"{{\\s+env.Getenv\\s+\".*\"\\s+}}\"/",
"\"${var.nrn}\""
)
service_spec_parsed = jsondecode(local.service_spec_rendered)
# Process the template by replacing the template variables
# replace is done because some old templates contain gomplate placeholders
service_spec_rendered = replace(
data.http.service_spec_template.response_body,
"/\"{{\\s+env.Getenv\\s+\".*\"\\s+}}\"/",
"\"${var.nrn}\""
)
service_spec_parsed = jsondecode(local.service_spec_rendered)
}

# Create service specification
resource "nullplatform_service_specification" "from_template" {
name = local.service_spec_parsed.name
visible_to = [var.nrn]
type = local.service_spec_parsed.type
attributes = jsonencode(local.service_spec_parsed.attributes)
type = local.service_spec_parsed.type
attributes = jsonencode(local.service_spec_parsed.attributes)
use_default_actions = local.service_spec_parsed.use_default_actions

selectors {
Expand All @@ -56,6 +62,31 @@ locals {
}
}

################################################################################
# Step 2.5: Process Scope Configuration (optional)
################################################################################

locals {
# Replace the NRN gomplate placeholder with the organization_nrn variable
scope_configuration_rendered = var.create_scope_configuration ? replace(
data.http.scope_configuration_template[0].response_body,
"/\"{{\\s+env.Getenv\\s+\".*\"\\s+}}\"/",
"\"${var.organization_nrn}\""
) : "{}"
scope_configuration = var.create_scope_configuration ? jsondecode(local.scope_configuration_rendered) : null
}

resource "nullplatform_provider_specification" "from_scope_configuration" {
count = var.create_scope_configuration ? 1 : 0

name = local.scope_configuration.name
description = local.scope_configuration.description
category = local.scope_configuration.category
allow_dimensions = local.scope_configuration.allow_dimensions
visible_to = [var.organization_nrn]
schema = jsonencode(local.scope_configuration.schema)
}

################################################################################
# Step 3: Process and Create Scope Type
################################################################################
Expand All @@ -79,19 +110,21 @@ resource "nullplatform_scope_type" "from_template" {
# Process action templates - direct JSON parsing (they don't contain template variables)
# replace is done because some old templates contain gomplate placeholders
locals {
# Only parse templates that returned a 200 — missing files return an HTML 404 page
action_specs_parsed = {
for name in var.action_spec_names :
name => jsondecode(replace(
data.http.action_templates[name].response_body,
"/\"{{\\s+env.Getenv\\s+\".*\"\\s+}}\"/",
"\"\""
data.http.action_templates[name].response_body,
"/\"{{\\s+env.Getenv\\s+\".*\"\\s+}}\"/",
"\"\""
))
if data.http.action_templates[name].status_code == 200
}
}

# Create action specifications
resource "nullplatform_action_specification" "from_templates" {
for_each = toset(var.action_spec_names)
for_each = toset(keys(local.action_specs_parsed))
depends_on = [nullplatform_service_specification.from_template]

service_specification_id = local.service_specification_id
Expand Down
10 changes: 10 additions & 0 deletions modules/nullplatform/scope-definition/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,14 @@ output "scope_name" {
output "scope_description" {
value = var.scope_description
description = "The name of the scope definition"
}

output "scope_configuration" {
value = local.scope_configuration
description = "Parsed scope configuration from scope-configuration.json.tpl, or null if not fetched"
}

output "provider_specification_id" {
value = var.create_scope_configuration ? nullplatform_provider_specification.from_scope_configuration[0].id : null
description = "The ID of the created provider specification, or null if scope configuration was not fetched"
}
16 changes: 14 additions & 2 deletions modules/nullplatform/scope-definition/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ variable "github_ref" {
variable "github_scope_path" {
type = string
default = "k8s"
description = "Path within the repository for the specific scope (e.g., k8s, ecs)"
description = "Path within the repository for the specific scope (e.g., k8s, ecs)"
}

variable "scope_name" {
Expand All @@ -32,7 +32,7 @@ variable "scope_name" {
variable "scope_description" {
type = string
description = "Description of the scope type to be created"
}
}

variable "action_spec_names" {
type = list(string)
Expand All @@ -54,6 +54,18 @@ variable "action_spec_names" {
description = "List of action specification template names to fetch and create"
}

variable "organization_nrn" {
type = string
description = "Organization NRN used to replace the NRN placeholder in scope-configuration.json.tpl"
default = ""
}

variable "create_scope_configuration" {
type = bool
default = false
description = "Whether to fetch and apply scope-configuration.json.tpl from the template repo. Set to true only if the file exists for this scope."
}

# NRN Patch Configuration
variable "np_api_key" {
type = string
Expand Down
Loading