This commit is contained in:
mr
2026-01-07 16:56:27 +01:00
parent 3d416169e3
commit ec5c2972c3
949 changed files with 137032 additions and 49 deletions

115
internal/cluster.go Normal file
View File

@@ -0,0 +1,115 @@
package internal
import (
"bytes"
"fmt"
"oc-k8s/utils"
"os"
"os/exec"
)
func Help_Cluster() {
fmt.Println(`
Cluster commands: oc-k8s <action> cluster [env_folder] [release]
create - Create a new kind cluster named 'opencloud'
delete - Delete the kind cluster named 'opencloud'
help - Show this help message
Usage:
oc-k8s create cluster [env_folder] [release]
env_folder - Helm config folder (required, default: .)
release - Release values name (required, default: dev)
oc-k8s delete cluster [env_folder] [release]
env_folder - Helm config folder (required, default: .)
release - Release values name (required, default: dev)
oc-k8s help cluster `)
}
func Delete_Cluster(args ...string) error {
folder := "."
env := "dev"
if len(args) > 0 {
folder = args[0]
}
if len(args) > 1 {
env = args[1]
}
clusterName := "opencloud"
if b, err := os.ReadFile(folder + "/" + env + "-values.yaml"); err == nil {
clusterName, _ = utils.Extract(string(b), "clusterName")
}
utils.Exec("kind delete cluster --name " + clusterName)
return nil
}
func Create_Cluster(args ...string) error {
Delete_Cluster(args...)
folder := "."
env := "dev"
if len(args) > 0 {
folder = args[0]
}
if len(args) > 1 {
env = args[1]
}
clusterName := "opencloud"
if b, err := os.ReadFile(folder + "/" + env + "-values.yaml"); err == nil {
clusterName, _ = utils.Extract(string(b), "clusterName")
}
utils.Exec("kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.9.0/deploy/longhorn.yaml ")
kindConfig := `
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 30950
hostPort: 80
protocol: TCP
- containerPort: 30951
hostPort: 443
protocol: TCP
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5000"]
endpoint = ["http://dev-docker-registry-ui-registry-server.opencloud.svc.cluster.local:5000"]
`
cmd := exec.Command("kind", "create", "cluster", "--name", clusterName, "--config=-")
cmd.Stdin = bytes.NewBufferString(kindConfig)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return err
}
fmt.Println("[WARNING] New cluster should be merged into your current config !")
if err := utils.Exec("kind get kubeconfig --name " + clusterName + " > /tmp/kind-" + clusterName + ".kubeconfig"); err != nil {
return err
}
if err := utils.Exec("KUBECONFIG=~/.kube/config:/tmp/kind-" + clusterName + ".kubeconfig kubectl config view --flatten --merge --minify > /tmp/merged-kubeconfig.yaml"); err != nil {
return err
}
if err := utils.Exec("sudo mv /tmp/merged-kubeconfig.yaml ~/.kube/config"); err != nil {
return err
}
if err := utils.Exec("chmod 600 ~/.kube/config"); err != nil {
return err
}
if err := utils.Exec("kubectl config get-contexts"); err != nil {
return err
}
if err := utils.Exec("kubectl config use-context kind-opencloud"); err != nil {
return err
}
return nil
}

96
internal/db.go Normal file
View File

@@ -0,0 +1,96 @@
package internal
import (
"errors"
"fmt"
"oc-k8s/utils"
"os"
"strings"
)
func Help_DB() {
fmt.Println(`
Cluster commands: oc-k8s <action> cluster
create - Add datas in db
replace - Replace datas in db
delete - Delete datas in db
help - Show this help message
Usage:
oc-k8s create db [file_path] [release] [db_name] [env_folder]
file_path - Datas folder files path (required)
release - Release values name (default: dev)
db_name - db name (default: opencloud)
env_folder - Helm config folder (required, default: .)
oc-k8s upgrade db [file_path] [release] [db_name] [env_folder]
file_path - Datas folder files path (required)
release - Release values name (default: dev)
db_name - db name (default: opencloud)
env_folder - Helm config folder (required, default: .)
oc-k8s delete db [release] [db_name] [env_folder]
release - Release values name (default: dev)
db_name - db name (default: opencloud)
env_folder - Helm config folder (required, default: .)
oc-k8s help db `)
}
func Delete_DB(args ...string) error {
release := "dev"
db_name := "dev"
if len(args) > 0 {
release = args[0]
}
if len(args) > 1 {
db_name = args[1]
}
podName := "$(kubectl get pods -n " + release + " -o=name | grep " + release + "-mongodb-* | sed 's|pod/||')"
return utils.Exec("kubectl exec " + podName + ": -- mongosh --eval \"db.getSiblingDB('" + db_name + "').dropDatabase()\"")
}
func getFileNames(folderPath string) []string {
fileNames := []string{}
entries, err := os.ReadDir(folderPath)
if err != nil {
return fileNames
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
fileNames = append(fileNames, entry.Name())
}
return fileNames
}
func Create_DB(args ...string) error {
filePath := ""
if len(args) == 0 {
return errors.New("missing db datas file path")
} else {
filePath = args[0]
}
release := "dev"
db_name := "dev"
if len(args) > 1 {
release = args[1]
}
if len(args) > 2 {
db_name = args[2]
}
podName := "$(kubectl get pods -n " + release + " -o=name | grep " + release + "-mongodb-* | sed 's|pod/||')"
for _, fileName := range getFileNames(filePath) {
fmt.Println("ADD file " + fileName + " in collection")
if err := utils.Exec("kubectl cp " + fileName + " " + podName + ":/tmp/" + fileName); err != nil {
return err
}
if err := utils.Exec("kubectl exec " + podName + ": -- mongoimport --db " + db_name + " --collection " + strings.ReplaceAll(fileName, ".json", "") + " --file /tmp/" + fileName + " --jsonArray"); err != nil {
return err
}
}
return nil
}
func Upgrade_DB(args ...string) error {
Delete_DB(args[1:]...)
return Create_DB(args...)
}

55
internal/func.go Normal file
View File

@@ -0,0 +1,55 @@
package internal
import (
"fmt"
"oc-k8s/utils"
)
func Help_Func() {
fmt.Println(`
Main commands: oc-k8s <action>
install - Install opencloud dependancies [arch] [version]
start - Start opencloud k8s
stop - Stop opencloud k8s
Usage:
oc-k8s install [arch] [version]
arch - Arch of OS (required)
kind_version - version of kind (required)
oc-k8s start [env_folder] [release] [namespace] [branch] [target] [hostname]
env_folder - Helm config folder (required, default: .)
release - environnement selected (default: dev)
namespace - namespace selected (default: dev)
branch - Git branch to build (default: main)
target - make target (default: all)
oc-k8s stop`)
Help_Cluster()
Help_Services()
Help_Helm()
Help_Values()
Help_K3S()
Help_Kind()
Help_DB()
}
func Start(args ...string) error {
utils.Exec("sudo sysctl -w fs.inotify.max_user_instances=256")
utils.Exec("sudo /etc/init.d/apache2 stop")
utils.Exec("sudo nginx -s stop")
Create_Cluster(args...)
Create_Services(args...)
Create_Helm(args...)
return nil
}
func Stop(args ...string) error {
Delete_Helm(args...)
Delete_Cluster(args...)
return nil
}
func Install_Func(args ...string) error {
Install_K3S()
Install_Kind(args...)
Install_Helm()
return nil
}

109
internal/helm.go Normal file
View File

@@ -0,0 +1,109 @@
package internal
import (
"fmt"
"oc-k8s/utils"
"os"
)
func Help_Helm() {
fmt.Println(`
Helm commands: oc-k8s <action> helm
install - Install Helm
create - Install a helm release for the given environment (default: dev)
delete - Uninstall a helm release for the given environment (default: dev)
help - Show this help message
Usage:
oc-k8s install helm
oc-k8s create helm [env_folder] [release] [namespace]
env_folder - Helm config folder (required, default: .)
release - environnement selected (default: dev)
namespace - namespace selected (default: dev)
oc-k8s upgrade helm [env_folder] [release] [namespace]
env_folder - Helm config folder (required, default: .)
release - environnement selected (default: dev)
namespace - namespace selected (default: dev)
oc-k8s delete helm [release] [namespace]
release - environnement selected (default: dev)
namespace - namespace selected (default: dev)
oc-k8sh help helm`)
}
func Install_Helm() error {
utils.Exec("curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash")
utils.Exec("helm version")
return nil
}
func Delete_Helm(args ...string) error {
env := "dev"
namespace := "dev"
if len(args) > 0 {
env = args[0]
}
if len(args) > 1 {
namespace = args[1]
}
utils.Exec("helm uninstall " + env + " -n " + namespace)
utils.Exec("kubectl delete namespace " + namespace + " &")
return nil
}
func Create_Helm(args ...string) error {
folder := "."
release := "dev"
namespace := "dev"
if len(args) > 0 {
folder = args[0]
}
Delete_Cluster(args[1:]...)
if len(args) > 1 {
release = args[1]
}
if len(args) > 2 {
namespace = args[2]
}
clusterName := "opencloud"
if b, err := os.ReadFile(folder + "/" + release + "-values.yaml"); err == nil {
clusterName, _ = utils.Extract(string(b), "clusterName")
}
if err := utils.Exec("helm dependency update"); err != nil {
return err
}
if err := utils.Exec("helm dependency build"); err != nil {
return err
}
utils.Exec("kubectl delete sc longhorn-nor1")
utils.Exec("sudo ulimit -n 1000000")
if err := utils.Exec("helm install " + release + " " + clusterName + " -n " + namespace + " --create-namespace -f " + folder + "/" + release + "-values.yaml --debug"); err != nil {
return err
}
utils.Exec("kind get kubeconfig --name opencloud > ./deployed_config")
utils.Exec("kind export logs ./kind-logs")
return nil
}
func Upgrade_Helm(args ...string) error {
folder := "."
release := "dev"
namespace := "dev"
if len(args) > 0 {
folder = args[0]
}
Delete_Cluster(args[1:]...)
if len(args) > 1 {
release = args[1]
}
if len(args) > 2 {
namespace = args[2]
}
clusterName := "opencloud"
if b, err := os.ReadFile(folder + "/" + release + "-values.yaml"); err == nil {
clusterName, _ = utils.Extract(string(b), "clusterName")
}
return utils.Exec("helm upgrade " + release + " " + clusterName + " -n " + namespace + " --create-namespace -f " + folder + "/" + release + "-values.yaml")
}

29
internal/k3s.go Normal file
View File

@@ -0,0 +1,29 @@
package internal
import (
"fmt"
"oc-k8s/utils"
)
func Help_K3S() {
fmt.Println(`
K3S commands: oc-k8s <action> k3s
install - Install k3s
help - Show this help message
Usage:
oc-k8s install k3s
oc-k8s help values `)
}
func Install_K3S() error {
utils.Exec("sudo /usr/local/bin/k3s-uninstall.sh")
utils.Exec("sudo rm -rf /etc/rancher /var/lib/rancher ~/.kube")
if err := utils.Exec("curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644"); err != nil {
return err
}
if err := utils.Exec("sudo systemctl status k3s"); err != nil {
return err
}
return nil
}

32
internal/kind.go Normal file
View File

@@ -0,0 +1,32 @@
package internal
import (
"fmt"
"oc-k8s/utils"
)
func Help_Kind() {
fmt.Println(`
Kind commands: oc-k8s <action> kind
install - Install kind
help - Show this help message
Usage:
oc-k8s install kind [arch] [version]
arch - Arch of OS (required)
kind_version - version of kind (required)
oc-k8s help values `)
}
func Install_Kind(args ...string) error {
arch := "linux-amd64"
version := "v0.30.0"
if len(args) > 0 {
arch = args[0]
}
if len(args) > 1 {
version = args[1]
}
utils.Exec("curl -Lo kind-linux-amd64 https://kind.sigs.k8s.io/dl/" + version + "/kind-" + arch)
return nil
}

85
internal/services.go Normal file
View File

@@ -0,0 +1,85 @@
package internal
import (
"fmt"
"oc-k8s/utils"
"os"
)
var REPOS = []string{
"oc-auth",
"oc-catalog",
"oc-datacenter",
"oc-front",
"oc-monitord",
"oc-peer",
"oc-shared",
"oc-scheduler",
"oc-schedulerd",
"oc-workflow",
"oc-workspace",
}
func Help_Service() {
fmt.Println(`
Service commands: oc-k8s <action> services
create - Build all opencloud services
help - Show this help message
Usage:
oc-k8s create services [env_folder] [branch] [target]
env_folder - Helm config folder (required, default: .)
branch - Git branch to build (default: main)
target - make target (default: all)
oc-k8s help services `)
}
func Create_Service(args ...string) error {
folder := "."
release := "dev"
branch := "main"
target := "all"
if len(args) > 0 {
folder = args[0]
}
if len(args) > 1 {
release = args[1]
}
if len(args) > 3 {
branch = args[3]
}
if len(args) > 4 {
target = args[4]
}
hostname := "beta.opencloud.com"
if b, err := os.ReadFile(folder + "/" + release + "-values.yaml"); err == nil {
hostname, _ = utils.Extract(string(b), "host")
}
for _, repo := range REPOS {
repo_url := "https://cloud.o-forge.io/core/" + repo + ".git"
host := "$(ip -4 addr show $(ip route | awk '/default/ {print $5}') | awk '/inet / {print $2}' | cut -d/ -f1)"
port := "6443"
ca := "$(kubectl config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')"
cert := "$(kubectl config view --raw --minify -o jsonpath='{.users[0].user.client-certificate-data}')"
key := "$(kubectl config view --raw --minify -o jsonpath='{.users[0].user.client-key-data}')"
if inf, err := os.Stat("./" + repo); err != nil || !inf.IsDir() {
fmt.Println("Cloning repository: " + repo)
if err := utils.Exec("git clone " + repo_url); err != nil {
return err
}
}
fmt.Println("Repository '" + repo + "' now exists. Pulling latest changes...")
if err := utils.Exec("cd " + repo + " && git checkout " + branch + " && git pull"); err != nil {
return err
}
if err := utils.Exec("cd " + repo + " && export HOST=" + hostname + " && export KUBERNETES_SERVICE_HOST=" + host + " && export KUBERNETES_SERVICE_PORT=" + port + " && export KUBE_CA=" + ca + " && export KUBE_CERT=" + cert + " && export KUBE_DATA=" + key + " && make " + target); err != nil {
return err
}
}
return nil
}

117
internal/values.go Normal file
View File

@@ -0,0 +1,117 @@
package internal
import (
"bufio"
"fmt"
"oc-k8s/utils"
"os"
"regexp"
"strings"
)
func Help_Values() {
fmt.Println(`
Values commands: oc-k8s <action> values
create - Create a new values release yaml
help - Show this help message
Usage:
oc-k8s create values [release] [env_folder] [env_file]
release - Release values name (required)
env_folder - Helm config folder (optionnal, default: .)
env_file - env to map (optionnal)
oc-k8s help values `)
}
var varPattern = regexp.MustCompile(`\$\{([A-Za-z_][A-Za-z0-9_]*)[:-]([^}]+)\}`)
func Create_Values(args ...string) error {
folder := "."
release := "dev"
conf := ""
if len(args) > 0 {
release = args[0]
}
if len(args) > 1 {
folder = args[1]
}
if len(args) > 2 {
conf = args[2]
}
return generateConfig(conf, release, folder)
}
func generateConfig(confFile string, release string, output_folder string) error {
// Load env file if provided
var err error
confs := map[string]string{}
if confFile != "" {
if confs, err = loadEnvFile(confFile); err != nil {
return err
}
} else {
confFile = "no configuration file"
}
// Read template
content, err := utils.ReadFS("assets/values.yaml.template")
if err != nil {
return err
}
rendered := renderTemplate(string(content), confs)
// Ensure output directory exists
if err := os.MkdirAll(output_folder, 0755); err != nil {
return err
}
// Write output
if err := os.WriteFile(output_folder+"/"+release+"-values.yaml", []byte(rendered), 0644); err != nil {
return err
}
fmt.Printf("Rendered %s from %s using %s\n", output_folder+"/"+release+"-values.yaml", "assets/values.yaml.template", confFile)
return nil
}
func loadEnvFile(path string) (map[string]string, error) {
envs := map[string]string{}
file, err := os.Open(path)
if err != nil {
return envs, err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := strings.TrimSpace(parts[0])
val := strings.Trim(strings.TrimSpace(parts[1]), `"'`)
envs[key] = val
}
return envs, scanner.Err()
}
func renderTemplate(input string, envs map[string]string) string {
return varPattern.ReplaceAllStringFunc(input, func(match string) string {
sub := varPattern.FindStringSubmatch(match)
varName := sub[1]
defaultVal := sub[2][1:]
if val, ok := envs[varName]; ok && val != "" {
return val
}
return defaultVal
})
}