Skip to content

snowplow-devops/terraform-provider-snowplow

Repository files navigation

Snowplow Terraform Provider

Actions Status Go Report Card Release License

Overview

Terraform provider for emitting Snowplow events.

Quick start

Assuming git is installed:

 host> git clone https://github.com/snowplow-devops/terraform-provider-snowplow
 host> cd terraform-provider-snowplow
 host> make test
 host> make

To remove all build files:

 host> make clean

To format the golang code in the source directory:

 host> make format

Note: Always run format before submitting any code.

Note: The make test command also generates a code coverage file which can be found at build/coverage/coverage.html.

Installation

First download the pre-compiled binary for your platform from the release assets at the following links or generate the binaries locally using the provided make command:

https://github.com/snowplow-devops/terraform-provider-snowplow/releases/latest

From here you will need to move the binary into your Terraform plugins directory - depending on your platform / installation this might change but generally speaking they are located at:

  • Darwin & Linux: ~/.terraform.d/plugins
  • Windows: %APPDATA%\terraform.d\plugins

How to use?

Setting up the provider

To actually start tracking Snowplow events from Terraform you will need to configure the provider and a resource:

# Minimal configuration
provider "snowplow" {
  collector_uri = "com.acme.collector"
}

# Optional extra configuration options
provider "snowplow" {
  collector_uri        = "com.acme.collector"
  tracker_app_id       = "terraform" # Default; ""
  tracker_namespace    = "terraform" # Default; ""
  tracker_platform     = "mob" # Default; srv (server)
  emitter_request_type = "GET" # Default; POST
  emitter_protocol     = "HTTP" # Default; HTTPS
}

Now that the provider is configured we can track an event!

Tracking events

Currently only one tracking resource has been exposed in the form of a SelfDescribing Event - the other pre-built options do not really make sense in a Terraform world!

How to track: self_describing_event

locals {
  tf_module_context = {
    name    = "aws_module"
    version = "1.1.2"
  }
}

resource "snowplow_track_self_describing_event" "module_action" {
  create_event = {
    iglu_uri = "iglu:com.acme/lifecycle/jsonschema/1-0-0",
    payload  = "{\"actionType\":\"create\"}"
  }

  update_event = {
    iglu_uri = "iglu:com.acme/lifecycle/jsonschema/1-0-0",
    payload  = "{\"actionType\":\"update\"}"
  }

  delete_event = {
    iglu_uri = "iglu:com.acme/lifecycle/jsonschema/1-0-0",
    payload  = "{\"actionType\":\"delete\"}"
  }

  contexts = [
    {
      iglu_uri = "iglu:com.acme/module_context/jsonschema/1-0-0",
      payload  = "${jsonencode(local.tf_module_context)}",
    },
  ]
}

To get around nested dictionary limitations in Terraform 0.11.x we are using stringified JSON as inputs for the payloads. In the example above we are leveraging the jsonencode builtin function to handle converting a Terraform dictionary into a JSON but you can also hand-craft encoded JSON strings if you prefer.

The above function lets you define a single event which is coupled with as many contexts as you would like to attach - when you run terraform apply it will send an event to your defined collector and on a 200 OK response code from the collector log this as a successful resource creation.

Its important to define a base event for each part of the resource lifecycle so that you can differentiate your events later and to be able to reason about where in the lifecycle a resource might be.

How to stop Terraform turning primitives into strings

We are using a lot of stringified JSON as input above - the jsonencode function unfortunately turns a lot of our primitives ("floats", "ints" and "booleans") into strings through this conversion. One way to get around this is to use regex to "fix" the payload after conversion:

# Convert int, floats
payload_1 = "${replace(jsonencode(var.payload), "/\"([0-9]+\\.?[0-9]*)\"/", "$1")}"

# Convert "true" > true
payload_2 = "${replace(local.payload_1, "/\"(true)\"/", "$1")}"

# Convert "false" > false
payload_3 = "${replace(local.payload_2, "/\"(false)\"/", "$1")}"

Publishing

This is handled through CI/CD on Github Actions. However all binaries will be generated by using the make command for local publishing.

Copyright and license

Snowplow Terraform Provider is copyright 2019-2023 Snowplow Analytics Ltd.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this software except in compliance with the License.

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.