Skip to content

Commit 193f64c

Browse files
fix: Missing reloader.go
1 parent f721020 commit 193f64c

3 files changed

Lines changed: 264 additions & 9 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ vendor
1111
dist
1212
Reloader
1313
!**/chart/reloader
14+
!**/internal/reloader
1415
*.tgz
1516
styles/
1617
site/
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
package reloader
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"os/exec"
8+
"path/filepath"
9+
"strings"
10+
"time"
11+
)
12+
13+
// Config holds configuration for a Reloader deployment.
14+
type Config struct {
15+
Version string
16+
Image string
17+
Namespace string
18+
ReloadStrategy string
19+
}
20+
21+
// Manager handles Reloader deployment operations.
22+
type Manager struct {
23+
config Config
24+
kubeContext string
25+
}
26+
27+
// NewManager creates a new Reloader manager.
28+
func NewManager(config Config) *Manager {
29+
return &Manager{
30+
config: config,
31+
}
32+
}
33+
34+
// SetKubeContext sets the kubeconfig context to use.
35+
func (m *Manager) SetKubeContext(kubeContext string) {
36+
m.kubeContext = kubeContext
37+
}
38+
39+
// kubectl returns kubectl command with optional context.
40+
func (m *Manager) kubectl(ctx context.Context, args ...string) *exec.Cmd {
41+
if m.kubeContext != "" {
42+
args = append([]string{"--context", m.kubeContext}, args...)
43+
}
44+
return exec.CommandContext(ctx, "kubectl", args...)
45+
}
46+
47+
// namespace returns the namespace for this reloader instance.
48+
func (m *Manager) namespace() string {
49+
if m.config.Namespace != "" {
50+
return m.config.Namespace
51+
}
52+
return fmt.Sprintf("reloader-%s", m.config.Version)
53+
}
54+
55+
// releaseName returns the release name for this instance.
56+
func (m *Manager) releaseName() string {
57+
return fmt.Sprintf("reloader-%s", m.config.Version)
58+
}
59+
60+
// Job returns the Prometheus job name for this Reloader instance.
61+
func (m *Manager) Job() string {
62+
return fmt.Sprintf("reloader-%s", m.config.Version)
63+
}
64+
65+
// Deploy deploys Reloader to the cluster using raw manifests.
66+
func (m *Manager) Deploy(ctx context.Context) error {
67+
ns := m.namespace()
68+
name := m.releaseName()
69+
70+
fmt.Printf("Deploying Reloader (%s) with image %s...\n", m.config.Version, m.config.Image)
71+
72+
manifest := m.buildManifest(ns, name)
73+
74+
applyCmd := m.kubectl(ctx, "apply", "-f", "-")
75+
applyCmd.Stdin = strings.NewReader(manifest)
76+
applyCmd.Stdout = os.Stdout
77+
applyCmd.Stderr = os.Stderr
78+
if err := applyCmd.Run(); err != nil {
79+
return fmt.Errorf("applying manifest: %w", err)
80+
}
81+
82+
fmt.Printf("Waiting for Reloader deployment to be ready...\n")
83+
waitCmd := m.kubectl(ctx, "rollout", "status", "deployment", name,
84+
"-n", ns,
85+
"--timeout=120s")
86+
waitCmd.Stdout = os.Stdout
87+
waitCmd.Stderr = os.Stderr
88+
if err := waitCmd.Run(); err != nil {
89+
return fmt.Errorf("waiting for deployment: %w", err)
90+
}
91+
92+
time.Sleep(2 * time.Second)
93+
94+
fmt.Printf("Reloader (%s) deployed successfully\n", m.config.Version)
95+
return nil
96+
}
97+
98+
// buildManifest creates the raw Kubernetes manifest for Reloader.
99+
func (m *Manager) buildManifest(ns, name string) string {
100+
var args []string
101+
args = append(args, "--log-format=json")
102+
if m.config.ReloadStrategy != "" && m.config.ReloadStrategy != "default" {
103+
args = append(args, fmt.Sprintf("--reload-strategy=%s", m.config.ReloadStrategy))
104+
}
105+
106+
argsYAML := ""
107+
if len(args) > 0 {
108+
argsYAML = " args:\n"
109+
for _, arg := range args {
110+
argsYAML += fmt.Sprintf(" - %q\n", arg)
111+
}
112+
}
113+
114+
return fmt.Sprintf(`---
115+
apiVersion: v1
116+
kind: Namespace
117+
metadata:
118+
name: %[1]s
119+
---
120+
apiVersion: v1
121+
kind: ServiceAccount
122+
metadata:
123+
name: %[2]s
124+
namespace: %[1]s
125+
---
126+
apiVersion: rbac.authorization.k8s.io/v1
127+
kind: ClusterRole
128+
metadata:
129+
name: %[2]s
130+
rules:
131+
- apiGroups: ["*"]
132+
resources: ["*"]
133+
verbs: ["*"]
134+
---
135+
apiVersion: rbac.authorization.k8s.io/v1
136+
kind: ClusterRoleBinding
137+
metadata:
138+
name: %[2]s
139+
roleRef:
140+
apiGroup: rbac.authorization.k8s.io
141+
kind: ClusterRole
142+
name: %[2]s
143+
subjects:
144+
- kind: ServiceAccount
145+
name: %[2]s
146+
namespace: %[1]s
147+
---
148+
apiVersion: apps/v1
149+
kind: Deployment
150+
metadata:
151+
name: %[2]s
152+
namespace: %[1]s
153+
labels:
154+
app: %[2]s
155+
app.kubernetes.io/name: reloader
156+
loadtest-version: %[3]s
157+
spec:
158+
replicas: 1
159+
selector:
160+
matchLabels:
161+
app: %[2]s
162+
template:
163+
metadata:
164+
labels:
165+
app: %[2]s
166+
app.kubernetes.io/name: reloader
167+
loadtest-version: %[3]s
168+
annotations:
169+
prometheus.io/scrape: "true"
170+
prometheus.io/port: "9090"
171+
prometheus.io/path: "/metrics"
172+
spec:
173+
serviceAccountName: %[2]s
174+
securityContext:
175+
runAsNonRoot: true
176+
runAsUser: 65534
177+
containers:
178+
- name: reloader
179+
image: %[4]s
180+
imagePullPolicy: IfNotPresent
181+
ports:
182+
- name: http
183+
containerPort: 9090
184+
%[5]s resources:
185+
requests:
186+
cpu: 10m
187+
memory: 64Mi
188+
limits:
189+
cpu: 500m
190+
memory: 256Mi
191+
securityContext:
192+
allowPrivilegeEscalation: false
193+
readOnlyRootFilesystem: true
194+
`, ns, name, m.config.Version, m.config.Image, argsYAML)
195+
}
196+
197+
// Cleanup removes all Reloader resources from the cluster.
198+
func (m *Manager) Cleanup(ctx context.Context) error {
199+
ns := m.namespace()
200+
name := m.releaseName()
201+
202+
delDeploy := m.kubectl(ctx, "delete", "deployment", name, "-n", ns, "--ignore-not-found")
203+
delDeploy.Run()
204+
205+
delCRB := m.kubectl(ctx, "delete", "clusterrolebinding", name, "--ignore-not-found")
206+
delCRB.Run()
207+
208+
delCR := m.kubectl(ctx, "delete", "clusterrole", name, "--ignore-not-found")
209+
delCR.Run()
210+
211+
delNS := m.kubectl(ctx, "delete", "namespace", ns, "--wait=false", "--ignore-not-found")
212+
if err := delNS.Run(); err != nil {
213+
return fmt.Errorf("deleting namespace: %w", err)
214+
}
215+
216+
return nil
217+
}
218+
219+
// CollectLogs collects logs from the Reloader pod and writes them to the specified file.
220+
func (m *Manager) CollectLogs(ctx context.Context, logPath string) error {
221+
ns := m.namespace()
222+
name := m.releaseName()
223+
224+
if err := os.MkdirAll(filepath.Dir(logPath), 0755); err != nil {
225+
return fmt.Errorf("creating log directory: %w", err)
226+
}
227+
228+
cmd := m.kubectl(ctx, "logs",
229+
"-n", ns,
230+
"-l", fmt.Sprintf("app=%s", name),
231+
"--tail=-1")
232+
233+
out, err := cmd.Output()
234+
if err != nil {
235+
cmd = m.kubectl(ctx, "logs",
236+
"-n", ns,
237+
"-l", "app.kubernetes.io/name=reloader",
238+
"--tail=-1")
239+
out, err = cmd.Output()
240+
if err != nil {
241+
return fmt.Errorf("collecting logs: %w", err)
242+
}
243+
}
244+
245+
if err := os.WriteFile(logPath, out, 0644); err != nil {
246+
return fmt.Errorf("writing logs: %w", err)
247+
}
248+
249+
return nil
250+
}

test/loadtest/internal/scenarios/scenarios.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ func (s *SecretsAndMixedScenario) Run(ctx context.Context, client kubernetes.Int
11371137
for time.Now().Before(endTime) {
11381138
select {
11391139
case <-ctx.Done():
1140-
return s.calculateExpected(secretUpdateCount, cmUpdateCount, numSecretOnlyDeploys, numConfigMapOnlyDeploys, numMixedDeploys), nil
1140+
return s.calculateExpected(secretUpdateCount, cmUpdateCount, numSecrets, numConfigMaps, numSecretOnlyDeploys, numConfigMapOnlyDeploys, numMixedDeploys), nil
11411141
case <-ticker.C:
11421142
if updateSecret {
11431143
// Update a random Secret
@@ -1169,21 +1169,25 @@ func (s *SecretsAndMixedScenario) Run(ctx context.Context, client kubernetes.Int
11691169
}
11701170

11711171
log.Printf("S10: Completed %d Secret updates and %d ConfigMap updates", secretUpdateCount, cmUpdateCount)
1172-
return s.calculateExpected(secretUpdateCount, cmUpdateCount, numSecretOnlyDeploys, numConfigMapOnlyDeploys, numMixedDeploys), nil
1172+
return s.calculateExpected(secretUpdateCount, cmUpdateCount, numSecrets, numConfigMaps, numSecretOnlyDeploys, numConfigMapOnlyDeploys, numMixedDeploys), nil
11731173
}
11741174

1175-
func (s *SecretsAndMixedScenario) calculateExpected(secretUpdates, cmUpdates, secretOnlyDeploys, cmOnlyDeploys, mixedDeploys int) ExpectedMetrics {
1176-
// Secret updates trigger: secret-only deploys + mixed deploys
1177-
secretTriggeredReloads := secretUpdates * (secretOnlyDeploys + mixedDeploys)
1178-
// ConfigMap updates trigger: cm-only deploys + mixed deploys
1179-
cmTriggeredReloads := cmUpdates * (cmOnlyDeploys + mixedDeploys)
1175+
func (s *SecretsAndMixedScenario) calculateExpected(secretUpdates, cmUpdates, numSecrets, numConfigMaps, secretOnlyDeploys, cmOnlyDeploys, mixedDeploys int) ExpectedMetrics {
1176+
// Average deploys triggered per random secret update
1177+
avgSecretReloads := float64(secretOnlyDeploys)/float64(numSecrets) + float64(mixedDeploys)/float64(numSecrets)
1178+
secretTriggeredReloads := int(float64(secretUpdates) * avgSecretReloads)
1179+
1180+
// Average deploys triggered per random CM update
1181+
avgCMReloads := float64(cmOnlyDeploys)/float64(numConfigMaps) + float64(mixedDeploys)/float64(numConfigMaps)
1182+
cmTriggeredReloads := int(float64(cmUpdates) * avgCMReloads)
1183+
11801184
totalExpectedReloads := secretTriggeredReloads + cmTriggeredReloads
11811185

11821186
return ExpectedMetrics{
11831187
ActionTotal: totalExpectedReloads,
11841188
ReloadExecutedTotal: totalExpectedReloads,
1185-
Description: fmt.Sprintf("S10: %d Secret updates (→%d reloads) + %d CM updates (→%d reloads) = %d total",
1186-
secretUpdates, secretTriggeredReloads, cmUpdates, cmTriggeredReloads, totalExpectedReloads),
1189+
Description: fmt.Sprintf("S10: %d Secret updates (→%d reloads, avg %.1f/update) + %d CM updates (→%d reloads, avg %.1f/update) = %d total",
1190+
secretUpdates, secretTriggeredReloads, avgSecretReloads, cmUpdates, cmTriggeredReloads, avgCMReloads, totalExpectedReloads),
11871191
}
11881192
}
11891193

0 commit comments

Comments
 (0)