Deploying Weather Dashboard Project using Nodered, Influx as well as Grafana via Terraform

Project Infrastructure

What is Terraform and why we use it?

Node-red workflow
File structure

Creating a non-root user

Login as a Root user
Create a user under IAM service
Choose programmatic access
Choose programmatic access
Create user without tags
Keep credentials (Access key ID and Secret access key)
Cloud9
Name environment
Configure settings
Create environment
Cloud9 interface
$ terraform workspace new prod
Created and switched to workspace "prod"!
You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.
$ terraform planAn execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:# module.container["grafana"].docker_container.app_container[0] will be created
+ resource "docker_container" "app_container" {
+ attach = false
+ bridge = (known after apply)
+ command = (known after apply)
+ container_logs = (known after apply)
+ entrypoint = (known after apply)
+ env = (known after apply)
+ exit_code = (known after apply)
+ gateway = (known after apply)
+ hostname = (known after apply)
+ id = (known after apply)
+ image = (known after apply)
+ init = (known after apply)
+ ip_address = (known after apply)
+ ip_prefix_length = (known after apply)
+ ipc_mode = (known after apply)
+ log_driver = "json-file"
+ logs = false
+ must_run = true
+ name = (known after apply)
+ network_data = (known after apply)
+ read_only = false
+ remove_volumes = true
+ restart = "no"
+ rm = false
+ security_opts = (known after apply)
+ shm_size = (known after apply)
+ start = true
+ stdin_open = false
+ tty = false
+ healthcheck {
+ interval = (known after apply)
+ retries = (known after apply)
+ start_period = (known after apply)
+ test = (known after apply)
+ timeout = (known after apply)
}
+ labels {
+ label = (known after apply)
+ value = (known after apply)
}
+ ports {
+ external = 3000
+ internal = 3000
+ ip = "0.0.0.0"
+ protocol = "tcp"
}
+ volumes {
+ container_path = "/etc/grafana"
+ volume_name = (known after apply)
}
+ volumes {
+ container_path = "/var/lib/grafana"
+ volume_name = (known after apply)
}
}
# module.container["grafana"].random_string.random[0] will be created
+ resource "random_string" "random" {
+ id = (known after apply)
+ length = 4
+ lower = true
+ min_lower = 0
+ min_numeric = 0
+ min_special = 0
+ min_upper = 0
+ number = true
+ result = (known after apply)
+ special = false
+ upper = false
}
# module.container["influxdb"].docker_container.app_container[0] will be created
+ resource "docker_container" "app_container" {
+ attach = false
+ bridge = (known after apply)
+ command = (known after apply)
+ container_logs = (known after apply)
+ entrypoint = (known after apply)
+ env = (known after apply)
+ exit_code = (known after apply)
+ gateway = (known after apply)
+ hostname = (known after apply)
+ id = (known after apply)
+ image = (known after apply)
+ init = (known after apply)
+ ip_address = (known after apply)
+ ip_prefix_length = (known after apply)
+ ipc_mode = (known after apply)
+ log_driver = "json-file"
+ logs = false
+ must_run = true
+ name = (known after apply)
+ network_data = (known after apply)
+ read_only = false
+ remove_volumes = true
+ restart = "no"
+ rm = false
+ security_opts = (known after apply)
+ shm_size = (known after apply)
+ start = true
+ stdin_open = false
+ tty = false
+ healthcheck {
+ interval = (known after apply)
+ retries = (known after apply)
+ start_period = (known after apply)
+ test = (known after apply)
+ timeout = (known after apply)
}
+ labels {
+ label = (known after apply)
+ value = (known after apply)
}
+ ports {
+ external = 8086
+ internal = 8086
+ ip = "0.0.0.0"
+ protocol = "tcp"
}
+ volumes {
+ container_path = "/var/lib/influxdb"
+ volume_name = (known after apply)
}
}
# module.container["influxdb"].random_string.random[0] will be created
+ resource "random_string" "random" {
+ id = (known after apply)
+ length = 4
+ lower = true
+ min_lower = 0
+ min_numeric = 0
+ min_special = 0
+ min_upper = 0
+ number = true
+ result = (known after apply)
+ special = false
+ upper = false
}
# module.container["nodered"].docker_container.app_container[0] will be created
+ resource "docker_container" "app_container" {
+ attach = false
+ bridge = (known after apply)
+ command = (known after apply)
+ container_logs = (known after apply)
+ entrypoint = (known after apply)
+ env = (known after apply)
+ exit_code = (known after apply)
+ gateway = (known after apply)
+ hostname = (known after apply)
+ id = (known after apply)
+ image = (known after apply)
+ init = (known after apply)
+ ip_address = (known after apply)
+ ip_prefix_length = (known after apply)
+ ipc_mode = (known after apply)
+ log_driver = "json-file"
+ logs = false
+ must_run = true
+ name = (known after apply)
+ network_data = (known after apply)
+ read_only = false
+ remove_volumes = true
+ restart = "no"
+ rm = false
+ security_opts = (known after apply)
+ shm_size = (known after apply)
+ start = true
+ stdin_open = false
+ tty = false
+ healthcheck {
+ interval = (known after apply)
+ retries = (known after apply)
+ start_period = (known after apply)
+ test = (known after apply)
+ timeout = (known after apply)
}
+ labels {
+ label = (known after apply)
+ value = (known after apply)
}
+ ports {
+ external = 1880
+ internal = 1880
+ ip = "0.0.0.0"
+ protocol = "tcp"
}
+ volumes {
+ container_path = "/data"
+ volume_name = (known after apply)
}
}
# module.container["nodered"].random_string.random[0] will be created
+ resource "random_string" "random" {
+ id = (known after apply)
+ length = 4
+ lower = true
+ min_lower = 0
+ min_numeric = 0
+ min_special = 0
+ min_upper = 0
+ number = true
+ result = (known after apply)
+ special = false
+ upper = false
}
# module.image["grafana"].docker_image.container_image will be created
+ resource "docker_image" "container_image" {
+ id = (known after apply)
+ latest = (known after apply)
+ name = "grafana/grafana"
+ output = (known after apply)
}
# module.image["influxdb"].docker_image.container_image will be created
+ resource "docker_image" "container_image" {
+ id = (known after apply)
+ latest = (known after apply)
+ name = "quay.io/influxdb/influxdb:v2.0.2"
+ output = (known after apply)
}
# module.image["nodered"].docker_image.container_image will be created
+ resource "docker_image" "container_image" {
+ id = (known after apply)
+ latest = (known after apply)
+ name = "nodered/node-red:latest-minimal"
+ output = (known after apply)
}
# module.container["grafana"].module.volume[0].docker_volume.container_volume[0] will be created
+ resource "docker_volume" "container_volume" {
+ driver = (known after apply)
+ id = (known after apply)
+ mountpoint = (known after apply)
+ name = (known after apply)
}
# module.container["grafana"].module.volume[0].docker_volume.container_volume[1] will be created
+ resource "docker_volume" "container_volume" {
+ driver = (known after apply)
+ id = (known after apply)
+ mountpoint = (known after apply)
+ name = (known after apply)
}
# module.container["influxdb"].module.volume[0].docker_volume.container_volume[0] will be created
+ resource "docker_volume" "container_volume" {
+ driver = (known after apply)
+ id = (known after apply)
+ mountpoint = (known after apply)
+ name = (known after apply)
}
# module.container["nodered"].module.volume[0].docker_volume.container_volume[0] will be created
+ resource "docker_volume" "container_volume" {
+ driver = (known after apply)
+ id = (known after apply)
+ mountpoint = (known after apply)
+ name = (known after apply)
}
Plan: 13 to add, 0 to change, 0 to destroy.Changes to Outputs:
+ application_access = [
+ {
+ grafana = {
+ application_access = (known after apply)
}
+ influxdb = {
+ application_access = (known after apply)
}
+ nodered = {
+ application_access = (known after apply)
}
},
]
------------------------------------------------------------------------Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
$ terraform apply --auto-approve
module.container["grafana"].random_string.random[0]: Creating...
module.container["influxdb"].random_string.random[0]: Creating...
module.container["nodered"].random_string.random[0]: Creating...
module.container["grafana"].random_string.random[0]: Creation complete after 0s [id=dk9q]
module.container["nodered"].random_string.random[0]: Creation complete after 0s [id=yyfv]
module.container["influxdb"].random_string.random[0]: Creation complete after 0s [id=nvbv]
module.container["influxdb"].module.volume[0].docker_volume.container_volume[0]: Creating...
module.image["grafana"].docker_image.container_image: Creating...
module.image["nodered"].docker_image.container_image: Creating...
module.image["influxdb"].docker_image.container_image: Creating...
module.container["grafana"].module.volume[0].docker_volume.container_volume[0]: Creating...
module.container["nodered"].module.volume[0].docker_volume.container_volume[0]: Creating...
module.container["grafana"].module.volume[0].docker_volume.container_volume[1]: Creating...
module.container["nodered"].module.volume[0].docker_volume.container_volume[0]: Creation complete after 0s [id=nodered-prod-yyfv-volume-0]
module.container["influxdb"].module.volume[0].docker_volume.container_volume[0]: Creation complete after 0s [id=influxdb-prod-nvbv-volume-0]
module.container["grafana"].module.volume[0].docker_volume.container_volume[1]: Creation complete after 0s [id=grafana-prod-dk9q-volume-1]
module.container["grafana"].module.volume[0].docker_volume.container_volume[0]: Creation complete after 0s [id=grafana-prod-dk9q-volume-0]
module.image["grafana"].docker_image.container_image: Still creating... [10s elapsed]
module.image["nodered"].docker_image.container_image: Still creating... [10s elapsed]
module.image["influxdb"].docker_image.container_image: Still creating... [10s elapsed]
module.image["influxdb"].docker_image.container_image: Creation complete after 19s [id=sha256:86516adf96b152e8da1b29827a54930cd58667596bd643cd298e55189c3c131equay.io/influxdb/influxdb:v2.0.2]
module.image["grafana"].docker_image.container_image: Creation complete after 19s [id=sha256:1d1f9e7812951b3c0ae79066edba26c5ef27d25c5f4fb5b6b37a998659b812adgrafana/grafana]
module.image["nodered"].docker_image.container_image: Still creating... [20s elapsed]
module.image["nodered"].docker_image.container_image: Creation complete after 22s [id=sha256:8c01614b4e0900c1adf6a4d9656e2cabbd89f7699bbb2f51ac2c26f59483b619nodered/node-red:latest-minimal]
module.container["influxdb"].docker_container.app_container[0]: Creating...
module.container["grafana"].docker_container.app_container[0]: Creating...
module.container["nodered"].docker_container.app_container[0]: Creating...
module.container["grafana"].docker_container.app_container[0]: Provisioning with 'local-exec'...
module.container["grafana"].docker_container.app_container[0] (local-exec): Executing: ["/bin/sh" "-c" "echo grafana-prod-dk9q: 172.17.0.3:3000 >> test.txt"]
module.container["grafana"].docker_container.app_container[0]: Creation complete after 2s [id=d73ad9a7f347958c0c7968cb9b9d637df349f5adce66000e4522f566455de51c]
module.container["influxdb"].docker_container.app_container[0]: Provisioning with 'local-exec'...
module.container["influxdb"].docker_container.app_container[0] (local-exec): Executing: ["/bin/sh" "-c" "echo influxdb-prod-nvbv: 172.17.0.2:8086 >> test.txt"]
module.container["influxdb"].docker_container.app_container[0]: Creation complete after 2s [id=053f80300f5ec4744a84294b59e2c8ca886796e03e3348dc5870874102667ac1]
module.container["nodered"].docker_container.app_container[0]: Provisioning with 'local-exec'...
module.container["nodered"].docker_container.app_container[0] (local-exec): Executing: ["/bin/sh" "-c" "echo nodered-prod-yyfv: 172.17.0.4:1880 >> test.txt"]
module.container["nodered"].docker_container.app_container[0]: Creation complete after 2s [id=fe26ff36c167c794c95080eb8a449e4e7ea49d1c3cfdd3ea8eb2a799556767e2]
Apply complete! Resources: 13 added, 0 changed, 0 destroyed.Outputs:application_access = [
{
"grafana" = {
"application_access" = {
"grafana-prod-dk9q" = "172.17.0.3:3000"
}
}
"influxdb" = {
"application_access" = {
"influxdb-prod-nvbv" = "172.17.0.2:8086"
}
}
"nodered" = {
"application_access" = {
"nodered-prod-yyfv" = "172.17.0.4:1880"
}
}
},
]
Security group settings
Subscribe current weather data
Select free tier
Create a new account
API key noted down

First, we head to our Influx by accessing ipv4 of your EC2 instance at port 8086

Influx interface
Influx settings
Ready to quick start
Load your data
Token for influx
Data explorer

Now we will be navigating to your Nodered application by accessing

Nodered interface
[{"id":"60a93e77.2fa18","type":"tab","label":"API Call","disabled":false,"info":""},{"id":"75924f56.e2a3c","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"database","name":"derekmtc","usetls":false,"tls":"","influxdbVersion":"2.0","url":"http://172.17.0.3:8086","rejectUnauthorized":true},{"id":"499047ca.862b48","type":"http request","z":"60a93e77.2fa18","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://api.openweathermap.org/data/2.5/weather?q=cape%20canaveral&units=imperial&appid={API-KEY}","tls":"","persist":false,"proxy":"","authType":"","x":270,"y":360,"wires":[["9b8212d1.64cf8"]]},{"id":"ba92047d.ff54e8","type":"inject","z":"60a93e77.2fa18","name":"Get","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"10","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"","payloadType":"date","x":110,"y":400,"wires":[["499047ca.862b48","530ab01f.d5867"]]},{"id":"9b8212d1.64cf8","type":"json","z":"60a93e77.2fa18","name":"","property":"payload","action":"","pretty":false,"x":450,"y":420,"wires":[["e6c14187.d5f5"]]},{"id":"ba5f977d.7fd188","type":"function","z":"60a93e77.2fa18","name":"","func":"msg.payload = [\n    [{\n        temperature: msg.weather.main.temp,\n        humidity: msg.weather.main.humidity\n    },\n    {\n        location: msg.weather.name\n    }],\n];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":600,"y":580,"wires":[["b46f13a2.db485"]]},{"id":"e6c14187.d5f5","type":"change","z":"60a93e77.2fa18","name":"","rules":[{"t":"set","p":"weather","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":500,"wires":[["ba5f977d.7fd188","eab0f4bf.0c0ea8"]]},{"id":"530ab01f.d5867","type":"http request","z":"60a93e77.2fa18","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://api.openweathermap.org/data/2.5/weather?q=houston&units=imperial&appid={API-KEY}","tls":"","persist":false,"proxy":"","authType":"","x":270,"y":460,"wires":[["9b8212d1.64cf8"]]},{"id":"eab0f4bf.0c0ea8","type":"debug","z":"60a93e77.2fa18","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":790,"y":420,"wires":[]},{"id":"b46f13a2.db485","type":"influxdb out","z":"60a93e77.2fa18","influxdb":"75924f56.e2a3c","name":"influxdb","measurement":"current","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"ms","retentionPolicyV18Flux":"","org":"derekmtc","bucket":"weather","x":800,"y":500,"wires":[]}]
Import nodes
Error page
Locate and install node-red-contrib-influxdb
Nodes installed
Update http request and replace API-KEY
Organization and bucket updated
Influx name and url from cloud9 filled in
Double check our application deployment
Submit it
Create new password if preferred
Add data source
Select influxDB
Settings
More settings
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": 1,
"links": [],
"panels": [
{
"collapsed": false,
"datasource": null,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 14,
"panels": [],
"title": "Space Center Houston: Houston, Tx",
"type": "row"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"max": 120,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "#EAB839",
"value": 80
},
{
"color": "red",
"value": 90
}
]
},
"unit": "fahrenheit"
},
"overrides": []
},
"gridPos": {
"h": 11,
"w": 4,
"x": 0,
"y": 1
},
"id": 10,
"options": {
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true,
"text": {}
},
"pluginVersion": "7.4.2",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"weather\")\r\n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\r\n |> filter(fn: (r) =>\r\n r._measurement == \"current\" and\r\n r._field == \"temperature\" and \r\n r.location == \"Houston\"\r\n )",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"title": "Space Center Houston Temperature",
"type": "gauge"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": null,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 11,
"w": 8,
"x": 4,
"y": 1
},
"hiddenSeries": false,
"id": 5,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.2",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"weather\")\r\n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\r\n |> filter(fn: (r) =>\r\n r._measurement == \"current\" and\r\n r._field == \"temperature\" and \r\n r.location == \"Houston\"\r\n )",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Space Center Houston Temperature",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 11,
"w": 4,
"x": 12,
"y": 1
},
"id": 8,
"options": {
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true,
"text": {}
},
"pluginVersion": "7.4.2",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"weather\")\r\n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\r\n |> filter(fn: (r) =>\r\n r._measurement == \"current\" and\r\n r._field == \"humidity\" and \r\n r.location == \"Houston\"\r\n )",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"title": "Space Center Houston Humidity",
"type": "gauge"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": null,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 11,
"w": 8,
"x": 16,
"y": 1
},
"hiddenSeries": false,
"id": 4,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.2",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"weather\")\r\n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\r\n |> filter(fn: (r) =>\r\n r._measurement == \"current\" and\r\n r._field == \"humidity\" and \r\n r.location == \"Houston\"\r\n )",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Space Center Houston Humidity",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"collapsed": false,
"datasource": null,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 12
},
"id": 12,
"panels": [],
"title": "Kennedy Space Center: Cape Canaveral, Fl",
"type": "row"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"max": 120,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "#EAB839",
"value": 80
},
{
"color": "red",
"value": 90
}
]
},
"unit": "fahrenheit"
},
"overrides": []
},
"gridPos": {
"h": 11,
"w": 4,
"x": 0,
"y": 13
},
"id": 7,
"options": {
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true,
"text": {}
},
"pluginVersion": "7.4.2",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"weather\")\r\n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\r\n |> filter(fn: (r) =>\r\n r._measurement == \"current\" and\r\n r._field == \"temperature\" and \r\n r.location == \"Cape Canaveral\"\r\n )",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"title": "Kennedy Space Center Temperature",
"type": "gauge"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": null,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 11,
"w": 8,
"x": 4,
"y": 13
},
"hiddenSeries": false,
"id": 2,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.2",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"weather\")\r\n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\r\n |> filter(fn: (r) =>\r\n r._measurement == \"current\" and\r\n r._field == \"temperature\" and \r\n r.location == \"Cape Canaveral\"\r\n )",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Kennedy Space Center Temperature",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 11,
"w": 4,
"x": 12,
"y": 13
},
"id": 9,
"options": {
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true,
"text": {}
},
"pluginVersion": "7.4.2",
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"weather\")\r\n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\r\n |> filter(fn: (r) =>\r\n r._measurement == \"current\" and\r\n r._field == \"humidity\" and \r\n r.location == \"Cape Canaveral\"\r\n )",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"title": "Kennedy Space Center Humidity",
"type": "gauge"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": null,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 11,
"w": 8,
"x": 16,
"y": 13
},
"hiddenSeries": false,
"id": 3,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.2",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"weather\")\r\n |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\r\n |> filter(fn: (r) =>\r\n r._measurement == \"current\" and\r\n r._field == \"humidity\" and \r\n r.location == \"Cape Canaveral\"\r\n )",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Kennedy Space Center Humidity",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
}
],
"refresh": "5s",
"schemaVersion": 27,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-5m",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Launch Weather",
"uid": "Qrs6bNyGz",
"version": 5
}
Grafana monitoring

Clean Up:

$ terraform destroy
.
.
.
Destroy complete! Resources: 13 destroyed.
Delete Cloud9 Environment

Conclusion:

Amazon Web Service Certified Solutions Architect Professional & Devops Engineer, Digital Designer

Amazon Web Service Certified Solutions Architect Professional & Devops Engineer, Digital Designer