43 Commits

Author SHA1 Message Date
4f38f3a851 add ability to log to file, update to v2.28.1 and fix 'first upgrade' issue 2025-09-13 00:49:05 +03:00
d51a98efb3 update README.md 2025-08-10 14:32:53 +03:00
670d6da550 update README.md 2025-08-10 14:29:36 +03:00
b6087afc46 change panic to fatal log 2025-08-10 14:28:32 +03:00
4ede8161f8 remove unused files for ansible 2025-08-10 01:12:49 +03:00
c2f41356cb add roles support for worker nodes 2025-08-09 21:46:23 +03:00
55fdd58f92 update README for supported versions 2025-08-09 17:05:31 +03:00
5466c3e36f add supported k8s version check 2025-08-09 17:00:02 +03:00
5e8b03ff10 remove docker build 2025-06-22 00:38:37 +03:00
4142a9db61 kube-forge v2: embede python with ansible (kubespray) and cobra as cli building tool 2025-06-22 00:37:47 +03:00
c2df2abc78 actualized for kubespray version 2.28.0 2025-06-15 20:25:45 +03:00
c819d4f51f add ability to specify local_path_provisioner data dir for PersistentVolumes 2024-12-29 12:32:25 +03:00
46e057e41b add ability to specify default LB when using ipvs 2024-12-21 15:33:15 +03:00
e2dabc8728 fix kubelet data dir setting 2024-12-14 22:33:46 +03:00
4294f52703 update to latest 2.26.0 kubespray version and add dns zones settings to coredns 2024-12-14 21:56:19 +03:00
be9c8a28fd fix download issues when using scale 2024-12-14 18:56:34 +03:00
1c366bdb6b update kube-forge concept and add ability to change data dir for containerd 2024-11-24 17:59:37 +03:00
78cf06e314 migrate from kubespray to library helm client 2024-06-20 00:20:50 +03:00
3109816dee update observability module 2024-06-02 21:34:03 +03:00
4e302c4e8b update demo app 2024-06-02 21:17:22 +03:00
b8461de213 update demo app 2024-06-02 21:15:30 +03:00
805a6e0ea0 add demo application 2024-06-02 20:04:39 +03:00
659a6a9d87 add demo application 2024-06-02 20:01:00 +03:00
0efab9f3a9 add demo application 2024-06-02 19:50:34 +03:00
1176542890 add demo application 2024-06-02 19:48:29 +03:00
2aa57de134 add demo application 2024-06-02 19:41:49 +03:00
0692ae5569 add demo application 2024-06-02 19:38:51 +03:00
507f07ee57 add demo application 2024-06-02 19:33:40 +03:00
83ce5b53f3 add demo application 2024-06-02 19:23:12 +03:00
cd368c7755 update images for registry and cicd modules and add ability to set registry mirrors for orchestrator 2024-06-01 21:38:17 +03:00
005f7bfbe9 change default images to prevent error during installation 2024-06-01 18:53:42 +03:00
d4db0cd840 update grafana module (https://git.kvazaric.ru/gstykalin/kube-forge/-/issues/7) 2024-05-30 00:05:06 +03:00
4992a8e48a update .gitlab-ci.yml 2024-05-25 23:03:14 +03:00
72007080ce update .gitlab-ci.yml 2024-05-25 23:01:31 +03:00
3542ac522b update .gitlab-ci.yml 2024-05-25 22:58:06 +03:00
d162439eac update README.md 2024-05-25 21:53:59 +03:00
f84c27e622 add ability to specify paths for argocd and grafana (https://git.kvazaric.ru/gstykalin/kube-forge/-/issues/1) 2024-05-25 21:31:10 +03:00
36d886d94a add ability to enable verbose logging 2024-05-17 00:20:33 +03:00
5ac4607f79 add prepare release job 2024-05-16 00:50:27 +03:00
71bd08d255 add prepare release job 2024-05-16 00:42:48 +03:00
53b1d35835 add prepare release job 2024-05-16 00:40:20 +03:00
a8f1be0297 add prepare release job 2024-05-16 00:34:19 +03:00
9f6f598acc add prepare release job 2024-05-16 00:23:05 +03:00
1033 changed files with 27494 additions and 30349 deletions

9
.gitignore vendored
View File

@@ -5,3 +5,12 @@
*k8s-admin*
vault-keys.json
config.yaml
temp
*id_rsa*
.venv
.ropeproject
*__pycache__
bin
internal/python/data
logs
*.log

View File

@@ -1,83 +0,0 @@
variables:
DOCKER_IMAGE: harbor.kvazaric.ru/kube-forge/kube-forge
KANIKO_IMAGE: harbor.kvazaric.ru/postgres-tasks/kaniko_executor:debug
KANIKO_CONTEXT: ${CI_PROJECT_DIR}
RELEASE_CLI_IMAGE: harbor.kvazaric.ru/kube-forge/release-cli:v0.18.0
PREPARE_RELEASE:
options:
- "No"
- "Yes"
value: "No"
description: Create release from this build?
WITHOUT_BUILD:
options:
- "No"
- "Yes"
value: "Yes"
description: Create release without building?
stages:
- build
- release
build-docker:
variables:
DOCKERFILE_PATH: Dockerfile
IMAGE_DESTINATION: image
stage: build
image:
name: ${KANIKO_IMAGE}
entrypoint: [""]
allow_failure: false
tags:
- build
- docker
before_script:
- mkdir -p /kaniko/.docker
- echo "${DOCKER_AUTH_CONFIG}" > /kaniko/.docker/config.json
- VERSION=$(cat ${CI_PROJECT_DIR}/build/version.txt)
script:
- |
/kaniko/executor --context "${KANIKO_CONTEXT}" \
--dockerfile ${CI_PROJECT_DIR}/build/docker/Dockerfile \
--destination "${DOCKER_IMAGE}:${VERSION}-${CI_COMMIT_SHORT_SHA}"
dependencies: []
rules:
- if: $PREPARE_RELEASE == "Yes" && $WITHOUT_BUILD == "Yes"
when: never
- changes:
- build/docker/**/*
- cmd/**/*
- internal/**/*
- kubespray/**/*
- go.sum
- go.mod
- requirements.txt
- ansible.cfg
if: $CI_COMMIT_REF_NAME =~ /^(master)$/
when: always
make-release:
stage: release
image: ${RELEASE_CLI_IMAGE}
tags:
- build
- docker
rules:
- if: $PREPARE_RELEASE == "Yes"
script:
- VERSION=$(cat ${CI_PROJECT_DIR}/build/version.txt)
- echo "Preparing release for version ${VERSION}-${CI_COMMIT_SHORT_SHA}"
release: # See https://docs.gitlab.com/ee/ci/yaml/#release for available properties
name: kube-forge:${VERSION}-${CI_COMMIT_SHORT_SHA}
tag_name: "${CI_COMMIT_SHORT_SHA}"
description: "${VERSION}-${CI_COMMIT_SHORT_SHA}"
assets:
links:
- name: "Docker image"
url: "harbor.kvazaric.ru/kube-forge/kube-forge:${VERSION}-${CI_COMMIT_SHORT_SHA}"
link_type: "image"
when: on_success

19
Makefile Normal file
View File

@@ -0,0 +1,19 @@
BINNAME := kube-forge
BINDIR := $(CURDIR)/bin
TARGETS := darwin/amd64 darwin/arm64 linux/amd64 linux/arm linux/arm64 windows/amd64 windows/arm64
.PHONY: run
run:
@'$(BINDIR)/'$(BINNAME)
.PHONY: build
build:
@go generate ./...
@go build -v -trimpath -ldflags "-s -w" -o '$(BINDIR)/'$(BINNAME) ./cmd/main/main.go
.PHONY: clean
clean:
@rm -r ${BINDIR}
.DEFAULT_GOAL := build

View File

@@ -1,13 +1,54 @@
## Устнановка
### Docker-образ
## Примеры запуска
### Docker-образ
## С помощью исполняемого файла
```shell
docker run -v $(pwd)/config.yaml:/application/config.yaml \
-v $(pwd)/id_rsa:/root/.ssh/id_rsa \
-v $(pwd)/config:/root/.ssh/config harbor.kvazaric.ru/kube-forge/kube-forge:1.0-5dcd4a83 apply
kube-forge -c config.yaml apply
```
## Параметры:
- "-с" путь до конфигурационного файла
- "-o" директория для сохранения админ-конфига для доступа к кластеру
- "-p" пароль для авторизации через SSH
- "-v" включить расширенное логирование
- "-h" help для основных параметров и команд
- --log-file" путь до файла для сохранение логов установки
## Поддерживаемые версии Kubernetes
На данный момент поддерживается установка/обновление следующих версий:
- 1.32.8
- 1.32.7
- 1.32.6
- 1.32.5
- 1.32.4
- 1.32.3
- 1.32.2
- 1.32.1
- 1.32.0
- 1.31.9
- 1.31.8
- 1.31.7
- 1.31.6
- 1.31.5
- 1.31.4
- 1.31.3
- 1.31.2
- 1.31.1
- 1.31.0
- 1.30.13
- 1.30.12
- 1.30.11
- 1.30.10
- 1.30.9
- 1.30.8
- 1.30.7
- 1.30.6
- 1.30.5
- 1.30.4
- 1.30.3
- 1.30.2
- 1.30.1
- 1.30.0

View File

@@ -1,22 +0,0 @@
[ssh_connection]
pipelining=True
ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100 -o UserKnownHostsFile=/dev/null
#control_path = ~/.ssh/ansible-%%r@%%h:%%p
[defaults]
# https://github.com/ansible/ansible/issues/56930 (to ignore group names with - and .)
force_valid_group_names = ignore
host_key_checking=False
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp
fact_caching_timeout = 86400
stdout_callback = dense
display_skipped_hosts = no
library = ./library
callbacks_enabled = profile_tasks,ara_default
roles_path = roles:$VIRTUAL_ENV/usr/local/share/kubespray/roles:$VIRTUAL_ENV/usr/local/share/ansible/roles:/usr/share/kubespray/roles
deprecation_warnings=False
inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo, .creds, .gpg
[inventory]
ignore_patterns = artifacts, credentials

View File

@@ -1,5 +0,0 @@
## Сборка Docker
## Сборка Linux
### Debian

View File

@@ -1,5 +0,0 @@
Package: kube-forge
Version: 1.0
Architecture: amd64
Maintainer: Kvazaric <kvazaric.official@gmail.com>
Description: A program to install Kubernetes-based platform to facilitate the development, desting and dperation of Ccntainerized applications

View File

@@ -1,4 +0,0 @@
k8s-admin.conf
docs
*/build
examples

View File

@@ -1,29 +0,0 @@
## Install dependencies
FROM python:3.12 as deps
WORKDIR /application
COPY ./requirements.txt ./
RUN apt-get update -y && \
apt-get install sshpass -y && \
pip3 install -r requirements.txt
## Build executable
FROM golang:alpine as builder
WORKDIR /application
COPY go.mod go.sum ./
RUN go mod download
WORKDIR /application
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -v -o kube-forge ./cmd/main/main.go
FROM deps
WORKDIR /application
COPY . .
COPY --from=builder /application/kube-forge /application/kube-forge
ENV ANSIBLE_HOST_KEY_CHECKING=False
ENTRYPOINT ["./kube-forge", "-c", "config.yaml", "-d", "."]

View File

@@ -1 +0,0 @@
1.0

20
cmd/apply-modules.go Normal file
View File

@@ -0,0 +1,20 @@
package cmd
import (
"kube-forge/internal/templates"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(applyModulesCmd)
}
var applyModulesCmd = &cobra.Command{
Use: "apply-modules",
Short: "Apply only additional modules",
Run: func(cmd *cobra.Command, args []string) {
templates.ApplyK8sTemplates()
installAndConfigureModules()
},
}

22
cmd/apply.go Normal file
View File

@@ -0,0 +1,22 @@
package cmd
import (
"kube-forge/internal/kubespray"
"kube-forge/internal/templates"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(applyCmd)
}
var applyCmd = &cobra.Command{
Use: "apply",
Short: "Apply configuration",
Run: func(cmd *cobra.Command, args []string) {
templates.ApplyK8sTemplates()
kubespray.InstallCluster("")
installAndConfigureModules()
},
}

View File

@@ -1,48 +1,9 @@
package main
import (
"flag"
"fmt"
"kube-forge/internal/config"
"kube-forge/internal/kubespray"
"kube-forge/internal/templates"
"os"
"kube-forge/cmd"
)
func parseArgs() (string, string, string) {
var password, configPath, workDir string
flag.StringVar(&password, "p", "", "Password to access hosts")
flag.StringVar(&configPath, "c", "/etc/kube-forge/config.yaml", "Path to config file")
flag.StringVar(&workDir, "d", "/var/lib/kube-forge", "Path to kube-forge work dir")
flag.Parse()
return password, configPath, workDir
}
func main() {
password, configPath, workDir := parseArgs()
config := config.CreateConfig(configPath, workDir, password)
repositories, releases := templates.GetHelmAppsConfigData()
config.Repositories = repositories
config.Releases = releases
templates.ApplyK8sTemplates()
for _, cmd := range os.Args {
switch cmd {
case "apply":
kubespray.InstallCluster("")
return
case "apply-modules":
kubespray.InstallCluster("helm-apps")
return
case "upgrade":
kubespray.UpgradeCluster("")
return
case "scale":
kubespray.ScaleCluster()
return
}
}
fmt.Println("No such command\nAvailable commands: apply, apply-modules, upgrade, scale")
cmd.Execute()
}

21
cmd/reset.go Normal file
View File

@@ -0,0 +1,21 @@
package cmd
import (
"kube-forge/internal/kubespray"
"kube-forge/internal/templates"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(resetCmd)
}
var resetCmd = &cobra.Command{
Use: "reset",
Short: "Reset cluster",
Run: func(cmd *cobra.Command, args []string) {
templates.ApplyK8sTemplates()
kubespray.ResetCluster()
},
}

45
cmd/root.go Normal file
View File

@@ -0,0 +1,45 @@
package cmd
import (
"fmt"
"kube-forge/internal/additional"
"kube-forge/internal/config"
"kube-forge/internal/csi"
"os"
"github.com/spf13/cobra"
)
func installAndConfigureModules() {
csi.ApplyCharts()
additional.ApplyCharts()
}
func init() {
rootCmd.PersistentFlags().StringVarP(&config.ConfigFile, "config", "c", "config.yaml", "path to configuration file for cluster")
rootCmd.PersistentFlags().StringVarP(&config.Output, "output", "o", "", "directory to store k8s admin config")
rootCmd.PersistentFlags().StringVarP(&config.Password, "password", "p", "", "password to access hosts via SSH")
rootCmd.PersistentFlags().CountVarP(&config.Verbose, "verbose", "v", "enable verbose logging (use -v, -vv, -vvv for increasing levels)")
rootCmd.PersistentFlags().StringVar(&config.LogFile, "log-file", "", "path to log file for verbose output")
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
var (
rootCmd = &cobra.Command{
Use: "kube-forge <subcommand>",
Short: "Kube-forge will help you to deploy K8s clusters",
Long: `An easy to use K8s installer`,
Args: func(cmd *cobra.Command, args []string) error {
if err := cobra.MinimumNArgs(0)(cmd, args); err != nil {
return err
}
return nil
},
}
)

21
cmd/scale.go Normal file
View File

@@ -0,0 +1,21 @@
package cmd
import (
"kube-forge/internal/kubespray"
"kube-forge/internal/templates"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(scaleCmd)
}
var scaleCmd = &cobra.Command{
Use: "scale",
Short: "Scale cluster. Use when adding new nodes",
Run: func(cmd *cobra.Command, args []string) {
templates.ApplyK8sTemplates()
kubespray.ScaleCluster()
},
}

21
cmd/upgrade.go Normal file
View File

@@ -0,0 +1,21 @@
package cmd
import (
"kube-forge/internal/kubespray"
"kube-forge/internal/templates"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(upgradeCmd)
}
var upgradeCmd = &cobra.Command{
Use: "upgrade",
Short: "Upgrade cluster. Use when changing version of K8s",
Run: func(cmd *cobra.Command, args []string) {
templates.ApplyK8sTemplates()
kubespray.UpgradeCluster("")
},
}

15
cmd/utils.go Normal file
View File

@@ -0,0 +1,15 @@
package cmd
import (
"log"
"os/user"
)
func GetUserHomeDir() string {
usr, err := user.Current()
if err != nil {
log.Fatalf("cant get user home directory: %v", err)
}
homePath := usr.HomeDir
return homePath
}

View File

@@ -1,123 +1,56 @@
credentials:
user: sre-admin
user: georgest
ask_sudo_password: false
private_key_file: /home/sre-admin/.ssh/id_rsa
private_key_file: /Users/georgest/.ssh/id_rsa
hosts:
- hostname: vbox-prod-k8s-master-01
ip: "10.250.50.22"
roles: [control_plane, etcd]
- hostname: vbox-prod-k8s-slave-01
ip: "10.250.50.23"
roles: [node]
- hostname: vbox-prod-k8s-slave-02
ip: "10.250.50.21"
roles: [node]
master:
- hostname: k8s-master-1
ip: "172.16.1.136"
worker:
- hostname: k8s-worker-1
ip: "172.16.1.135"
# roles: [infra]
- hostname: k8s-worker-2
ip: "172.16.1.137"
# roles: [ingress]
orchestrator:
version: v1.29.0
version: "1.32.4"
cluster_name: cluster.local
kubelet_dir: "/app/k8s/kubelet"
proxy_mode: "ipvs"
proxy_scheduler: "lc"
container_engine:
install: true
type: "containerd"
data_dir: "/app/containerd"
state_dir: "/app/containerd-state"
dns:
servers:
- 8.8.8.8
- 8.8.4.4
- 1.1.1.1
disable_host_nameservers: false
ping_access_ip: true
auto_renew_certificates: true
pod_security_policy_enabled: true
registry_mirrors:
- host: https://mirror.gcr.io
skip_verify: false
- host: https://quay.io
skip_verify: false
modules:
admin_password: changeit
observability:
enabled: true
logging:
enabled: true
events:
enabled: true
tracing:
enabled: true
monitoring:
enabled: true
alert_manager:
enabled: true
route:
receiver: kvazaric_notifications
group_wait: 1s
repeat_interval: 180m
routes:
- receiver: "kvazaric_notifications"
group_by: ["alertname"]
group_wait: 1s
repeat_interval: 8737h
matchers:
- fireOnce=true
receivers:
- name: kvazaric_notifications
telegram_configs:
- send_resolved: true
api_url: https://api.telegram.org
bot_token: bot_token
chat_id: -10000
parse_mode: HTML
message: '{% raw %}{{ "{{" }} template "default-message" . {{ "}}" }}{% endraw %}'
http_config:
follow_redirects: true
enable_http2: false
blackbox:
enabled: true
kube_state:
enabled: true
node:
enabled: true
visualization:
enabled: true
grafana:
enabled: true
expose:
type: ingress # ingress or NodePort
domain: grafana.disk.lt.t1.cloud
tls:
enabled: true
cicd:
enabled: true
argo_cd:
expose:
type: ingress # ingress or NodePort
domain: argocd.disk.lt.t1.cloud
tls:
enabled: true
rollouts:
enabled: true
updates_operator:
enabled: true
secrets_storage:
enabled: true
key_shares: 5
key_threshold: 3
expose:
type: ingress # ingress or NodePort
domain: vault.disk.lt.t1.cloud
tls:
enabled: true
csi_integration:
enabled: true
registry:
enabled: true
expose:
type: ingress # ingress or nodePort
domain: harbor.disk.lt.t1.cloud
tls:
enabled: true
enabled_scanner: true
additional:
cert_manager:
enabled: true
account_email: adminmail@gmail.com
ingress:
enabled: true
host_network: true
account_email: gstykalin@mail.ru
storage:
local_path_provisioner:
data_dir: "/app/local-path-provisioner"
longhorn:
enabled: true
enabled: false
secrets_store_csi_driver:
enabled: true
enabled: false

View File

@@ -1 +0,0 @@
https://github.com/argoproj/argocd-example-apps/tree/master/guestbook

View File

@@ -1,65 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: canary-demo-preview
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: canary-demo
---
apiVersion: v1
kind: Service
metadata:
name: canary-demo
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: canary-demo
---
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: canary-demo
spec:
replicas: 5
revisionHistoryLimit: 1
selector:
matchLabels:
app: canary-demo
template:
metadata:
labels:
app: canary-demo
spec:
containers:
- name: canary-demo
image: argoproj/rollouts-demo:green
imagePullPolicy: Always
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m
strategy:
canary:
canaryService: canary-demo-preview
steps:
- setWeight: 20
- pause: {}
- setWeight: 40
- pause: { duration: 10 }
- setWeight: 60
- pause: { duration: 10 }
- setWeight: 80
- pause: { duration: 10 }

View File

@@ -1,38 +0,0 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-inject-example
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault-inject-example-deployment
spec:
replicas: 1
selector:
matchLabels:
app: vault-inject-example
template:
metadata:
labels:
app: vault-inject-example
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "vault-example"
vault.hashicorp.com/agent-inject-secret-env: "vault-example/creds"
vault.hashicorp.com/auth-path: "auth/kubernetes-local"
vault.hashicorp.com/agent-inject-template-env: |
{{- with secret "vault-example/creds" -}}
{{- range $key, $value := .Data.data }}
export {{ $key }}={{ $value }}
{{- end }}
{{- end }}
spec:
containers:
- name: app
image: "postgres:latest"
env:
- name: POSTGRES_PASSWORD
value: admin
serviceAccountName: vault-inject-example

183
go.mod
View File

@@ -1,79 +1,152 @@
module kube-forge
go 1.22.0
toolchain go1.22.2
go 1.25.1
require (
github.com/BurntSushi/toml v1.2.1
github.com/Masterminds/sprig/v3 v3.2.3
github.com/BurntSushi/toml v1.5.0
github.com/Masterminds/sprig/v3 v3.3.0
github.com/apenella/go-ansible v1.3.0
github.com/apenella/go-ansible/v2 v2.0.0
github.com/apenella/go-ansible/v2 v2.2.0
github.com/ilyakaznacheev/cleanenv v1.5.0
golang.org/x/crypto v0.22.0
sigs.k8s.io/yaml v1.4.0
github.com/kluctl/go-embed-python v0.0.0-3.13.1-20241219-1
github.com/mittwald/go-helm-client v0.12.18
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.10.1
gopkg.in/yaml.v2 v2.4.0
helm.sh/helm/v3 v3.19.0
)
require (
dario.cat/mergo v1.0.2 // indirect
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/apenella/go-common-utils/data v0.0.0-20220913191136-86daaa87e7df // indirect
github.com/apenella/go-common-utils/error v0.0.0-20220913191136-86daaa87e7df // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/Masterminds/squirrel v1.5.4 // indirect
github.com/apenella/go-common-utils/data v0.0.0-20221227202648-5452d804e940 // indirect
github.com/apenella/go-common-utils/error v0.0.0-20221227202648-5452d804e940 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/chai2010/gettext-go v1.0.3 // indirect
github.com/containerd/containerd v1.7.28 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/docker-credential-helpers v0.9.3 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-openapi/jsonpointer v0.22.0 // indirect
github.com/go-openapi/jsonreference v0.21.1 // indirect
github.com/go-openapi/swag v0.24.1 // indirect
github.com/go-openapi/swag/cmdutils v0.24.0 // indirect
github.com/go-openapi/swag/conv v0.24.0 // indirect
github.com/go-openapi/swag/fileutils v0.24.0 // indirect
github.com/go-openapi/swag/jsonname v0.24.0 // indirect
github.com/go-openapi/swag/jsonutils v0.24.0 // indirect
github.com/go-openapi/swag/loading v0.24.0 // indirect
github.com/go-openapi/swag/mangling v0.24.0 // indirect
github.com/go-openapi/swag/netutils v0.24.0 // indirect
github.com/go-openapi/swag/stringutils v0.24.0 // indirect
github.com/go-openapi/swag/typeutils v0.24.0 // indirect
github.com/go-openapi/swag/yamlutils v0.24.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.11 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/gosuri/uitable v0.0.4 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmoiron/sqlx v1.4.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/spdystream v0.5.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rubenv/sql-migrate v1.8.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.9.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.33.0 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.42.0 // indirect
golang.org/x/net v0.44.0 // indirect
golang.org/x/oauth2 v0.31.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/term v0.35.0 // indirect
golang.org/x/text v0.29.0 // indirect
golang.org/x/time v0.13.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect
google.golang.org/grpc v1.75.1 // indirect
google.golang.org/protobuf v1.36.9 // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.30.0 // indirect
k8s.io/apimachinery v0.30.0 // indirect
k8s.io/client-go v0.30.0 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
k8s.io/api v0.34.1 // indirect
k8s.io/apiextensions-apiserver v0.34.1 // indirect
k8s.io/apimachinery v0.34.1 // indirect
k8s.io/apiserver v0.34.1 // indirect
k8s.io/cli-runtime v0.34.1 // indirect
k8s.io/client-go v0.34.1 // indirect
k8s.io/component-base v0.34.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
k8s.io/kubectl v0.34.1 // indirect
k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d // indirect
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
oras.land/oras-go/v2 v2.6.0 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/kustomize/api v0.20.1 // indirect
sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)

529
go.sum
View File

@@ -1,62 +1,187 @@
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
github.com/apenella/go-ansible v1.3.0 h1:INNaVzrgQMNIO9Yvnly6lA5KfN/pY3m1Z37gpmlUzPM=
github.com/apenella/go-ansible v1.3.0/go.mod h1:qiLWolQqLkCoqFlPvdsKhxk7O0qjIBCPNhUKpH/vjaU=
github.com/apenella/go-ansible/v2 v2.0.0 h1:9aZkU8dQ2fVITYX5V1CiQ3VX4PnNPBTgv31wJFd2Ito=
github.com/apenella/go-ansible/v2 v2.0.0/go.mod h1:ifhiX4d0bpynb8yhdzLTmGl/38HqTYr/26PfjB1enXQ=
github.com/apenella/go-common-utils/data v0.0.0-20220913191136-86daaa87e7df h1:sEikY2P+NZK/7VZUwIsnXIGElhsuFDSxh1bZYwHxdcI=
github.com/apenella/go-common-utils/data v0.0.0-20220913191136-86daaa87e7df/go.mod h1:cLVL6GjUiKG/WyBzX+KD6h/XRV/HnNZIZbMNNiBgQ9o=
github.com/apenella/go-common-utils/error v0.0.0-20220913191136-86daaa87e7df h1:SvlYbjlsSQDS7hbVT1h012/zdgvcwWJ+Yd9XRiiY/8s=
github.com/apenella/go-common-utils/error v0.0.0-20220913191136-86daaa87e7df/go.mod h1:+3dyIlHX350xJIUIffwMLswZXU+N2FwDE05VuKqxYdw=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/apenella/go-ansible/v2 v2.2.0 h1:IldFymiRy9hc+rCyZ0dj4jJfLUmW9wjzU4JxoOMy9KE=
github.com/apenella/go-ansible/v2 v2.2.0/go.mod h1:G3JNiTazO5t/PEriJFywV/4RFu2RtzAxxR7Z5SoYF78=
github.com/apenella/go-common-utils/data v0.0.0-20221227202648-5452d804e940 h1:heIU8S8TKSbqebsLywfM4n8pvQtqjDZHU6gVPbzrQHQ=
github.com/apenella/go-common-utils/data v0.0.0-20221227202648-5452d804e940/go.mod h1:cLVL6GjUiKG/WyBzX+KD6h/XRV/HnNZIZbMNNiBgQ9o=
github.com/apenella/go-common-utils/error v0.0.0-20221227202648-5452d804e940 h1:M6LTqQBjGqTf9t0O2i0GunjhlsX4REK8aSS44sGOEv4=
github.com/apenella/go-common-utils/error v0.0.0-20221227202648-5452d804e940/go.mod h1:+3dyIlHX350xJIUIffwMLswZXU+N2FwDE05VuKqxYdw=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70=
github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chai2010/gettext-go v1.0.3 h1:9liNh8t+u26xl5ddmWLmsOsdNLwkdRTg5AG+JnTiM80=
github.com/chai2010/gettext-go v1.0.3/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/containerd/containerd v1.7.28 h1:Nsgm1AtcmEh4AHAJ4gGlNSaKgXiNccU270Dnf81FQ3c=
github.com/containerd/containerd v1.7.28/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM=
github.com/distribution/distribution/v3 v3.0.0/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8=
github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI=
github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs=
github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.22.0 h1:TmMhghgNef9YXxTu1tOopo+0BGEytxA+okbry0HjZsM=
github.com/go-openapi/jsonpointer v0.22.0/go.mod h1:xt3jV88UtExdIkkL7NloURjRQjbeUgcxFblMjq2iaiU=
github.com/go-openapi/jsonreference v0.21.1 h1:bSKrcl8819zKiOgxkbVNRUBIr6Wwj9KYrDbMjRs0cDA=
github.com/go-openapi/jsonreference v0.21.1/go.mod h1:PWs8rO4xxTUqKGu+lEvvCxD5k2X7QYkKAepJyCmSTT8=
github.com/go-openapi/swag v0.24.1 h1:DPdYTZKo6AQCRqzwr/kGkxJzHhpKxZ9i/oX0zag+MF8=
github.com/go-openapi/swag v0.24.1/go.mod h1:sm8I3lCPlspsBBwUm1t5oZeWZS0s7m/A+Psg0ooRU0A=
github.com/go-openapi/swag/cmdutils v0.24.0 h1:KlRCffHwXFI6E5MV9n8o8zBRElpY4uK4yWyAMWETo9I=
github.com/go-openapi/swag/cmdutils v0.24.0/go.mod h1:uxib2FAeQMByyHomTlsP8h1TtPd54Msu2ZDU/H5Vuf8=
github.com/go-openapi/swag/conv v0.24.0 h1:ejB9+7yogkWly6pnruRX45D1/6J+ZxRu92YFivx54ik=
github.com/go-openapi/swag/conv v0.24.0/go.mod h1:jbn140mZd7EW2g8a8Y5bwm8/Wy1slLySQQ0ND6DPc2c=
github.com/go-openapi/swag/fileutils v0.24.0 h1:U9pCpqp4RUytnD689Ek/N1d2N/a//XCeqoH508H5oak=
github.com/go-openapi/swag/fileutils v0.24.0/go.mod h1:3SCrCSBHyP1/N+3oErQ1gP+OX1GV2QYFSnrTbzwli90=
github.com/go-openapi/swag/jsonname v0.24.0 h1:2wKS9bgRV/xB8c62Qg16w4AUiIrqqiniJFtZGi3dg5k=
github.com/go-openapi/swag/jsonname v0.24.0/go.mod h1:GXqrPzGJe611P7LG4QB9JKPtUZ7flE4DOVechNaDd7Q=
github.com/go-openapi/swag/jsonutils v0.24.0 h1:F1vE1q4pg1xtO3HTyJYRmEuJ4jmIp2iZ30bzW5XgZts=
github.com/go-openapi/swag/jsonutils v0.24.0/go.mod h1:vBowZtF5Z4DDApIoxcIVfR8v0l9oq5PpYRUuteVu6f0=
github.com/go-openapi/swag/loading v0.24.0 h1:ln/fWTwJp2Zkj5DdaX4JPiddFC5CHQpvaBKycOlceYc=
github.com/go-openapi/swag/loading v0.24.0/go.mod h1:gShCN4woKZYIxPxbfbyHgjXAhO61m88tmjy0lp/LkJk=
github.com/go-openapi/swag/mangling v0.24.0 h1:PGOQpViCOUroIeak/Uj/sjGAq9LADS3mOyjznmHy2pk=
github.com/go-openapi/swag/mangling v0.24.0/go.mod h1:Jm5Go9LHkycsz0wfoaBDkdc4CkpuSnIEf62brzyCbhc=
github.com/go-openapi/swag/netutils v0.24.0 h1:Bz02HRjYv8046Ycg/w80q3g9QCWeIqTvlyOjQPDjD8w=
github.com/go-openapi/swag/netutils v0.24.0/go.mod h1:WRgiHcYTnx+IqfMCtu0hy9oOaPR0HnPbmArSRN1SkZM=
github.com/go-openapi/swag/stringutils v0.24.0 h1:i4Z/Jawf9EvXOLUbT97O0HbPUja18VdBxeadyAqS1FM=
github.com/go-openapi/swag/stringutils v0.24.0/go.mod h1:5nUXB4xA0kw2df5PRipZDslPJgJut+NjL7D25zPZ/4w=
github.com/go-openapi/swag/typeutils v0.24.0 h1:d3szEGzGDf4L2y1gYOSSLeK6h46F+zibnEas2Jm/wIw=
github.com/go-openapi/swag/typeutils v0.24.0/go.mod h1:q8C3Kmk/vh2VhpCLaoR2MVWOGP8y7Jc8l82qCTd1DYI=
github.com/go-openapi/swag/yamlutils v0.24.0 h1:bhw4894A7Iw6ne+639hsBNRHg9iZg/ISrOVr+sJGp4c=
github.com/go-openapi/swag/yamlutils v0.24.0/go.mod h1:DpKv5aYuaGm/sULePoeiG8uwMpZSfReo1HR3Ik0yaG8=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=
github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw=
github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4=
github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -65,160 +190,290 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kluctl/go-embed-python v0.0.0-3.13.1-20241219-1 h1:x1cSEj4Ug5mpuZgUHLvUmlc5r//KHFn6iYiRSrRcVy4=
github.com/kluctl/go-embed-python v0.0.0-3.13.1-20241219-1/go.mod h1:3ebNU9QBrNpUO+Hj6bHaGpkh5pymDHQ+wwVPHTE4mCE=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mittwald/go-helm-client v0.12.18 h1:i9cJNv/YC3ZPKUKVNYTlrOO7ZO6YFKE/ak3J5TeYHPU=
github.com/mittwald/go-helm-client v0.12.18/go.mod h1:dLl5NkdKCvwKvLIdZzg4MDbxhSKmuimdmM3WpsAzS0I=
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY=
github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho=
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U=
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc=
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ=
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rubenv/sql-migrate v1.8.0 h1:dXnYiJk9k3wetp7GfQbKJcPHjVJL6YK19tKj8t2Ns0o=
github.com/rubenv/sql-migrate v1.8.0/go.mod h1:F2bGFBwCU+pnmbtNYDeKvSuvL6lBVtXDXUUv5t+u1qw=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sosedoff/ansible-vault-go v0.2.0 h1:XqkBdqbXgTuFQ++NdrZvSdUTNozeb6S3V5x7FVs17vg=
github.com/sosedoff/ansible-vault-go v0.2.0/go.mod h1:wMU54HNJfY0n0KIgbpA9m15NBfaUDlJrAsaZp0FwzkI=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 h1:UW0+QyeyBVhn+COBec3nGhfnFe5lwB0ic1JBVjzhk0w=
go.opentelemetry.io/contrib/bridges/prometheus v0.57.0/go.mod h1:ppciCHRLsyCio54qbzQv0E4Jyth/fLWDTJYfvWpcSVk=
go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 h1:jmTVJ86dP60C01K3slFQa2NQ/Aoi7zA+wy7vMOKD9H4=
go.opentelemetry.io/contrib/exporters/autoexport v0.57.0/go.mod h1:EJBheUMttD/lABFyLXhce47Wr6DPWYReCzaZiXadH7g=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 h1:cMyu9O88joYEaI47CnQkxO1XZdpoTF9fEnW2duIddhw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0/go.mod h1:6Am3rn7P9TVVeXYG+wtcGE7IE1tsQ+bP3AuWcKt/gOI=
go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU=
go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU=
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU=
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0/go.mod h1:zKU4zUgKiaRxrdovSS2amdM5gOc59slmo/zJwGX+YBg=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0 h1:SZmDnHcgp3zwlPBS2JX2urGYe/jBKEIT6ZedHRUyCz8=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0/go.mod h1:fdWW0HtZJ7+jNpTKUR0GpMEDP69nR8YBJQxNiVCE3jk=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0 h1:cC2yDI3IQd0Udsux7Qmq8ToKAx1XCilTQECZ0KDZyTw=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0/go.mod h1:2PD5Ex6z8CFzDbTdOlwyNIUywRr1DN0ospafJM1wJ+s=
go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk=
go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8=
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs=
go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo=
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo=
golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg=
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU=
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA=
k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE=
k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=
k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=
k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
helm.sh/helm/v3 v3.19.0 h1:krVyCGa8fa/wzTZgqw0DUiXuRT5BPdeqE/sQXujQ22k=
helm.sh/helm/v3 v3.19.0/go.mod h1:Lk/SfzN0w3a3C3o+TdAKrLwJ0wcZ//t1/SDXAvfgDdc=
k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM=
k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk=
k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI=
k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc=
k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4=
k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA=
k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0=
k8s.io/cli-runtime v0.34.1 h1:btlgAgTrYd4sk8vJTRG6zVtqBKt9ZMDeQZo2PIzbL7M=
k8s.io/cli-runtime v0.34.1/go.mod h1:aVA65c+f0MZiMUPbseU/M9l1Wo2byeaGwUuQEQVVveE=
k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY=
k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8=
k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A=
k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
k8s.io/kubectl v0.34.1 h1:1qP1oqT5Xc93K+H8J7ecpBjaz511gan89KO9Vbsh/OI=
k8s.io/kubectl v0.34.1/go.mod h1:JRYlhJpGPyk3dEmJ+BuBiOB9/dAvnrALJEiY/C5qa6A=
k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPGPs+Ki1gHw4w1R0=
k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 h1:slmdOY3vp8a7KQbHkL+FLbvbkgMqmXojpFUO/jENuqQ=
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3/go.mod h1:oVgVk4OWVDi43qWBEyGhXgYxt7+ED4iYNpTngSLX2Iw=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc=
oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I=
sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM=
sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78=
sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=

View File

@@ -0,0 +1,79 @@
package additional
import (
"kube-forge/internal/config"
"kube-forge/internal/helm_client"
"kube-forge/internal/templates"
"time"
go_helm_client "github.com/mittwald/go-helm-client"
)
var HELM_REPOS = []config.RepoSettings{
{
Name: "kube-forge",
URL: "https://git.kvazaric.ru/api/v4/projects/41/packages/helm/stable",
},
}
func getCertManagerSpec() go_helm_client.ChartSpec {
appConfig := config.GetConfig()
return go_helm_client.ChartSpec{
ReleaseName: "cert-manager",
ChartName: appConfig.Modules.Additional.CertManager.ChartRef,
Version: appConfig.Modules.Additional.CertManager.ChartVersion,
Namespace: appConfig.Modules.Additional.CertManager.Namespace,
CreateNamespace: true,
Atomic: true,
Timeout: time.Second * 600,
ValuesYaml: templates.GetHelmValuesByTemplate("templates/helm-apps/releases/additional-modules/cert-manager.yml.tmpl"),
}
}
func getIngressNginxSpec() go_helm_client.ChartSpec {
appConfig := config.GetConfig()
return go_helm_client.ChartSpec{
ReleaseName: "ingress-nginx",
ChartName: appConfig.Modules.Additional.Ingress.ChartRef,
Version: appConfig.Modules.Additional.Ingress.ChartVersion,
Namespace: appConfig.Modules.Additional.Ingress.Namespace,
CreateNamespace: true,
Atomic: true,
Timeout: time.Second * 600,
ValuesYaml: templates.GetHelmValuesByTemplate("templates/helm-apps/releases/additional-modules/ingress-nginx.yml.tmpl"),
}
}
func getDockerSecretsGeneratorSpec() go_helm_client.ChartSpec {
appConfig := config.GetConfig()
return go_helm_client.ChartSpec{
ReleaseName: "docker-secrets-generator",
ChartName: appConfig.Modules.Additional.DockerSecrets.ChartRef,
Version: appConfig.Modules.Additional.DockerSecrets.ChartVersion,
Namespace: appConfig.Modules.Additional.DockerSecrets.Namespace,
CreateNamespace: true,
Atomic: true,
Timeout: time.Second * 600,
ValuesYaml: templates.GetHelmValuesByTemplate("templates/helm-apps/releases/additional-modules/docker-secrets-generator.yml.tmpl"),
}
}
func ApplyCharts() {
appConfig := config.GetConfig()
helm_client.AddHelmRepos("kube-system", HELM_REPOS)
if appConfig.Modules.Additional.CertManager.Enabled {
helm_client.InstallChart(getCertManagerSpec())
} else {
helm_client.DeleteChart(getCertManagerSpec())
}
if appConfig.Modules.Additional.Ingress.Enabled && appConfig.Modules.Additional.Ingress.Type == "nginx" {
helm_client.InstallChart(getIngressNginxSpec())
} else {
helm_client.DeleteChart(getIngressNginxSpec())
}
if appConfig.Modules.Additional.DockerSecrets.Repositories != nil {
helm_client.InstallChart(getDockerSecretsGeneratorSpec())
} else {
helm_client.DeleteChart(getDockerSecretsGeneratorSpec())
}
}

View File

@@ -2,7 +2,7 @@ package config
import (
"github.com/apenella/go-ansible/pkg/options"
"github.com/apenella/go-ansible/pkg/playbook"
"github.com/apenella/go-ansible/v2/pkg/playbook"
)
type AnsiblePlaybookConfig struct {

View File

@@ -2,10 +2,21 @@ package config
import (
"fmt"
"kube-forge/internal/files"
"kube-forge/internal/logging"
"path/filepath"
"github.com/ilyakaznacheev/cleanenv"
)
var (
ConfigFile string
Output string
Password string
Verbose int
LogFile string
)
type Host struct {
Hostname string `yaml:"hostname"`
Ip string `yaml:"ip"`
@@ -15,52 +26,74 @@ type Host struct {
}
type Config struct {
WorkDir string
Credentials struct {
BaseDir string
InventoryDir string
Verbose int
LogFile string
KubeconfigFile string
Forks string `yaml:"forks" env-default:"10"`
InstallationName string `yaml:"installation_name" env-default:"cluster.local"`
Credentials struct {
User string `yaml:"user"`
Password string `yaml:"password"`
AskSudoPassword bool `yaml:"ask_sudo_password"`
PrivateKeyFile string `yaml:"private_key_file"`
} `yaml:"credentials"`
Hosts []Host `yaml:"hosts"`
Hosts struct {
Masters []Host `yaml:"master"`
Workers []Host `yaml:"worker"`
} `yaml:"hosts"`
Orchestrator Orchestrator `yaml:"orchestrator"`
Modules struct {
AdminPassword string `yaml:"admin_password"`
AdditionalRepositories interface{} `yaml:"additional_repositories"`
Additional Additional `yaml:"additional"`
Observability Observability `yaml:"observability"`
Registry Registry `yaml:"registry"`
Cicd Cicd `yaml:"cicd"`
SecretsStorage SecretsStorage `yaml:"secrets_storage"`
Additional Additional `yaml:"additional"`
} `yaml:"modules"`
Repositories string
Releases string
}
var instance *Config
func CreateConfig(configPath string, workDir string, password string) *Config {
func createConfig(configFile string, out string, password string, verbose int, logFile string) *Config {
instance = &Config{}
instance.WorkDir = workDir
if err := cleanenv.ReadConfig(configPath, instance); err != nil {
if err := cleanenv.ReadConfig(configFile, instance); err != nil {
helper, _ := cleanenv.GetDescription(instance, nil)
panic(fmt.Sprintf("%s\n%s", helper, err))
logging.Log.Fatal(fmt.Sprintf("%s\n%s", helper, err))
}
instance.BaseDir = files.CreateTempDir()
instance.InventoryDir = filepath.Join(instance.BaseDir, "inventory")
files.CreateDirWithAllParents(instance.InventoryDir)
if out != "" {
files.CreateDirWithAllParents(out)
instance.KubeconfigFile = filepath.Join(out, "k8s-admin.conf")
} else {
instance.KubeconfigFile = filepath.Join(files.GetWorkingDir(), "k8s-admin.conf")
}
if password != "" {
instance.Credentials.Password = password
}
generateCreds(instance)
instance.Verbose = verbose
instance.LogFile = logFile
err := validateConfig(*instance)
if err != nil {
logging.Log.Fatal(err.Error())
}
logging.SetupLogging(instance.Verbose, instance.LogFile)
return instance
}
func GetConfig() *Config {
if instance == nil {
createConfig(ConfigFile, Output, Password, Verbose, LogFile)
}
return instance
}

11
internal/config/errors.go Normal file
View File

@@ -0,0 +1,11 @@
package config
import "fmt"
type UnsupportedK8sVersion struct {
Version string
}
func (e *UnsupportedK8sVersion) Error() string {
return fmt.Sprintf("kubernetes version %s is not supported\n\ncurrently supported: %v", e.Version, kubernetesVersions)
}

61
internal/config/helm.go Normal file
View File

@@ -0,0 +1,61 @@
package config
import (
"io"
"log"
"os"
"time"
helm_client "github.com/mittwald/go-helm-client"
)
type RepoSettings struct {
Name string
URL string
Username string
Password string
}
type ChartSettings struct {
ReleaseName string
ChartRef string
ChartVersion string
Namespace string
CreateNamespace bool
Atomic bool
Timeout time.Duration
ValuesYaml string
}
func GetHelmClient(namespace string) helm_client.Client {
config := GetConfig()
file, err := os.Open(config.KubeconfigFile)
if err != nil {
log.Fatalf("failed to open file: %s", err)
}
defer file.Close()
kubeconfig, err := io.ReadAll(file)
if err != nil {
log.Fatalf("failed to read file: %s", err)
}
opts := &helm_client.KubeConfClientOptions{
Options: &helm_client.Options{
Namespace: namespace,
RepositoryCache: "/tmp/.helmcache",
RepositoryConfig: "/tmp/.helmrepo",
Debug: true,
Linting: true, // Change this to false if you don't want linting.
DebugLog: func(format string, v ...any) {
// Change this to your own logger. Default is 'log.Printf(format, v...)'.
},
},
KubeContext: "",
KubeConfig: kubeconfig,
}
client, err := helm_client.NewClientFromKubeConf(opts)
if err != nil {
log.Fatalf("error while creating helm client: %s", err)
}
return client
}

View File

@@ -1,21 +0,0 @@
package config
import (
"path/filepath"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
var kubernetesConfig *rest.Config
func GetKubernetesConfig() *rest.Config {
appConfig := GetConfig()
kubeconfigPath := filepath.Join(appConfig.WorkDir, "k8s-admin.conf")
kubernetesConfig, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
if err != nil {
panic(err.Error())
}
return kubernetesConfig
}

View File

@@ -5,6 +5,7 @@ type Additional struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/cert-manager"`
ChartVersion string `yaml:"chart_version" env-default:"v1.14.5"`
Enabled bool `yaml:"enabled"`
Namespace string `yaml:"namespace" env-default:"cert-manager"`
HaEnabled bool `yaml:"ha_enabled"`
DnsServers []string `yaml:"dns_servers" env-default:"8.8.8.8,1.1.1.1"`
AccountEmail string `yaml:"account_email"`
@@ -19,6 +20,7 @@ type Additional struct {
ChartVersion string `yaml:"chart_version" env-default:"4.10.1"`
Type string `yaml:"type" env-default:"nginx"`
Enabled bool `yaml:"enabled"`
Namespace string `yaml:"namespace" env-default:"ingress-nginx"`
IngressClassName string `yaml:"ingress_class_name" env-default:"nginx"`
HostNetwork bool `yaml:"host_network"`
EnableAdmissionWebhooks bool `yaml:"enable_admission_webhooks"`
@@ -36,29 +38,34 @@ type Additional struct {
LoadBalancer struct {
Type string `yaml:"type" env-default:"metallb"`
Install bool `yaml:"install"`
Enabled bool `yaml:"enabled"`
} `yaml:"load_balancer"`
DockerSecrets struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/docker-secrets-generator"`
ChartVersion string `yaml:"chart_version" env-default:"0.1.0"`
Repositories interface{} `yaml:"repositories"`
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/docker-secrets-generator"`
ChartVersion string `yaml:"chart_version" env-default:"0.1.0"`
Namespace string `yaml:"namespace" env-default:"kube-system"`
Repositories any `yaml:"repositories"`
} `yaml:"docker_secrets"`
Storage struct {
LocalPathProvisioner struct {
Enabled bool `yaml:"enabled"`
StorageClassName string `yaml:"storage_class_name" env-default:"local-path"`
ReclaimPolicy string `yaml:"reclaim_policy" env-default:"Delete"`
DataDir string `yaml:"data_dir" env-default:"/opt/local-path-provisioner/"`
} `yaml:"local_path_provisioner"`
Longhorn struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/longhorn"`
ChartVersion string `yaml:"chart_version" env-default:"1.6.1"`
Enabled bool `yaml:"enabled"`
Namespace string `yaml:"namespace" env-default:"longhorn-system"`
} `yaml:"longhorn"`
SecretsStoreCsiDriver struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/secrets-store-csi-driver"`
ChartVersion string `yaml:"chart_version" env-default:"1.4.3"`
Enabled bool `yaml:"enabled"`
Namespace string `yaml:"namespace" env-default:"kube-system"`
} `yaml:"secrets_store_csi_driver"`
} `yaml:"storage"`
}

View File

@@ -1,52 +0,0 @@
package config
type Cicd struct {
Enabled bool `yaml:"enabled"`
ArgoCd struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/argo-cd"`
ChartVersion string `yaml:"chart_version" env-default:"5.46.7"`
AdminPassword string
Ha struct {
Enabled bool `yaml:"enabled"`
Autoscaling bool `yaml:"autoscaling"`
} `yaml:"ha"`
Expose struct {
Type string `yaml:"type"`
Domain string `yaml:"domain"`
NodePortHttp int `yaml:"node_port_http" env-default:"30005"`
NodePortHttps int `yaml:"node_port_https" env-default:"30006"`
Tls struct {
Enabled bool `yaml:"enabled"`
} `yaml:"tls"`
} `yaml:"expose"`
Repositories interface{} `yaml:"repositories"`
Rbac struct {
AdditionalPolicies string `yaml:"additional_policies"`
} `yaml:"argo_cd"`
ServiceIngress struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/service-ingress"`
ChartVersion string `yaml:"chart_version" env-default:"0.1.0"`
} `yaml:"service_ingress"`
} `yaml:"argo_cd"`
UpdatesOperator struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/keel"`
ChartVersion string `yaml:"chart_version" env-default:"1.0.3"`
Enabled bool `yaml:"enabled"`
} `yaml:"updates_operator"`
Rollouts struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/argo-rollouts"`
ChartVersion string `yaml:"chart_version" env-default:"2.35.1"`
Enabled bool `yaml:"enabled"`
Ha struct {
Enabled bool `yaml:"enabled"`
} `yaml:"ha"`
Expose struct {
Type string `yaml:"type"`
NodePort int `yaml:"node_port" env-default:"30010"`
} `yaml:"expose"`
Controller struct {
} `yaml:"controller"`
Dashboard struct {
} `yaml:"dashboard"`
} `yaml:"rollouts"`
}

View File

@@ -1,172 +0,0 @@
package config
type Observability struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/observability"`
ChartVersion string `yaml:"chart_version" env-default:"0.1.0"`
Enabled bool `yaml:"enabled"`
Logging Logging `yaml:"logging"`
Tracing Tracing `yaml:"tracing"`
Monitoring Monitoring `yaml:"monitoring"`
Visualization Visualization `yaml:"visualization"`
}
type Logging struct {
Enabled bool `yaml:"enabled"`
Operator struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/fluent-operator"`
ChartVersion string `yaml:"chart_version" env-default:"2.7.0"`
Image string `yaml:"image" env-default:"kubesphere/fluent-operator"`
Tag string `yaml:"tag" env-default:"v2.7.0"`
InitContainer struct {
Image string `yaml:"image" env-default:"docker"`
Tag string `yaml:"tag" env-default:"20.10"`
} `yaml:"initcontainer"`
} `yaml:"operator"`
Fluentd struct {
Image string `yaml:"image" env-default:"kubesphere/fluentd"`
Tag string `yaml:"tag" env-default:"v1.15.3"`
} `yaml:"fluentd"`
FluentBit struct {
Image string `yaml:"image" env-default:"kubesphere/fluent-bit"`
Tag string `yaml:"tag" env-default:"v2.2.2"`
} `yaml:"fluent_bit"`
Loki struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/loki"`
ChartVersion string `yaml:"chart_version" env-default:"5.47.2"`
Registry string `yaml:"registry" env-default:"docker.io"`
Image string `yaml:"image" env-default:"grafana/loki"`
Tag string `yaml:"tag" env-default:"null"`
Persistence struct {
StorageClass string `yaml:"storage_class" env-default:"local-path"`
StorageSize string `yaml:"storage_size" env-default:"10Gi"`
Retention string `yaml:"retention" env-default:"168h"`
} `yaml:"persistence"`
AlertManagerUrl string `yaml:"alert_manager_url" env-default:"http://observability-alert-manager:9093"`
AdditionalRulesGroups string `yaml:"additional_rules_groups" env-default:""`
} `yaml:"loki"`
Events struct {
Enabled bool `yaml:"enabled"`
Exporter struct {
Image string `yaml:"image" env-default:"ghcr.io/resmoio/kubernetes-event-exporter"`
Tag string `yaml:"tag" env-default:"v1.4"`
} `yaml:"exporter"`
Cron struct {
Image string `yaml:"image" env-default:"bitnami/kubectl"`
Tag string `yaml:"tag" env-default:"1.27.5-debian-11-r8"`
Schedule string `yaml:"schedule" env-default:"*/2 * * * *"`
} `yaml:"cron"`
} `yaml:"events"`
}
type Tracing struct {
Enabled bool `yaml:"enabled"`
Operator struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/opentelemetry-operator"`
ChartVersion string `yaml:"chart_version" env-default:"0.55.0"`
Image string `yaml:"image" env-default:"ghcr.io/open-telemetry/opentelemetry-operator/opentelemetry-operator"`
Tag string `yaml:"tag" env-default:""`
} `yaml:"operator"`
Collector struct {
Image string `yaml:"image" env-default:"otel/opentelemetry-collector-contrib"`
Tag string `yaml:"tag" env-default:"0.95.0"`
} `yaml:"collector"`
Tempo struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/tempo"`
ChartVersion string `yaml:"chart_version" env-default:"1.7.2"`
Image string `yaml:"image" env-default:"grafana/tempo"`
Tag string `yaml:"tag" env-default:""`
Retention string `yaml:"retention" env-default:"24h"`
ListenPort int `yaml:"listen_port" env-default:"3100"`
Persistence struct {
StorageClass string `yaml:"storage_class" env-default:"local-path"`
StorageSize string `yaml:"storage_size" env-default:"10Gi"`
} `yaml:"persistence"`
TempoQuery struct {
Image string `yaml:"image" env-default:"grafana/tempo-query"`
Tag string `yaml:"tag" env-default:"null"`
ListenPort int `yaml:"listen_port" env-default:"16686"`
} `yaml:"tempo_query"`
} `yaml:"tempo"`
}
type Monitoring struct {
Enabled bool `yaml:"enabled"`
Prometheus struct {
Image string `yaml:"image" env-default:"prom/prometheus"`
Tag string `yaml:"tag" env-default:"v2.45.0"`
ScrapeInterval string `yaml:"scrape_interval" env-default:"15s"`
Persistence struct {
StorageClass string `yaml:"storage_class" env-default:"local-path"`
StorageSize string `yaml:"storage_size" env-default:"3Gi"`
Retention string `yaml:"retention" env-default:"7d"`
} `yaml:"persistence"`
Operator struct {
Image string `yaml:"image" env-default:"ghcr.io/prometheus-operator/prometheus-operator"`
Tag string `yaml:"tag" env-default:"v0.65.2"`
ConfigReloader struct {
Image string `yaml:"image" env-default:"ghcr.io/prometheus-operator/prometheus-config-reloader"`
Tag string `yaml:"tag" env-default:"v0.65.2"`
} `yaml:"config_reloader"`
KubeRbacProxy struct {
Image string `yaml:"image" env-default:"bitnami/kube-rbac-proxy"`
Tag string `yaml:"tag" env-default:"0.14.1"`
} `yaml:"kube_rbac_proxy"`
} `yaml:"operator"`
} `yaml:"prometheus"`
AlertManager struct {
Enabled bool `yaml:"enabled"`
Image string `yaml:"image" env-default:"prom/alertmanager"`
Tag string `yaml:"tag" env-default:"v0.26.0"`
AdditionalMessageTemplates interface{} `yaml:"additionalMessageTemplates"`
Route interface{} `yaml:"route"`
Receivers interface{} `yaml:"receivers"`
} `yaml:"alert_manager"`
Blackbox struct {
Enabled bool `yaml:"enabled"`
Image string `yaml:"image" env-default:"prom/blackbox-exporter"`
Tag string `yaml:"tag" env-default:"v0.24.0"`
AdditionalModules string `yaml:"routes" env-default:""`
} `yaml:"blackbox"`
KubeState struct {
Enabled bool `yaml:"enabled"`
Image string `yaml:"image" env-default:"bitnami/kube-state-metrics"`
Tag string `yaml:"tag" env-default:"2.9.2"`
} `yaml:"kube_state"`
Node struct {
Enabled bool `yaml:"enabled"`
Image string `yaml:"image" env-default:"prom/node-exporter"`
Tag string `yaml:"tag" env-default:"v1.5.0"`
} `yaml:"node"`
MetricsServer struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/metrics-server"`
ChartVersion string `yaml:"chart_version" env-default:"3.12.1"`
Image string `yaml:"image" env-default:"registry.k8s.io/metrics-server/metrics-server"`
Tag string `yaml:"tag" env-default:""`
}
}
type Visualization struct {
Enabled bool `yaml:"enabled"`
Grafana struct {
Enabled bool `yaml:"enabled"`
Image string `yaml:"image" env-default:"grafana/grafana"`
Tag string `yaml:"tag" env-default:"10.4.1"`
Expose struct {
Type string `yaml:"type" env-default:"ingress"`
Domain string `yaml:"domain" env-default:""`
NodePortHttp int `yaml:"node_port_http" env-default:"30007"`
Tls struct {
Enabled bool `yaml:"enabled"`
}
} `yaml:"expose"`
Persistence struct {
StorageClass string `yaml:"storage_class" env-default:"local-path"`
StorageSize string `yaml:"storage_size" env-default:"2Gi"`
} `yaml:"persistence"`
Config struct {
Auth string `yaml:"auth" env-default:""`
AuthGenericAuth string `yaml:"auth_generic_auth" env-default:""`
AdditionalDatasources interface{} `yaml:"additional_datasources"`
} `yaml:"config"`
} `yaml:"grafana"`
}

View File

@@ -1,32 +0,0 @@
package config
type Registry struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/harbor"`
ChartVersion string `yaml:"chart_version" env-default:"1.14.2"`
Enabled bool `yaml:"enabled"`
AdminPassword string
Namespace string `yaml:"namespace" env-default:"registry"`
Version string `yaml:"version" env-default:"v2.10.1"`
Expose struct {
Type string `yaml:"type" env-default:"nodePort"`
Domain string `yaml:"domain" env-default:""`
NodePortHttp int `yaml:"node_port_http" env-default:"30002"`
NodePortHttps int `yaml:"node_port_https" env-default:"30003"`
} `yaml:"expose"`
Tls struct {
Enabled bool `yaml:"enabled"`
CertificateGenerator struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/certificate-generator"`
ChartVersion string `yaml:"chart_version" env-default:"0.1.0"`
} `yaml:"certificate_generator"`
} `yaml:"tls"`
Persistence struct {
StorageClass string `yaml:"storage_class" env-default:"local-path"`
RegistrySize string `yaml:"registry_size" env-default:"10Gi"`
JobserviceSize string `yaml:"jobservice_size" env-default:"1Gi"`
DatabaseSize string `yaml:"database_size" env-default:"2Gi"`
RedisSize string `yaml:"redis_size" env-default:"1Gi"`
TrivySize string `yaml:"trivy_size" env-default:"5Gi"`
} `yaml:"persistence"`
EnabledScanner bool `yaml:"enabled_scanner"`
}

View File

@@ -1,46 +0,0 @@
package config
type SecretsStorage struct {
ChartRef string `yaml:"chart_ref" env-default:"kube-forge/vault"`
ChartVersion string `yaml:"chart_version" env-default:"0.1.0"`
Enabled bool `yaml:"enabled"`
KeyShares int `yaml:"key_shares" env-default:"5"`
KeyThreshold int `yaml:"key_threshold" env-default:"3"`
UnsealKeys []string `yaml:"unseal_keys" env-default:"[]"`
AuthToken string `yaml:"auth_token" env-default:""`
Expose struct {
Type string `yaml:"type"`
Domain string `yaml:"domain"`
NodePort int `yaml:"node_port"`
Tls struct {
Enabled bool `yaml:"enabled"`
} `yaml:"tls"`
} `yaml:"expose"`
CsiIntegration struct {
Enabled bool `yaml:"enabled"`
Image string `yaml:"image" env-default:"hashicorp/vault-csi-provider"`
Tag string `yaml:"tag" env-default:"1.4.1"`
} `yaml:"csi_integration"`
Injector struct {
Image string `yaml:"image" env-default:"hashicorp/vault-k8s"`
Tag string `yaml:"tag" env-default:"1.3.1"`
} `yaml:"injector"`
Server struct {
Image string `yaml:"image" env-default:"hashicorp/vault"`
Tag string `yaml:"tag" env-default:"1.16.0"`
Persistence struct {
DataStorage struct {
StorageClass string `yaml:"storage_class" env-default:"local-path"`
Size string `yaml:"size" env-default:"10Gi"`
} `yaml:"data_storage"`
AuditStorage struct {
StorageClass string `yaml:"storage_class" env-default:"local-path"`
Size string `yaml:"size" env-default:"10Gi"`
} `yaml:"audit_storage"`
} `yaml:"persistence"`
} `yaml:"server"`
Agent struct {
Image string `yaml:"image" env-default:"hashicorp/vault"`
Tag string `yaml:"tag" env-default:"1.16.0"`
} `yaml:"agent"`
}

View File

@@ -3,20 +3,31 @@ package config
type Dns struct {
Servers []string `yaml:"servers" env-default:"8.8.8.8,8.8.4.4"`
DisableHostNameservers bool `yaml:"disable_host_nameservers"`
CoreDNSExternalZones []any `yaml:"coredns_external_zones"`
}
type RegistryMirror struct {
Host string `yaml:"host"`
SkipVerify bool `yaml:"skip_verify"`
}
type Orchestrator struct {
Version string `yaml:"version" env-default:"v1.29.0"`
ClusterName string `yaml:"cluster_name" env-default:"k8s-cluster.local"`
ClusterName string `yaml:"cluster_name" env-default:"cluster.local"`
BinDir string `yaml:"bin_dir" env-default:"/usr/local/bin"`
SysctlFilePath string `yaml:"sysctl_file_path" env-default:"/etc/sysctl.d/99-sysctl.conf"`
LoadbalancerApiserverPort int `yaml:"loadbalancer_apiserver_port" env-default:"6443"`
ProxyMode string `yaml:"proxy_mode" env-default:"ipvs"`
ProxyScheduler string `yaml:"proxy_scheduler" env-default:"rr"`
Dns Dns `yaml:"dns"`
CloudProvider string `yaml:"cloud_provider"`
ExgernalCloudProvider string `yaml:"external_cloud_provider"`
KubeletDir string `yaml:"kubelet_dir" env-default:"/var/lib/kubelet"`
ContainerEngine struct {
Type string `yaml:"type" env-default:"containerd"`
Install bool `yaml:"install"`
Type string `yaml:"type" env-default:"containerd"`
Install bool `yaml:"install"`
DataDir string `yaml:"data_dir" env-default:"/var/lib/containerd"`
StateDir string `yaml:"state_dir" env-default:"/run/containerd"`
} `yaml:"container_engine"`
PingAccessIp bool `yaml:"ping_access_ip"`
AutoRenewCertificates bool `yaml:"auto_renew_certificates"`
@@ -27,5 +38,16 @@ type Orchestrator struct {
Plugin string `yaml:"plugin" env-default:"calico"`
ServiceAddresses string `yaml:"service_addresses" env-default:"10.233.0.0/18"`
PodsSubnet string `yaml:"pods_subnet" env-default:"10.233.64.0/18"`
Calico struct {
EnableBpf bool `yaml:"enable_bpf"`
} `yaml:"calico"`
Cilium struct {
EnableBpf bool `yaml:"enable_bpf"`
Hubble struct {
Install bool `yaml:"install"`
EnableMetrics bool `yaml:"enable_metrics"`
} `yaml:"hubble"`
} `yaml:"cilium"`
} `yaml:"network"`
RegistryMirrors []RegistryMirror `yaml:"registry_mirrors"`
}

View File

@@ -0,0 +1,48 @@
package config
import (
"slices"
)
var kubernetesVersions = []string{
"1.32.8",
"1.32.7",
"1.32.6",
"1.32.5",
"1.32.4",
"1.32.3",
"1.32.2",
"1.32.1",
"1.32.0",
"1.31.9",
"1.31.8",
"1.31.7",
"1.31.6",
"1.31.5",
"1.31.4",
"1.31.3",
"1.31.2",
"1.31.1",
"1.31.0",
"1.30.13",
"1.30.12",
"1.30.11",
"1.30.10",
"1.30.9",
"1.30.8",
"1.30.7",
"1.30.6",
"1.30.5",
"1.30.4",
"1.30.3",
"1.30.2",
"1.30.1",
"1.30.0",
}
func validateConfig(cfg Config) error {
if !slices.Contains(kubernetesVersions, cfg.Orchestrator.Version) {
return &UnsupportedK8sVersion{Version: cfg.Orchestrator.Version}
}
return nil
}

View File

@@ -1,18 +0,0 @@
package config
import (
"golang.org/x/crypto/bcrypt"
)
func getBcryptHash(input string) string {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(input), bcrypt.DefaultCost)
if err != nil {
panic(err)
}
return string(hashedPassword)
}
func generateCreds(config *Config) {
config.Modules.Cicd.ArgoCd.AdminPassword = getBcryptHash(config.Modules.AdminPassword)
config.Modules.Registry.AdminPassword = config.Modules.AdminPassword
}

60
internal/csi/helm.go Normal file
View File

@@ -0,0 +1,60 @@
package csi
import (
"kube-forge/internal/config"
"kube-forge/internal/helm_client"
"kube-forge/internal/templates"
"time"
go_helm_client "github.com/mittwald/go-helm-client"
)
var HELM_REPOS = []config.RepoSettings{
{
Name: "kube-forge",
URL: "https://git.kvazaric.ru/api/v4/projects/41/packages/helm/stable",
},
}
func getLonghornSpec() go_helm_client.ChartSpec {
appConfig := config.GetConfig()
return go_helm_client.ChartSpec{
ReleaseName: "longhorn",
ChartName: appConfig.Modules.Additional.Storage.Longhorn.ChartRef,
Version: appConfig.Modules.Additional.Storage.Longhorn.ChartVersion,
Namespace: appConfig.Modules.Additional.Storage.Longhorn.Namespace,
CreateNamespace: true,
Atomic: true,
Timeout: time.Second * 600,
ValuesYaml: templates.GetHelmValuesByTemplate("templates/helm-apps/releases/additional-modules/longhorn.yml.tmpl"),
}
}
func getSecretsStoreSpec() go_helm_client.ChartSpec {
appConfig := config.GetConfig()
return go_helm_client.ChartSpec{
ReleaseName: "csi-secrets-store",
ChartName: appConfig.Modules.Additional.Storage.SecretsStoreCsiDriver.ChartRef,
Version: appConfig.Modules.Additional.Storage.SecretsStoreCsiDriver.ChartVersion,
Namespace: appConfig.Modules.Additional.Storage.SecretsStoreCsiDriver.Namespace,
CreateNamespace: true,
Atomic: true,
Timeout: time.Second * 60,
ValuesYaml: templates.GetHelmValuesByTemplate("templates/helm-apps/releases/additional-modules/secrets-store-csi-driver.yml.tmpl"),
}
}
func ApplyCharts() {
appConfig := config.GetConfig()
helm_client.AddHelmRepos("kube-system", HELM_REPOS)
if appConfig.Modules.Additional.Storage.Longhorn.Enabled {
helm_client.InstallChart(getLonghornSpec())
} else {
helm_client.DeleteChart(getLonghornSpec())
}
if appConfig.Modules.Additional.Storage.SecretsStoreCsiDriver.Enabled {
helm_client.InstallChart(getSecretsStoreSpec())
} else {
helm_client.DeleteChart(getSecretsStoreSpec())
}
}

30
internal/files/main.go Normal file
View File

@@ -0,0 +1,30 @@
package files
import (
"kube-forge/internal/logging"
"os"
)
func GetWorkingDir() string {
cwd, err := os.Getwd()
if err != nil {
logging.Log.Fatal(err)
}
return cwd
}
func CreateTempDir() string {
tempDir, err := os.MkdirTemp("", "kube-forge-")
if err != nil {
logging.Log.Fatal(err)
}
return tempDir
}
func CreateDirWithAllParents(directory string) {
err := os.MkdirAll(directory, 0755)
if err != nil {
logging.Log.Fatal(err)
}
}

View File

@@ -0,0 +1,32 @@
package helm_client
import (
"context"
"kube-forge/internal/config"
"kube-forge/internal/logging"
go_helm_client "github.com/mittwald/go-helm-client"
)
func InstallChart(chartSpec go_helm_client.ChartSpec) {
helmClient := config.GetHelmClient(chartSpec.Namespace)
_, error := helmClient.GetRelease(chartSpec.ReleaseName)
if error != nil {
logging.Log.Infof("Installing %s", chartSpec.ChartName)
} else {
logging.Log.Infof("Upgrading %s", chartSpec.ChartName)
}
if _, err := helmClient.InstallOrUpgradeChart(context.Background(), &chartSpec, nil); err != nil {
logging.Log.Fatal(err)
}
}
func DeleteChart(chartSpec go_helm_client.ChartSpec) {
helmClient := config.GetHelmClient(chartSpec.Namespace)
_, error := helmClient.GetRelease(chartSpec.ReleaseName)
if error != nil {
return
}
logging.Log.Warnf("Uninstalling %s", chartSpec.ChartName)
helmClient.UninstallRelease(&chartSpec)
}

View File

@@ -0,0 +1,28 @@
package helm_client
import (
"kube-forge/internal/config"
"kube-forge/internal/logging"
"helm.sh/helm/v3/pkg/repo"
)
func AddHelmRepo(namespace string, repoSettings config.RepoSettings) {
helmClient := config.GetHelmClient(namespace)
chartRepo := repo.Entry{
Name: repoSettings.Name,
URL: repoSettings.URL,
Username: repoSettings.Username,
Password: repoSettings.Password,
}
if err := helmClient.AddOrUpdateChartRepo(chartRepo); err != nil {
logging.Log.Fatal(err)
}
}
func AddHelmRepos(namespace string, helmRepos []config.RepoSettings) {
for _, repoSettings := range helmRepos {
AddHelmRepo(namespace, repoSettings)
}
}

View File

@@ -1,5 +0,0 @@
package kubernetes_client
import "errors"
var NoSuchVarInPod = errors.New("No such variable in pod!")

View File

@@ -1,101 +0,0 @@
package kubernetes_client
import (
"bytes"
"context"
"fmt"
"kube-forge/internal/config"
"net/http"
"strings"
"time"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/remotecommand"
)
func ExecuteCommandInPodContainer(commandArray []string, namespace string, podName string, container string) (string, error) {
clientset, err := kubernetes.NewForConfig(config.GetKubernetesConfig())
if err != nil {
panic(err.Error())
}
execRequest := clientset.CoreV1().RESTClient().Post().
Resource("pods").
Name(podName).
Namespace(namespace).
SubResource("exec").
Param("container", container).
Param("stderr", "true").
Param("stdout", "true")
for _, com := range commandArray {
execRequest = execRequest.Param("command", com)
}
stderr := bytes.NewBufferString("")
stdout := bytes.NewBufferString("")
streamOptions := remotecommand.StreamOptions{
Stdout: stdout,
Stderr: stderr,
Tty: false,
}
exec, err := remotecommand.NewSPDYExecutor(config.GetKubernetesConfig(), http.MethodPost, execRequest.URL())
if err != nil {
fmt.Println(err.Error())
}
err = exec.StreamWithContext(context.Background(), streamOptions)
if err != nil {
if stderr.Len() == 0 {
panic(err)
}
outputErr := stderr.String()
return outputErr, err
}
output := stdout.String()
return output, nil
}
func GetPodByName(podName string, podNamespace string) (*corev1.Pod, error) {
clientset, err := kubernetes.NewForConfig(config.GetKubernetesConfig())
if err != nil {
panic(err.Error())
}
for i := 15; i > 0; i-- {
time.Sleep(time.Second * 1)
pod, err := clientset.CoreV1().
Pods(podNamespace).
Get(context.Background(), podName, metav1.GetOptions{})
if err != nil || pod.Status.Phase != "Running" {
continue
}
return pod, nil
}
return nil, err
}
func GetEnvVariableFromPodContainer(envVarName string, podNamespace string, podName string, containerName string) (string, error) {
commandArray := []string{"env"}
output, err := ExecuteCommandInPodContainer(
commandArray, podNamespace, podName, containerName,
)
if err != nil {
return output, err
}
lines := strings.Split(output, "\n")
for _, line := range lines {
if strings.HasPrefix(line, envVarName+"=") {
parts := strings.Split(line, "=")
if len(parts) == 2 {
value := parts[1]
return value, nil
}
}
}
return "", NoSuchVarInPod
}

View File

@@ -1,29 +1,27 @@
package kubespray
import (
"fmt"
"kube-forge/internal/config"
"kube-forge/internal/secrets_storage"
)
func InstallCluster(tags string) {
appConfig := config.GetConfig()
runPlaybook("kubespray/project/cluster.yml", tags)
CopyK8SAdminConfig("k8s-admin.conf")
config := config.GetConfig()
if config.Modules.SecretsStorage.Enabled {
fmt.Println("## Additional Vault Configuration")
secrets_storage.InitVault()
secrets_storage.UnsealVault()
secrets_storage.AddKubernetesLocalIntegration()
}
CopyK8SAdminConfig(appConfig.KubeconfigFile)
}
func UpgradeCluster(tags string) {
appConfig := config.GetConfig()
runPlaybook("kubespray/project/upgrade_cluster.yml", tags)
CopyK8SAdminConfig("k8s-admin.conf")
CopyK8SAdminConfig(appConfig.KubeconfigFile)
}
func ScaleCluster() {
appConfig := config.GetConfig()
runPlaybook("kubespray/project/scale.yml", "")
CopyK8SAdminConfig("k8s-admin.conf")
CopyK8SAdminConfig(appConfig.KubeconfigFile)
}
func ResetCluster() {
runPlaybook("kubespray/project/reset.yml", "")
}

View File

@@ -0,0 +1,76 @@
package kubespray
import (
"context"
"fmt"
"kube-forge/internal/config"
"kube-forge/internal/logging"
"kube-forge/internal/python"
"os"
"path/filepath"
"github.com/apenella/go-ansible/v2/pkg/execute"
"github.com/apenella/go-ansible/v2/pkg/execute/stdoutcallback"
"github.com/apenella/go-ansible/v2/pkg/playbook"
)
func runPlaybook(playbookPath string, tags string) {
config := config.GetConfig()
var callbackExecute execute.Executor
epExec := python.NewPythonExec()
envVars := map[string]string{
"ANSIBLE_DISPLAY_SKIPPED_HOSTS": "false",
"ANSIBLE_DISPLAY_OK_HOSTS": "false",
"ANSIBLE_FORCE_COLOR": "true",
"ANSIBLE_HOST_KEY_CHECKING": "false",
"ANSIBLE_FORKS": config.Forks,
}
playbookOptions := getPlaybookParameters(tags)
playbookCmd := playbook.NewAnsiblePlaybookCmd(
playbook.WithPlaybooks(
filepath.Join(epExec.ResourcesFsPath, playbookPath),
),
playbook.WithPlaybookOptions(&playbookOptions),
playbook.WithBinary(
filepath.Join(epExec.PythonLibFsPath, "bin", "ansible-playbook"),
),
)
execute := execute.NewDefaultExecute(
execute.WithCmd(playbookCmd),
execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()),
execute.WithExecutable(epExec),
)
if config.Verbose > 0 {
envVars["ANSIBLE_STDOUT_CALLBACK"] = "unixy"
envVars["ANSIBLE_VERBOSITY"] = fmt.Sprintf("%d", config.Verbose)
envVars["ANSIBLE_DISPLAY_SKIPPED_HOSTS"] = "true"
envVars["ANSIBLE_DISPLAY_OK_HOSTS"] = "true"
} else {
envVars["ANSIBLE_STDOUT_CALLBACK"] = "dense"
envVars["ANSIBLE_ACTION_WARNINGS"] = "false"
envVars["ANSIBLE_DEVEL_WARNING"] = "false"
envVars["ANSIBLE_DEPRECATION_WARNINGS"] = "false"
envVars["ANSIBLE_DUPLICATE_YAML_DICT_KEY"] = "ignore"
envVars["ANSIBLE_HOST_PATTERN_MISMATCH"] = "ignore"
envVars["ANSIBLE_SYSTEM_WARNINGS"] = "false"
}
if config.LogFile != "" {
envVars["ANSIBLE_LOG_PATH"] = config.LogFile
}
callbackExecute = stdoutcallback.NewDefaultStdoutCallbackExecute(execute)
for key, value := range envVars {
os.Setenv(key, value)
}
err := callbackExecute.Execute(context.Background())
if err != nil {
logging.Log.Fatal(err)
}
}

View File

@@ -0,0 +1,54 @@
package kubespray
import (
"fmt"
"io"
"kube-forge/internal/config"
"kube-forge/internal/logging"
"os"
"path/filepath"
"github.com/apenella/go-ansible/v2/pkg/playbook"
)
func getPlaybookParameters(tags string) playbook.AnsiblePlaybookOptions {
cfg := config.GetConfig()
ansiblePlaybookOptions := playbook.AnsiblePlaybookOptions{
Inventory: filepath.Join(cfg.InventoryDir, "hosts"),
Tags: tags,
User: cfg.Credentials.User,
Become: true,
}
if cfg.Credentials.PrivateKeyFile != "" {
ansiblePlaybookOptions.PrivateKey = cfg.Credentials.PrivateKeyFile
}
if cfg.Credentials.AskSudoPassword {
ansiblePlaybookOptions.AskBecomePass = true
}
return ansiblePlaybookOptions
}
func CopyK8SAdminConfig(outFile string) {
config := config.GetConfig()
var adminDefaultConfigPath = filepath.Join(config.InventoryDir, "artifacts/admin.conf")
source, err := os.Open(adminDefaultConfigPath)
if err != nil {
logging.Log.Fatal(err)
}
defer source.Close()
destination, err := os.Create(outFile)
if err != nil {
logging.Log.Fatal(err)
}
defer destination.Close()
_, err = io.Copy(destination, source)
if err != nil {
logging.Log.Fatal(err)
}
logging.Log.Info(fmt.Sprintf("K8s admin config: %s", outFile))
}

View File

@@ -1,75 +0,0 @@
package kubespray
import (
"context"
"io"
"kube-forge/internal/config"
"os"
"path/filepath"
"github.com/apenella/go-ansible/v2/pkg/execute"
"github.com/apenella/go-ansible/v2/pkg/execute/stdoutcallback"
"github.com/apenella/go-ansible/v2/pkg/playbook"
)
func getPlaybookParameters(tags string) playbook.AnsiblePlaybookOptions {
cfg := config.GetConfig()
ansiblePlaybookOptions := playbook.AnsiblePlaybookOptions{
Inventory: filepath.Join(cfg.WorkDir, "kubespray/inventory/hosts"),
Tags: tags,
User: cfg.Credentials.User,
Become: true,
}
if cfg.Credentials.PrivateKeyFile != "" {
ansiblePlaybookOptions.PrivateKey = cfg.Credentials.PrivateKeyFile
}
if cfg.Credentials.AskSudoPassword {
ansiblePlaybookOptions.AskBecomePass = true
}
return ansiblePlaybookOptions
}
func CopyK8SAdminConfig(pathInDataDir string) {
config := config.GetConfig()
dataDir := config.WorkDir
var adminDefaultConfigPath = filepath.Join(dataDir, "kubespray/inventory/artifacts/admin.conf")
var adminOutConfigPath = filepath.Join(dataDir, pathInDataDir)
source, err := os.Open(adminDefaultConfigPath)
if err != nil {
panic(err)
}
defer source.Close()
destination, err := os.Create(adminOutConfigPath)
if err != nil {
panic(err)
}
defer destination.Close()
_, err = io.Copy(destination, source)
if err != nil {
panic(err)
}
}
func runPlaybook(playbookPath string, tags string) {
playbookOptions := getPlaybookParameters(tags)
playbookCmd := playbook.NewAnsiblePlaybookCmd(
playbook.WithPlaybooks(playbookPath),
playbook.WithPlaybookOptions(&playbookOptions),
)
exec := stdoutcallback.NewDebugStdoutCallbackExecute(
execute.NewDefaultExecute(
execute.WithCmd(playbookCmd),
execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()),
),
)
err := exec.Execute(context.Background())
if err != nil {
panic(err)
}
}

45
internal/logging/log.go Normal file
View File

@@ -0,0 +1,45 @@
package logging
import (
"io"
"os"
"github.com/sirupsen/logrus"
)
var Log = logrus.New()
func init() {
Log.SetLevel(logrus.InfoLevel)
Log.SetFormatter(&logrus.TextFormatter{})
}
func SetupLogging(verboseLevel int, logFilePath string) {
switch verboseLevel {
case 1:
Log.SetLevel(logrus.DebugLevel)
case 2:
Log.SetLevel(logrus.TraceLevel)
default:
if verboseLevel >= 3 {
Log.SetLevel(logrus.TraceLevel)
}
}
if logFilePath != "" {
logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
Log.Warnf("Failed to open log file %s: %v. Continuing without file logging.", logFilePath, err)
return
}
if verboseLevel > 0 {
multiWriter := io.MultiWriter(os.Stdout, logFile)
Log.SetOutput(multiWriter)
Log.Debugf("Verbose logging enabled with file output (level: %d)", verboseLevel)
} else {
Log.SetOutput(logFile)
}
Log.Infof("Logging to file: %s", logFilePath)
}
}

View File

@@ -0,0 +1,28 @@
package main
import (
"kube-forge/internal/logging"
"runtime"
"strings"
"github.com/kluctl/go-embed-python/pip"
)
var platforms = map[string][]string{
"darwin-amd64": {"macosx_11_0_x86_64", "macosx_12_0_x86_64"},
"darwin-arm64": {"macosx_11_0_arm64", "macosx_12_0_arm64"},
"linux-amd64": {"manylinux_2_17_x86_64", "manylinux_2_28_x86_64", "manylinux2014_x86_64"},
"linux-arm64": {"manylinux_2_17_aarch64", "manylinux_2_28_aarch64", "manylinux2014_aarch64"},
"windows-amd64": {"win_amd64"},
}
func main() {
os := runtime.GOOS
arch := runtime.GOARCH
pipPlatform := platforms[strings.Join([]string{os, arch}, "-")]
err := pip.CreateEmbeddedPipPackages("requirements.txt", os, arch, pipPlatform, "./data/")
if err != nil {
logging.Log.Fatal(err)
}
}

3
internal/python/main.go Normal file
View File

@@ -0,0 +1,3 @@
package python
//go:generate go run ./generate

View File

@@ -0,0 +1,4 @@
ansible==11.9.0
cryptography
jmespath
netaddr

162
internal/python/utils.go Normal file
View File

@@ -0,0 +1,162 @@
package python
import (
"context"
"fmt"
"io"
"kube-forge/internal/logging"
"kube-forge/internal/python/data"
"kube-forge/internal/resources"
"os"
"os/exec"
"path/filepath"
executable "github.com/apenella/go-ansible/v2/pkg/execute/exec"
"github.com/kluctl/go-embed-python/embed_util"
"github.com/kluctl/go-embed-python/python"
)
type PythonExec struct {
ep *python.EmbeddedPython
PythonLibFsPath string
ResourcesFsPath string
}
type CmdWrapper struct {
*exec.Cmd
}
func (c *CmdWrapper) CombinedOutput() ([]byte, error) {
return c.Cmd.CombinedOutput()
}
func (c *CmdWrapper) Environ() []string {
return c.Cmd.Environ()
}
func (c *CmdWrapper) Output() ([]byte, error) {
return c.Cmd.Output()
}
func (c *CmdWrapper) Run() error {
return c.Cmd.Run()
}
func (c *CmdWrapper) Start() error {
return c.Cmd.Start()
}
func (c *CmdWrapper) StderrPipe() (io.ReadCloser, error) {
return c.Cmd.StderrPipe()
}
func (c *CmdWrapper) StdinPipe() (io.WriteCloser, error) {
return c.Cmd.StdinPipe()
}
func (c *CmdWrapper) StdoutPipe() (io.ReadCloser, error) {
return c.Cmd.StdoutPipe()
}
func (c *CmdWrapper) String() string {
return c.Cmd.String()
}
func (c *CmdWrapper) Wait() error {
return c.Cmd.Wait()
}
type ErrorCmd struct {
err error
}
func (e *ErrorCmd) CombinedOutput() ([]byte, error) {
return nil, e.err
}
func (e *ErrorCmd) Environ() []string {
return nil
}
func (e *ErrorCmd) Output() ([]byte, error) {
return nil, e.err
}
func (e *ErrorCmd) Run() error {
return e.err
}
func (e *ErrorCmd) Start() error {
return e.err
}
func (e *ErrorCmd) StderrPipe() (io.ReadCloser, error) {
return nil, e.err
}
func (e *ErrorCmd) StdinPipe() (io.WriteCloser, error) {
return nil, e.err
}
func (e *ErrorCmd) StdoutPipe() (io.ReadCloser, error) {
return nil, e.err
}
func (e *ErrorCmd) String() string {
return fmt.Sprintf("ErrorCmd: %v", e.err)
}
func (e *ErrorCmd) Wait() error {
return e.err
}
func NewPythonExec() *PythonExec {
tmpDir := filepath.Join(os.TempDir(), "go-ansible")
pythonDir := tmpDir + "-python"
pythonLibDir := tmpDir + "-python-lib"
resourcesDir := tmpDir + "-resources"
pythonLibFs, err := embed_util.NewEmbeddedFilesWithTmpDir(data.Data, pythonLibDir, true)
if err != nil {
logging.Log.Fatal(err)
}
pythonLibFsPath := pythonLibFs.GetExtractedPath()
resourcesFs, _ := embed_util.NewEmbeddedFilesWithTmpDir(resources.Kubespray, resourcesDir, true)
resourcesFsPath := resourcesFs.GetExtractedPath()
ep, _ := python.NewEmbeddedPythonWithTmpDir(pythonDir, true)
ep.AddPythonPath(pythonLibFs.GetExtractedPath())
ep.AddPythonPath(resourcesFs.GetExtractedPath())
return &PythonExec{
ep: ep,
PythonLibFsPath: pythonLibFsPath,
ResourcesFsPath: resourcesFsPath,
}
}
func (e *PythonExec) Command(name string, arg ...string) executable.Cmder {
cmd := append([]string{name}, arg...)
execCmd, err := e.ep.PythonCmd2(cmd)
if err != nil {
return &ErrorCmd{err: fmt.Errorf("failed to create python command: %w", err)}
}
return &CmdWrapper{Cmd: execCmd}
}
func (e *PythonExec) CommandContext(ctx context.Context, name string, arg ...string) executable.Cmder {
cmd := append([]string{name}, arg...)
execCmd, err := e.ep.PythonCmd2(cmd)
if err != nil {
return &ErrorCmd{err: fmt.Errorf("failed to create python command: %w", err)}
}
ctxCmd := exec.CommandContext(ctx, execCmd.Path, execCmd.Args[1:]...)
ctxCmd.Env = execCmd.Env
ctxCmd.Dir = execCmd.Dir
ctxCmd.Stdin = execCmd.Stdin
ctxCmd.Stdout = execCmd.Stdout
ctxCmd.Stderr = execCmd.Stderr
return &CmdWrapper{Cmd: ctxCmd}
}

View File

@@ -1,9 +0,0 @@
package registry
func CreateDockerRepositories() {
}
func CreateHelmRepositories() {
}

View File

@@ -0,0 +1,24 @@
---
- name: Check Ansible version
hosts: all
gather_facts: false
become: false
run_once: true
vars:
minimal_ansible_version: 2.16.4
maximal_ansible_version: 2.17.0
tags: always
tasks:
- name: "Check that python netaddr is installed"
assert:
msg: "Python netaddr is not present"
that: "'127.0.0.1' | ansible.utils.ipaddr"
tags:
- check
- name: "Check that jinja is not too old (install via pip)"
assert:
msg: "Your Jinja version is too old, install via pip"
that: "{% set test %}It works{% endset %}{{ test == 'It works' }}"
tags:
- check

View File

@@ -0,0 +1,46 @@
---
- name: Check ansible version
import_playbook: ansible_version.yml
# These are inventory compatibility tasks with two purposes:
# - to ensure we keep compatibility with old style group names
# - to reduce inventory boilerplate (defining parent groups / empty groups)
- name: Define groups for legacy less structured inventories
hosts: all
gather_facts: false
tags: always
tasks:
- name: Match needed groups by their old names or definition
vars:
group_mappings:
kube_control_plane:
- kube-master
kube_node:
- kube-node
calico_rr:
- calico-rr
no_floating:
- no-floating
k8s_cluster:
- kube_node
- kube_control_plane
- calico_rr
group_by:
key: "{{ (group_names | intersect(item.value) | length > 0) | ternary(item.key, '_all') }}"
loop: "{{ group_mappings | dict2items }}"
- name: Check inventory settings
hosts: all
gather_facts: false
tags: always
roles:
- validate_inventory
- name: Install bastion ssh config
hosts: bastion[0]
gather_facts: false
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray_defaults }
- { role: bastion-ssh-config, tags: ["localhost", "bastion"] }

View File

@@ -7,101 +7,95 @@
- name: Prepare for etcd install
hosts: k8s_cluster:etcd
gather_facts: False
gather_facts: false
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubespray_defaults }
- { role: kubernetes/preinstall, tags: preinstall }
- {
role: "container-engine",
tags: "container-engine",
when: deploy_container_engine,
}
- { role: "container-engine", tags: "container-engine", when: deploy_container_engine }
- { role: download, tags: download, when: "not skip_downloads" }
- name: Install etcd
vars:
etcd_cluster_setup: true
etcd_events_cluster_setup: "{{ etcd_events_cluster_enabled }}"
import_playbook: install_etcd.yml
- name: Install Kubernetes nodes
hosts: k8s_cluster
gather_facts: False
gather_facts: false
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubespray_defaults }
- { role: kubernetes/node, tags: node }
- name: Install the control plane
hosts: kube_control_plane
gather_facts: False
gather_facts: false
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubespray_defaults }
- { role: kubernetes/control-plane, tags: master }
- { role: kubernetes/client, tags: client }
- { role: kubernetes-apps/cluster_roles, tags: cluster-roles }
- name: Invoke kubeadm and install a CNI
hosts: k8s_cluster
gather_facts: False
gather_facts: false
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/kubeadm, tags: kubeadm }
- { role: kubespray_defaults }
- { role: kubernetes/kubeadm, tags: kubeadm}
- { role: kubernetes/node-label, tags: node-label }
- { role: kubernetes/node-taint, tags: node-taint }
- role: kubernetes-apps/gateway_api
when: gateway_api_enabled
tags: gateway_api
delegate_to: "{{ groups['kube_control_plane'][0] }}"
run_once: true
- { role: network_plugin, tags: network }
- { role: kubernetes-apps/kubelet-csr-approver, tags: kubelet-csr-approver }
- name: Install Calico Route Reflector
hosts: calico_rr
gather_facts: False
gather_facts: false
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: network_plugin/calico/rr, tags: ["network", "calico_rr"] }
- { role: kubespray_defaults }
- { role: network_plugin/calico/rr, tags: ['network', 'calico_rr'] }
- name: Patch Kubernetes for Windows
hosts: kube_control_plane[0]
gather_facts: False
gather_facts: false
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubespray_defaults }
- { role: win_nodes/kubernetes_patch, tags: ["master", "win_nodes"] }
- name: Install Kubernetes and Helm apps
- name: Install Kubernetes apps
hosts: kube_control_plane
gather_facts: False
gather_facts: false
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- {
role: kubernetes-apps/external_cloud_controller,
tags: external-cloud-controller,
}
- { role: kubespray_defaults }
- { role: kubernetes-apps/external_cloud_controller, tags: external-cloud-controller }
- { role: kubernetes-apps/network_plugin, tags: network }
- { role: kubernetes-apps/policy_controller, tags: policy-controller }
- { role: kubernetes-apps/ingress_controller, tags: ingress-controller }
- { role: kubernetes-apps/external_provisioner, tags: external-provisioner }
- { role: kubernetes-apps, tags: apps }
- { role: helm-apps, tags: helm-apps }
- name: Apply resolv.conf changes now that cluster DNS is up
hosts: k8s_cluster
gather_facts: False
gather_facts: false
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- {
role: kubernetes/preinstall,
when: "dns_mode != 'none' and resolvconf_mode == 'host_resolvconf'",
tags: resolvconf,
dns_late: true,
}
- { role: kubespray_defaults }
- { role: kubernetes/preinstall, when: "dns_mode != 'none' and resolvconf_mode == 'host_resolvconf'", tags: resolvconf, dns_late: true }

View File

@@ -5,19 +5,17 @@
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
gather_facts: false
environment: "{{ proxy_disable_env }}"
vars:
# Need to disable pipelining for bootstrap-os as some systems have requiretty in sudoers set, which makes pipelining
# fail. bootstrap-os fixes this on these systems, so in later plays it can be enabled.
ansible_ssh_pipelining: false
roles:
- { role: kubespray-defaults }
- { role: bootstrap-os, tags: bootstrap-os}
- { role: bootstrap_os, tags: bootstrap_os}
- name: Gather facts
hosts: k8s_cluster:etcd:calico_rr
gather_facts: False
gather_facts: false
tags: always
tasks:
- name: Gather and compute network facts
import_role:
name: network_facts
- name: Gather minimal facts
setup:
gather_subset: '!all'

View File

@@ -2,7 +2,7 @@
- name: Add worker nodes to the etcd play if needed
hosts: kube_node
roles:
- { role: kubespray-defaults }
- { role: kubespray_defaults }
tasks:
- name: Check if nodes needs etcd client certs (depends on network_plugin)
group_by:
@@ -16,14 +16,11 @@
- name: Install etcd
hosts: etcd:kube_control_plane:_kubespray_needs_etcd
gather_facts: False
gather_facts: false
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubespray_defaults }
- role: etcd
tags: etcd
vars:
etcd_cluster_setup: true
etcd_events_cluster_setup: "{{ etcd_events_cluster_enabled }}"
when: etcd_deployment_type != "kubeadm"

View File

@@ -6,7 +6,7 @@
hosts: etcd[0]
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults}
- { role: kubespray_defaults}
- role: recover_control_plane/etcd
when: etcd_deployment_type != "kubeadm"
@@ -14,7 +14,7 @@
hosts: kube_control_plane[0]
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults}
- { role: kubespray_defaults}
- { role: recover_control_plane/control-plane }
- name: Apply whole cluster install
@@ -24,5 +24,5 @@
hosts: kube_control_plane
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults}
- { role: kubespray_defaults}
- { role: recover_control_plane/post-recover }

View File

@@ -0,0 +1,58 @@
---
- name: Validate nodes for removal
hosts: localhost
tasks:
- name: Assert that nodes are specified for removal
assert:
that:
- node is defined
- node | length > 0
msg: "No nodes specified for removal. The `node` variable must be set explicitly."
- name: Common tasks for every playbooks
import_playbook: boilerplate.yml
- name: Confirm node removal
hosts: "{{ node | default('this_is_unreachable') }}"
gather_facts: false
tasks:
- name: Confirm Execution
pause:
prompt: "Are you sure you want to delete nodes state? Type 'yes' to delete nodes."
register: pause_result
run_once: true
when:
- not (skip_confirmation | default(false) | bool)
- name: Fail if user does not confirm deletion
fail:
msg: "Delete nodes confirmation failed"
when: pause_result.user_input | default('yes') != 'yes'
- name: Gather facts
import_playbook: facts.yml
when: reset_nodes | default(True) | bool
- name: Reset node
hosts: "{{ node | default('this_is_unreachable') }}"
gather_facts: false
environment: "{{ proxy_disable_env }}"
pre_tasks:
- name: Gather information about installed services
service_facts:
when: reset_nodes | default(True) | bool
roles:
- { role: kubespray_defaults, when: reset_nodes | default(True) | bool }
- { role: remove_node/pre_remove, tags: pre-remove }
- role: remove-node/remove-etcd-node
when: "'etcd' in group_names"
- { role: reset, tags: reset, when: reset_nodes | default(True) | bool }
# Currently cannot remove first control plane node or first etcd node
- name: Post node removal
hosts: "{{ node | default('this_is_unreachable') }}"
gather_facts: false
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray_defaults, when: reset_nodes | default(True) | bool }
- { role: remove-node/post-remove, tags: post-remove }

View File

@@ -0,0 +1,24 @@
---
- name: Common tasks for every playbooks
import_playbook: boilerplate.yml
- name: Gather facts
import_playbook: facts.yml
- name: Reset cluster
hosts: etcd:k8s_cluster:calico_rr
gather_facts: false
pre_tasks:
- name: Gather information about installed services
service_facts:
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray_defaults }
- {
role: kubernetes/preinstall,
when: "dns_mode != 'none' and resolvconf_mode == 'host_resolvconf'",
tags: resolvconf,
dns_early: true,
}
- { role: reset, tags: reset }

View File

@@ -7,14 +7,14 @@ addusers:
etcd:
name: etcd
comment: "Etcd user"
create_home: no
system: yes
create_home: false
system: true
shell: /sbin/nologin
kube:
name: kube
comment: "Kubernetes user"
create_home: no
system: yes
create_home: false
system: true
shell: /sbin/nologin
group: "{{ kube_cert_group }}"

View File

@@ -2,22 +2,18 @@
role_name_check: 1
dependency:
name: galaxy
driver:
name: vagrant
provider:
name: libvirt
platforms:
- name: adduser-01
box: generic/ubuntu2004
cpus: 1
memory: 512
provider_options:
driver: kvm
- name: ubuntu20
cloud_image: ubuntu-2004
vm_cpu_cores: 1
vm_memory: 512
provisioner:
name: ansible
config_options:
defaults:
callbacks_enabled: profile_tasks
timeout: 120
playbooks:
create: ../../../../tests/cloud_playbooks/create-kubevirt.yml
verifier:
name: testinfra

View File

@@ -3,6 +3,6 @@ addusers:
- name: kube
comment: "Kubernetes user"
shell: /sbin/nologin
system: yes
system: true
group: "{{ kube_cert_group }}"
create_home: no
create_home: false

View File

@@ -2,14 +2,14 @@
addusers:
- name: etcd
comment: "Etcd user"
create_home: yes
create_home: true
home: "{{ etcd_data_dir }}"
system: yes
system: true
shell: /sbin/nologin
- name: kube
comment: "Kubernetes user"
create_home: no
system: yes
create_home: false
system: true
shell: /sbin/nologin
group: "{{ kube_cert_group }}"

View File

@@ -2,14 +2,14 @@
addusers:
- name: etcd
comment: "Etcd user"
create_home: yes
create_home: true
home: "{{ etcd_data_dir }}"
system: yes
system: true
shell: /sbin/nologin
- name: kube
comment: "Kubernetes user"
create_home: no
system: yes
create_home: false
system: true
shell: /sbin/nologin
group: "{{ kube_cert_group }}"

View File

@@ -12,4 +12,4 @@
dest: "{{ ssh_bastion_confing__name }}"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: 0644
mode: "0644"

View File

@@ -2,17 +2,11 @@
role_name_check: 1
dependency:
name: galaxy
driver:
name: vagrant
provider:
name: libvirt
platforms:
- name: bastion-01
box: generic/ubuntu2004
cpus: 1
memory: 512
provider_options:
driver: kvm
cloud_image: ubuntu-2004
vm_cpu_cores: 1
vm_memory: 512
provisioner:
name: ansible
config_options:
@@ -27,5 +21,7 @@ provisioner:
bastion:
hosts:
bastion-01:
playbooks:
create: ../../../../tests/cloud_playbooks/create-kubevirt.yml
verifier:
name: testinfra

View File

@@ -19,4 +19,4 @@
template:
src: "{{ ssh_bastion_confing__name }}.j2"
dest: "{{ playbook_dir }}/{{ ssh_bastion_confing__name }}"
mode: 0640
mode: "0640"

View File

@@ -0,0 +1,10 @@
---
- name: Warn for usage of deprecated role
fail:
msg: bootstrap-os is deprecated, switch to bootstrap_os
ignore_errors: true # noqa ignore-errors
run_once: true
- name: Compat for direct role import
import_role:
name: bootstrap_os

View File

@@ -2,21 +2,33 @@
## CentOS/RHEL/AlmaLinux specific variables
# Use the fastestmirror yum plugin
centos_fastestmirror_enabled: false
# Timeout (in seconds) for checking RHEL subscription status
rh_subscription_check_timeout: 180
## Flatcar Container Linux specific variables
# Disable locksmithd or leave it in its current state
coreos_locksmithd_disable: false
# Install epel repo on Centos/RHEL
epel_enabled: false
## Oracle Linux specific variables
# Install public repo on Oracle Linux
use_oracle_public_repo: true
## Ubuntu specific variables
# Disable unattended-upgrades for Linux kernel and all packages start with linux- on Ubuntu
ubuntu_kernel_unattended_upgrades_disabled: false
# Stop unattended-upgrades if it is currently running on Ubuntu
ubuntu_stop_unattended_upgrades: false
fedora_coreos_packages:
- python
- python3-libselinux
- ethtool # required in kubeadm preflight phase for verifying the environment
- ipset # required in kubeadm preflight phase for verifying the environment
- conntrack-tools # required by kube-proxy
- containernetworking-plugins # required by crio
## General
# Set the hostname to inventory_hostname

View File

@@ -0,0 +1,3 @@
---
dependencies:
- role: kubespray_defaults

View File

@@ -0,0 +1,7 @@
---
- name: Converge
hosts: all
gather_facts: false
become: true
roles:
- role: bootstrap_os

View File

@@ -0,0 +1,37 @@
---
role_name_check: 1
dependency:
name: galaxy
platforms:
- name: ubuntu20
cloud_image: ubuntu-2004
vm_cpu_cores: 1
vm_memory: 512
- name: ubuntu22
cloud_image: ubuntu-2204
vm_cpu_cores: 1
vm_memory: 512
- name: almalinux9
cloud_image: almalinux-9
vm_cpu_cores: 1
vm_memory: 512
- name: debian12
cloud_image: debian-12
vm_cpu_cores: 1
vm_memory: 512
provisioner:
name: ansible
config_options:
defaults:
callbacks_enabled: profile_tasks
timeout: 120
inventory:
group_vars:
all:
user:
name: foo
comment: My test comment
playbooks:
create: ../../../../tests/cloud_playbooks/create-kubevirt.yml
verifier:
name: testinfra

View File

@@ -1,13 +1,16 @@
---
- name: Enable selinux-ng repo for Amazon Linux for container-selinux
command: amazon-linux-extras enable selinux-ng
- name: Enable EPEL repo for Amazon Linux
yum_repository:
name: epel
file: epel
description: Extra Packages for Enterprise Linux 7 - $basearch
baseurl: http://download.fedoraproject.org/pub/epel/7/$basearch
gpgcheck: yes
gpgcheck: true
gpgkey: http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7
skip_if_unavailable: yes
enabled: yes
repo_gpgcheck: no
skip_if_unavailable: true
enabled: true
repo_gpgcheck: false
when: epel_enabled

View File

@@ -12,7 +12,7 @@
value: "{{ http_proxy | default(omit) }}"
state: "{{ http_proxy | default(False) | ternary('present', 'absent') }}"
no_extra_spaces: true
mode: 0644
mode: "0644"
become: true
when: not skip_http_proxy_on_os_packages
@@ -21,7 +21,7 @@
get_url:
url: https://yum.oracle.com/public-yum-ol7.repo
dest: /etc/yum.repos.d/public-yum-ol7.repo
mode: 0644
mode: "0644"
when:
- use_oracle_public_repo | default(true)
- '''ID="ol"'' in os_release.stdout_lines'
@@ -34,7 +34,7 @@
section: "{{ item }}"
option: enabled
value: "1"
mode: 0644
mode: "0644"
with_items:
- ol7_latest
- ol7_addons
@@ -59,7 +59,7 @@
section: "ol{{ ansible_distribution_major_version }}_addons"
option: "{{ item.option }}"
value: "{{ item.value }}"
mode: 0644
mode: "0644"
with_items:
- { option: "name", value: "ol{{ ansible_distribution_major_version }}_addons" }
- { option: "enabled", value: "1" }
@@ -75,12 +75,12 @@
section: "extras"
option: "{{ item.option }}"
value: "{{ item.value }}"
mode: 0644
mode: "0644"
with_items:
- { option: "name", value: "CentOS-{{ ansible_distribution_major_version }} - Extras" }
- { option: "enabled", value: "1" }
- { option: "gpgcheck", value: "0" }
- { option: "baseurl", value: "http://mirror.centos.org/{{ 'altarch' if (ansible_distribution_major_version | int) <= 7 and ansible_architecture == 'aarch64' else 'centos' }}/{{ ansible_distribution_major_version }}/extras/$basearch/{% if ansible_distribution_major_version | int > 7 %}os/{% endif %}" }
- { option: "baseurl", value: "http://mirror.centos.org/centos/{{ ansible_distribution_major_version }}/extras/$basearch/os/" }
when:
- use_oracle_public_repo | default(true)
- '''ID="ol"'' in os_release.stdout_lines'
@@ -92,9 +92,9 @@
- name: Check presence of fastestmirror.conf
stat:
path: /etc/yum/pluginconf.d/fastestmirror.conf
get_attributes: no
get_checksum: no
get_mime: no
get_attributes: false
get_checksum: false
get_mime: false
register: fastestmirror
# the fastestmirror plugin can actually slow down Ansible deployments
@@ -108,11 +108,3 @@
when:
- fastestmirror.stat.exists
- not centos_fastestmirror_enabled
# libselinux-python is required on SELinux enabled hosts
# See https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#managed-node-requirements
- name: Install libselinux python package
package:
name: "{{ ((ansible_distribution_major_version | int) < 8) | ternary('libselinux-python', 'python3-libselinux') }}"
state: present
become: true

View File

@@ -7,7 +7,7 @@
state: present
- name: Make sure docker service is enabled
systemd:
systemd_service:
name: docker
masked: false
enabled: true

View File

@@ -55,22 +55,10 @@
raw: apt-get update --allow-releaseinfo-change
become: true
when:
- '''ID=debian'' in os_release.stdout_lines'
- '''VERSION_ID="10"'' in os_release.stdout_lines or ''VERSION_ID="11"'' in os_release.stdout_lines'
- os_release_dict['ID'] == 'debian'
- os_release_dict['VERSION_ID'] in ["10", "11"]
register: bootstrap_update_apt_result
changed_when:
- '"changed its" in bootstrap_update_apt_result.stdout'
- '"value from" in bootstrap_update_apt_result.stdout'
ignore_errors: true
- name: Set the ansible_python_interpreter fact
set_fact:
ansible_python_interpreter: "/usr/bin/python3"
# Workaround for https://github.com/ansible/ansible/issues/25543
- name: Install dbus for the hostname module
package:
name: dbus
state: present
use: apt
become: true

View File

@@ -28,7 +28,7 @@
raw: "nohup bash -c 'sleep 5s && shutdown -r now'"
become: true
ignore_errors: true # noqa ignore-errors
ignore_unreachable: yes
ignore_unreachable: true
when: need_bootstrap.rc != 0
- name: Wait for the reboot to complete
@@ -38,9 +38,3 @@
delay: 5
sleep: 5
when: need_bootstrap.rc != 0
- name: Store the fact if this is an fedora core os host
set_fact:
is_fedora_coreos: True
tags:
- facts

View File

@@ -17,20 +17,14 @@
value: "{{ http_proxy | default(omit) }}"
state: "{{ http_proxy | default(False) | ternary('present', 'absent') }}"
no_extra_spaces: true
mode: 0644
mode: "0644"
become: true
when: not skip_http_proxy_on_os_packages
- name: Install python3 on fedora
raw: "dnf install --assumeyes --quiet python3"
# libselinux-python3 is required on SELinux enabled hosts
# See https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#managed-node-requirements
- name: Install ansible requirements
raw: "dnf install --assumeyes python3 python3-dnf libselinux-python3"
become: true
when:
- need_bootstrap.rc != 0
# libselinux-python3 is required on SELinux enabled hosts
# See https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#managed-node-requirements
- name: Install libselinux-python3
package:
name: libselinux-python3
state: present
become: true

View File

@@ -9,12 +9,6 @@
tags:
- facts
- name: Force binaries directory for Flatcar Container Linux by Kinvolk
set_fact:
bin_dir: "/opt/bin"
tags:
- facts
- name: Run bootstrap.sh
script: bootstrap.sh
become: true
@@ -22,14 +16,17 @@
when:
- need_bootstrap.rc != 0
- name: Set the ansible_python_interpreter fact
# Workaround ansible https://github.com/ansible/ansible/pull/82821
# We set the interpreter rather than ansible_python_interpreter to allow
# - using virtual env with task level ansible_python_interpreter later
# - let users specify an ansible_python_interpreter in group_vars
- name: Make interpreter discovery works on Flatcar
set_fact:
ansible_python_interpreter: "{{ bin_dir }}/python"
tags:
- facts
ansible_interpreter_python_fallback: "{{ (ansible_interpreter_python_fallback | default([])) + ['/opt/bin/python'] }}"
- name: Disable auto-upgrade
systemd:
systemd_service:
name: locksmithd.service
masked: true
state: stopped

View File

@@ -0,0 +1,62 @@
---
- name: Fetch /etc/os-release
raw: cat /etc/os-release
register: os_release
changed_when: false
# This command should always run, even in check mode
check_mode: false
- name: Include distro specifics vars and tasks
vars:
os_release_dict: "{{ os_release.stdout_lines | select('regex', '^.+=.*$') | map('regex_replace', '\"', '') |
map('split', '=') | community.general.dict }}"
block:
- name: Include vars
include_vars: "{{ item }}"
tags:
- facts
with_first_found:
- &search
files:
- "{{ os_release_dict['ID'] }}-{{ os_release_dict['VARIANT_ID'] }}.yml"
- "{{ os_release_dict['ID'] }}.yml"
paths:
- vars/
skip: true
- name: Include tasks
include_tasks: "{{ included_tasks_file }}"
with_first_found:
- <<: *search
paths: []
loop_control:
loop_var: included_tasks_file
- name: Install system packages
import_role:
name: system_packages
tags:
- system-packages
- name: Create remote_tmp for it is used by another module
file:
path: "{{ ansible_remote_tmp | default('~/.ansible/tmp') }}"
state: directory
mode: "0700"
- name: Gather facts
setup:
gather_subset: '!all'
filter: ansible_*
- name: Assign inventory name to unconfigured hostnames (non-CoreOS, non-Flatcar, Suse and ClearLinux, non-Fedora)
hostname:
name: "{{ inventory_hostname }}"
when: override_system_hostname
- name: Ensure bash_completion.d folder exists
file:
name: /etc/bash_completion.d/
state: directory
owner: root
group: root
mode: "0755"

View File

@@ -0,0 +1,3 @@
---
- name: Import Centos boostrap for openEuler
import_tasks: centos.yml

View File

@@ -0,0 +1,3 @@
---
- name: Import Opensuse bootstrap
import_tasks: opensuse.yml

View File

@@ -0,0 +1,3 @@
---
- name: Import Opensuse bootstrap
import_tasks: opensuse.yml

View File

@@ -8,9 +8,9 @@
- name: Check that /etc/sysconfig/proxy file exists
stat:
path: /etc/sysconfig/proxy
get_attributes: no
get_checksum: no
get_mime: no
get_attributes: false
get_checksum: false
get_mime: false
register: stat_result
- name: Create the /etc/sysconfig/proxy empty file

View File

@@ -12,7 +12,7 @@
value: "{{ http_proxy | default(omit) }}"
state: "{{ http_proxy | default(False) | ternary('present', 'absent') }}"
no_extra_spaces: true
mode: 0644
mode: "0644"
become: true
when: not skip_http_proxy_on_os_packages
@@ -28,6 +28,7 @@
register: rh_subscription_status
changed_when: "rh_subscription_status.rc != 0"
ignore_errors: true # noqa ignore-errors
timeout: "{{ rh_subscription_check_timeout }}"
become: true
- name: RHEL subscription Organization ID/Activation Key registration
@@ -62,17 +63,6 @@
- rh_subscription_username is defined
- rh_subscription_status.changed
# container-selinux is in extras repo
- name: Enable RHEL 7 repos
community.general.rhsm_repository:
name:
- "rhel-7-server-rpms"
- "rhel-7-server-extras-rpms"
state: "{{ 'enabled' if (rhel_enable_repos | default(True) | bool) else 'disabled' }}"
when:
- ansible_distribution_major_version == "7"
- (not rh_subscription_status.changed) or (rh_subscription_username is defined) or (rh_subscription_org_id is defined)
# container-selinux is in appstream repo
- name: Enable RHEL 8 repos
community.general.rhsm_repository:
@@ -87,9 +77,9 @@
- name: Check presence of fastestmirror.conf
stat:
path: /etc/yum/pluginconf.d/fastestmirror.conf
get_attributes: no
get_checksum: no
get_mime: no
get_attributes: false
get_checksum: false
get_mime: false
register: fastestmirror
# the fastestmirror plugin can actually slow down Ansible deployments
@@ -103,11 +93,3 @@
when:
- fastestmirror.stat.exists
- not centos_fastestmirror_enabled
# libselinux-python is required on SELinux enabled hosts
# See https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#managed-node-requirements
- name: Install libselinux python package
package:
name: "{{ ((ansible_distribution_major_version | int) < 8) | ternary('libselinux-python', 'python3-libselinux') }}"
state: present
become: true

View File

@@ -0,0 +1,29 @@
---
- name: Import Debian bootstrap
import_tasks: debian.yml
- name: Check unattended-upgrades file exist
stat:
path: /etc/apt/apt.conf.d/50unattended-upgrades
register: unattended_upgrades_file_stat
when:
- ubuntu_kernel_unattended_upgrades_disabled
- name: Disable kernel unattended-upgrades
lineinfile:
path: "{{ unattended_upgrades_file_stat.stat.path }}"
insertafter: "Unattended-Upgrade::Package-Blacklist"
line: '"linux-";'
state: present
become: true
when:
- ubuntu_kernel_unattended_upgrades_disabled
- unattended_upgrades_file_stat.stat.exists
- name: Stop unattended-upgrades service
service:
name: unattended-upgrades
state: stopped
enabled: false
become: true
when: ubuntu_stop_unattended_upgrades

View File

@@ -0,0 +1,2 @@
---
is_fedora_coreos: true

Some files were not shown because too many files have changed in this diff Show More