Skip to content

Commit

Permalink
feat: distribution is a dict and nodes and cluster are top level (#1288)
Browse files Browse the repository at this point in the history
* feat: distribution is a dict and nodes and cluster are top level

Signed-off-by: Devin Buhl <[email protected]>

* chore: housekeeping

Signed-off-by: Devin Buhl <[email protected]>

---------

Signed-off-by: Devin Buhl <[email protected]>
  • Loading branch information
onedr0p authored Feb 2, 2024
1 parent cba35dc commit 89673cd
Show file tree
Hide file tree
Showing 55 changed files with 330 additions and 302 deletions.
31 changes: 17 additions & 14 deletions .github/tests/config-k0s.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
---
skip_tests: true

distribution: k0s
distribution:
type: k0s

timezone: Etc/UTC

nodes:
host_network: 10.10.10.0/24
dns_servers: ["1.1.1.1"]
search_domain: "fake"
inventory:
- name: k8s-controller-0
address: 10.10.10.100
controller: true
ssh_username: fake
- name: k8s-worker-0
address: 10.10.10.101
controller: false
ssh_username: fake

cluster:
nodes:
host_network: 10.10.10.0/24
dns_servers: ["1.1.1.1"]
search_domain: "fake"
inventory:
- name: k8s-controller-0
address: 10.10.10.100
controller: true
ssh_username: fake
- name: k8s-worker-0
address: 10.10.10.101
controller: false
ssh_username: fake
pod_network: 10.69.0.0/16
service_network: 10.96.0.0/16
endpoint_vip: 10.10.10.254
Expand Down
32 changes: 18 additions & 14 deletions .github/tests/config-k3s-ipv4.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
---
skip_tests: true

distribution: k3s
distribution:
type: k3s

timezone: Etc/UTC

nodes:
host_network: 10.10.10.0/24
dns_servers: ["1.1.1.1"]
search_domain: "fake"
inventory:
- name: k8s-controller-0
address: 10.10.10.100
controller: true
ssh_username: fake
- name: k8s-worker-0
address: 10.10.10.101
controller: false
ssh_username: fake


cluster:
nodes:
host_network: 10.10.10.0/24
dns_servers: ["1.1.1.1"]
search_domain: "fake"
inventory:
- name: k8s-controller-0
address: 10.10.10.100
controller: true
ssh_username: fake
- name: k8s-worker-0
address: 10.10.10.101
controller: false
ssh_username: fake
pod_network: 10.69.0.0/16
service_network: 10.96.0.0/16
endpoint_vip: 10.10.10.254
Expand Down
31 changes: 17 additions & 14 deletions .github/tests/config-k3s-ipv6.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
---
skip_tests: true

distribution: k3s
distribution:
type: k3s

timezone: Etc/UTC

nodes:
host_network: 10.10.10.0/24
dns_servers: ["1.1.1.1"]
search_domain: "fake"
inventory:
- name: k8s-controller-0
address: 10.10.10.100
controller: true
ssh_username: fake
- name: k8s-worker-0
address: 10.10.10.101
controller: false
ssh_username: fake

cluster:
nodes:
host_network: 10.10.10.0/24
dns_servers: ["1.1.1.1"]
search_domain: "fake"
inventory:
- name: k8s-controller-0
address: 10.10.10.100
controller: true
ssh_username: fake
- name: k8s-worker-0
address: 10.10.10.101
controller: false
ssh_username: fake
pod_network: 10.42.0.0/16,fd7f:8f5:e87c:a::/64
service_network: 10.43.0.0/16,fd7f:8f5:e87c:e::/112
endpoint_vip: 10.10.10.254
Expand Down
53 changes: 28 additions & 25 deletions .github/tests/config-talos.yaml
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
---
skip_tests: true

distribution: talos
distribution:
type: talos
talos:
schematics:
enabled: true
id: df491c50a5acc05b977ef00c32050e1ceb0df746e40b33c643ac8a9bfb7c7263
customization: |-
extraKernelArgs:
- net.ifnames=0
systemExtensions:
officialExtensions:
- siderolabs/intel-ucode
- siderolabs/i915-ucode
timezone: Etc/UTC

nodes:
host_network: 10.10.10.0/24
dns_servers: ["1.1.1.1"]
search_domain: "fake"
inventory:
- name: k8s-controller-0
address: 10.10.10.100
controller: true
talos_disk_device: fake
- name: k8s-worker-0
address: 10.10.10.101
controller: false
talos_disk_device: fake

cluster:
nodes:
host_network: 10.10.10.0/24
dns_servers: ["1.1.1.1"]
search_domain: "fake"
inventory:
- name: k8s-controller-0
address: 10.10.10.100
controller: true
talos_disk_device: fake
- name: k8s-worker-0
address: 10.10.10.101
controller: false
talos_disk_device: fake
talos:
schematics:
enabled: true
id: df491c50a5acc05b977ef00c32050e1ceb0df746e40b33c643ac8a9bfb7c7263
customization: |-
extraKernelArgs:
- net.ifnames=0
systemExtensions:
officialExtensions:
- siderolabs/intel-ucode
- siderolabs/i915-ucode
pod_network: 10.69.0.0/16
service_network: 10.96.0.0/16
endpoint_vip: 10.10.10.254
Expand Down
67 changes: 6 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,88 +214,33 @@ You have two different options for setting up your local workstation.
### 🔧 Stage 3: Bootstrap configuration
> [!NOTE]
> The [config.sample.yaml](./config.sample.yaml) file contain necessary information that is **vital** to the bootstrap process.
> The [config.sample.yaml](./config.sample.yaml) file contains config that is **vital** to the bootstrap process.
1. Generate the `config.yaml` from the [config.sample.yaml](./config.sample.yaml) configuration file.
```sh
task init
```
#### 🔧 Stage 3: Flux
2. Fill out the `config.yaml` configuration file using the comments in that file as a guide.
📍 _Using [SOPS](https://github.com/getsops/sops) with [Age](https://github.com/FiloSottile/age) allows us to encrypt secrets and use them with Flux._
1. Create a Age private / public key (this file is gitignored)
```sh
task sops:age-keygen
```
2. Fill out the appropriate vars in `config.yaml`
#### Stage 3: Flux with Cloudflare DNS
> [!NOTE]
> To use `cert-manager` with the Cloudflare DNS challenge you will need to create a API Token.
1. Head over to Cloudflare and create a API Token by going [here](https://dash.cloudflare.com/profile/api-tokens).
2. Under the `API Tokens` section click the blue `Create Token` button.
3. Click the blue `Use template` button for the `Edit zone DNS` template.
4. Name your token something like `home-kubernetes`
5. Under `Permissions`, click `+ Add More` and add each permission below:
```text
Zone - DNS - Edit
Account - Cloudflare Tunnel - Read
```

6. Limit the permissions to a specific account and zone resources.
7. Fill out the appropriate vars in `config.yaml`

#### Stage 3: Flux with Cloudflare Tunnel

> [!NOTE]
> To expose services to the internet you will need to create a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/).

1. Authenticate cloudflared to your domain

```sh
cloudflared tunnel login
```

2. Create the tunnel

```sh
cloudflared tunnel create k8s
```

3. In the `~/.cloudflared` directory there will be a json file with details you need. Ignore the `cert.pem` file.

4. Fill out the appropriate vars in `config.yaml`

#### Stage 3: Finishing up

1. Complete filling out the rest of the `config.yaml` configuration file.

2. Once done run the following command which will verify and generate all the files needed to continue.
3. Run the following command which will generate all the files needed to continue.
```sh
task configure
```
3. Push you changes to git
4. Push you changes to git
📍 **Verify** all the `*.sops.yaml` and `*.sops.yaml` files under `./kubernetes` directory is **encrypted** with SOPS
📍 _**Verify** all the `./kubernetes/**/*.sops.*` files are **encrypted** with SOPS_
```sh
git add -A
git commit -m "Initial commit :rocket:"
git push
```
4. Continue on to ⚡ [**Stage 4**](#-stage-4-prepare-your-nodes-for-kubernetes)
5. Continue on to ⚡ [**Stage 4**](#-stage-4-prepare-your-nodes-for-kubernetes)
### ⚡ Stage 4: Prepare your nodes for Kubernetes
Expand Down
12 changes: 11 additions & 1 deletion bootstrap/scripts/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@

from typing import Any
from netaddr import IPNetwork
from bcrypt import hashpw, gensalt

import makejinja
import validation

def encrypt(value: str) -> str:
return hashpw(value.encode(), gensalt(rounds=10)).decode("ascii")


def nthhost(value: str, query: int) -> str:
value = IPNetwork(value)
try:
Expand All @@ -20,6 +25,7 @@ def nthhost(value: str, query: int) -> str:
return False
return value


def import_filter(file: Path) -> Callable[[dict[str, Any]], bool]:
module_path = file.relative_to(Path.cwd()).with_suffix("")
module_name = str(module_path).replace("/", ".")
Expand All @@ -31,6 +37,7 @@ def import_filter(file: Path) -> Callable[[dict[str, Any]], bool]:
spec.loader.exec_module(module)
return module.main


class Plugin(makejinja.plugin.Plugin):
def __init__(self, data: dict[str, Any], config: makejinja.config.Config):
self._data = data
Expand All @@ -45,12 +52,15 @@ def __init__(self, data: dict[str, Any], config: makejinja.config.Config):

validation.validate(data)


def filters(self) -> makejinja.plugin.Filters:
return [nthhost]
return [encrypt, nthhost]


def path_filters(self):
return [self._mjfilter_func]


def _mjfilter_func(self, path: Path) -> bool:
return not any(
path.is_relative_to(excluded_dir) for excluded_dir in self._excluded_dirs
Expand Down
19 changes: 11 additions & 8 deletions bootstrap/scripts/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
TALOS_CLI_TOOLS = ["talosctl", "talhelper"]
K0S_CLI_TOOLS = ["k0sctl"]


def required(*keys: str):
def wrapper_outter(func: Callable):
@wraps(func)
Expand All @@ -22,7 +21,6 @@ def wrapper(data: dict, *args, **kwargs) -> None:
return wrapper
return wrapper_outter


def _validate_network(network: str, family: int) -> str:
try:
network = netaddr.IPNetwork(network)
Expand All @@ -40,9 +38,10 @@ def validate_python_version() -> None:


@required("distribution")
def validate_cli_tools(distribution: str, **_) -> None:
if distribution not in DISTRIBUTIONS:
raise ValueError(f"Invalid distribution {distribution}")
def validate_cli_tools(distribution: dict, **_) -> None:
distro = distribution.get("type")
if distro not in DISTRIBUTIONS:
raise ValueError(f"Invalid distribution {distro}")
for tool in GLOBAL_CLI_TOOLS:
if not which(tool):
raise ValueError(f"Missing required CLI tool {tool}")
Expand All @@ -55,9 +54,10 @@ def validate_cli_tools(distribution: str, **_) -> None:


@required("distribution")
def validate_distribution(distribution: str, **_) -> None:
if distribution not in DISTRIBUTIONS:
raise ValueError(f"Invalid distribution {distribution}")
def validate_distribution(distribution: dict, **_) -> None:
distro = distribution.get("type")
if distro not in DISTRIBUTIONS:
raise ValueError(f"Invalid distribution {distro}")


@required("timezone")
Expand Down Expand Up @@ -98,6 +98,9 @@ def validate_cluster_networks(cluster: dict, feature_gates: dict, **_) -> None:


def massage_config(data: dict) -> dict:
data["distribution"] = data.get("distribution", {})
data["nodes"] = data.get("nodes", [])
data["cluster"] = data.get("cluster", {})
data["flux"] = data.get("flux", {})
data["cloudflare"] = data.get("cloudflare", {})
data["feature_gates"] = data.get("feature_gates", {})
Expand Down
Loading

0 comments on commit 89673cd

Please sign in to comment.