Skip to content

Commit 56bacb5

Browse files
committed
Add must-gather tool to the operator image #3149
Signed-off-by: Israel Blancas <[email protected]>
1 parent 85a2b1f commit 56bacb5

File tree

7 files changed

+480
-2
lines changed

7 files changed

+480
-2
lines changed

.github/workflows/publish-images.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
for platform in $(echo $PLATFORMS | tr "," "\n"); do
4848
arch=${platform#*/}
4949
echo "Building manager for $arch"
50-
make manager ARCH=$arch
50+
make manager must-gather ARCH=$arch
5151
done
5252
5353
- name: Docker meta

Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ COPY --from=certificates /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-ce
1515

1616
# Copy binary built on the host
1717
COPY bin/manager_${TARGETARCH} manager
18+
COPY bin/must-gather_${TARGETARCH} must-gather
1819

1920
USER 65532:65532
2021

Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ ci: generate fmt vet test ensure-generate-is-noop
140140
manager: generate
141141
CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(ARCH) go build -o bin/manager_${ARCH} -ldflags "${COMMON_LDFLAGS} ${OPERATOR_LDFLAGS}" main.go
142142

143+
must-gather:
144+
CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(ARCH) go build -o bin/must-gather_${ARCH} -ldflags "${COMMON_LDFLAGS} ${OPERATOR_LDFLAGS}" ./cmd/gather/main.go
145+
143146
# Build target allocator binary
144147
.PHONY: targetallocator
145148
targetallocator:
@@ -328,7 +331,7 @@ scorecard-tests: operator-sdk
328331
# buildx is used to ensure same results for arm based systems (m1/2 chips)
329332
.PHONY: container
330333
container: GOOS = linux
331-
container: manager
334+
container: manager must-gather
332335
docker build -t ${IMG} .
333336

334337
# Push the container image, used only for local dev purposes

cmd/gather/cluster/cluster.go

+317
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
package cluster
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"os"
8+
"path/filepath"
9+
10+
otelv1alpha1 "github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1"
11+
otelv1beta1 "github.com/open-telemetry/opentelemetry-operator/apis/v1beta1"
12+
"github.com/open-telemetry/opentelemetry-operator/cmd/gather/config"
13+
routev1 "github.com/openshift/api/route/v1"
14+
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
15+
appsv1 "k8s.io/api/apps/v1"
16+
autoscalingv2 "k8s.io/api/autoscaling/v2"
17+
corev1 "k8s.io/api/core/v1"
18+
networkingv1 "k8s.io/api/networking/v1"
19+
policy1 "k8s.io/api/policy/v1"
20+
rbacv1 "k8s.io/api/rbac/v1"
21+
"k8s.io/apimachinery/pkg/labels"
22+
23+
"sigs.k8s.io/controller-runtime/pkg/client"
24+
)
25+
26+
type Cluster struct {
27+
config *config.Config
28+
}
29+
30+
func NewCluster(cfg *config.Config) Cluster {
31+
return Cluster{config: cfg}
32+
}
33+
34+
func (c *Cluster) GetOpenTelemetryCollectors() error {
35+
otelCols := otelv1beta1.OpenTelemetryCollectorList{}
36+
37+
err := c.config.KubernetesClient.List(context.TODO(), &otelCols, &client.ListOptions{})
38+
if err != nil {
39+
return err
40+
}
41+
42+
log.Println("OpenTelemetryCollectors found:", len(otelCols.Items))
43+
44+
errorDetected := false
45+
46+
for _, otelCol := range otelCols.Items {
47+
err := c.processOTELCollector(&otelCol)
48+
if err != nil {
49+
log.Fatalln(err)
50+
errorDetected = true
51+
}
52+
}
53+
54+
if errorDetected {
55+
return fmt.Errorf("something failed while getting the opentelemtrycollectors")
56+
}
57+
return nil
58+
}
59+
60+
func (c *Cluster) GetInstrumentations() error {
61+
instrumentations := otelv1alpha1.InstrumentationList{}
62+
63+
err := c.config.KubernetesClient.List(context.TODO(), &instrumentations, &client.ListOptions{})
64+
if err != nil {
65+
return err
66+
}
67+
68+
log.Println("Instrumentations found:", len(instrumentations.Items))
69+
70+
errorDetected := false
71+
72+
for _, instr := range instrumentations.Items {
73+
outputDir := filepath.Join(c.config.CollectionDir, instr.Namespace)
74+
err := os.MkdirAll(outputDir, os.ModePerm)
75+
if err != nil {
76+
log.Fatalln(err)
77+
errorDetected = true
78+
continue
79+
}
80+
81+
writeToFile(outputDir, &instr)
82+
83+
if err != nil {
84+
85+
}
86+
}
87+
88+
if errorDetected {
89+
return fmt.Errorf("something failed while getting the opentelemtrycollectors")
90+
}
91+
return nil
92+
}
93+
94+
func (c *Cluster) processOTELCollector(otelCol *otelv1beta1.OpenTelemetryCollector) error {
95+
log.Printf("Processing OpenTelemetryCollector %s/%s", otelCol.Namespace, otelCol.Name)
96+
folder, err := createFolder(c.config.CollectionDir, otelCol)
97+
if err != nil {
98+
return err
99+
}
100+
writeToFile(folder, otelCol)
101+
102+
err = c.processOwnedResources(otelCol)
103+
if err != nil {
104+
return err
105+
}
106+
107+
return nil
108+
}
109+
110+
func (c *Cluster) processOwnedResources(otelCol *otelv1beta1.OpenTelemetryCollector) error {
111+
folder, err := createFolder(c.config.CollectionDir, otelCol)
112+
if err != nil {
113+
return err
114+
}
115+
errorDetected := false
116+
117+
// ClusterRole
118+
crs := rbacv1.ClusterRoleList{}
119+
err = c.getOwnerResources(&crs, otelCol)
120+
if err != nil {
121+
errorDetected = true
122+
log.Fatalln(err)
123+
}
124+
for _, cr := range crs.Items {
125+
writeToFile(folder, &cr)
126+
}
127+
128+
// ClusterRoleBindings
129+
crbs := rbacv1.ClusterRoleBindingList{}
130+
err = c.getOwnerResources(&crbs, otelCol)
131+
if err != nil {
132+
errorDetected = true
133+
log.Fatalln(err)
134+
}
135+
for _, crb := range crbs.Items {
136+
writeToFile(folder, &crb)
137+
}
138+
139+
// ConfigMaps
140+
cms := corev1.ConfigMapList{}
141+
err = c.getOwnerResources(&cms, otelCol)
142+
if err != nil {
143+
errorDetected = true
144+
log.Fatalln(err)
145+
}
146+
for _, c := range cms.Items {
147+
writeToFile(folder, &c)
148+
}
149+
150+
// DaemonSets
151+
daemonsets := appsv1.DaemonSetList{}
152+
err = c.getOwnerResources(&daemonsets, otelCol)
153+
if err != nil {
154+
errorDetected = true
155+
log.Fatalln(err)
156+
}
157+
for _, d := range daemonsets.Items {
158+
writeToFile(folder, &d)
159+
}
160+
161+
// Deployments
162+
deployments := appsv1.DeploymentList{}
163+
err = c.getOwnerResources(&deployments, otelCol)
164+
if err != nil {
165+
errorDetected = true
166+
log.Fatalln(err)
167+
}
168+
for _, d := range deployments.Items {
169+
writeToFile(folder, &d)
170+
}
171+
172+
// HPAs
173+
hpas := autoscalingv2.HorizontalPodAutoscalerList{}
174+
err = c.getOwnerResources(&hpas, otelCol)
175+
if err != nil {
176+
errorDetected = true
177+
log.Fatalln(err)
178+
}
179+
for _, h := range hpas.Items {
180+
writeToFile(folder, &h)
181+
}
182+
183+
// Ingresses
184+
ingresses := networkingv1.IngressList{}
185+
err = c.getOwnerResources(&ingresses, otelCol)
186+
if err != nil {
187+
errorDetected = true
188+
log.Fatalln(err)
189+
}
190+
for _, i := range ingresses.Items {
191+
writeToFile(folder, &i)
192+
}
193+
194+
// PersistentVolumes
195+
pvs := corev1.PersistentVolumeList{}
196+
err = c.getOwnerResources(&pvs, otelCol)
197+
if err != nil {
198+
errorDetected = true
199+
log.Fatalln(err)
200+
}
201+
for _, p := range pvs.Items {
202+
writeToFile(folder, &p)
203+
}
204+
205+
// PersistentVolumeClaims
206+
pvcs := corev1.PersistentVolumeClaimList{}
207+
err = c.getOwnerResources(&pvcs, otelCol)
208+
if err != nil {
209+
errorDetected = true
210+
log.Fatalln(err)
211+
}
212+
for _, p := range pvcs.Items {
213+
writeToFile(folder, &p)
214+
}
215+
216+
// PodDisruptionBudget
217+
pdbs := policy1.PodDisruptionBudgetList{}
218+
err = c.getOwnerResources(&pdbs, otelCol)
219+
if err != nil {
220+
errorDetected = true
221+
log.Fatalln(err)
222+
}
223+
for _, pdb := range pdbs.Items {
224+
writeToFile(folder, &pdb)
225+
}
226+
227+
// PodMonitors
228+
pms := monitoringv1.PodMonitorList{}
229+
err = c.getOwnerResources(&pms, otelCol)
230+
if err != nil {
231+
errorDetected = true
232+
log.Fatalln(err)
233+
}
234+
for _, pm := range pms.Items {
235+
writeToFile(folder, pm)
236+
}
237+
238+
// Routes
239+
rs := routev1.RouteList{}
240+
err = c.getOwnerResources(&rs, otelCol)
241+
if err != nil {
242+
errorDetected = true
243+
log.Fatalln(err)
244+
}
245+
for _, r := range rs.Items {
246+
writeToFile(folder, &r)
247+
}
248+
249+
// Services
250+
services := corev1.ServiceList{}
251+
err = c.getOwnerResources(&services, otelCol)
252+
if err != nil {
253+
errorDetected = true
254+
log.Fatalln(err)
255+
}
256+
for _, s := range services.Items {
257+
writeToFile(folder, &s)
258+
}
259+
260+
// ServiceMonitors
261+
sms := monitoringv1.ServiceMonitorList{}
262+
err = c.getOwnerResources(&sms, otelCol)
263+
if err != nil {
264+
errorDetected = true
265+
log.Fatalln(err)
266+
}
267+
for _, s := range sms.Items {
268+
writeToFile(folder, s)
269+
}
270+
271+
// ServiceAccounts
272+
sas := corev1.ServiceAccountList{}
273+
err = c.getOwnerResources(&sas, otelCol)
274+
if err != nil {
275+
errorDetected = true
276+
log.Fatalln(err)
277+
}
278+
for _, s := range sas.Items {
279+
writeToFile(folder, &s)
280+
}
281+
282+
// StatefulSets
283+
statefulsets := appsv1.StatefulSetList{}
284+
err = c.getOwnerResources(&statefulsets, otelCol)
285+
if err != nil {
286+
errorDetected = true
287+
log.Fatalln(err)
288+
}
289+
for _, s := range statefulsets.Items {
290+
writeToFile(folder, &s)
291+
}
292+
293+
if errorDetected {
294+
return fmt.Errorf("something failed while getting the associated resources")
295+
}
296+
297+
return nil
298+
}
299+
300+
func (c *Cluster) getOwnerResources(objList client.ObjectList, otelCol *otelv1beta1.OpenTelemetryCollector) error {
301+
return c.config.KubernetesClient.List(context.TODO(), objList, &client.ListOptions{
302+
LabelSelector: labels.SelectorFromSet(labels.Set{
303+
"app.kubernetes.io/instance": fmt.Sprintf("%s.%s", otelCol.Namespace, otelCol.Name),
304+
"app.kubernetes.io/managed-by": "opentelemetry-operator",
305+
"app.kubernetes.io/part-of": "opentelemetry",
306+
}),
307+
})
308+
}
309+
310+
func hasOwnerReference(obj client.Object, otelCol *otelv1beta1.OpenTelemetryCollector) bool {
311+
for _, ownerRef := range obj.GetOwnerReferences() {
312+
if ownerRef.Kind == otelCol.Kind && ownerRef.UID == otelCol.UID {
313+
return true
314+
}
315+
}
316+
return false
317+
}

0 commit comments

Comments
 (0)