mirror of
https://gitea.fenix-dev.com/fenix-gitea-admin/iac-opentofu-private.git
synced 2025-10-27 15:53:06 +00:00
Compare commits
1 Commits
a7f3b6d7e1
...
fenix
| Author | SHA1 | Date | |
|---|---|---|---|
| 946987862e |
@ -2,7 +2,7 @@ name: IAC
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ dev ]
|
branches: [ main ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@ -15,185 +15,39 @@ jobs:
|
|||||||
PM_API_TOKEN_SECRET: ${{ secrets.PM_API_TOKEN_SECRET }}
|
PM_API_TOKEN_SECRET: ${{ secrets.PM_API_TOKEN_SECRET }}
|
||||||
BW_EMAIL: ${{ secrets.BW_EMAIL }}
|
BW_EMAIL: ${{ secrets.BW_EMAIL }}
|
||||||
BW_PASSWORD: ${{ secrets.BW_PASSWORD }}
|
BW_PASSWORD: ${{ secrets.BW_PASSWORD }}
|
||||||
BW_CLIENTID: ${{ secrets.BW_CLIENTID }}
|
|
||||||
BW_CLIENTSECRET: ${{ secrets.BW_CLIENTSECRET }}
|
|
||||||
VAULTWARDEN_LINK: ${{secrets.VAULTWARDEN_LINK }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Verificar se commit pede por [deploy-opentofu]
|
|
||||||
if: "!contains(gitea.event.head_commit.message, '[deploy-opentofu]')"
|
|
||||||
run: |
|
|
||||||
echo "Commit não contém [deploy-opentofu], a pipeline será ignorada."
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
- name: Executar deploy opentofu
|
|
||||||
run: echo "Commit contém [deploy-opentofu], a pipeline será executada."
|
|
||||||
|
|
||||||
|
|
||||||
- name: Updating apt-get
|
- name: Updating apt-get
|
||||||
run: |
|
run: |
|
||||||
apt-get update -y
|
apt-get update -y
|
||||||
|
|
||||||
- name: Install setup
|
|
||||||
run: |
|
|
||||||
apt install -y curl jq
|
|
||||||
curl -fsSL https://deb.nodesource.com/setup_18.x
|
|
||||||
|
|
||||||
- name: Cloning iac repository
|
- name: Cloning iac repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
path: infra/iac
|
path: infra/iac
|
||||||
|
|
||||||
#- name: cloning iac secrets repository
|
- name: cloning iac secrets repository
|
||||||
# uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
# with:
|
with:
|
||||||
# repository: fenix-gitea-admin/iac-opentofu-private-secrets
|
repository: fenix-gitea-admin/iac-teste-secrets
|
||||||
# token: ${{ secrets.GGITEA_TOKEN }}
|
token: ${{ secrets.GGITEA_TOKEN }}
|
||||||
# path: infra/secrets
|
path: infra/secrets
|
||||||
|
|
||||||
|
- name: vaultwarden login
|
||||||
- name: Install cloudflare prerequisites
|
|
||||||
run: |
|
|
||||||
apt-get install -y curl ca-certificates jq openssh-client net-tools iproute2
|
|
||||||
- name: Install cloudflared
|
|
||||||
run: |
|
|
||||||
# pacote .deb oficial - funcionará numa runner Ubuntu x86_64
|
|
||||||
curl -L -o cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
|
|
||||||
dpkg -i cloudflared.deb
|
|
||||||
cloudflared --version
|
|
||||||
|
|
||||||
- name: Install dante-server
|
|
||||||
run: |
|
|
||||||
apt-get install -y dante-server openssl
|
|
||||||
#libssl1.1
|
|
||||||
|
|
||||||
|
|
||||||
- name: Configure dante-server
|
|
||||||
run: |
|
|
||||||
cat <<EOF | tee /etc/danted.conf
|
|
||||||
logoutput: stderr
|
|
||||||
internal: 127.0.0.1 port = 1080
|
|
||||||
external: lo
|
|
||||||
method: none
|
|
||||||
clientmethod: none
|
|
||||||
client pass {
|
|
||||||
from: 0.0.0.0/0 to: 0.0.0.0/0
|
|
||||||
log: connect disconnect
|
|
||||||
}
|
|
||||||
# encaminhar tudo para o listener TCP do cloudflared
|
|
||||||
socks pass {
|
|
||||||
from: 0.0.0.0/0 to: 0.0.0.0/0
|
|
||||||
command: connect udpassociate bind
|
|
||||||
log: connect disconnect
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
|
|
||||||
- name: vaultwarden urls as secrets
|
|
||||||
run: |
|
|
||||||
echo "config"
|
|
||||||
echo "$VAULTWARDEN_LINK"
|
|
||||||
bw config server $VAULTWARDEN_LINK
|
|
||||||
echo "login"
|
|
||||||
bw login --apikey
|
|
||||||
echo "session"
|
|
||||||
BW_SESSION=$(bw unlock "$BW_PASSWORD" --raw)
|
|
||||||
echo "$BW_SESSION"
|
|
||||||
echo "getting item"
|
|
||||||
bw get item "iac.proxmox.ssh.link" --session "$BW_SESSION"
|
|
||||||
bw get item "iac.proxmox.ssh.link" --session "$BW_SESSION" | jq -r '.notes' > "proxmox-ssh-link.txt"
|
|
||||||
|
|
||||||
- name: Start cloudflared Access TCP -> SOCKS5 (background)
|
|
||||||
env:
|
|
||||||
CF_SVC_ID: ${{ secrets.CF_SVC_ID }}
|
|
||||||
CF_SVC_SECRET: ${{ secrets.CF_SVC_SECRET }}
|
|
||||||
run: |
|
|
||||||
Hostname=$(cat proxmox-ssh-link.txt)
|
|
||||||
|
|
||||||
# Inicia cloudflared access tcp/ssh com service token e listener socks local
|
|
||||||
# O binário 'cloudflared' tem variações de flags entre versões; estes flags funcionam nas versões recentes.
|
|
||||||
nohup cloudflared access tcp \
|
|
||||||
--hostname "$Hostname" \
|
|
||||||
--listener "tcp://127.0.0.1:1081" \
|
|
||||||
--service-token-id "$CF_SVC_ID" \
|
|
||||||
--service-token-secret "$CF_SVC_SECRET" \
|
|
||||||
> cloudflared.log 2>&1 &
|
|
||||||
|
|
||||||
# espera a porta do listener estar pronta (timeout 30s)
|
|
||||||
for i in $(seq 1 30); do
|
|
||||||
ss -tnl | grep -q ":1081" && break
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
|
|
||||||
if ! ss -tnl | grep -q ":1081"; then
|
|
||||||
echo "SOCKS listener not ready after 30s, printing cloudflared.log"
|
|
||||||
tail -n +1 cloudflared.log
|
|
||||||
cat cloudflared.log
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "cloudflared socks listener ready at $SOCKS_LISTENER"
|
|
||||||
sleep 1
|
|
||||||
# opcional: ver primeiros logs
|
|
||||||
tail -n 50 cloudflared.log || true
|
|
||||||
|
|
||||||
- name: Start dante-server
|
|
||||||
run: |
|
|
||||||
pkill danted || true
|
|
||||||
danted -f /etc/danted.conf -D > dante.log 2>&1 &
|
|
||||||
sleep 3
|
|
||||||
cat dante.log
|
|
||||||
|
|
||||||
|
|
||||||
- name: vaultwarden getsecrets
|
|
||||||
working-directory: infra/iac
|
working-directory: infra/iac
|
||||||
run: |
|
run: |
|
||||||
BW_SESSION=$(bw unlock "$BW_PASSWORD" --raw)
|
BW_SESSION=$(bw login)
|
||||||
echo "$BW_SESSION"
|
|
||||||
|
|
||||||
# Ler o arquivo de referência
|
|
||||||
for secret in $(jq -c '.secrets[]' secrets/vault-secrets-map.json); do
|
|
||||||
name=$(echo "$secret" | jq -r '.name')
|
|
||||||
type=$(echo "$secret" | jq -r '.type')
|
|
||||||
output=$(echo "$secret" | jq -r '.output')
|
|
||||||
echo "$name $type $output"
|
|
||||||
item_id=$(bw get item "$name" | jq -r '.id')
|
|
||||||
echo "$item_id"
|
|
||||||
mkdir -p "$(dirname "$output")"
|
|
||||||
echo "dir made"
|
|
||||||
if [ "$type" == "attachment" ]; then
|
|
||||||
echo "attachment get"
|
|
||||||
bw get attachment "$output" --itemid "$item_id" --output "$output" --session "$BW_SESSION"
|
|
||||||
elif [ "$type" == "note" ]; then
|
|
||||||
echo "note get"
|
|
||||||
bw get item "$name" --session "$BW_SESSION" | jq -r '.notes' > "$output"
|
|
||||||
#cat $output
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
pip install ruamel.yaml
|
|
||||||
|
|
||||||
- name: Init OpenTofu
|
- name: Init OpenTofu
|
||||||
working-directory: infra/iac
|
working-directory: infra/iac
|
||||||
run: |
|
run: tofu init
|
||||||
tofu init
|
|
||||||
|
|
||||||
- name: Plan
|
- name: Plan
|
||||||
working-directory: infra/iac
|
working-directory: infra/iac
|
||||||
run: |
|
run: |
|
||||||
# Find all .tfvars in the secrets folder
|
# Find all .auto.tfvars in the secrets folder
|
||||||
VAR_FILES=""
|
VAR_FILES=""
|
||||||
ls -la ../secrets/secrets
|
for f in ../secrets/secrets/*.auto.tfvars; do
|
||||||
for f in ../secrets/secrets/*.tfvars; do
|
|
||||||
echo "found - $f"
|
|
||||||
VAR_FILES="$VAR_FILES -var-file=$f"
|
VAR_FILES="$VAR_FILES -var-file=$f"
|
||||||
done
|
done
|
||||||
tofu plan $VAR_FILES -out=./tfplan | tee ./tfplan.txt
|
tofu plan $VAR_FILES -out=./tfplan | tee ./tfplan.txt
|
||||||
|
|||||||
18
LICENSE
18
LICENSE
@ -1,18 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2025 fenix-gitea-admin
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
||||||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
|
||||||
following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
||||||
portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
|
||||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
|
||||||
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
@ -1 +0,0 @@
|
|||||||
the most stable branch is main, dev is where tests are made, and the remaining branches are personal and can undergo changes at any time
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
locale: "pt_PT.UTF-8"
|
|
||||||
keyboard:
|
|
||||||
layout: "pt"
|
|
||||||
variant: "nodeadkeys"
|
|
||||||
|
|
||||||
users:
|
|
||||||
- default
|
|
||||||
|
|
||||||
ssh_pwauth: true
|
|
||||||
|
|
||||||
package_update: true
|
|
||||||
packages:
|
|
||||||
- qemu-guest-agent
|
|
||||||
- net-tools
|
|
||||||
- curl
|
|
||||||
runcmd:
|
|
||||||
- systemctl enable qemu-guest-agent
|
|
||||||
- systemctl start qemu-guest-agent
|
|
||||||
- echo "done" > /tmp/cloud-config.done
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
package_update: true
|
|
||||||
%{ if length(each.value.extra_packages) > 0 ~}
|
|
||||||
packages:
|
|
||||||
%{ for pkg in each.value.extra_packages ~}
|
|
||||||
- ${pkg}
|
|
||||||
%{ endfor ~}
|
|
||||||
%{ endif ~}
|
|
||||||
|
|
||||||
%{ if length(each.value.extra_users) > 0 ~}
|
|
||||||
users:
|
|
||||||
%{ for u in each.value.extra_users ~}
|
|
||||||
- name: ${u.name}
|
|
||||||
groups:
|
|
||||||
%{ if length(u.groups) > 0 ~}
|
|
||||||
%{ for g in u.groups ~}
|
|
||||||
- ${g}
|
|
||||||
%{ endfor ~}
|
|
||||||
%{ endif ~}
|
|
||||||
shell: /bin/bash
|
|
||||||
sudo: ALL=(ALL) NOPASSWD:ALL
|
|
||||||
%{ endfor ~}
|
|
||||||
|
|
||||||
chpasswd:
|
|
||||||
list: ${"|"}
|
|
||||||
%{ for u in each.value.extra_users ~}
|
|
||||||
${u.name}:${u.password}
|
|
||||||
%{ endfor ~}
|
|
||||||
expire: false
|
|
||||||
%{ endif ~}
|
|
||||||
|
|
||||||
%{ if length(each.value.extra_runcmd) > 0 ~}
|
|
||||||
runcmd:
|
|
||||||
%{ for cmd in each.value.extra_runcmd ~}
|
|
||||||
- ${cmd}
|
|
||||||
%{ endfor ~}
|
|
||||||
%{ endif ~}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
#cloud-config
|
|
||||||
${content}
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
FROM ghcr.io/opentofu/opentofu:1.9-minimal AS tofu
|
|
||||||
|
|
||||||
FROM ubuntu:24.04
|
|
||||||
|
|
||||||
# Copy the tofu binary
|
|
||||||
COPY --from=tofu /usr/local/bin/tofu /usr/local/bin/tofu
|
|
||||||
|
|
||||||
|
|
||||||
# Atualizar pacotes e instalar dependências básicas
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
curl \
|
|
||||||
git \
|
|
||||||
unzip \
|
|
||||||
jq \
|
|
||||||
gnupg \
|
|
||||||
ca-certificates \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Instalar Node.js 18 via NodeSource
|
|
||||||
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
|
|
||||||
apt-get install -y nodejs
|
|
||||||
|
|
||||||
# Verificar versões (opcional para debug)
|
|
||||||
RUN node -v && npm -v
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RUN npm install -g @bitwarden/cli
|
|
||||||
|
|
||||||
WORKDIR /workspace
|
|
||||||
@ -5,7 +5,6 @@ https://opentofu.org/docs/intro/ - quick start and explaning who to work in team
|
|||||||
https://opentofu.org/docs/intro/ - CICD for opentofu explained
|
https://opentofu.org/docs/intro/ - CICD for opentofu explained
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tofu init
|
tofu init
|
||||||
tofu plan --var-file=opentofu-varfile.json
|
tofu plan --var-file=opentofu-varfile.json
|
||||||
yes
|
yes
|
||||||
|
|||||||
12
main.tf
12
main.tf
@ -1,16 +1,20 @@
|
|||||||
terraform {
|
terraform {
|
||||||
required_providers {
|
required_providers {
|
||||||
|
random = {
|
||||||
|
source = "hashicorp/random"
|
||||||
|
version = "~> 3.6"
|
||||||
|
}
|
||||||
vaultwarden = {
|
vaultwarden = {
|
||||||
source = "ottramst/vaultwarden"
|
source = "ottramst/vaultwarden"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
}
|
}
|
||||||
bitwarden = {
|
bitwarden = {
|
||||||
source = "maxlaverse/bitwarden"
|
source = "maxlaverse/bitwarden"
|
||||||
version = ">= 0.16.0"
|
version = ">= 0.15.0"
|
||||||
}
|
}
|
||||||
proxmox = {
|
proxmox = {
|
||||||
source = "bpg/proxmox"
|
source = "telmate/proxmox"
|
||||||
version = "= 0.75.0"
|
version = "3.0.2-rc03"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
backend "consul" {
|
backend "consul" {
|
||||||
@ -20,3 +24,5 @@ terraform {
|
|||||||
lock = true # enable state locking
|
lock = true # enable state locking
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
provider "random" {}
|
||||||
@ -1,45 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from ruamel.yaml import YAML
|
|
||||||
import sys
|
|
||||||
import json
|
|
||||||
from collections.abc import Mapping
|
|
||||||
|
|
||||||
def deep_merge_yaml(dict1, dict2):
|
|
||||||
result = dict1.copy()
|
|
||||||
for key, value in dict2.items():
|
|
||||||
if key in result:
|
|
||||||
if isinstance(result[key], list) and isinstance(value, list):
|
|
||||||
result[key] = result[key] + value
|
|
||||||
elif isinstance(result[key], Mapping) and isinstance(value, Mapping):
|
|
||||||
result[key] = deep_merge_yaml(result[key], value)
|
|
||||||
else:
|
|
||||||
result[key] = value
|
|
||||||
else:
|
|
||||||
result[key] = value
|
|
||||||
return result
|
|
||||||
|
|
||||||
def main():
|
|
||||||
input_data = json.load(sys.stdin)
|
|
||||||
file1 = input_data["file1"]
|
|
||||||
file2 = input_data["file2"]
|
|
||||||
|
|
||||||
yaml = YAML()
|
|
||||||
yaml.indent(mapping=2, sequence=4, offset=2)
|
|
||||||
|
|
||||||
with open(file1, "r") as f1, open(file2, "r") as f2:
|
|
||||||
yaml1 = yaml.load(f1)
|
|
||||||
yaml2 = yaml.load(f2)
|
|
||||||
|
|
||||||
merged = deep_merge_yaml(yaml1, yaml2)
|
|
||||||
|
|
||||||
from io import StringIO
|
|
||||||
output = StringIO()
|
|
||||||
yaml.dump(merged, output)
|
|
||||||
|
|
||||||
print(json.dumps({
|
|
||||||
"merged_yaml": output.getvalue()
|
|
||||||
}))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
179
proxmox.tf
179
proxmox.tf
@ -1,180 +1,3 @@
|
|||||||
provider "proxmox" {
|
provider "proxmox" {
|
||||||
endpoint = var.proxmox_server
|
pm_api_url = var.proxmox_server
|
||||||
api_token = var.proxmox_apikey
|
|
||||||
ssh {
|
|
||||||
agent = true
|
|
||||||
username = var.proxmox_username_ssh
|
|
||||||
socks5_server = var.proxmox_server_ssh
|
|
||||||
password = var.proxmox_password_ssh
|
|
||||||
|
|
||||||
node {
|
|
||||||
name = "fenix"
|
|
||||||
address = "127.0.0.1"
|
|
||||||
port = 1081
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "proxmox_virtual_environment_download_file" "latest_ubunto_cloud_img" {
|
|
||||||
content_type = "iso"
|
|
||||||
datastore_id = "local"
|
|
||||||
node_name = "fenix"
|
|
||||||
url = "https://cloud-images.ubuntu.com/jammy/20250725/jammy-server-cloudimg-amd64.img"
|
|
||||||
file_name = "jammyservercloudimgamd64.img"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "proxmox_virtual_environment_file" "cloud_init_yaml" {
|
|
||||||
node_name = "fenix"
|
|
||||||
datastore_id = "local-snippets"
|
|
||||||
content_type = "snippets"
|
|
||||||
|
|
||||||
source_raw {
|
|
||||||
file_name = "user-data-cloud-config.yaml"
|
|
||||||
data = file("${path.module}/cloud-init-base.yaml")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
locals {
|
|
||||||
rendered_yaml_per_vm ={
|
|
||||||
for vm in var.proxmox_k8s_vms : vm.name =>
|
|
||||||
templatefile("${path.module}/cloud-init-vm.yaml.tftpl",
|
|
||||||
{
|
|
||||||
each = {
|
|
||||||
value = vm
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
data "external" "merged_yaml" {
|
|
||||||
for_each = { for vm in var.proxmox_k8s_vms : vm.name => vm }
|
|
||||||
|
|
||||||
depends_on = [local_file.rendered_yaml_file]
|
|
||||||
|
|
||||||
program = ["python3", "${path.module}/merge_yaml.py"]
|
|
||||||
|
|
||||||
query = {
|
|
||||||
file1 = "${path.module}/cloud-init-base.yaml"
|
|
||||||
file2 = "${path.module}/cloud-init-extra-${each.key}.yaml"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
resource "local_file" "rendered_yaml_file" {
|
|
||||||
for_each = { for vm in var.proxmox_k8s_vms : vm.name => vm }
|
|
||||||
|
|
||||||
content = local.rendered_yaml_per_vm[each.key]
|
|
||||||
filename = "${path.module}/cloud-init-extra-${each.key}.yaml"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Gerar um snippet cloud-init por VM
|
|
||||||
resource "proxmox_virtual_environment_file" "vm_user_data" {
|
|
||||||
for_each = { for vm in var.proxmox_k8s_vms : vm.name => vm }
|
|
||||||
|
|
||||||
node_name = "fenix"
|
|
||||||
datastore_id = "local-snippets"
|
|
||||||
content_type = "snippets"
|
|
||||||
source_raw {
|
|
||||||
file_name = "cloud-init-iac-k8s-${each.key}.yaml"
|
|
||||||
data = templatefile("${path.module}/cloud-init-wrapper.yaml.tftpl", {
|
|
||||||
content = data.external.merged_yaml[each.key].result["merged_yaml"]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
resource "proxmox_virtual_environment_vm" "proxmox-kubernetes-VM-template" {
|
|
||||||
|
|
||||||
depends_on = [proxmox_virtual_environment_download_file.latest_ubunto_cloud_img, proxmox_virtual_environment_file.cloud_init_yaml]
|
|
||||||
name = "proxmox-kubernetes-VM-template"
|
|
||||||
node_name = "fenix"
|
|
||||||
vm_id = 1002
|
|
||||||
template = true
|
|
||||||
started = false
|
|
||||||
|
|
||||||
agent {
|
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
tags = ["opentofu", "kubernetes", "fedora"]
|
|
||||||
machine = "q35"
|
|
||||||
bios = "seabios"
|
|
||||||
description = "kubernetes VM Template created via iac"
|
|
||||||
|
|
||||||
cpu {
|
|
||||||
cores = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
memory {
|
|
||||||
dedicated = 4096
|
|
||||||
}
|
|
||||||
|
|
||||||
disk {
|
|
||||||
datastore_id = "local-lvm"
|
|
||||||
file_id = proxmox_virtual_environment_download_file.latest_ubunto_cloud_img.id
|
|
||||||
interface = "scsi0"
|
|
||||||
file_format = "qcow2"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Configuração da interface de rede
|
|
||||||
network_device {
|
|
||||||
bridge = "vmbr0" # rede de gestão para comunicação com Cluster A
|
|
||||||
}
|
|
||||||
|
|
||||||
initialization {
|
|
||||||
dns {
|
|
||||||
servers = ["1.1.1.1"]
|
|
||||||
}
|
|
||||||
ip_config {
|
|
||||||
ipv4 {
|
|
||||||
address = "dhcp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
user_data_file_id = proxmox_virtual_environment_file.cloud_init_yaml.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
resource "proxmox_virtual_environment_vm" "k8s_vms" {
|
|
||||||
for_each = { for vm in var.proxmox_k8s_vms : vm.name => vm }
|
|
||||||
depends_on = [proxmox_virtual_environment_vm.proxmox-kubernetes-VM-template]
|
|
||||||
name = each.value.name
|
|
||||||
node_name = each.value.node_name
|
|
||||||
vm_id = each.value.vm_id
|
|
||||||
|
|
||||||
clone {
|
|
||||||
vm_id = proxmox_virtual_environment_vm.proxmox-kubernetes-VM-template.id
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu {
|
|
||||||
cores = each.value.cores
|
|
||||||
}
|
|
||||||
|
|
||||||
memory {
|
|
||||||
dedicated = each.value.memory
|
|
||||||
}
|
|
||||||
|
|
||||||
disk {
|
|
||||||
datastore_id = each.value.data_store
|
|
||||||
size = each.value.disk_size
|
|
||||||
interface = "scsi1"
|
|
||||||
}
|
|
||||||
|
|
||||||
initialization {
|
|
||||||
ip_config {
|
|
||||||
ipv4 {
|
|
||||||
address = each.value.ip
|
|
||||||
gateway = each.value.gateway
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
user_data_file_id = proxmox_virtual_environment_file.vm_user_data[each.key].id
|
|
||||||
}
|
|
||||||
|
|
||||||
agent {
|
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -3,56 +3,3 @@ variable "proxmox_server" {
|
|||||||
type = string
|
type = string
|
||||||
sensitive = false
|
sensitive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
variable "proxmox_server_ssh" {
|
|
||||||
description = "Proxmox server ssh url"
|
|
||||||
type = string
|
|
||||||
sensitive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "proxmox_username_ssh" {
|
|
||||||
description = "Proxmox server ssh username"
|
|
||||||
type = string
|
|
||||||
sensitive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "proxmox_password_ssh" {
|
|
||||||
description = "Proxmox server ssh password"
|
|
||||||
type = string
|
|
||||||
sensitive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "proxmox_apikey" {
|
|
||||||
description = "Proxmox server api key"
|
|
||||||
type = string
|
|
||||||
sensitive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "node_name" {
|
|
||||||
default = "fenix"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Lista de VMs (override de valores específicos)
|
|
||||||
variable "proxmox_k8s_vms" {
|
|
||||||
type = list(object({
|
|
||||||
name = string
|
|
||||||
vm_id = number
|
|
||||||
node_name = string
|
|
||||||
ip = string
|
|
||||||
ip2 = string
|
|
||||||
ip3 = string
|
|
||||||
cores = optional(number)
|
|
||||||
memory = optional(number)
|
|
||||||
data_store = optional(string)
|
|
||||||
gateway = string
|
|
||||||
disk_size = optional(number)
|
|
||||||
extra_users = optional(list(object({
|
|
||||||
name = string
|
|
||||||
password = string
|
|
||||||
groups = list(string)
|
|
||||||
})))
|
|
||||||
extra_packages = optional(list(string))
|
|
||||||
extra_runcmd = optional(list(string))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
@ -3,56 +3,3 @@ PM_API_TOKEN_ID = "tokenid"
|
|||||||
PM_API_TOKEN_SECRET = "tokensecret"
|
PM_API_TOKEN_SECRET = "tokensecret"
|
||||||
# tokenid is read automatically from PM_API_TOKEN_ID
|
# tokenid is read automatically from PM_API_TOKEN_ID
|
||||||
# token is read automatically from PM_API_TOKEN_SECRET
|
# token is read automatically from PM_API_TOKEN_SECRET
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proxmox_server = "https://proxmox.example.com:443/api2/json"
|
|
||||||
proxmox_apikey = "user@pam!token=fdjkdslfjdsflkj"
|
|
||||||
proxmox_server_ssh = "127.0.0.1:1080"
|
|
||||||
proxmox_username_ssh = "user"
|
|
||||||
proxmox_password_ssh = "password"
|
|
||||||
# tokenid is read automatically from PM_API_TOKEN_ID
|
|
||||||
# token is read automatically from PM_API_TOKEN_SECRET
|
|
||||||
|
|
||||||
proxmox_k8s_vms = [
|
|
||||||
{
|
|
||||||
name = "k8s-master-01"
|
|
||||||
vm_id = 3001
|
|
||||||
node_name = "node"
|
|
||||||
ip = "192.168.1.99/24"
|
|
||||||
cores = 2
|
|
||||||
memory = 2000
|
|
||||||
disk_size = 32
|
|
||||||
data_store = "local-lvm"
|
|
||||||
gateway = "192.168.1.1"
|
|
||||||
extra_users = [
|
|
||||||
{
|
|
||||||
name = "user"
|
|
||||||
password = "pass"
|
|
||||||
groups = ["sudo"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
extra_packages = []
|
|
||||||
extra_runcmd = []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name = "k8s-worker-01"
|
|
||||||
vm_id = 3002
|
|
||||||
node_name = "node"
|
|
||||||
ip = "192.168.1.101/24"
|
|
||||||
cores = 1
|
|
||||||
memory = 2000
|
|
||||||
disk_size = 32
|
|
||||||
data_store = "local-lvm"
|
|
||||||
gateway = "192.168.1.1"
|
|
||||||
extra_users = [
|
|
||||||
{
|
|
||||||
name = "user"
|
|
||||||
password = "pass"
|
|
||||||
groups = ["sudo"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
extra_packages = []
|
|
||||||
extra_runcmd = []
|
|
||||||
},
|
|
||||||
]
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"secrets": [
|
|
||||||
{
|
|
||||||
"name": "iac.opentofu.consul.secrets",
|
|
||||||
"type": "note",
|
|
||||||
"output": "../secrets/secrets/consul.secrets.tfvars"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "iac.opentofu.proxmox.secrets",
|
|
||||||
"type": "note",
|
|
||||||
"output": "../secrets/secrets/proxmox.secrets.tfvars"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "iac.opentofu.vaultwarden.secrets",
|
|
||||||
"type": "note",
|
|
||||||
"output": "../secrets/secrets/vaultwarden.secrets.tfvars"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -4,5 +4,3 @@ vaultwarden_master_password = "SuperSecretMasterPassword"
|
|||||||
vaultwarden_admin_token = "tokenadmin"
|
vaultwarden_admin_token = "tokenadmin"
|
||||||
vaultwarden_client_id = "clientid"
|
vaultwarden_client_id = "clientid"
|
||||||
vaultwarden_client_secret = "clientsecret"
|
vaultwarden_client_secret = "clientsecret"
|
||||||
# email is read automatically from BW_EMAIL
|
|
||||||
# password is read automatically from BW_PASSWORD
|
|
||||||
@ -16,13 +16,6 @@ resource "vaultwarden_account_register" "vaultwarden-acount-fenix" {
|
|||||||
password = var.vaultwarden_master_password
|
password = var.vaultwarden_master_password
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "bitwarden_item_login" "administrative-user" {
|
|
||||||
name = "teste"
|
|
||||||
username = "teste"
|
|
||||||
password = "teste"
|
|
||||||
collection_ids = [vaultwarden_organization_collection.vaultwarden-collection-iac.id]
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "vaultwarden_organization" "vaultwarden-organization-fenix-iac" {
|
resource "vaultwarden_organization" "vaultwarden-organization-fenix-iac" {
|
||||||
name = "fenix-iac"
|
name = "fenix-iac"
|
||||||
}
|
}
|
||||||
@ -33,28 +26,9 @@ resource "vaultwarden_organization_collection" "vaultwarden-collection-iac" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
resource "bitwarden_item_secure_note" "hosts-ini" {
|
resource "bitwarden_item_login" "administrative-user" {
|
||||||
name = "iac.ansible.hosts.ini"
|
name = "teste"
|
||||||
notes = <<EOT
|
username = "teste"
|
||||||
${local.hosts_ini}
|
password = "teste"
|
||||||
EOT
|
|
||||||
organization_id = vaultwarden_organization.vaultwarden-organization-fenix-iac.id
|
|
||||||
collection_ids = [vaultwarden_organization_collection.vaultwarden-collection-iac.id]
|
collection_ids = [vaultwarden_organization_collection.vaultwarden-collection-iac.id]
|
||||||
reprompt = true
|
|
||||||
}
|
|
||||||
|
|
||||||
locals{
|
|
||||||
hosts_ini = <<EOT
|
|
||||||
|
|
||||||
[master]
|
|
||||||
master1 ansible_host=${split("/", var.proxmox_k8s_vms[0].ip)[0]} ansible_user=${var.proxmox_k8s_vms[0].extra_users[0].name} ansible_ssh_pass=${var.proxmox_k8s_vms[0].extra_users[0].password} ansible_ssh_common_args='-o StrictHostKeyChecking=no'
|
|
||||||
|
|
||||||
[workers]
|
|
||||||
%{ for i, vm in var.proxmox_k8s_vms ~}
|
|
||||||
%{ if i != 0 }
|
|
||||||
worker-${replace(split("/", vm.ip)[0], ".", "-")} ansible_host=${split("/", vm.ip)[0]} ansible_user=${vm.extra_users[0].name} ansible_ssh_pass=${vm.extra_users[0].password} ansible_ssh_common_args='-o StrictHostKeyChecking=no'
|
|
||||||
%{ endif }
|
|
||||||
%{ endfor }
|
|
||||||
|
|
||||||
EOT
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user