Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add CLI for simple template transformation #121

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
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
5 changes: 4 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ on:

jobs:
build:
runs-on: ubuntu-latest
# runs-on: ubuntu-latest
runs-on:
- codebuild-ft-gha-cb-dev2-${{ github.run_id }}-${{ github.run_attempt }}
- instance-size:large

strategy:
matrix:
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/manual-lambda.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Manual Lambda

on: workflow_dispatch

jobs:
build:
runs-on:
- codebuild-ft-gha-cb-dev2-lambda-${{ github.run_id }}-${{ github.run_attempt }}

steps:
- name: sleep
run: sleep 60
12 changes: 12 additions & 0 deletions .github/workflows/manual.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Manual Standard

on: workflow_dispatch

jobs:
build:
runs-on:
- codebuild-ft-gha-cb-dev2-${{ github.run_id }}-${{ github.run_attempt }}

steps:
- name: sleep
run: sleep 60
7 changes: 4 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
run: npm whoami
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- uses: actions/setup-python@v3
- uses: actions/setup-python@v5
with:
python-version: "3.8"
- uses: aws-actions/setup-sam@v2
Expand All @@ -44,7 +44,7 @@ jobs:
- name: NPM security audit
run: npm run audit
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v1
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.SAR_DEPLOYMENT_IAM_ROLE }}
role-session-name: github-action-sar-deploy-session
Expand All @@ -53,10 +53,11 @@ jobs:
run: |
cp README.md serverless-plugin
[[ "${{ github.event.release.prerelease }}" = true ]] && export NPM_PUBLISH_ARGS="--tag next" || export NPM_PUBLISH_ARGS=""
npm publish ${NPM_PUBLISH_ARGS} --workspace slic-watch-core --workspace serverless-slic-watch-plugin
npm publish ${NPM_PUBLISH_ARGS} --workspace slic-watch-core --workspace serverless-slic-watch-plugin --include-workspace-root
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: SAR publish
if: ${{ github.event.release.prerelease == false }}
run: |
sam build --base-dir . --template-file cf-macro/template.yaml
sam package --output-template-file packaged.yaml --s3-bucket ${SAR_BUCKET_NAME}
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Validate

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
build:
# runs-on: ubuntu-latest
runs-on:
- codebuild-ft-gha-cb-dev2-lambda-${{ github.run_id }}-${{ github.run_attempt }}

strategy:
matrix:
node-version: [18, 20]

steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}.x
cache: 'npm'
- run: npm ci
- run: npm test
name: Run unit tests
- name: Build TypeScript
run: npm run build
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ core/dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
Expand Down Expand Up @@ -260,5 +259,5 @@ lerna-debug*

samconfig.toml
packaged.yaml
.tgz
*.tgz
*.tar.gz
13 changes: 13 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
*.ipynb
*-test-project/
*-test-project-*/
.tap/
cdk.out/
docs/
*.ts
tests/
coverage/
.cache/
.idea/
.github/
*.tgz
155 changes: 93 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,74 +13,48 @@ SLIC Watch supports: _AWS Lambda, API Gateway, DynamoDB, Kinesis Data Streams, S
Supported tools include:
* ⚡️ **Serverless Framework** v3 via the [_SLIC Watch Serverless Plugin_](#getting-started-with-serverless-framework)
* 🐿 **AWS SAM**, 📦 **AWS CDK** and ☁️ **CloudFormation** using the [_CloudFormation Macro_](#getting-started-with-aws-sam-cdk-or-cloudformation), published in the Serverless Application Repository (SAR).
* 💻 **SLIC Watch CLI** You can run SLIC Watch to transform CloudFormation templates directly using [the CLI](#getting-started-with-the-cli).

## Contents
- [slic-watch](#slic-watch)
- [Contents](#contents)
- [Getting Started with Serverless Framework](#getting-started-with-serverless-framework)
- [Getting Started with AWS SAM, CDK or CloudFormation](#getting-started-with-aws-sam-cdk-or-cloudformation)
- [Deploying the SLIC Watch Macro](#deploying-the-slic-watch-macro)
- [Adding the SLIC Watch Transform to SAM or CloudFormation templates](#adding-the-slic-watch-transform-to-sam-or-cloudformation-templates)
- [Adding the SLIC Watch Transform to CDK Apps](#adding-the-slic-watch-transform-to-cdk-apps)
- [Features](#features)
- [Lambda Functions](#lambda-functions)
- [API Gateway](#api-gateway)
- [DynamoDB](#dynamodb)
- [Kinesis Data Streams](#kinesis-data-streams)
- [SQS Queues](#sqs-queues)
- [Step Functions](#step-functions)
- [ECS / Fargate](#ecs--fargate)
- [SNS](#sns)
- [EventBridge](#eventbridge)
- [Application Load Balancer](#application-load-balancer)
- [AppSync](#appsync)
- [Configuration](#configuration)
- [Top-level configuration](#top-level-configuration)
- [Resource-level configuration](#resource-level-configuration)
- [Serverless Framework function-level configuration](#serverless-framework-function-level-configuration)
- [SAM/CloudFormation function-level configuration](#samcloudformation-function-level-configuration)
- [CDK function-level configuration](#cdk-function-level-configuration)
- [A note on CloudWatch cost](#a-note-on-cloudwatch-cost)
- [References](#references)
- [Other Projects](#other-projects)
- [Reading](#reading)
- [LICENSE](#license)
## Getting Started with Serverless Framework

_If you are using AWS SAM or CloudFormation, skip to the section below._

1. 📦 Install the plugin:
```bash
npm install serverless-slic-watch-plugin --save-dev
```
2. 🖋️ Add the plugin to the `plugins` section of `serverless.yml`:
```yaml
plugins:
- serverless-slic-watch-plugin
```
3. 🪛 _Optionally_, add some configuration for the plugin to the `custom -> slicWatch` section of `serverless.yml`.
Here, you can specify a reference to the SNS topic for alarms. This is optional, but it's usually something you want
so you can receive alarm notifications via email, Slack, etc.

```yaml
custom:
slicWatch:
alarmActionsConfig: {
alarmActions: [{'Fn::Ref': myTopic}]
}
```
See the [Configuration](#configuration) section below for more detailed instructions on fine tuning SLIC Watch to your needs.


4. 🚢 Deploy your application in the usual way, for example:
```
sls deploy
```
5. 👀 Head to the CloudWatch section of the AWS Console to check out your new dashboards 📊 and alarms ⏰ !

<!-- toc -->

- [Getting Started with AWS SAM, CDK or CloudFormation](#getting-started-with-aws-sam-cdk-or-cloudformation)
* [Deploying the SLIC Watch Macro](#deploying-the-slic-watch-macro)
* [Adding the SLIC Watch Transform to SAM or CloudFormation templates](#adding-the-slic-watch-transform-to-sam-or-cloudformation-templates)
* [Adding the SLIC Watch Transform to CDK Apps](#adding-the-slic-watch-transform-to-cdk-apps)
- [Getting Started with Serverless Framework](#getting-started-with-serverless-framework)
- [Getting Started with the CLI](#getting-started-with-the-cli)
- [Features](#features)
* [Lambda Functions](#lambda-functions)
* [API Gateway](#api-gateway)
* [DynamoDB](#dynamodb)
* [Kinesis Data Streams](#kinesis-data-streams)
* [SQS Queues](#sqs-queues)
* [Step Functions](#step-functions)
* [ECS / Fargate](#ecs--fargate)
* [SNS](#sns)
* [EventBridge](#eventbridge)
* [Application Load Balancer](#application-load-balancer)
* [AppSync](#appsync)
- [Configuration](#configuration)
* [Top-level configuration](#top-level-configuration)
* [Resource-level configuration](#resource-level-configuration)
+ [Serverless Framework function-level configuration](#serverless-framework-function-level-configuration)
+ [SAM/CloudFormation function-level configuration](#samcloudformation-function-level-configuration)
+ [CDK function-level configuration](#cdk-function-level-configuration)
- [A note on CloudWatch cost](#a-note-on-cloudwatch-cost)
- [References](#references)
* [Other Projects](#other-projects)
* [Reading](#reading)
- [LICENSE](#license)

<!-- tocstop -->

## Getting Started with AWS SAM, CDK or CloudFormation

_If you are using The Serverless Framework, skip to the section below._

ℹ️ **IMPORTANT**: If you are using AWS SAM, CDK, or just plain CloudFormation, the most important thing to know is that your AWS account/region should have the **SLIC Watch Macro** deployed before you do anything. Once that's done, it is very simple to add this macro as a transform to your SAM or CloudFormation template.

### Deploying the SLIC Watch Macro
Expand Down Expand Up @@ -179,6 +153,63 @@ this.templateOptions.metadata = {
}
```

## Getting Started with Serverless Framework

1. 📦 Install the plugin:
```bash
npm install serverless-slic-watch-plugin --save-dev
```
2. 🖋️ Add the plugin to the `plugins` section of `serverless.yml`:
```yaml
plugins:
- serverless-slic-watch-plugin
```
3. 🪛 _Optionally_, add some configuration for the plugin to the `custom -> slicWatch` section of `serverless.yml`.
Here, you can specify a reference to the SNS topic for alarms. This is optional, but it's usually something you want
so you can receive alarm notifications via email, Slack, etc.

```yaml
custom:
slicWatch:
alarmActionsConfig: {
alarmActions: [{'Fn::Ref': myTopic}]
}
```
See the [Configuration](#configuration) section below for more detailed instructions on fine tuning SLIC Watch to your needs.


4. 🚢 Deploy your application in the usual way, for example:
```
sls deploy
```
5. 👀 Head to the CloudWatch section of the AWS Console to check out your new dashboards 📊 and alarms ⏰ !

## Getting Started with the CLI

SLIC Watch can be run as a standalone CLI, allowing you to transform a CloudFormation template YAML or JSON, creating a new template with alarms and dashboards added. The CLI is useful for:

- Exploring and troubleshooting SLIC Watch in development
- In CI/CD environments where you deploy CloudFormation templates and do not wish to use the Macro as a `Transform`.

SLIC Watch configuration is done using `Metadata` in the input template. See [this section](#adding-the-slic-watch-transform-to-sam-or-cloudformation-templates) to see how.

```sh
npm install slic-watch --global
```

The CLI can generate YAML or JSON based on the extension of the output file you provide:

```sh
slic-watch cf-template.json transformed-template.json
```

_or_

```sh
slic-watch cf-template.yml transformed-template.yml
```


## Features

CloudWatch Alarms and Dashboard widgets are created for all supported resources in the CloudFormation stack generated by The Serverless Framework. This includes generated resources as well as resources specified explicitly in the `resources` section.
Expand Down
2 changes: 1 addition & 1 deletion RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ In order to release a new version of the project:

1. Update the package version with `npm version <version>` to apply that version across all sub packages. If the Major version has changed, the Macro name will be automatically updated by [the sync-macro-version script](scripts/sync-macro-version.cjs)
2. Push these changes (`git push --tags`)
3. Draft a new release in GitHub (the CI will do the publish to npm) with the same name as the version tag. If you select "pre-release", this will be published in NPM as a `next` label so it will only be installed by users who explictly request the `@next` version.
3. Draft a new release in GitHub (the CI will do the publish to npm) with the same name as the version tag. If you select "pre-release", this will be published in NPM as a `next` label so it will only be installed by users who explicitly request the `@next` version.
2 changes: 1 addition & 1 deletion cdk-test-project/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cdk-test-project",
"version": "3.2.1",
"version": "3.3.1-rc4",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
Expand Down
2 changes: 1 addition & 1 deletion cf-macro/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface MacroResponse {

/**
* CloudFormation Macro implementation. Accepts the CloudFormation fragment to be transformed
* and generates the transformed teamplte with alarms and dashboard
* and generates the transformed template with alarms and dashboard
*/
export async function handler (event: Event): Promise<MacroResponse> {
let status = 'success'
Expand Down
2 changes: 1 addition & 1 deletion cf-macro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/fourTheorem/slic-watch.git",
"directory": "cf-macro"
},
"version": "3.2.1",
"version": "3.3.1-rc4",
"private": true,
"scripts": {
"test": "tap --coverage-report=html --no-browser --no-check-coverage tests/**/*.test.ts",
Expand Down
2 changes: 1 addition & 1 deletion cf-macro/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Metadata:
ReadmeUrl: ../README.md
Labels: ["monitoring", "observability", "cloudwatch"]
HomePageUrl: https://github.com/fourTheorem/slic-watch
SemanticVersion: 3.2.1
SemanticVersion: 3.3.1-rc4
SourceCodeUrl: https://github.com/fourTheorem/slic-watch
Resources:
SlicWatch:
Expand Down
42 changes: 42 additions & 0 deletions cli/commands/transform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { readFile, writeFile } from 'node:fs/promises'
import { parse, stringify } from 'yaml'
import { addAlarms, addDashboard } from 'slic-watch-core/index'
import { type SlicWatchConfig, resolveSlicWatchConfig } from 'slic-watch-core/inputs/general-config'
import { setLogger } from 'slic-watch-core/logging'
import { cliLogger } from '../lib/cli-logger'

setLogger(cliLogger)

export default async function transform (inputFile: string, outputFile: string) {
const outputToJson = outputFile.endsWith('.json')
try {
const input = await readFile(inputFile)
const template = parse(input.toString())
const slicWatchConfig: SlicWatchConfig = template.Metadata?.slicWatch ?? {}

const config = resolveSlicWatchConfig(slicWatchConfig)
if (typeof config.enabled === 'undefined') {
// SLIC Watch is enabled by default for the CLI
config.enabled = true
}

setLogger(cliLogger)
addAlarms(config.alarms, config.alarmActionsConfig, template)
addDashboard(config.dashboard, template)

// If the input template had a `SlicWatch` transform, remove it
// since it has now been applied so CloudFormation will not try and apply
// it again on deployment.
const transform = template.Transform as string | undefined
if (typeof transform === 'string' && transform.startsWith('SlicWatch')) {
delete template.Transform
} else if (Array.isArray(transform)) {
template.Transform = (template.Transform as string[]).filter(transform => !transform.startsWith('SlicWatch'))
}
const output = outputToJson ? JSON.stringify(template, null, ' ') : stringify(template, { aliasDuplicateObjects: false })
await writeFile(outputFile, output)
} catch (err) {
cliLogger.error(err)
process.exit(1)
}
}
Loading
Loading