Skip to main content
Glama
overrides.ts22.4 kB
import { PropOverrideFn, SchemaOverrideFn } from "../types.ts"; import { ExpandedPkgSpec } from "../../spec/pkgs.ts"; import { ACTION_FUNC_SPECS, MANAGEMENT_FUNCS } from "./funcs.ts"; import { ulid } from "https://deno.land/x/ulid@v0.3.0/mod.ts"; import { FuncArgumentSpec } from "../../bindings/FuncArgumentSpec.ts"; import { addSecretProp, arnProp, arrayPropForOverride, attachExtraActionFunction, attachExtraManagementFunction, attachQualificationFunction, objectPropForOverride, policyDocumentProp, propForOverride, stringPropForOverride, suggest, } from "../generic/overrides.ts"; import { addPropSuggestSource, createScalarProp } from "../../spec/props.ts"; import { createFunc, modifyFunc, strippedBase64 } from "../../spec/funcs.ts"; // AWS-specific property overrides!!! export const AWS_PROP_OVERRIDES: Record< string, Record<string, PropOverrideFn | PropOverrideFn[]> > = { // AWS::EC2 "AWS::EC2::FlowLog": { DeliverLogsPermissionArn: arnProp("AWS::IAM::Role"), }, "AWS::EC2::LaunchTemplate": { "LaunchTemplateData/LicenseSpecifications/LicenseSpecificationsItem/LicenseConfigurationArn": arnProp("AWS::LicenseManager::LicenseConfiguration"), }, "AWS::EC2::NetworkInterface": { "GroupSet/GroupSetItem": suggest("AWS::EC2::SecurityGroup", "GroupId"), }, "AWS::EC2::Route": { GatewayId: [ suggest("AWS::EC2::InternetGateway", "InternetGatewayId"), suggest("AWS::EC2::VPNGateway", "VPNGatewayId"), ], }, "AWS::EC2::VPCCidrBlock": { Ipv4IpamPoolId: suggest("AWS::EC2::IPAMPool", "IpamPoolId"), Ipv6IpamPoolId: suggest("AWS::EC2::IPAMPool", "IpamPoolId"), }, "AWS::EC2::VPCEndpointConnectionNotification": { ConnectionNotificationArn: arnProp("AWS::SNS::Topic", "TopicArn"), }, // AWS::ECS "AWS::ECS::TaskDefinition": { "ContainerDefinitions/ContainerDefinitionsItem/Secrets/SecretsItem/ValueFrom": [ suggest("AWS::SecretsManager::Secret", "Id"), suggest("AWS::SSM::Parameter", "/domain/Name"), ], }, // AWS::ElasticLoadBalancingV2 "AWS::ElasticLoadBalancingV2::TargetGroup": { "Targets/TargetsItem/Id": [ suggest("AWS::EC2::Instance", "InstanceId"), suggest("AWS::Lambda::Function", "Arn"), suggest("AWS::ElasticLoadBalancingV2::LoadBalancer", "LoadBalancerArn"), ], }, // AWS::KMS "AWS::KMS::Key": { KeyPolicy: policyDocumentProp, }, // AWS::Logs "AWS::Logs::LogGroup": { DataProtectionPolicy: policyDocumentProp, }, // AWS::Organizations "AWS::Organizations::OrganizationalUnit": { ParentId: [ suggest("AWS::Organizations::Organization", "RootId"), suggest("AWS::Organizations::OrganizationalUnit", "/resource_value/Id"), ], }, "AWS::Organizations::Account": { "ParentIds/ParentIdsItem": [ suggest("AWS::Organizations::Organization", "RootId"), suggest("AWS::Organizations::OrganizationalUnit", "/resource_value/Id"), ], }, "AWS::Organizations::Policy": { "TargetIds/TargetIdsItem": [ suggest("AWS::Organizations::Organization", "RootId"), suggest("AWS::Organizations::OrganizationalUnit", "/resource_value/Id"), suggest("AWS::Organizations::Account", "/resource_value/AccountId"), ], }, // Props that exist on resources across all of AWS ".*": { // Policy document props ".*(PolicyDocument|PolicyText)": policyDocumentProp, // AWS::EC2 ARNs/IDs/Versions ".*IpamArn": arnProp("AWS::EC2::IPAM"), ".*IpamPoolArn": arnProp("AWS::EC2::IPAMPool"), ".*IpamScopeArn": arnProp("AWS::EC2::IPAMScope"), ".*LaunchTemplate*/Version": [ suggest("AWS::EC2::LaunchTemplate", "LatestVersionNumber"), suggest("AWS::EC2::LaunchTemplate", "DefaultVersionNumber"), ], ".*LocalGatewayRouteTableArn": arnProp( "AWS::EC2::LocalGatewayRouteTable", "LocalGatewayRouteTableArn", ), ".*GroupId": suggest("AWS::EC2::SecurityGroup", "GroupId"), ".*GroupName": suggest("AWS::EC2::SecurityGroup", "/domain/GroupName"), // AWS::ElasticLoadBalancingV2 ARNs ".*LoadBalancerArn": arnProp( "AWS::ElasticLoadBalancingV2::LoadBalancer", "LoadBalancerArn", ), ".*(TargetGroupArn|TargetGroup/Arn)": arnProp( "AWS::ElasticLoadBalancingV2::TargetGroup", "TargetGroupArn", ), // AWS::KMS ARNs ".*KmsKeyArn": arnProp("AWS::KMS::Key"), // AWS::IAM ARNs ".*(InstanceProfileArn|InstanceProfile/Arn|InstanceProfileSpecification/Arn)": arnProp("AWS::IAM::InstanceProfile"), ".*RoleArn": arnProp("AWS::IAM::Role"), ".*SAMLProviderArn": arnProp("AWS::IAM::SAMLProvider"), // AWS::Lambda ARNs ".*(LambdaArn|LambdaFunctionArn)": arnProp("AWS::Lambda::Function"), // AWS::LicenseManager ARNs ".*(LicenseArn|LicenseConfigurationArn)": arnProp( "AWS::LicenseManager::License", "LicenseArn", ), // AWS::Logs ARNs ".*LogGroupArn": arnProp("AWS::Logs::LogGroup"), // AWS::NetworkManager ARNs ".*CoreNetworkArn": arnProp( "AWS::NetworkManager::CoreNetwork", "CoreNetworkArn", ), // AWS::RDS ARNs ".*DbInstanceArn": arnProp("AWS::RDS::DBInstance", "DBInstanceArn"), ".*DbClusterArn": arnProp("AWS::RDS::DBCluster", "DBClusterArn"), ".*DbProxyArn": arnProp("AWS::RDS::DBProxy", "DBProxyArn"), // AWS::ResourceGroups ARNs ".*ResourceGroupArn": arnProp("AWS::ResourceGroups::Group"), // AWS::SNS ARNs ".*TopicArn": arnProp("AWS::SNS::Topic", "TopicArn"), // AWS::VpcLattice ARNs ".*ResourceConfigurationArn": arnProp( "AWS::VpcLattice::ResourceConfiguration", ), ".*ServiceNetworkArn": arnProp("AWS::VpcLattice::ServiceNetwork"), }, }; // AWS-specific schema overrides export const AWS_SCHEMA_OVERRIDES = new Map<string, SchemaOverrideFn>([ [ "AWS::EC2::Instance", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const domainId = variant.domain.uniqueId; const overrideUserDataAttributeFuncCode = Deno.readTextFileSync( "./src/pipelines/aws/funcs/overrides/AWS::EC2::Instance/attribute/base64EncodeUserData.ts", ); const overrideUserDataAttributeFuncArgs: FuncArgumentSpec[] = [ { name: "data", kind: "string", elementKind: null, uniqueId: ulid(), deleted: false, }, ]; const base64EncodedUserDataFunc = createFunc( "Set UserData prop and base64 encode if needed", "jsAttribute", "json", strippedBase64(overrideUserDataAttributeFuncCode), "5a5b8c9d6e7f8a5b0c1d2e3f4a5b6c7d8e9f0a1b2c3d8e5f6a7b8c9d0e1f2a3b", overrideUserDataAttributeFuncArgs, ); spec.funcs.push(base64EncodedUserDataFunc); const userDataProp = propForOverride(variant.domain, "UserData"); userDataProp.data.widgetKind = "CodeEditor"; // Create the Reboot Action const { func: rebootFunc, actionFuncSpec: rebootActionFuncSpec } = attachExtraActionFunction( "./src/pipelines/aws/funcs/overrides/AWS::EC2::Instance/actions/reboot.ts", "Reboot Ec2 Instance", "other", "5e38470604abb5c3ccc2ab60b31c5c0a05e9b381a2db73a15f4f8d55ec441bbd", ); spec.funcs.push(rebootFunc); variant.actionFuncs.push(rebootActionFuncSpec); // Create the Stop Action const { func: stopFunc, actionFuncSpec: stopActionFuncSpec } = attachExtraActionFunction( "./src/pipelines/aws/funcs/overrides/AWS::EC2::Instance/actions/stop.ts", "Stop Ec2 Instance", "other", "de2c03b1caff5e7a1011a8c0ac6dc6dc99af77d15d0bc1f93e7c4eb9d7307f22", ); spec.funcs.push(stopFunc); variant.actionFuncs.push(stopActionFuncSpec); // Create the Start Action const { func: startFunc, actionFuncSpec: startActionFuncSpec } = attachExtraActionFunction( "./src/pipelines/aws/funcs/overrides/AWS::EC2::Instance/actions/start.ts", "Start Ec2 Instance", "other", "f78a129cebfdb45c688df8622056e5ee2b81a41d8896c2ce7b24d0a709102d1f", ); spec.funcs.push(startFunc); variant.actionFuncs.push(startActionFuncSpec); if (domainId) { const { func, leafFuncSpec } = attachQualificationFunction( "./src/pipelines/aws/funcs/overrides/AWS::EC2::Instance/qualifications/isValidEc2InstanceType.ts", "Is Valid EC2 Instance Type", "e7aff7bc9553442c95e4446e86d239d0d8d25a31fff38fbcfe00cd18da8236f1", domainId, ); // This qualification needs to have secrets as part of the input leafFuncSpec.inputs.push("secrets"); spec.funcs.push(func); variant.leafFunctions.push(leafFuncSpec); } }, ], [ "AWS::Route53::RecordSet", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const { func: discoverFunc, mgmtFuncSpec: discoverFuncSpec } = attachExtraManagementFunction( "./src/pipelines/aws/funcs/overrides/AWS::Route53::RecordSet/management/discover.ts", "Discover on AWS", "2432de7a389b82f644353e9807b27fbb42769784b095a0f14abdad07c35bdb19", ); spec.funcs.push(discoverFunc); variant.managementFuncs.push(discoverFuncSpec); const { func: importFunc, mgmtFuncSpec: importFuncSpec } = attachExtraManagementFunction( "./src/pipelines/aws/funcs/overrides/AWS::Route53::RecordSet/management/import.ts", "Import from AWS", "9d01a77a07f2c30ed6a8af62b59455e9d720ae50b09e747c9f8c0e2b0306a4a4", ); spec.funcs.push(importFunc); variant.managementFuncs.push(importFuncSpec); const { func: createDeploymentFunc, actionFuncSpec: createActionFuncSpec, } = attachExtraActionFunction( "./src/pipelines/aws/funcs/overrides/AWS::Route53::RecordSet/actions/create.ts", "Create Route53 RecordSet", "create", "2ebacb3b5a978529f2d047f43e812187d11a06b692a933decc8d4c31d81e4424", ); spec.funcs.push(createDeploymentFunc); variant.actionFuncs.push(createActionFuncSpec); const { func: refreshDeploymentFunc, actionFuncSpec: refreshActionFuncSpec, } = attachExtraActionFunction( "./src/pipelines/aws/funcs/overrides/AWS::Route53::RecordSet/actions/refresh.ts", "Refresh Route53 RecordSet", "refresh", "a2c37fc391c835788c5138b94ac91d3b7b60f7882e6713ad5c69bb52e62b8594", ); spec.funcs.push(refreshDeploymentFunc); variant.actionFuncs.push(refreshActionFuncSpec); }, ], [ "AWS::CertificateManager::Certificate", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const { func: createDeploymentFunc, actionFuncSpec: createActionFuncSpec, } = attachExtraActionFunction( "./src/pipelines/aws/funcs/overrides/AWS::CertificateManager::Certificate/actions/create.ts", "Create ACM Certificate", "create", "af05d87120cfb700256c527d2bbf598b00db64b9afed4f1f95f74e317cb010b8", ); spec.funcs.push(createDeploymentFunc); variant.actionFuncs.push(createActionFuncSpec); const { func: refreshDeploymentFunc, actionFuncSpec: refreshActionFuncSpec, } = attachExtraActionFunction( "./src/pipelines/aws/funcs/overrides/AWS::CertificateManager::Certificate/actions/refresh.ts", "Refresh ACM Certificate", "refresh", "edc4c3ffcccf276adf6f9e44695c65a7b8a632c9e68bb0e3f2061274c1e442a3", ); spec.funcs.push(refreshDeploymentFunc); variant.actionFuncs.push(refreshActionFuncSpec); }, ], [ "AWS::ECS::Service", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const { func: forceNewDeploymentFunc, actionFuncSpec: forceNewDeploymentActionFuncSpec, } = attachExtraActionFunction( "./src/pipelines/aws/funcs/overrides/AWS::ECS::Service/actions/forceNewDeployment.ts", "Force New Deployment", "other", "c676a418fba5b9b4c69444165db7a3fbc7ef19f1f018d4d8c0b3a2ff935d64b5", ); spec.funcs.push(forceNewDeploymentFunc); variant.actionFuncs.push(forceNewDeploymentActionFuncSpec); }, ], [ "AWS::EC2::LaunchTemplate", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const ltData = objectPropForOverride( variant.domain, "LaunchTemplateData", ); const prop = propForOverride(ltData, "UserData"); prop.data.widgetKind = "CodeEditor"; const importTargetId = MANAGEMENT_FUNCS["Import from AWS"].id; const newImportId = "0583c411a5b41594706ae8af473ed6d881357a1e692fb53981417f625f99374b"; const importPath = "./src/pipelines/aws/funcs/overrides/AWS::EC2::LaunchTemplate/import.ts"; modifyFunc(spec, importTargetId, newImportId, importPath); const discoverTargetId = MANAGEMENT_FUNCS["Discover on AWS"].id; const newDiscoverId = "cfebba8fc2d7cd88e5fc2b0c47a777b3737b8c2bcb88fbbb143be48018f22836"; const discoverPath = "./src/pipelines/aws/funcs/overrides/AWS::EC2::LaunchTemplate/discover.ts"; modifyFunc(spec, discoverTargetId, newDiscoverId, discoverPath); }, ], [ "AWS::RDS::DBParameterGroup", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const prop = propForOverride(variant.domain, "Parameters"); prop.kind = "map"; if (prop.kind === "map") { prop.typeProp = createScalarProp( "parameter", "string", prop.metadata.propPath, false, ); } }, ], [ "AWS::SecretsManager::Secret", (spec: ExpandedPkgSpec) => { addSecretProp("Secret String", "secretString", ["SecretString"])(spec); }, ], [ "AWS::RDS::DBCluster", addSecretProp("Secret String", "secretString", ["MasterUserPassword"]), ], [ "AWS::RDS::DBInstance", (spec: ExpandedPkgSpec) => { addSecretProp("Secret String", "secretString", ["MasterUserPassword"])( spec, ); }, ], [ "AWS::EC2::SecurityGroupIngress", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const domainId = variant.domain.uniqueId; if (!domainId) return; const { func, leafFuncSpec } = attachQualificationFunction( "./src/pipelines/aws/funcs/overrides/AWS::EC2::SecurityGroupIngress/qualifications/checkForEitherGroupIdOrGroupName.ts", "GroupId OR GroupName", "23f026310223509f053b55bfa386772eecc2d00e3090dbeb65766ac63f8c53a2", domainId, ); spec.funcs.push(func); variant.leafFunctions.push(leafFuncSpec); }, ], [ "AWS::AutoScaling::AutoScalingGroup", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; // Modify the existing update function instead of replacing it const updateTargetId = ACTION_FUNC_SPECS["Update Asset"].id; const newUpdateId = "c7e6bf82e9d7fa438f6a9151a1b1f4c6f4b18ae50eacf462bc81d2b31278e1c5"; const updatePath = "./src/pipelines/aws/funcs/overrides/AWS::AutoScaling::AutoScalingGroup/actions/awsCloudControlUpdate.ts"; modifyFunc(spec, updateTargetId, newUpdateId, updatePath); const { func: refreshInstancesFunc, actionFuncSpec: refreshInstancesFuncSpec, } = attachExtraActionFunction( "./src/pipelines/aws/funcs/overrides/AWS::AutoScaling::AutoScalingGroup/actions/instanceRefresh.ts", "Refresh Autoscaling Group Instances", "other", "300d62f40cb1268e6f4cd2320be8c373da7f148d0d9e6e69d1b2879202794b5f", ); spec.funcs.push(refreshInstancesFunc); variant.actionFuncs.push(refreshInstancesFuncSpec); }, ], [ "AWS::ImageBuilder::Component", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const prop = propForOverride(variant.domain, "Data"); prop!.data.widgetKind = "CodeEditor"; }, ], [ "AWS::ECS::Cluster", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const configurationProp = objectPropForOverride( variant.domain, "Configuration", ); const managedStorageConfigurationProp = objectPropForOverride( configurationProp, "ManagedStorageConfiguration", ); const fargateKmsProp = propForOverride( managedStorageConfigurationProp, "FargateEphemeralStorageKmsKeyId", ); addPropSuggestSource(fargateKmsProp, { schema: "AWS:KMS:Key", prop: "/resource_value/KeyId", }); const kmsKeyIdProp = propForOverride( managedStorageConfigurationProp, "KmsKeyId", ); addPropSuggestSource(kmsKeyIdProp, { schema: "AWS:KMS:Key", prop: "/resource_value/KeyId", }); }, ], [ "AWS::ApiGatewayV2::Route", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const requestModelsProp = propForOverride( variant.domain, "RequestModels", ); requestModelsProp.kind = "json"; requestModelsProp!.data.widgetKind = "CodeEditor"; const requestParametersProp = propForOverride( variant.domain, "RequestParameters", ); requestParametersProp.kind = "json"; requestParametersProp!.data.widgetKind = "CodeEditor"; }, ], [ "AWS::ECS::TaskDefinition", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; // List of props to remove read-only const propsToRemove = [ "ContainerDefinitions", "Cpu", "EnableFaultInjection", "ExecutionRoleArn", "InferenceAccelerators", "Memory", "NetworkMode", "PlacementConstraints", "ProxyConfiguration", "RequiresCompatibilities", "RuntimePlatform", "TaskRoleArn", "Volumes", "PidMode", "IpcMode", "EphemeralStorage", ]; const containerDefsProp = arrayPropForOverride( variant.domain, "ContainerDefinitions", ); let itemProp = containerDefsProp.typeProp; itemProp = addPropSuggestSource(itemProp, { schema: "TaskDefinition ContainerDefinitions", prop: "/domain", }); const extraProp = objectPropForOverride(variant.domain, "extra"); const propUsageMapProp = propForOverride(extraProp, "PropUsageMap"); if (!propUsageMapProp.data?.defaultValue) { throw new Error("Prop has no default value"); } const defaultValue = JSON.parse( propUsageMapProp.data.defaultValue as string, ); let createOnly = defaultValue["createOnly"]; const updatable = defaultValue["updatable"]; propsToRemove.forEach((propName) => { const prop = propForOverride(variant.domain, propName); const currentWidgetOptions = prop.data.widgetOptions; prop.data.widgetOptions = currentWidgetOptions?.filter( (w) => w.label !== "si_create_only_prop", ) ?? null; createOnly = createOnly?.filter((p: string) => p !== propName); updatable.push(propName); }); defaultValue["createOnly"] = createOnly; defaultValue["updatable"] = updatable; propUsageMapProp!.data.defaultValue = JSON.stringify(defaultValue); const updateTargetId = ACTION_FUNC_SPECS["Update Asset"].id; const newUpdateId = "7eb4e58626f9fd7ee003bb9a1de814ab31cbb8ea2ae87d844864058bc4296c63"; const newUpdatePath = "./src/pipelines/aws/funcs/overrides/AWS::ECS::TaskDefinition/actions/update.ts"; modifyFunc(spec, updateTargetId, newUpdateId, newUpdatePath); }, ], [ "AWS::EKS::Nodegroup", (_spec: ExpandedPkgSpec) => { // Placeholder - no current overrides for this schema }, ], [ "AWS::EC2::VPNConnection", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const resource_value = variant.resourceValue; const typeProp = stringPropForOverride(variant.domain, "Type"); typeProp.data.widgetKind = "ComboBox"; typeProp.data.defaultValue = "ipsec.1"; typeProp.data.inputs = []; typeProp.data.funcUniqueId = null; typeProp.data.widgetOptions = [ { label: "si_create_only_prop", value: "true" }, ]; const transitGatewayAttachmentIdProp = createScalarProp( "TransitGatewayAttachmentId", "string", ["root", "resource_value"], false, ); transitGatewayAttachmentIdProp.data.widgetKind = "Text"; resource_value.entries.push(transitGatewayAttachmentIdProp); const refreshTargetId = ACTION_FUNC_SPECS["Refresh Asset"].id; const newRefreshId = "fd3706e543528a703c674f42c07d3f2443b2e3c40bfc88a81a7f4501af5e7122"; const refreshPath = "./src/pipelines/aws/funcs/overrides/AWS::EC2::VPNConnection/actions/refresh.ts"; modifyFunc(spec, refreshTargetId, newRefreshId, refreshPath); }, ], [ "AWS::EC2::CustomerGateway", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const typeProp = stringPropForOverride(variant.domain, "Type"); typeProp.data.widgetKind = "ComboBox"; typeProp.data.defaultValue = "ipsec.1"; typeProp.data.inputs = []; typeProp.data.funcUniqueId = null; typeProp.data.widgetOptions = [ { label: "si_create_only_prop", value: "true" }, ]; }, ], [ "AWS::S3::Bucket", (spec: ExpandedPkgSpec) => { const variant = spec.schemas[0].variants[0]; const domain = variant.domain; const bucketNameProp = stringPropForOverride(domain, "BucketName"); bucketNameProp.data.widgetKind = "Text"; bucketNameProp.data.inputs = []; bucketNameProp.data.funcUniqueId = null; bucketNameProp.data.widgetOptions = [ { label: "si_create_only_prop", value: "true" }, ]; }, ], ]);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server