Terraform provider for emitting Snowplow events.
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
.
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
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!
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!
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.
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")}"
This is handled through CI/CD on Github Actions. However all binaries will be generated by using the make
command for local publishing.
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.