Skip to content

Commit

Permalink
WIP: building a terraform module for hooking up CloudWatch Metrics to…
Browse files Browse the repository at this point in the history
… honeycomb

Things we need:
1. hashicorp/terraform-provider-aws#18870 to be merged (ismith is subscribed to this PR)
2. To test the module - sandbox account should be fine, we don't need anything complex here that'd require putting it in dogfood or terraform cloud
  - This includes testing the include_filters/exclude_filters variables
3. Documentarion in README.md
4. Documentation strings in variables.tf
5. version.tf needs a version for hashicorp/aws, and we should consider loosening the terraform.required_version constraint
6. Decide/document a release process (tl;dr: semver tags in github)

**Asana:**
https://app.asana.com/0/1199917178609623/1200319907426032
  • Loading branch information
ismith committed May 13, 2021
1 parent 26d4c8d commit 0972e86
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 5 deletions.
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
# Default Community Health Files

This repository contains default community health files for repositories in the Honeycomb organization and will automatically be picked up if they are not overwritten.

More details on this repository structure can be found here: https://docs.github.com/en/github/building-a-strong-community/creating-a-default-community-health-file
148 changes: 148 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Following roles taken from https://github.com/hashicorp/terraform-provider-aws/pull/18870/files?file-filters%5B%5D=.markdown
resource "aws_iam_role" "firehose_to_s3" {
name_prefix = var.name
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "firehose.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

resource "aws_iam_role_policy" "firehose_to_s3" {
name_prefix = var.name
role = aws_iam_role.firehose_to_s3.id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket",
"s3:ListBucketMultipartUploads",
"s3:PutObject"
],
"Resource": [
"${aws_s3_bucket.metric_stream.arn}",
"${aws_s3_bucket.metric_stream.arn}/*"
]
}
]
}
EOF
}

# https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-metric-streams-trustpolicy.html
resource "aws_iam_role" "metric_stream_to_firehose" {
name_prefix = var.name
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "streams.metrics.cloudwatch.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
# https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-metric-streams-trustpolicy.html
resource "aws_iam_role_policy" "metric_stream_to_firehose" {
name_prefix = var.name
role = aws_iam_role.metric_stream_to_firehose.id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"firehose:PutRecord",
"firehose:PutRecordBatch"
],
"Resource": "${aws_kinesis_firehose_delivery_stream.metrics.arn}"
}
]
}
EOF
}

resource "aws_s3_bucket" "metric_stream" {
bucket = var.name
acl = "private"

tags = var.tags
}

resource "aws_kinesis_firehose_delivery_stream" "metrics" {
name = var.name
destination = "http_endpoint"

s3_configuration {
role_arn = aws_iam_role.firehose_to_s3.arn
bucket_arn = aws_s3_bucket.metric_stream.arn

buffer_size = var.s3_buffer_size
buffer_interval = var.s3_buffer_interval
compression_format = var.s3_compression_format
}

http_endpoint_configuration {
url = "${var.honeycomb_api_base_url}/${var.honeycomb_dataset_name}"
name = "Honeycomb-${var.honeycomb_dataset_name}"

access_key = var.honeycomb_api_key
buffering_size = var.http_buffering_size
buffering_interval = var.http_buffering_interval
role_arn = aws_iam_role.firehose_to_s3.arn
s3_backup_mode = var.s3_backup_mode

request_configuration {
content_encoding = var.http_content_encoding
}
}
}

# The aws_cloudwatch_metric_stream resource is not yet available in the
# hashicorp/aws provider, though it has a PR open: https://github.com/hashicorp/terraform-provider-aws/pull/18870
#
# However, in the interest of unblocking #proj-metrics, we can create this
# resource from the aws cli:
# ```
# aws cloudwatch put-metric-stream \
# --name dogfood-metric-stream \
# --firehose-arn $firehose_arn \
# --role-arn $role_arn \
# --output-format opentelemetry0.7
# ```
# ($firehose_arn and $role_arn being resources created in terraform.)

resource "aws_cloudwatch_metric_stream" "metric-stream" {
name = var.name
role_arn = aws_iam_role.firehose.arn
firehose_arn = aws_kinesis_firehose_delivery_stream.metrics.arn
output_format = var.output_format

include_filter = var.namespace_include_filter
exclude_filter = var.namespace_exclude_filter

tags = var.tags
}
11 changes: 11 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
output "s3_bucket" {
value = aws_s3_bucket.metric_stream.bucket
}

output cloudwatch_metric_stream_arn {
value = aws_cloudwatch_metric_stream.metric-stream.arn
}

output cloudwatch_metric_stream_name {
value = aws_cloudwatch_metric_stream.metric-stream.name
}
87 changes: 87 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Required variables
variable "name" {
type = string
# required, no default
}

var "honeycomb_dataset_name" {
type = string
}

var "honeycomb_api_key" {
type = string
sensitive = true
}


# Optional variables for customer configuration
var "tags" {
type = map(string)
default = {}
}

var "namespace_include_filter" {
type = list(string)
# TODO: does default null satisfy type list(string), or do we need to go with
# type any? (sigh)
#
# Also, if this is list(string), we need to map it to: s -> { namespace = s };
# or we could use list(object{namespace=string})
#
# This variable needs testing. (And should be consistent with the
# namespace_exclude_filter below.)
default = null
}

var "namespace_exclude_filter" {
type = list(string)
default = null
}

var "s3_buffer_size" {
type = number
default = 10
}

var "s3_buffer_interval" {
type = number
default = 400
}

var "s3_compression_format" {
type = string
default = "GZIP"
}

var "http_buffering_size" {
type = number
default = 15
}

var "http_buffering_interval" {
type = number
default = 600
}

var "http_content_encoding" {
type = string
default = "GZIP"
}

var "s3_backup_mode" {
type = string
default = "FailedDataOnly"
}


# Optional variables you are unlikely to modify
var "honeycomb_api_base_url" {
type = string
default = "https://api.honeycomb.io/1/kinesis_events"
}

var "output_format" {
type = string
default = "opentelemetry0.7"
}

9 changes: 9 additions & 0 deletions versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
terraform {
# TODO: not sure we need >= 0.13! But it's what we can test against.
required_version = ">= 0.13"
required_providers {
aws = {
source = "hashicorp/aws"
version = "TODO" # TODO: pending https://github.com/hashicorp/terraform-provider-aws/pull/18870
}
}

0 comments on commit 0972e86

Please sign in to comment.