Skip to content

Commit 88cac30

Browse files
committed
poc - etcd analysis uses UBI, installs required tools at runtime
1 parent 49fb05a commit 88cac30

5 files changed

Lines changed: 95 additions & 15 deletions

File tree

cmd/aro/mirror.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,6 @@ func mirror(ctx context.Context, _log *logrus.Entry) error {
159159
// https://gitlab.cee.redhat.com/service/app-interface/-/blob/master/data/services/osd-operators/cicd/saas/saas-managed-upgrade-operator.yaml?ref_type=heads
160160
"quay.io/app-sre/managed-upgrade-operator:v0.1.1297-ge922e64",
161161

162-
// https://quay.io/repository/redhat_emp1/octosql-etcd
163-
"quay.io/redhat_emp1/octosql-etcd:latest",
164-
165162
// https://registry.redhat.io/openshift4/ose-must-gather (standard OpenShift must-gather)
166163
"registry.redhat.io/openshift4/ose-must-gather:latest",
167164

pkg/frontend/admin_openshiftcluster_etcdanalysis.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
)
3030

3131
const (
32-
etcdAnalysisImage = "arosvc.azurecr.io/redhat_emp1/octosql-etcd:latest"
32+
etcdAnalysisImage = "arosvc.azurecr.io/ubi9/ubi-minimal:latest"
3333
etcdDataDir = "/var/lib/etcd"
3434
etcdAnalysisSAPrefix = "etcd-analysis-privileged"
3535
etcdAnalysisSuffixLength = 8
@@ -175,8 +175,10 @@ func etcdAnalysisStream(ctx context.Context, log *logrus.Entry, k adminactions.K
175175
runJobStream(ctx, log, k, job, nopWriteCloser{w}, defaultJobRetryDelay)
176176
}
177177

178-
// buildEtcdAnalysisJob builds the Job that runs octosql-etcd against the snapshot.
178+
// buildEtcdAnalysisJob builds the Job that runs OctoSQL analysis against the snapshot.
179179
func buildEtcdAnalysisJob(vmName, filename, saName string) *batchv1.Job {
180+
snapshotPath := "/snapshot/" + filename
181+
180182
return &batchv1.Job{
181183
ObjectMeta: metav1.ObjectMeta{
182184
Name: "etcd-analysis-" + utilrand.String(5),
@@ -196,10 +198,13 @@ func buildEtcdAnalysisJob(vmName, filename, saName string) *batchv1.Job {
196198
},
197199
Containers: []corev1.Container{
198200
{
199-
Name: "analyzer",
200-
Image: etcdAnalysisImage,
201-
Command: []string{"/usr/local/bin/analyze-snapshot.sh"},
202-
Args: []string{"--delete", "/snapshot/" + filename},
201+
Name: "analyzer",
202+
Image: etcdAnalysisImage,
203+
Command: []string{
204+
"/bin/bash", "-c",
205+
etcdAnalysisScript,
206+
},
207+
Args: []string{"--delete", snapshotPath},
203208
SecurityContext: &corev1.SecurityContext{
204209
Privileged: pointerutils.ToPtr(true),
205210
},

pkg/frontend/admin_openshiftcluster_etcdanalysis_test.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -419,14 +419,18 @@ func TestBuildEtcdAnalysisJob(t *testing.T) {
419419
if c.Image != etcdAnalysisImage {
420420
t.Errorf("container.Image = %q, want %q", c.Image, etcdAnalysisImage)
421421
}
422-
wantCommand := []string{"/usr/local/bin/analyze-snapshot.sh"}
422+
wantCommand := []string{"/bin/bash", "-c", etcdAnalysisScript}
423423
if len(c.Command) != len(wantCommand) {
424-
t.Errorf("container.Command = %v, want %v", c.Command, wantCommand)
424+
t.Errorf("container.Command length = %d, want %d", len(c.Command), len(wantCommand))
425425
} else {
426-
for i, v := range wantCommand {
427-
if c.Command[i] != v {
428-
t.Errorf("container.Command[%d] = %q, want %q", i, c.Command[i], v)
429-
}
426+
if c.Command[0] != wantCommand[0] {
427+
t.Errorf("container.Command[0] = %q, want %q", c.Command[0], wantCommand[0])
428+
}
429+
if c.Command[1] != wantCommand[1] {
430+
t.Errorf("container.Command[1] = %q, want %q", c.Command[1], wantCommand[1])
431+
}
432+
if c.Command[2] != etcdAnalysisScript {
433+
t.Errorf("container.Command[2] does not match embedded etcdAnalysisScript")
430434
}
431435
}
432436
if len(c.Args) < 2 {

pkg/frontend/scripts.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ var backupOrFixEtcd string
1010

1111
//go:embed scripts/etcdkeycount.sh
1212
var etcdKeyCountScript string
13+
14+
//go:embed scripts/etcdanalysis.sh
15+
var etcdAnalysisScript string
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/bin/bash
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the Apache License 2.0.
4+
#
5+
# Installs OctoSQL and analyzes an etcd snapshot.
6+
# Usage: etcdanalysis.sh [--delete] /path/to/snapshot.snapshot
7+
set -euo pipefail
8+
9+
DELETE_SNAPSHOT=false
10+
if [ "${1:-}" = "--delete" ]; then
11+
DELETE_SNAPSHOT=true
12+
shift
13+
fi
14+
15+
SNAPSHOT_PATH="${1:-}"
16+
if [ -z "$SNAPSHOT_PATH" ]; then
17+
echo "Error: snapshot path required" >&2
18+
echo "Usage: $0 [--delete] /path/to/snapshot.snapshot" >&2
19+
exit 1
20+
fi
21+
22+
OCTOSQL_VERSION="0.13.0"
23+
24+
echo "Installing dependencies..."
25+
microdnf install -y curl tar gzip jq ca-certificates 2>&1
26+
27+
echo "Downloading OctoSQL ${OCTOSQL_VERSION}..."
28+
curl -sL "https://github.com/cube2222/octosql/releases/download/v${OCTOSQL_VERSION}/octosql_${OCTOSQL_VERSION}_linux_amd64.tar.gz" | \
29+
tar -xz -C /usr/local/bin octosql
30+
chmod +x /usr/local/bin/octosql
31+
32+
echo "Installing etcdsnapshot plugin..."
33+
export HOME=/tmp
34+
export OCTOSQL_NO_TELEMETRY=1
35+
octosql plugin repository add https://raw.githubusercontent.com/tjungblu/octosql-plugin-etcdsnapshot/main/plugin_repository.json 2>&1
36+
octosql plugin install etcdsnapshot/etcdsnapshot 2>&1
37+
38+
echo "Analyzing snapshot: ${SNAPSHOT_PATH}"
39+
SNAPSHOT_DIR=$(dirname "$SNAPSHOT_PATH")
40+
SNAPSHOT_FILE=$(basename "$SNAPSHOT_PATH")
41+
cd "$SNAPSHOT_DIR"
42+
43+
# Get metadata
44+
echo ""
45+
echo "=== Snapshot Metadata ==="
46+
octosql -ojson "SELECT * FROM ${SNAPSHOT_FILE}?meta=true" 2>/dev/null || echo "Warning: metadata query failed"
47+
48+
# Top 20 namespaces by total size
49+
echo ""
50+
echo "=== Top 20 Namespaces by Size ==="
51+
octosql -ojson "SELECT namespace, COUNT(*) as key_count, SUM(valueSize) as total_bytes FROM ${SNAPSHOT_FILE} WHERE namespace IS NOT NULL GROUP BY namespace ORDER BY total_bytes DESC LIMIT 20" 2>/dev/null || echo "Warning: namespace query failed"
52+
53+
# Top 20 largest individual resources
54+
echo ""
55+
echo "=== Top 20 Largest Resources ==="
56+
octosql -ojson "SELECT namespace, resourceType, name, valueSize FROM ${SNAPSHOT_FILE} WHERE namespace IS NOT NULL ORDER BY valueSize DESC LIMIT 20" 2>/dev/null || echo "Warning: largest resources query failed"
57+
58+
# Resource type distribution
59+
echo ""
60+
echo "=== Resource Type Distribution ==="
61+
octosql -ojson "SELECT resourceType, COUNT(*) as count, SUM(valueSize) as total_bytes FROM ${SNAPSHOT_FILE} WHERE resourceType IS NOT NULL GROUP BY resourceType ORDER BY total_bytes DESC LIMIT 30" 2>/dev/null || echo "Warning: resource type query failed"
62+
63+
# Clean up snapshot if requested
64+
if [ "$DELETE_SNAPSHOT" = "true" ]; then
65+
echo ""
66+
echo "Deleting snapshot file: ${SNAPSHOT_PATH}"
67+
rm -f "$SNAPSHOT_PATH"
68+
fi
69+
70+
echo ""
71+
echo "Analysis complete."

0 commit comments

Comments
 (0)