-
Notifications
You must be signed in to change notification settings - Fork 0
/
targets.go
180 lines (158 loc) · 4.99 KB
/
targets.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package magekubernetes
import (
"fmt"
"os"
"strings"
"github.com/magefile/mage/mg" // mg contains helpful utility functions, like Deps
"github.com/magefile/mage/sh" // sh contains helpful utility functions, like RunV
)
// Validate Kubernetes manifests for ArgCD applications related to this repository
func Validate() error {
templates, err := renderTemplates()
if err != nil {
return err
}
mg.Deps(mg.F(kubeScore, templates))
mg.Deps(mg.F(kubeConform, templates, "api-platform"))
mg.Deps(Pallets)
fmt.Println("Validation passed")
return nil
}
// KubeScore runs kube-score on Kubernetes manifests for ArgCD applications related to this repository
func KubeScore() error {
templates, err := renderTemplates()
if err != nil {
return err
}
return kubeScore(templates)
}
// KubeConform runs kubeconform on Kubernetes manifests for ArgCD applications related to this repository
func KubeConform() error {
templates, err := renderTemplates()
if err != nil {
return err
}
return kubeConform(templates, "api-platform")
}
// Pallets validates the pallet files in the .pallet directory
func Pallets() error {
pallets, err := listPalletFiles()
if err != nil {
return err
}
fmt.Println("Validating Pallets")
return kubeConform(strings.Join(pallets, ","), "pallets")
}
// ArgoCDListApps show the apps related to this repository
func ArgoCDListApps() error {
err := listArgoCDDeployments()
if err != nil {
return err
}
return nil
}
// ArgoCDDiff runs a diff between local changes and the current running state in ArgoCD
func ArgoCDDiff() error {
repo, err := repoURL()
if err != nil {
return err
}
apps, err := getArgoCDDeployments(repo)
if err != nil {
return err
}
err = getArgoCDDiff(apps)
if err != nil {
return err
}
return nil
}
// validateKyvernoPolicies runs Kyverno validation on rendered Kubernetes manifests.
func validateKyvernoPolicies(renderedTemplatePaths string) error {
policyDir := "kyverno-policies" // Directory where policies are stored
templateFiles, err := os.ReadDir(renderedTemplatePaths)
if err != nil {
return fmt.Errorf("failed to read rendered templates: %w", err)
}
for _, templateFile := range templateFiles {
// Skip if it’s a directory
if templateFile.IsDir() {
continue
}
// Construct the full path for the current template file
templatePath := fmt.Sprintf("%s/%s", renderedTemplatePaths, templateFile.Name())
policyFiles, err := os.ReadDir(policyDir)
if err != nil {
return fmt.Errorf("failed to read Kyverno policies: %w", err)
}
for _, policyFile := range policyFiles {
if !strings.HasSuffix(policyFile.Name(), ".yaml") {
continue
}
policyFilePath := fmt.Sprintf("%s/%s", policyDir, policyFile.Name())
cmdOptions := []string{
"apply", policyFilePath,
"--resource", templatePath,
"--policy-report",
"--output", "yaml",
}
output, err := sh.Output("kyverno", cmdOptions...)
if err != nil {
return fmt.Errorf("Kyverno validation failed for template '%s' with policy '%s': %w", templatePath, policyFilePath, err)
}
fmt.Printf("Kyverno validation for template '%s' with policy '%s' completed.\n", templatePath, policyFilePath)
if strings.Contains(output, "violation") || strings.Contains(output, "failed") {
return fmt.Errorf("Kyverno validation issues found in template '%s' with policy '%s': %s", templatePath, policyFilePath, output)
}
}
}
return nil
}
// ValidateKyverno runs render Kubernetes manifests and invokes validateKyvernoPolicies.
func ValidateKyverno() error {
// Render templates and obtain paths
renderedTemplates, err := renderTemplates()
if err != nil {
return fmt.Errorf("failed to render templates: %w", err)
}
// Validate rendered templates with Kyverno
err = validateKyvernoPolicies(renderedTemplates)
if err != nil {
return fmt.Errorf("Kyverno validation failed: %w", err)
}
fmt.Println("All templates passed Kyverno validation.")
return nil
}
func kubeScore(paths string) error {
if paths == "" {
fmt.Printf("No files presented to kube-score, skipping")
return nil
}
cmdOptions := []string{
"score"}
out, err := sh.Output("kube-score", append(cmdOptions, strings.Split(paths, ",")...)...)
if err != nil {
fmt.Printf("kube-score returned exit code: %d\n Output:\n %v Error:\n %v\n", sh.ExitStatus(err), out, err)
return err
}
fmt.Println("kube-score passed")
return nil
}
func kubeConform(paths string, schemaSelection string) error {
if paths == "" {
fmt.Printf("No files presented to kubeconform, skipping")
return nil
}
cmdOptions := []string{
"-strict",
"-verbose",
"-schema-location", "default",
"-schema-location", "https://raw.githubusercontent.com/coopnorge/kubernetes-schemas/main/" + schemaSelection + "/{{ .ResourceKind }}{{ .KindSuffix }}.json"}
out, err := sh.Output("kubeconform", append(cmdOptions, strings.Split(paths, ",")...)...)
if err != nil {
fmt.Printf("kubeconform returned exit code: %d\n Output:\n %v Error:\n %v\n", sh.ExitStatus(err), out, err)
return err
}
fmt.Println("kubeconform passed")
return nil
}