Skip to content

Commit

Permalink
Latest changes (#3)
Browse files Browse the repository at this point in the history
code: cleaner code and dropped lookup for modern method, dropped non-https responder, README update
pipeline: github actions workflow, pre-commit, docs, tflint and checkov
  • Loading branch information
atrull authored Nov 18, 2023
1 parent 935ccc2 commit 31d909d
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 30 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: "Module Test"
on: [push, pull_request]

permissions: read-all

jobs:
terraform-plan:
name: "Terraform Lint and Plan"
runs-on: ubuntu-latest
defaults:
run:
shell: bash

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Setup Terraform
uses: hashicorp/setup-terraform@v2

- uses: terraform-docs/gh-actions@main

- uses: terraform-linters/setup-tflint@v3

- name: Terraform Fmt
id: fmt
run: terraform fmt -no-color

- name: Terraform Init
id: init
run: terraform init

- name: Terraform Validate
id: validate
run: terraform validate -no-color

- name: Terraform Plan
id: plan
run: terraform plan -no-color 2>&1

- uses: bridgecrewio/checkov-action@v12
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.83.6
hooks:
- id: terraform_fmt
- id: terraform_docs
- id: terraform_checkov
- id: terraform_tflint
51 changes: 48 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,52 @@
# Overbuilt myip module

Collect and determine what is probably our source ip, only, providing the most common response, which we hope will always be the most correct.
## What it does:

See variables.tf for variables including the list of sources we can check.
This module polls a series of fairly well known but occasionally unreliable 'what is my ip' services. It then produces the most common response that is a valid ipv4 or ipv6 address (both outputs are separately provided).

See outputs.tf for outputs.
We support two providers - `curl` and `http`. `curl` is the default provider because it has better failure handling whereas `http` provider will fail a plan/apply if the endpoint doesn't respond.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | ~> 1.0 |
| <a name="requirement_curl"></a> [curl](#requirement\_curl) | ~> 1.0.2 |
| <a name="requirement_http"></a> [http](#requirement\_http) | ~> 3 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_curl"></a> [curl](#provider\_curl) | 1.0.2 |
| <a name="provider_http"></a> [http](#provider\_http) | 3.4.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [curl_curl.myip](https://registry.terraform.io/providers/anschoewe/curl/latest/docs/data-sources/curl) | data source |
| [http_http.myip](https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_data_provider"></a> [data\_provider](#input\_data\_provider) | `curl` or `http` providers are both supported - we recommend `curl` | `string` | `"curl"` | no |
| <a name="input_extra_service_urls"></a> [extra\_service\_urls](#input\_extra\_service\_urls) | Put your own in here if you want extra ones, this gets merged with the `service_urls` list | `list(string)` | `[]` | no |
| <a name="input_service_urls"></a> [service\_urls](#input\_service\_urls) | List of urls to use for getting our IP | `list(string)` | <pre>[<br> "https://api.seeip.org",<br> "https://ipinfo.io/ip",<br> "https://ifconfig.co",<br> "https://icanhazip.com",<br> "https://api.ipify.org",<br> "https://ifconfig.me",<br> "https://ipecho.net/plain",<br> "https://ifconfig.io",<br> "http://eth0.me/",<br> "https://ident.me",<br> "https://ipv4.ident.me"<br>]</pre> | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_ipv4"></a> [ipv4](#output\_ipv4) | n/a |
| <a name="output_ipv4_all_matches"></a> [ipv4\_all\_matches](#output\_ipv4\_all\_matches) | n/a |
| <a name="output_ipv6"></a> [ipv6](#output\_ipv6) | n/a |
| <a name="output_ipv6_all_matches"></a> [ipv6\_all\_matches](#output\_ipv6\_all\_matches) | n/a |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
43 changes: 19 additions & 24 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
terraform {
required_version = "~> 1.0"
required_providers {
curl = {
version = "1.0.2"
version = "~> 1.0.2"
source = "anschoewe/curl"
}
http = {
version = "~> 3"
source = "hashicorp/http"
}
}
}

# curl is the default method
data "curl" "myip" {
for_each = var.data_provider == "curl" ? toset(var.myip_service_urls) : []
for_each = var.data_provider == "curl" ? toset(local.service_urls) : []
http_method = "GET"
uri = each.key
}

# but we can use http if you prefer
data "http" "myip" {
for_each = var.data_provider == "http" ? toset(var.myip_service_urls) : []
for_each = var.data_provider == "http" ? toset(local.service_urls) : []
url = each.key
method = "GET"
request_timeout_ms = 500
}

locals {
# merge extra with primary list and make sure entries are unique
service_urls = distinct(concat(var.service_urls, var.extra_service_urls))

# build a list of responses
service_response_bodies = var.data_provider == "curl" ? values(data.curl.myip)[*].response : values(data.http.myip)[*].response_body
Expand All @@ -41,29 +48,17 @@ locals {
]

# what follows is a really long winded version of uniq -c | sort -n
ipv4_index_list = [for index, item in local.ipv4_matches : length([for i in slice(local.ipv4_matches, 0, index + 1) : i if i == item])]
ipv4_joined_index = zipmap(local.ipv4_matches, local.ipv4_index_list)
ipv4_reverse_index = { for k, v in local.ipv4_joined_index : v => k... }
ipv4_most_common_response = local.ipv4_reverse_index != {} ? lookup(
local.ipv4_reverse_index,
element(
sort(keys(local.ipv4_reverse_index)),
length(local.ipv4_reverse_index) - 1
)
) : []
ipv4_index_list = [for index, item in local.ipv4_matches : length([for i in slice(local.ipv4_matches, 0, index + 1) : i if i == item])]
ipv4_joined_index = zipmap(local.ipv4_matches, local.ipv4_index_list)
ipv4_reverse_index = { for k, v in local.ipv4_joined_index : v => k... }
ipv4_most_common_response = local.ipv4_reverse_index != {} ? local.ipv4_reverse_index[element(sort(keys(local.ipv4_reverse_index)), length(local.ipv4_reverse_index) - 1)] : []

# uniq -c | sort -n again but for ipv6
ipv6_index_list = [for index, item in local.ipv6_matches : length([for i in slice(local.ipv6_matches, 0, index + 1) : i if i == item])]
ipv6_joined_index = zipmap(local.ipv6_matches, local.ipv6_index_list)
ipv6_reverse_index = { for k, v in local.ipv6_joined_index : v => k... }
ipv6_most_common_response = local.ipv6_reverse_index != {} ? lookup(
local.ipv6_reverse_index,
element(
sort(keys(local.ipv6_reverse_index)),
length(local.ipv6_reverse_index) - 1
)
) : []
ipv6_index_list = [for index, item in local.ipv6_matches : length([for i in slice(local.ipv6_matches, 0, index + 1) : i if i == item])]
ipv6_joined_index = zipmap(local.ipv6_matches, local.ipv6_index_list)
ipv6_reverse_index = { for k, v in local.ipv6_joined_index : v => k... }
ipv6_most_common_response = local.ipv6_reverse_index != {} ? local.ipv6_reverse_index[element(sort(keys(local.ipv6_reverse_index)), length(local.ipv6_reverse_index) - 1)] : []

}

# See outputs.tf for where we spit out the winners
# See outputs.tf where we spit out the winners
14 changes: 11 additions & 3 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
variable "myip_service_urls" {
variable "service_urls" {
default = [
"https://api.seeip.org",
"https://ipinfo.io/ip",
Expand All @@ -8,13 +8,21 @@ variable "myip_service_urls" {
"https://ifconfig.me",
"https://ipecho.net/plain",
"https://ifconfig.io",
"http://eth0.me/",
"https://ident.me",
"https://ipv4.ident.me",
]
type = list(string)
description = "List of urls to use for getting our IP"
}

variable "extra_service_urls" {
default = []
type = list(string)
description = "Put your own in here if you want extra ones, this gets merged with the `service_urls` list"
}

variable "data_provider" {
default = "curl"
description = "(curl) or (http) provider are both supported."
type = string
description = "`curl` or `http` providers are both supported - we recommend `curl`"
}

0 comments on commit 31d909d

Please sign in to comment.