Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IMPLEMENT RENDER KUSTOMIZATIONS APPS + ADD TESTING TO POC CODE #2

Open
patrick-hermann-sva opened this issue Jan 3, 2024 · 0 comments
Assignees
Labels
enhancement New feature or request

Comments

@patrick-hermann-sva
Copy link
Contributor

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"math/rand"
	"os"
	"reflect"
	"strings"
	"text/template"

	sthingsBase "github.com/stuttgart-things/sthingsBase"

	"golang.org/x/exp/maps"
)

var (
	clusterVars = make(map[string]interface{})
	envVars     = make(map[string]interface{})
	appVars     = make(map[string]interface{})
)

const tmpl = `{{ range . }}apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: {{ .Name }}
  namespace: {{ .Namespace }}
spec:
  interval: 1h
  retryInterval: 1m
  timeout: 5m
  sourceRef:
    name: {{ .SourceRef.Name }}
    kind: {{ .SourceRef.Kind }}
  path: {{ .Path }}
  prune: true
  wait: true{{ if .Substitute.Variables }}
  postBuild:
    substitute:{{ range $key, $value := .Substitute.Variables }}
      {{ $key }}: {{$value }}{{end}}{{ end }}
  patches:
    - patch: |-
        - op: replace
          path: {{ .VersionTarget.Path }}
          value: {{ .VersionTarget.Version }}
      target:
        kind: {{ .VersionTarget.Kind }}
        name: {{ .VersionTarget.Name }}
        namespace: {{ .VersionTarget.Namespace }}
---
{{ end }}
`

func main() {

	// SET CLUSTER VARS
	clusterVars["network"] = "10.31.103"
	clusterVars["countVIPs"] = 2
	clusterVars["ingressDomain"] = "app.4sthings.tiab.ssc.sva.de"

	// SET ENV VARS

	// READIN ALL DEFAULTS
	content, err := os.ReadFile("defaults.json")
	if err != nil {
		log.Fatal(err)
	}

	defaults := DefaultKustomizations{}
	var apps []Kustomization

	err = json.Unmarshal(content, &defaults)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(defaults)

	// ALL DEFAULT KUSTOMIZATIONS FOR NETWORK
	network := []string{"metallb", "cert-manager", "ingress-nginx"}

	// COLLECT VALUES FOR KUSTOMIZATION
	for _, Kustomization2 := range defaults.Defaults {

		fmt.Println("CHECKING FOR", Kustomization2.Name)

		for _, kustomization := range network {

			if kustomization == Kustomization2.Name {

				fmt.Println("FOUND KUSTOMIZATION", Kustomization2.Name)

				// CHECK IF VARS ARE REQUIRED
				if len(Kustomization2.Substitute.Variables) > 0 {

					// GET ALL VARIABLE KEYS
					variableKeys := maps.Keys(Kustomization2.Substitute.Variables)

					// OUTPUT ALL KEYS
					fmt.Println("FOUND VARIABLES:", variableKeys) // [2 3]
					var value string

					for _, variable := range variableKeys {

						// CHECK + SET DEFAULT VAR REFERENCES | APP DEFAULTS
						if strings.Contains(Kustomization2.Substitute.Variables[variable], "defaultVar") {
							defaultKeyValue := strings.Split(Kustomization2.Substitute.Variables[variable], "+")
							Kustomization2.Substitute.Variables[variable] = defaultKeyValue[1]
						}

						// CHECK + SET CLUSTER VAR REFERENCES | CLUSTER DEFAULTS
						if strings.Contains(Kustomization2.Substitute.Variables[variable], "clusterVars") {
							clusterKeyValue := strings.Split(Kustomization2.Substitute.Variables[variable], "+")
							Kustomization2.Substitute.Variables[variable] = clusterVars[clusterKeyValue[1]].(string)
						}

						// CALL METHODS
						if strings.Contains(Kustomization2.Substitute.Variables[variable], "invokeMethod") {
							funcKeyValue := strings.Split(Kustomization2.Substitute.Variables[variable], "+")

							value = InvokeMethod(VariableLookup{}, funcKeyValue[1])

							Kustomization2.Substitute.Variables[variable] = value
						}

					}
				}

				apps = append(apps, Kustomization2)

			}
		}

	}

	fmt.Println(apps)

	t := template.New("Flux kustomization")

	t, err = t.Parse(tmpl)
	if err != nil {
		log.Fatal("Parse: ", err)
		return
	}

	err = t.Execute(os.Stdout, apps)
	if err != nil {
		log.Fatal("Execute: ", err)
		return
	}

}

type Substitute struct {
	Variables        map[string]string
	Secrets          map[string]string
	SecretsResources []string
}

type VersionTarget struct {
	Name, Kind, Namespace, Path, Version string
}

type SourceRef struct {
	Name, Kind string
}

type Kustomization struct {
	Name, Namespace, Version, Path string
	SourceRef                      SourceRef
	VersionTarget                  VersionTarget
	Substitute                     Substitute
}

type DefaultKustomizations struct {
	Defaults []Kustomization
}

type Cluster struct {
	Name, Cloud, Operator string
	InfraKustomization    []Kustomization
	Ips                   []string
}

type VariableLookup struct{}

func InvokeMethod(any interface{}, name string, args ...interface{}) string {
	inputs := make([]reflect.Value, len(args))
	for i := range args {
		inputs[i] = reflect.ValueOf(args[i])
	}

	ans := reflect.ValueOf(any).MethodByName(name).Call(inputs)

	return ans[0].Interface().(string)
}

func (y VariableLookup) GetVIP() string {

	network := clusterVars["network"].(string)
	countVIPs := clusterVars["countVIPs"].(int)
	availableIPs := envVars[network+"_AVAILABLE"].([]string)
	takenIPs := envVars[network+"_TAKEN"].([]string)

	fmt.Println("AVAILABLE IPs ", availableIPs)
	fmt.Println("TAKEN IPs ", takenIPs)
	fmt.Println("COUNT VIPs ", countVIPs)

	result := GetDifferenceQuantity(availableIPs, takenIPs)
	fmt.Println(result)

	var ipRanges []string
	for i := 0; i < countVIPs; i++ {
		randomIndex := rand.Intn(len(result))
		pick := result[randomIndex]
		ipRanges = append(ipRanges, pick+"-"+pick)
	}

	appVars["IPS"] = ipRanges

	fmt.Println(ipRanges)
	iptemplate := `|{{ range $value := .IPS }}
	- {{ $value }}{{ end}}`

	ips, _ := sthingsBase.RenderTemplateInline(string(iptemplate), "missingkey=error", "{{", "}}", appVars)
	fmt.Println("RENDERED", ips)

	return string(ips)
}

func GetDifferenceQuantity(a, b []string) []string {
	temp := map[string]int{}
	for _, s := range a {
		temp[s]++
	}
	for _, s := range b {
		temp[s]--
	}

	var result []string

	for s, v := range temp {
		if v != 0 {
			result = append(result, s)
		}
	}
	return result
}

// func getRandomOpt(lists []string) []string {
// 	rand.Seed(time.Now().UnixNano())
// 	randIdx := rand.Intn(len(s))

// }
@patrick-hermann-sva patrick-hermann-sva added the enhancement New feature or request label Jan 3, 2024
@patrick-hermann-sva patrick-hermann-sva self-assigned this Jan 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant