From 1b1397a3441430e00de3e2749cc2604f2291baf5 Mon Sep 17 00:00:00 2001 From: Tom Groves Date: Sat, 14 Mar 2026 12:22:08 +0000 Subject: [PATCH] fix(aws): auto-select SSM parameter tier to avoid 4096-char limit Large Nitric stacks produce a resource-index JSON that exceeds the 4,096-character limit of the SSM Standard tier, causing deployment failures. Detect the JSON size at deploy time and automatically upgrade to the Advanced tier (8,192-char limit) when needed. Applies to both the Pulumi provider (deploy/resources.go) and the Terraform CDKTF provider (deploytf/.nitric/modules/parameter/ and deploytf/resources.go). Small stacks are unaffected and continue to use the Standard tier at no additional cost. --- cloud/aws/deploy/resources.go | 10 ++++++++++ .../.nitric/modules/parameter/main.tf | 1 + .../.nitric/modules/parameter/variables.tf | 11 ++++++++++ .../deploytf/generated/parameter/Parameter.go | 20 +++++++++++++++++++ .../generated/parameter/ParameterConfig.go | 3 +++ cloud/aws/deploytf/resources.go | 8 ++++++++ 6 files changed, 53 insertions(+) diff --git a/cloud/aws/deploy/resources.go b/cloud/aws/deploy/resources.go index 5267c11bd..dd0ef394f 100644 --- a/cloud/aws/deploy/resources.go +++ b/cloud/aws/deploy/resources.go @@ -164,11 +164,21 @@ func (a *NitricAwsPulumiProvider) resourcesStore(ctx *pulumi.Context) error { return string(indexJson), nil }).(pulumi.StringOutput) + // Auto-select SSM parameter tier based on value size. + // Standard tier supports up to 4,096 chars; Advanced supports up to 8,192. + ssmTier := resourceIndexJson.ApplyT(func(val string) string { + if len(val) > 4096 { + return "Advanced" + } + return "Standard" + }).(pulumi.StringOutput) + _, err := ssm.NewParameter(ctx, "nitric-resource-index", &ssm.ParameterArgs{ // Create a deterministic name for the resource index Name: pulumi.Sprintf("/nitric/%s/resource-index", a.StackId), DataType: pulumi.String("text"), Type: pulumi.String("String"), + Tier: ssmTier, // Store the nitric resource index serialized as a JSON string Value: resourceIndexJson, }) diff --git a/cloud/aws/deploytf/.nitric/modules/parameter/main.tf b/cloud/aws/deploytf/.nitric/modules/parameter/main.tf index 483d91727..d29e62c19 100644 --- a/cloud/aws/deploytf/.nitric/modules/parameter/main.tf +++ b/cloud/aws/deploytf/.nitric/modules/parameter/main.tf @@ -13,6 +13,7 @@ resource "aws_ssm_parameter" "text_parameter" { type = "String" value = var.parameter_value data_type = "text" + tier = var.parameter_tier } # Create the access policy diff --git a/cloud/aws/deploytf/.nitric/modules/parameter/variables.tf b/cloud/aws/deploytf/.nitric/modules/parameter/variables.tf index 0bfdb43d9..1bd3f3def 100644 --- a/cloud/aws/deploytf/.nitric/modules/parameter/variables.tf +++ b/cloud/aws/deploytf/.nitric/modules/parameter/variables.tf @@ -12,3 +12,14 @@ variable "parameter_value" { description = "The text value of the parameter" type = string } + +variable "parameter_tier" { + description = "The tier of the SSM parameter (Standard or Advanced). Standard supports up to 4,096 characters; Advanced supports up to 8,192 characters." + type = string + default = "Standard" + + validation { + condition = contains(["Standard", "Advanced"], var.parameter_tier) + error_message = "parameter_tier must be one of: Standard, Advanced." + } +} diff --git a/cloud/aws/deploytf/generated/parameter/Parameter.go b/cloud/aws/deploytf/generated/parameter/Parameter.go index ede1b20e7..5ce59792d 100644 --- a/cloud/aws/deploytf/generated/parameter/Parameter.go +++ b/cloud/aws/deploytf/generated/parameter/Parameter.go @@ -36,6 +36,8 @@ type Parameter interface { Node() constructs.Node ParameterName() *string SetParameterName(val *string) + ParameterTier() *string + SetParameterTier(val *string) ParameterValue() *string SetParameterValue(val *string) // Experimental. @@ -169,6 +171,16 @@ func (j *jsiiProxy_Parameter) ParameterName() *string { return returns } +func (j *jsiiProxy_Parameter) ParameterTier() *string { + var returns *string + _jsii_.Get( + j, + "parameterTier", + &returns, + ) + return returns +} + func (j *jsiiProxy_Parameter) ParameterValue() *string { var returns *string _jsii_.Get( @@ -295,6 +307,14 @@ func (j *jsiiProxy_Parameter)SetParameterName(val *string) { ) } +func (j *jsiiProxy_Parameter)SetParameterTier(val *string) { + _jsii_.Set( + j, + "parameterTier", + val, + ) +} + func (j *jsiiProxy_Parameter)SetParameterValue(val *string) { if err := j.validateSetParameterValueParameters(val); err != nil { panic(err) diff --git a/cloud/aws/deploytf/generated/parameter/ParameterConfig.go b/cloud/aws/deploytf/generated/parameter/ParameterConfig.go index 91c388e21..4e79036c3 100644 --- a/cloud/aws/deploytf/generated/parameter/ParameterConfig.go +++ b/cloud/aws/deploytf/generated/parameter/ParameterConfig.go @@ -19,5 +19,8 @@ type ParameterConfig struct { ParameterName *string `field:"required" json:"parameterName" yaml:"parameterName"` // The text value of the parameter. ParameterValue *string `field:"required" json:"parameterValue" yaml:"parameterValue"` + // The tier of the SSM parameter (Standard or Advanced). + // Docs: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter#tier + ParameterTier *string `field:"optional" json:"parameterTier" yaml:"parameterTier"` } diff --git a/cloud/aws/deploytf/resources.go b/cloud/aws/deploytf/resources.go index e12355b38..a677a1405 100644 --- a/cloud/aws/deploytf/resources.go +++ b/cloud/aws/deploytf/resources.go @@ -76,10 +76,18 @@ func (a *NitricAwsTerraformProvider) ResourcesStore(stack cdktf.TerraformStack, return fmt.Errorf("failed to marshal resource index: %w", err) } + // Auto-select SSM parameter tier based on value size. + // Standard tier supports up to 4,096 chars; Advanced supports up to 8,192. + parameterTier := "Standard" + if len(indexJson) > 4096 { + parameterTier = "Advanced" + } + parameter.NewParameter(stack, jsii.String("nitric_resources"), ¶meter.ParameterConfig{ ParameterName: jsii.Sprintf("/nitric/%s/resource-index", *a.Stack.StackIdOutput()), ParameterValue: jsii.String(string(indexJson)), AccessRoleNames: jsii.Strings(accessRoleNames...), + ParameterTier: jsii.String(parameterTier), }) return nil