change panic to fatal log
This commit is contained in:
@@ -57,7 +57,7 @@ func createConfig(configFile string, out string, password string, verbose bool)
|
||||
|
||||
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()
|
||||
|
||||
@@ -17,7 +17,7 @@ func InstallChart(chartSpec go_helm_client.ChartSpec) {
|
||||
logging.Log.Infof("Upgrading %s", chartSpec.ChartName)
|
||||
}
|
||||
if _, err := helmClient.InstallOrUpgradeChart(context.Background(), &chartSpec, nil); err != nil {
|
||||
panic(err)
|
||||
logging.Log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package helm_client
|
||||
|
||||
import (
|
||||
"kube-forge/internal/config"
|
||||
"kube-forge/internal/logging"
|
||||
|
||||
"helm.sh/helm/v3/pkg/repo"
|
||||
)
|
||||
@@ -16,7 +17,7 @@ func AddHelmRepo(namespace string, repoSettings config.RepoSettings) {
|
||||
}
|
||||
|
||||
if err := helmClient.AddOrUpdateChartRepo(chartRepo); err != nil {
|
||||
panic(err)
|
||||
logging.Log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ package kubespray
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"kube-forge/internal/config"
|
||||
"kube-forge/internal/logging"
|
||||
"kube-forge/internal/python"
|
||||
@@ -15,48 +13,6 @@ import (
|
||||
"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 {
|
||||
panic(err)
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
destination, err := os.Create(outFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer destination.Close()
|
||||
_, err = io.Copy(destination, source)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logging.Log.Info(fmt.Sprintf("K8s admin config: %s", outFile))
|
||||
}
|
||||
|
||||
func runPlaybook(playbookPath string, tags string) {
|
||||
config := config.GetConfig()
|
||||
var callbackExecute execute.Executor
|
||||
@@ -111,6 +67,6 @@ func runPlaybook(playbookPath string, tags string) {
|
||||
|
||||
err := callbackExecute.Execute(context.Background())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logging.Log.Fatal(err)
|
||||
}
|
||||
}
|
||||
54
internal/kubespray/utilits.go
Normal file
54
internal/kubespray/utilits.go
Normal 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))
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"kube-forge/internal/logging"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -22,6 +23,6 @@ func main() {
|
||||
pipPlatform := platforms[strings.Join([]string{os, arch}, "-")]
|
||||
err := pip.CreateEmbeddedPipPackages("requirements.txt", os, arch, pipPlatform, "./data/")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logging.Log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"kube-forge/internal/logging"
|
||||
"kube-forge/internal/python/data"
|
||||
"kube-forge/internal/resources"
|
||||
"os"
|
||||
@@ -117,7 +118,7 @@ func NewPythonExec() *PythonExec {
|
||||
|
||||
pythonLibFs, err := embed_util.NewEmbeddedFilesWithTmpDir(data.Data, pythonLibDir, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logging.Log.Fatal(err)
|
||||
}
|
||||
pythonLibFsPath := pythonLibFs.GetExtractedPath()
|
||||
resourcesFs, _ := embed_util.NewEmbeddedFilesWithTmpDir(resources.Kubespray, resourcesDir, true)
|
||||
|
||||
@@ -15,7 +15,7 @@ func executeTemplateToString(template *template.Template, config *config.Config)
|
||||
templateResult := &bytes.Buffer{}
|
||||
err := template.Execute(templateResult, config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logging.Log.Fatal(err)
|
||||
}
|
||||
templateResultString := templateResult.String()
|
||||
return templateResultString
|
||||
@@ -24,12 +24,12 @@ func executeTemplateToString(template *template.Template, config *config.Config)
|
||||
func getTemplateFromEmbedFSFolder(embedFS embed.FS, templateFile string) *template.Template {
|
||||
templateData, err := embedFS.ReadFile(templateFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logging.Log.Fatal(err)
|
||||
}
|
||||
templateDataString := string(templateData)
|
||||
template, err := template.New("tmpl").Funcs(funcMap()).Parse(templateDataString)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logging.Log.Fatal(err)
|
||||
}
|
||||
return template
|
||||
}
|
||||
@@ -50,12 +50,12 @@ func applyTemplates(templates [][2]string) {
|
||||
|
||||
file, err := os.Create(outFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logging.Log.Fatal(err)
|
||||
}
|
||||
defer file.Close()
|
||||
err = tmpl.Execute(file, config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logging.Log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
197
test-conf/manifests/HA-test.yaml
Normal file
197
test-conf/manifests/HA-test.yaml
Normal file
@@ -0,0 +1,197 @@
|
||||
---
|
||||
# Namespace for testing
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: ha-test
|
||||
|
||||
---
|
||||
# ConfigMap with application configuration
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-config
|
||||
namespace: ha-test
|
||||
data:
|
||||
index.html: |
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>HA Cluster Test</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 40px; }
|
||||
.info { background: #e7f3ff; padding: 20px; border-radius: 5px; margin: 10px 0; }
|
||||
.hostname { color: #2196F3; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Kubernetes HA Cluster Test</h1>
|
||||
<div class="info">
|
||||
<p><strong>Pod Hostname:</strong> <span class="hostname" id="hostname"></span></p>
|
||||
<p><strong>Timestamp:</strong> <span id="timestamp"></span></p>
|
||||
<p><strong>Node IP:</strong> <span id="nodeip"></span></p>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById('hostname').textContent = window.location.hostname;
|
||||
document.getElementById('timestamp').textContent = new Date().toISOString();
|
||||
// Node IP will be shown via environment variable injection
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
---
|
||||
# Deployment with multiple replicas for HA testing
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ha-test-app
|
||||
namespace: ha-test
|
||||
labels:
|
||||
app: ha-test-app
|
||||
spec:
|
||||
replicas: 6 # Deploy across multiple nodes
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 1
|
||||
maxSurge: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: ha-test-app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: ha-test-app
|
||||
spec:
|
||||
# Anti-affinity to spread pods across nodes
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- ha-test-app
|
||||
topologyKey: kubernetes.io/hostname
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.25-alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
env:
|
||||
- name: NODE_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_IP
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.podIP
|
||||
volumeMounts:
|
||||
- name: nginx-config
|
||||
mountPath: /usr/share/nginx/html
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 80
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 80
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
volumes:
|
||||
- name: nginx-config
|
||||
configMap:
|
||||
name: nginx-config
|
||||
|
||||
---
|
||||
# Service to expose the deployment
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ha-test-service
|
||||
namespace: ha-test
|
||||
labels:
|
||||
app: ha-test-app
|
||||
spec:
|
||||
selector:
|
||||
app: ha-test-app
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: http
|
||||
type: ClusterIP
|
||||
|
||||
---
|
||||
# NodePort Service for external access (alternative to ingress)
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ha-test-nodeport
|
||||
namespace: ha-test
|
||||
labels:
|
||||
app: ha-test-app
|
||||
spec:
|
||||
selector:
|
||||
app: ha-test-app
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
nodePort: 30080
|
||||
protocol: TCP
|
||||
name: http
|
||||
type: NodePort
|
||||
|
||||
---
|
||||
# HorizontalPodAutoscaler for testing scaling
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: ha-test-hpa
|
||||
namespace: ha-test
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: ha-test-app
|
||||
minReplicas: 3
|
||||
maxReplicas: 12
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 70
|
||||
|
||||
---
|
||||
# PodDisruptionBudget for HA
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: ha-test-pdb
|
||||
namespace: ha-test
|
||||
spec:
|
||||
minAvailable: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: ha-test-app
|
||||
Reference in New Issue
Block a user