From 6754a7c908a13b1ffaa8cb0ec285d55656aaad19 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Fri, 17 Apr 2026 15:41:08 -0300 Subject: [PATCH] Add missing specs and terraform example --- .../adjust-provisioned-concurrency.json.tpl | 40 +++++++++++++ .../adjust-reserved-concurrency.json.tpl | 32 +++++++++++ lambda/specs/actions/create-scope.json.tpl | 29 ++++++++++ .../specs/actions/delete-deployment.json.tpl | 33 +++++++++++ lambda/specs/actions/delete-scope.json.tpl | 29 ++++++++++ .../actions/diagnose-deployment.json.tpl | 33 +++++++++++ lambda/specs/actions/diagnose-scope.json.tpl | 29 ++++++++++ .../actions/finalize-blue-green.json.tpl | 33 +++++++++++ lambda/specs/actions/invoke.json.tpl | 42 ++++++++++++++ .../actions/rollback-deployment.json.tpl | 33 +++++++++++ .../specs/actions/start-blue-green.json.tpl | 33 +++++++++++ lambda/specs/actions/start-initial.json.tpl | 33 +++++++++++ lambda/specs/actions/switch-traffic.json.tpl | 37 ++++++++++++ lambda/specs/actions/update-scope.json.tpl | 29 ++++++++++ lambda/specs/notification-channel.json.tpl | 35 ++++++++++++ lambda/specs/scope-configuration.json.tpl | 57 +++++++++++++++++++ lambda/specs/scope-type-definition.json.tpl | 9 +++ lambda/specs/terraform/main.tf | 55 ++++++++++++++++++ .../specs/terraform/terraform.tfvars.example | 7 +++ lambda/specs/terraform/variables.tf | 22 +++++++ 20 files changed, 650 insertions(+) create mode 100644 lambda/specs/actions/adjust-provisioned-concurrency.json.tpl create mode 100644 lambda/specs/actions/adjust-reserved-concurrency.json.tpl create mode 100644 lambda/specs/actions/create-scope.json.tpl create mode 100644 lambda/specs/actions/delete-deployment.json.tpl create mode 100644 lambda/specs/actions/delete-scope.json.tpl create mode 100644 lambda/specs/actions/diagnose-deployment.json.tpl create mode 100644 lambda/specs/actions/diagnose-scope.json.tpl create mode 100644 lambda/specs/actions/finalize-blue-green.json.tpl create mode 100644 lambda/specs/actions/invoke.json.tpl create mode 100644 lambda/specs/actions/rollback-deployment.json.tpl create mode 100644 lambda/specs/actions/start-blue-green.json.tpl create mode 100644 lambda/specs/actions/start-initial.json.tpl create mode 100644 lambda/specs/actions/switch-traffic.json.tpl create mode 100644 lambda/specs/actions/update-scope.json.tpl create mode 100644 lambda/specs/notification-channel.json.tpl create mode 100644 lambda/specs/scope-configuration.json.tpl create mode 100644 lambda/specs/scope-type-definition.json.tpl create mode 100644 lambda/specs/terraform/main.tf create mode 100644 lambda/specs/terraform/terraform.tfvars.example create mode 100644 lambda/specs/terraform/variables.tf diff --git a/lambda/specs/actions/adjust-provisioned-concurrency.json.tpl b/lambda/specs/actions/adjust-provisioned-concurrency.json.tpl new file mode 100644 index 0000000..e784189 --- /dev/null +++ b/lambda/specs/actions/adjust-provisioned-concurrency.json.tpl @@ -0,0 +1,40 @@ +{ + "name": "Adjust provisioned concurrency", + "slug": "adjust-provisioned-concurrency", + "type": "custom", + "retryable": true, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "icon": "material-symbols:expand-rounded", + "annotations": { + "show_on": ["performance"], + "runs_over": "scope" + }, + "enabled_when": "", + "parameters": { + "schema": { + "type": "object", + "required": ["scope_id", "value"], + "properties": { + "scope_id": { + "type": "number", + "readOnly": true, + "visibleOn": [] + }, + "value": { + "type": "integer", + "description": "Number of provisioned concurrent executions (0 to remove provisioning)", + "minimum": 0 + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/adjust-reserved-concurrency.json.tpl b/lambda/specs/actions/adjust-reserved-concurrency.json.tpl new file mode 100644 index 0000000..ad8cb3b --- /dev/null +++ b/lambda/specs/actions/adjust-reserved-concurrency.json.tpl @@ -0,0 +1,32 @@ +{ + "name": "adjust-reserved-concurrency", + "slug": "adjust-reserved-concurrency", + "type": "custom", + "retryable": true, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": ["scope_id", "value"], + "properties": { + "scope_id": { + "type": "string" + }, + "value": { + "type": "integer", + "description": "Number of reserved concurrent executions (0 to remove reservation)", + "minimum": 0 + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/create-scope.json.tpl b/lambda/specs/actions/create-scope.json.tpl new file mode 100644 index 0000000..46354cc --- /dev/null +++ b/lambda/specs/actions/create-scope.json.tpl @@ -0,0 +1,29 @@ +{ + "name": "create-scope", + "slug": "create-scope", + "type": "create", + "retryable": false, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id" + ], + "properties": { + "scope_id": { + "type": "string" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/delete-deployment.json.tpl b/lambda/specs/actions/delete-deployment.json.tpl new file mode 100644 index 0000000..4dabc9a --- /dev/null +++ b/lambda/specs/actions/delete-deployment.json.tpl @@ -0,0 +1,33 @@ +{ + "name": "delete-deployment", + "slug": "delete-deployment", + "type": "custom", + "retryable": false, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id", + "deployment_id" + ], + "properties": { + "scope_id": { + "type": "string" + }, + "deployment_id": { + "type": "string" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/delete-scope.json.tpl b/lambda/specs/actions/delete-scope.json.tpl new file mode 100644 index 0000000..9a5ea09 --- /dev/null +++ b/lambda/specs/actions/delete-scope.json.tpl @@ -0,0 +1,29 @@ +{ + "name": "delete-scope", + "slug": "delete-scope", + "type": "custom", + "retryable": false, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id" + ], + "properties": { + "scope_id": { + "type": "string" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/diagnose-deployment.json.tpl b/lambda/specs/actions/diagnose-deployment.json.tpl new file mode 100644 index 0000000..78c511a --- /dev/null +++ b/lambda/specs/actions/diagnose-deployment.json.tpl @@ -0,0 +1,33 @@ +{ + "name": "diagnose-deployment", + "slug": "diagnose-deployment", + "type": "custom", + "retryable": true, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id", + "deployment_id" + ], + "properties": { + "scope_id": { + "type": "string" + }, + "deployment_id": { + "type": "string" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/diagnose-scope.json.tpl b/lambda/specs/actions/diagnose-scope.json.tpl new file mode 100644 index 0000000..0cb8957 --- /dev/null +++ b/lambda/specs/actions/diagnose-scope.json.tpl @@ -0,0 +1,29 @@ +{ + "name": "diagnose-scope", + "slug": "diagnose-scope", + "type": "custom", + "retryable": true, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id" + ], + "properties": { + "scope_id": { + "type": "string" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/finalize-blue-green.json.tpl b/lambda/specs/actions/finalize-blue-green.json.tpl new file mode 100644 index 0000000..9ba7b31 --- /dev/null +++ b/lambda/specs/actions/finalize-blue-green.json.tpl @@ -0,0 +1,33 @@ +{ + "name": "finalize-blue-green", + "slug": "finalize-blue-green", + "type": "custom", + "retryable": false, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id", + "deployment_id" + ], + "properties": { + "scope_id": { + "type": "string" + }, + "deployment_id": { + "type": "string" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/invoke.json.tpl b/lambda/specs/actions/invoke.json.tpl new file mode 100644 index 0000000..1cacda0 --- /dev/null +++ b/lambda/specs/actions/invoke.json.tpl @@ -0,0 +1,42 @@ +{ + "name": "Invoke", + "slug": "invoke", + "type": "custom", + "retryable": true, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "icon": "material-symbols:pin-invoke-rounded", + "annotations": { + "show_on": ["performance"], + "runs_over": "scope" + }, + "enabled_when": "", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id" + ], + "properties": { + "scope_id": { + "type": "number", + "readOnly": true, + "visibleOn": [] + }, + "payload": { + "type": "string", + "description": "JSON payload to send to the Lambda function (optional)", + "default": "{}" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/rollback-deployment.json.tpl b/lambda/specs/actions/rollback-deployment.json.tpl new file mode 100644 index 0000000..26d3ce0 --- /dev/null +++ b/lambda/specs/actions/rollback-deployment.json.tpl @@ -0,0 +1,33 @@ +{ + "name": "rollback-deployment", + "slug": "rollback-deployment", + "type": "custom", + "retryable": true, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id", + "deployment_id" + ], + "properties": { + "scope_id": { + "type": "string" + }, + "deployment_id": { + "type": "string" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/start-blue-green.json.tpl b/lambda/specs/actions/start-blue-green.json.tpl new file mode 100644 index 0000000..a646cb8 --- /dev/null +++ b/lambda/specs/actions/start-blue-green.json.tpl @@ -0,0 +1,33 @@ +{ + "name": "start-blue-green", + "slug": "start-blue-green", + "type": "custom", + "retryable": true, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id", + "deployment_id" + ], + "properties": { + "scope_id": { + "type": "string" + }, + "deployment_id": { + "type": "string" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/start-initial.json.tpl b/lambda/specs/actions/start-initial.json.tpl new file mode 100644 index 0000000..9e6f167 --- /dev/null +++ b/lambda/specs/actions/start-initial.json.tpl @@ -0,0 +1,33 @@ +{ + "name": "start-initial", + "slug": "start-initial", + "type": "custom", + "retryable": true, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id", + "deployment_id" + ], + "properties": { + "scope_id": { + "type": "string" + }, + "deployment_id": { + "type": "string" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/switch-traffic.json.tpl b/lambda/specs/actions/switch-traffic.json.tpl new file mode 100644 index 0000000..a46b068 --- /dev/null +++ b/lambda/specs/actions/switch-traffic.json.tpl @@ -0,0 +1,37 @@ +{ + "name": "switch-traffic", + "slug": "switch-traffic", + "type": "custom", + "retryable": true, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id", + "deployment_id", + "desired_traffic" + ], + "properties": { + "scope_id": { + "type": "string" + }, + "deployment_id": { + "type": "string" + }, + "desired_traffic": { + "type": "number" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/actions/update-scope.json.tpl b/lambda/specs/actions/update-scope.json.tpl new file mode 100644 index 0000000..de010b7 --- /dev/null +++ b/lambda/specs/actions/update-scope.json.tpl @@ -0,0 +1,29 @@ +{ + "name": "update-scope", + "slug": "update-scope", + "type": "custom", + "retryable": true, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [ + "scope_id" + ], + "properties": { + "scope_id": { + "type": "string" + } + } + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} diff --git a/lambda/specs/notification-channel.json.tpl b/lambda/specs/notification-channel.json.tpl new file mode 100644 index 0000000..265a013 --- /dev/null +++ b/lambda/specs/notification-channel.json.tpl @@ -0,0 +1,35 @@ +{ + "nrn": "{{ env.Getenv "NRN" }}", + "status": "active", + "description": "Channel to handle AWS Lambda scopes", + "type": "agent", + "source": [ + "telemetry", + "service" + ], + "configuration": { + "api_key": "{{ env.Getenv "NP_API_KEY" }}", + "command": { + "data": { + "cmdline": "{{ env.Getenv "REPO_PATH" }}/lambda/entrypoint --service-path={{ env.Getenv "REPO_PATH" }}/lambda", + "environment": { + "NP_ACTION_CONTEXT": "'${NOTIFICATION_CONTEXT}'" + } + }, + "type": "exec" + }, + "selector": { + "environment": "{{ env.Getenv "ENVIRONMENT" }}" + } + }, + "filters": { + "$or": [ + { + "service.specification.slug": "{{ env.Getenv "SERVICE_SLUG" }}" + }, + { + "arguments.scope_provider": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}" + } + ] + } +} diff --git a/lambda/specs/scope-configuration.json.tpl b/lambda/specs/scope-configuration.json.tpl new file mode 100644 index 0000000..351c486 --- /dev/null +++ b/lambda/specs/scope-configuration.json.tpl @@ -0,0 +1,57 @@ +{ + "name": "AWS Lambda", + "description": "Configuration for AWS Lambda (state backend, placeholder image, and agent layer)", + "category": "scope-configurations", + "icon": "np:aws-lambda", + "visible_to": [ + "organization=1255165411" + ], + "allow_dimensions": false, + "schema": { + "type": "object", + "required": [ + "state" + ], + "properties": { + "agent": { + "type": "object", + "order": 3, + "title": "Null Agent", + "properties": { + "null_agent_layer_arn": { + "type": "string", + "title": "Lambda Layer ARN", + "description": "ARN of the nullplatform agent Lambda layer (required when USE_NULL_AGENT=true)" + } + } + }, + "state": { + "type": "object", + "order": 1, + "title": "IaC State (OpenTofu)", + "required": [ + "tofu_state_bucket" + ], + "properties": { + "tofu_state_bucket": { + "type": "string", + "title": "State Bucket", + "description": "S3 bucket name used to store OpenTofu/Terraform state" + } + } + }, + "deployment": { + "type": "object", + "order": 2, + "title": "Deployment", + "properties": { + "placeholder_image_uri": { + "type": "string", + "title": "Placeholder Image URI", + "description": "ECR image URI used as the Lambda placeholder container during scope creation (e.g. 123456789.dkr.ecr.us-east-1.amazonaws.com/my-repo/placeholder:latest)" + } + } + } + } + } +} \ No newline at end of file diff --git a/lambda/specs/scope-type-definition.json.tpl b/lambda/specs/scope-type-definition.json.tpl new file mode 100644 index 0000000..9dc2a0f --- /dev/null +++ b/lambda/specs/scope-type-definition.json.tpl @@ -0,0 +1,9 @@ +{ + "description": "Serverless functions on AWS Lambda", + "name": "AWS Lambda", + "nrn": "{{ env.Getenv "NRN" }}", + "provider_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "provider_type": "service", + "status": "active", + "type": "custom" +} diff --git a/lambda/specs/terraform/main.tf b/lambda/specs/terraform/main.tf new file mode 100644 index 0000000..a3a5feb --- /dev/null +++ b/lambda/specs/terraform/main.tf @@ -0,0 +1,55 @@ +locals { + scope_definition = { + git_repo = "nullplatform/scopes-lambda" + git_ref = "main" + git_scope_path = "lambda" + name = "Lambda" + description = "Serverless functions on AWS Lambda" + actions = [ + "adjust-provisioned-concurrency", + "adjust-reserved-concurrency", + "create-scope", + "delete-deployment", + "delete-scope", + "diagnose-deployment", + "diagnose-scope", + "finalize-blue-green", + "invoke", + "rollback-deployment", + "start-blue-green", + "start-initial", + "switch-traffic", + "update-scope", + ] + } +} + +module "scope_definition" { + source = "git::https://github.com/nullplatform/main-terraform-modules.git//modules/nullplatform/scope-definition?ref=main" + + nrn = var.nrn + np_api_key = var.np_api_key + + github_repo_url = "https://${var.github_token}@github.com/${local.scope_definition.git_repo}" + github_ref = local.scope_definition.git_ref + github_scope_path = local.scope_definition.git_scope_path + scope_name = local.scope_definition.name + scope_description = local.scope_definition.description + + action_spec_names = local.scope_definition.actions +} + +module "scope_definition_agent_association" { + source = "git::https://github.com/nullplatform/tofu-modules.git//nullplatform/scope_definition_agent_association?ref=main" + + api_key = var.np_api_key + nrn = var.nrn + scope_specification_id = module.scope_definition.service_specification_id + scope_specification_slug = module.scope_definition.service_specification_slug + tags_selectors = var.tags + + repository_notification_channel = "https://${var.github_token}@raw.githubusercontent.com/${local.scope_definition.git_repo}/refs/heads" + repository_notification_channel_branch = local.scope_definition.git_ref + service_path = local.scope_definition.git_scope_path + repo_path = "/root/.np/${local.scope_definition.git_repo}" +} diff --git a/lambda/specs/terraform/terraform.tfvars.example b/lambda/specs/terraform/terraform.tfvars.example new file mode 100644 index 0000000..faa7ac8 --- /dev/null +++ b/lambda/specs/terraform/terraform.tfvars.example @@ -0,0 +1,7 @@ +nrn = "" +np_api_key = "" +github_token = "" + +tags = { + "environment" = "" +} diff --git a/lambda/specs/terraform/variables.tf b/lambda/specs/terraform/variables.tf new file mode 100644 index 0000000..e5dfc26 --- /dev/null +++ b/lambda/specs/terraform/variables.tf @@ -0,0 +1,22 @@ +variable "nrn" { + description = "NullPlatform Resource Name for the scope" + type = string +} + +variable "np_api_key" { + description = "nullplatform API key for authentication" + type = string + sensitive = true +} + +variable "github_token" { + description = "GitHub personal access token for accessing private repos" + type = string + sensitive = true +} + +variable "tags" { + description = "Map of tags used to select and filter channels and agents" + type = map(string) +} +