fix: segfault in ingress, persistentvolumeclaim, statefulset in kube_inventory (#9585)

This commit is contained in:
Aleksandr Venger 2021-10-20 00:09:37 +03:00 committed by GitHub
parent 3e1ebdb4c7
commit a7582fb893
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 290 additions and 10 deletions

View File

@ -39,11 +39,17 @@ func (ki *KubernetesInventory) gatherIngress(i netv1.Ingress, acc telegraf.Accum
tags["ip"] = ingress.IP
for _, rule := range i.Spec.Rules {
if rule.IngressRuleValue.HTTP == nil {
continue
}
for _, path := range rule.IngressRuleValue.HTTP.Paths {
fields["backend_service_port"] = path.Backend.Service.Port.Number
if path.Backend.Service != nil {
tags["backend_service_name"] = path.Backend.Service.Name
fields["backend_service_port"] = path.Backend.Service.Port.Number
}
fields["tls"] = i.Spec.TLS != nil
tags["backend_service_name"] = path.Backend.Service.Name
tags["path"] = path.Path
tags["host"] = rule.Host

View File

@ -109,6 +109,114 @@ func TestIngress(t *testing.T) {
},
hasError: false,
},
{
name: "no HTTPIngressRuleValue",
handler: &mockHandler{
responseMap: map[string]interface{}{
"/ingress/": netv1.IngressList{
Items: []netv1.Ingress{
{
Status: netv1.IngressStatus{
LoadBalancer: v1.LoadBalancerStatus{
Ingress: []v1.LoadBalancerIngress{
{
Hostname: "chron-1",
IP: "1.0.0.127",
},
},
},
},
Spec: netv1.IngressSpec{
Rules: []netv1.IngressRule{
{
Host: "ui.internal",
IngressRuleValue: netv1.IngressRuleValue{
HTTP: nil,
},
},
},
},
ObjectMeta: metav1.ObjectMeta{
Generation: 12,
Namespace: "ns1",
Name: "ui-lb",
CreationTimestamp: metav1.Time{Time: now},
},
},
},
},
},
},
hasError: false,
},
{
name: "no IngressServiceBackend",
handler: &mockHandler{
responseMap: map[string]interface{}{
"/ingress/": netv1.IngressList{
Items: []netv1.Ingress{
{
Status: netv1.IngressStatus{
LoadBalancer: v1.LoadBalancerStatus{
Ingress: []v1.LoadBalancerIngress{
{
Hostname: "chron-1",
IP: "1.0.0.127",
},
},
},
},
Spec: netv1.IngressSpec{
Rules: []netv1.IngressRule{
{
Host: "ui.internal",
IngressRuleValue: netv1.IngressRuleValue{
HTTP: &netv1.HTTPIngressRuleValue{
Paths: []netv1.HTTPIngressPath{
{
Path: "/",
Backend: netv1.IngressBackend{
Service: nil,
},
},
},
},
},
},
},
},
ObjectMeta: metav1.ObjectMeta{
Generation: 12,
Namespace: "ns1",
Name: "ui-lb",
CreationTimestamp: metav1.Time{Time: now},
},
},
},
},
},
},
output: []telegraf.Metric{
testutil.MustMetric(
"kubernetes_ingress",
map[string]string{
"ingress_name": "ui-lb",
"namespace": "ns1",
"ip": "1.0.0.127",
"hostname": "chron-1",
"host": "ui.internal",
"path": "/",
},
map[string]interface{}{
"tls": false,
"generation": int64(12),
"created": now.UnixNano(),
},
time.Unix(0, 0),
),
},
hasError: false,
},
}
for _, v := range tests {

View File

@ -34,10 +34,12 @@ func (ki *KubernetesInventory) gatherPersistentVolumeClaim(pvc corev1.Persistent
"phase_type": phaseType,
}
tags := map[string]string{
"pvc_name": pvc.Name,
"namespace": pvc.Namespace,
"phase": string(pvc.Status.Phase),
"storageclass": *pvc.Spec.StorageClassName,
"pvc_name": pvc.Name,
"namespace": pvc.Namespace,
"phase": string(pvc.Status.Phase),
}
if pvc.Spec.StorageClassName != nil {
tags["storageclass"] = *pvc.Spec.StorageClassName
}
if pvc.Spec.Selector != nil {
for key, val := range pvc.Spec.Selector.MatchLabels {

View File

@ -134,6 +134,58 @@ func TestPersistentVolumeClaim(t *testing.T) {
),
},
},
{
name: "no storage class name",
handler: &mockHandler{
responseMap: map[string]interface{}{
"/persistentvolumeclaims/": &corev1.PersistentVolumeClaimList{
Items: []corev1.PersistentVolumeClaim{
{
Status: corev1.PersistentVolumeClaimStatus{
Phase: "bound",
},
Spec: corev1.PersistentVolumeClaimSpec{
VolumeName: "pvc-dc870fd6-1e08-11e8-b226-02aa4bc06eb8",
StorageClassName: nil,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"select1": "s1",
"select2": "s2",
},
},
},
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns1",
Name: "pc1",
Labels: map[string]string{
"lab1": "v1",
"lab2": "v2",
},
CreationTimestamp: metav1.Time{Time: now},
},
},
},
},
},
},
output: []telegraf.Metric{
testutil.MustMetric(
"kubernetes_persistentvolumeclaim",
map[string]string{
"pvc_name": "pc1",
"namespace": "ns1",
"phase": "bound",
"selector_select1": "s1",
"selector_select2": "s2",
},
map[string]interface{}{
"phase_type": 0,
},
time.Unix(0, 0),
),
},
hasError: false,
},
}
for _, v := range tests {

View File

@ -28,16 +28,20 @@ func (ki *KubernetesInventory) gatherStatefulSet(s v1.StatefulSet, acc telegraf.
"replicas_current": status.CurrentReplicas,
"replicas_ready": status.ReadyReplicas,
"replicas_updated": status.UpdatedReplicas,
"spec_replicas": *s.Spec.Replicas,
"observed_generation": s.Status.ObservedGeneration,
}
if s.Spec.Replicas != nil {
fields["spec_replicas"] = *s.Spec.Replicas
}
tags := map[string]string{
"statefulset_name": s.Name,
"namespace": s.Namespace,
}
for key, val := range s.Spec.Selector.MatchLabels {
if ki.selectorFilter.Match(key) {
tags["selector_"+key] = val
if s.Spec.Selector != nil {
for key, val := range s.Spec.Selector.MatchLabels {
if ki.selectorFilter.Match(key) {
tags["selector_"+key] = val
}
}
}

View File

@ -92,6 +92,114 @@ func TestStatefulSet(t *testing.T) {
},
hasError: false,
},
{
name: "no label selector",
handler: &mockHandler{
responseMap: map[string]interface{}{
"/statefulsets/": &v1.StatefulSetList{
Items: []v1.StatefulSet{
{
Status: v1.StatefulSetStatus{
Replicas: 2,
CurrentReplicas: 4,
ReadyReplicas: 1,
UpdatedReplicas: 3,
ObservedGeneration: 119,
},
Spec: v1.StatefulSetSpec{
Replicas: toInt32Ptr(3),
Selector: nil,
},
ObjectMeta: metav1.ObjectMeta{
Generation: 332,
Namespace: "ns1",
Name: "sts1",
CreationTimestamp: metav1.Time{Time: now},
},
},
},
},
},
},
output: []telegraf.Metric{
testutil.MustMetric(
"kubernetes_statefulset",
map[string]string{
"namespace": "ns1",
"statefulset_name": "sts1",
},
map[string]interface{}{
"generation": int64(332),
"observed_generation": int64(119),
"created": now.UnixNano(),
"spec_replicas": int32(3),
"replicas": int32(2),
"replicas_current": int32(4),
"replicas_ready": int32(1),
"replicas_updated": int32(3),
},
time.Unix(0, 0),
),
},
hasError: false,
},
{
name: "no desired number of replicas",
handler: &mockHandler{
responseMap: map[string]interface{}{
"/statefulsets/": &v1.StatefulSetList{
Items: []v1.StatefulSet{
{
Status: v1.StatefulSetStatus{
Replicas: 2,
CurrentReplicas: 4,
ReadyReplicas: 1,
UpdatedReplicas: 3,
ObservedGeneration: 119,
},
Spec: v1.StatefulSetSpec{
Replicas: nil,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"select1": "s1",
"select2": "s2",
},
},
},
ObjectMeta: metav1.ObjectMeta{
Generation: 332,
Namespace: "ns1",
Name: "sts1",
CreationTimestamp: metav1.Time{Time: now},
},
},
},
},
},
},
output: []telegraf.Metric{
testutil.MustMetric(
"kubernetes_statefulset",
map[string]string{
"namespace": "ns1",
"statefulset_name": "sts1",
"selector_select1": "s1",
"selector_select2": "s2",
},
map[string]interface{}{
"generation": int64(332),
"observed_generation": int64(119),
"created": now.UnixNano(),
"replicas": int32(2),
"replicas_current": int32(4),
"replicas_ready": int32(1),
"replicas_updated": int32(3),
},
time.Unix(0, 0),
),
},
hasError: false,
},
}
for _, v := range tests {