-
Notifications
You must be signed in to change notification settings - Fork 90
/
gather_sap_pods.go
140 lines (123 loc) · 4 KB
/
gather_sap_pods.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
package clusterconfig
import (
"context"
"fmt"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
batchv1client "k8s.io/client-go/kubernetes/typed/batch/v1"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
"github.com/openshift/insights-operator/pkg/record"
)
// GatherSAPPods Collects information about pods running in SAP/SDI namespaces.
//
// - Only pods with a failing status are collected.
// - Failed pods belonging to a job that has later succeeded are ignored.
//
// > **Note**
// > This data is collected only if the `installers.datahub.sap.com` resource is found in the cluster.
//
// ### API Reference
// - https://pkg.go.dev/k8s.io/client-go/kubernetes/typed/core/v1
// - https://pkg.go.dev/k8s.io/client-go/kubernetes/typed/batch/v1
// - https://pkg.go.dev/k8s.io/client-go/dynamic
//
// ### Sample data
// None
//
// ### Location in archive
// - `config/pod/{namespace}/{name}.json`
//
// ### Config ID
// `clusterconfig/sap_pods`
//
// ### Released version
// - 4.8.2
//
// ### Backported versions
// - 4.7.5+
// - 4.6.25+
//
// ### Changes
// None
func (g *Gatherer) GatherSAPPods(ctx context.Context) ([]record.Record, []error) {
gatherDynamicClient, err := dynamic.NewForConfig(g.gatherKubeConfig)
if err != nil {
return nil, []error{err}
}
gatherKubeClient, err := kubernetes.NewForConfig(g.gatherProtoKubeConfig)
if err != nil {
return nil, []error{err}
}
gatherJobsClient, err := batchv1client.NewForConfig(g.gatherKubeConfig)
if err != nil {
return nil, []error{err}
}
return gatherSAPPods(ctx, gatherDynamicClient, gatherKubeClient.CoreV1(), gatherJobsClient)
}
func gatherSAPPods(ctx context.Context,
dynamicClient dynamic.Interface,
coreClient corev1client.CoreV1Interface,
jobsClient batchv1client.BatchV1Interface) ([]record.Record, []error) {
datahubsResource := schema.GroupVersionResource{Group: "installers.datahub.sap.com", Version: "v1alpha1", Resource: "datahubs"}
datahubsList, err := dynamicClient.Resource(datahubsResource).List(ctx, metav1.ListOptions{})
if errors.IsNotFound(err) {
return nil, nil
}
if err != nil {
return nil, []error{err}
}
var records []record.Record
collectedNamespaces := map[string]struct{}{}
for _, datahub := range datahubsList.Items {
datahubNamespace := datahub.GetNamespace()
if _, exists := collectedNamespaces[datahubNamespace]; exists {
continue
}
collectedNamespaces[datahubNamespace] = struct{}{}
pods, err := coreClient.Pods(datahubNamespace).List(ctx, metav1.ListOptions{})
if errors.IsNotFound(err) {
continue
}
if err != nil {
return nil, []error{err}
}
for i := range pods.Items {
// Skip pods that are running correctly or those that have already successfully finished.
if pods.Items[i].Status.Phase == v1.PodRunning || pods.Items[i].Status.Phase == v1.PodSucceeded {
continue
}
// Indicates if the pod belongs to a successful job.
successfulJob := false
for _, owner := range pods.Items[i].ObjectMeta.OwnerReferences {
if owner.Kind != "Job" {
continue
}
ownerJob, err := jobsClient.Jobs(pods.Items[i].Namespace).Get(ctx, owner.Name, metav1.GetOptions{})
if err != nil {
return nil, []error{err}
}
if ownerJob.Status.Succeeded > 0 {
successfulJob = true
break
}
}
// If the job succeeded using a different pod after this pod failed,
// this pod is no longer relevant and should not be gathered.
if successfulJob {
continue
}
records = append(records, record.Record{
// There are already some (OpenShift/OCP) pods in `/config/pod/**`
Name: fmt.Sprintf("config/pod/%s/%s", pods.Items[i].Namespace, pods.Items[i].Name),
// It is impossible to use `&pod` here because it would end up being
// the last returned pod as the reference keeps changing with each iteration.
Item: record.ResourceMarshaller{Resource: &pods.Items[i]},
})
}
}
return records, nil
}