feat: Support remotely-managed cloudflare tunnels (#1378)
Co-authored-by: Devin Buhl <onedr0p@users.noreply.github.com>
This commit is contained in:
1 parent
deb038915a
commit
13f4f99992
4 files changed
+39
-16
No files matched your search
@@ -1,34 +1,38 @@
|
|||||||
from functools import wraps
|
from functools import wraps
|
||||||
from shutil import which
|
from shutil import which
|
||||||
from typing import Callable
|
from typing import Callable, cast
|
||||||
from zoneinfo import available_timezones
|
from zoneinfo import available_timezones
|
||||||
import netaddr
|
import netaddr
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
DISTRIBUTIONS = ["k3s", "talos"]
|
DISTRIBUTIONS = ["k3s", "talos"]
|
||||||
GLOBAL_CLI_TOOLS = ["age", "cloudflared", "flux", "helmfile", "sops", "jq", "kubeconform", "kustomize"]
|
GLOBAL_CLI_TOOLS = ["age", "flux", "helmfile", "sops", "jq", "kubeconform", "kustomize"]
|
||||||
TALOS_CLI_TOOLS = ["talosctl", "talhelper"]
|
TALOS_CLI_TOOLS = ["talosctl", "talhelper"]
|
||||||
|
CLOUDFLARE_TOOLS = ["cloudflared"]
|
||||||
|
|
||||||
|
|
||||||
def required(*keys: str):
|
def required(*keys: str):
|
||||||
def wrapper_outter(func: Callable):
|
def wrapper_outter(func: Callable):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(data: dict, *args, **kwargs) -> None:
|
def wrapper(data: dict, *_, **kwargs) -> None:
|
||||||
for key in keys:
|
for key in keys:
|
||||||
if data.get(key) is None:
|
if data.get(key) is None:
|
||||||
raise ValueError(f"Missing required key {key}")
|
raise ValueError(f"Missing required key {key}")
|
||||||
return func(*[data[key] for key in keys], **kwargs)
|
return func(*[data[key] for key in keys], **kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return wrapper_outter
|
return wrapper_outter
|
||||||
|
|
||||||
|
|
||||||
def validate_python_version() -> None:
|
def validate_python_version() -> None:
|
||||||
required_version = (3, 11, 0)
|
required_version = (3, 11, 0)
|
||||||
if sys.version_info < required_version:
|
if sys.version_info < required_version:
|
||||||
raise ValueError(f"Python version is below 3.11. Please upgrade.")
|
raise ValueError(f"Python {sys.version_info} is below 3.11. Please upgrade.")
|
||||||
|
|
||||||
|
|
||||||
@required("bootstrap_distribution")
|
@required("bootstrap_distribution", "bootstrap_cloudflare")
|
||||||
def validate_cli_tools(distribution: dict, **_) -> None:
|
def validate_cli_tools(distribution: str, cloudflare: dict, **_) -> None:
|
||||||
if distribution not in DISTRIBUTIONS:
|
if distribution not in DISTRIBUTIONS:
|
||||||
raise ValueError(f"Invalid distribution {distribution}")
|
raise ValueError(f"Invalid distribution {distribution}")
|
||||||
for tool in GLOBAL_CLI_TOOLS:
|
for tool in GLOBAL_CLI_TOOLS:
|
||||||
@@ -37,10 +41,18 @@ def validate_cli_tools(distribution: dict, **_) -> None:
|
|||||||
for tool in TALOS_CLI_TOOLS if distribution in ["talos"] else []:
|
for tool in TALOS_CLI_TOOLS if distribution in ["talos"] else []:
|
||||||
if not which(tool):
|
if not which(tool):
|
||||||
raise ValueError(f"Missing required CLI tool {tool}")
|
raise ValueError(f"Missing required CLI tool {tool}")
|
||||||
|
for tool in (
|
||||||
|
CLOUDFLARE_TOOLS
|
||||||
|
if cloudflare.get("enabled", False)
|
||||||
|
and cast(dict, cloudflare.get("tunnel", {})).get("token", "") == ""
|
||||||
|
else []
|
||||||
|
):
|
||||||
|
if not which(tool):
|
||||||
|
raise ValueError(f"Missing required CLI tool {tool}")
|
||||||
|
|
||||||
|
|
||||||
@required("bootstrap_distribution")
|
@required("bootstrap_distribution")
|
||||||
def validate_distribution(distribution: dict, **_) -> None:
|
def validate_distribution(distribution: str, **_) -> None:
|
||||||
if distribution not in DISTRIBUTIONS:
|
if distribution not in DISTRIBUTIONS:
|
||||||
raise ValueError(f"Invalid distribution {distribution}")
|
raise ValueError(f"Invalid distribution {distribution}")
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ spec:
|
|||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: cloudflared-secret
|
name: cloudflared-secret
|
||||||
key: TUNNEL_ID
|
key: TUNNEL_ID
|
||||||
|
TUNNEL_TOKEN:
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: cloudflared-secret
|
||||||
|
key: TUNNEL_TOKEN
|
||||||
args:
|
args:
|
||||||
- tunnel
|
- tunnel
|
||||||
- --config
|
- --config
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ metadata:
|
|||||||
name: cloudflared-secret
|
name: cloudflared-secret
|
||||||
stringData:
|
stringData:
|
||||||
TUNNEL_ID: "#{ bootstrap_cloudflare.tunnel.id }#"
|
TUNNEL_ID: "#{ bootstrap_cloudflare.tunnel.id }#"
|
||||||
|
TUNNEL_TOKEN: "#{ bootstrap_cloudflare.tunnel.token }#"
|
||||||
credentials.json: |
|
credentials.json: |
|
||||||
{
|
{
|
||||||
"AccountTag": "#{ bootstrap_cloudflare.tunnel.account_id }#",
|
"AccountTag": "#{ bootstrap_cloudflare.tunnel.account_id }#",
|
||||||
|
|||||||
+14
-9
@@ -187,18 +187,23 @@ bootstrap_cloudflare:
|
|||||||
# in your nodes host network that is NOT being used. This is announced over L2.
|
# in your nodes host network that is NOT being used. This is announced over L2.
|
||||||
gateway_vip: ""
|
gateway_vip: ""
|
||||||
# (Required) Options for Cloudflare Tunnel
|
# (Required) Options for Cloudflare Tunnel
|
||||||
# 1. Authenticate cloudflared to your domain
|
# For a locally-managed (aka CLI) tunnel:
|
||||||
# > cloudflared tunnel login
|
# 1. Authenticate cloudflared to your domain
|
||||||
# 2. Create the tunnel
|
# > cloudflared tunnel login
|
||||||
# > cloudflared tunnel create k8s
|
# 2. Create the tunnel
|
||||||
# 3. Copy the AccountTag, TunnelID, and TunnelSecret from the tunnel configuration file and paste them below
|
# > cloudflared tunnel create k8s
|
||||||
|
# 3. Copy the AccountTag, TunnelID, and TunnelSecret from the tunnel configuration file and paste them below
|
||||||
|
# For a remotely-managed (aka dashboard) tunnel: https://one.dash.cloudflare.com/
|
||||||
tunnel:
|
tunnel:
|
||||||
# (Required) Cloudflare Account ID (cat ~/.cloudflared/*.json | jq -r .AccountTag)
|
# (Required) Cloudflared Tunnel ID
|
||||||
account_id: ""
|
# If using CLI tunnel: (cat ~/.cloudflared/*.json | jq -r .TunnelID)
|
||||||
# (Required) Cloudflared Tunnel ID (cat ~/.cloudflared/*.json | jq -r .TunnelID)
|
|
||||||
id: ""
|
id: ""
|
||||||
# (Required) Cloudflared Tunnel Secret (cat ~/.cloudflared/*.json | jq -r .TunnelSecret)
|
# (Required: CLI) Cloudflare Account ID (cat ~/.cloudflared/*.json | jq -r .AccountTag)
|
||||||
|
account_id: ""
|
||||||
|
# (Required: CLI) Cloudflared Tunnel Secret (cat ~/.cloudflared/*.json | jq -r .TunnelSecret)
|
||||||
secret: ""
|
secret: ""
|
||||||
|
# (Required: dashboard) Cloudflared Tunnel Token
|
||||||
|
token: ""
|
||||||
# (Required) Provide WAN access to the cluster ingresses for external ingress classes
|
# (Required) Provide WAN access to the cluster ingresses for external ingress classes
|
||||||
# The Load balancer IP for external ingress, choose an available IP
|
# The Load balancer IP for external ingress, choose an available IP
|
||||||
# in your nodes host network that is NOT being used. This is announced over L2.
|
# in your nodes host network that is NOT being used. This is announced over L2.
|
||||||
|
|||||||
Reference in new issue
Block a user