diff --git a/plugins/inputs/kube_inventory/ingress.go b/plugins/inputs/kube_inventory/ingress.go index 69765b4dd3257..6fd424dc0aef5 100644 --- a/plugins/inputs/kube_inventory/ingress.go +++ b/plugins/inputs/kube_inventory/ingress.go @@ -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 diff --git a/plugins/inputs/kube_inventory/ingress_test.go b/plugins/inputs/kube_inventory/ingress_test.go index cd2af76d34045..77ceceaac22ba 100644 --- a/plugins/inputs/kube_inventory/ingress_test.go +++ b/plugins/inputs/kube_inventory/ingress_test.go @@ -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 { diff --git a/plugins/inputs/kube_inventory/persistentvolumeclaim.go b/plugins/inputs/kube_inventory/persistentvolumeclaim.go index a5d30d6dca6f4..2b06cce6b9fbb 100644 --- a/plugins/inputs/kube_inventory/persistentvolumeclaim.go +++ b/plugins/inputs/kube_inventory/persistentvolumeclaim.go @@ -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 { diff --git a/plugins/inputs/kube_inventory/persistentvolumeclaim_test.go b/plugins/inputs/kube_inventory/persistentvolumeclaim_test.go index b4e468acd71e7..00da84f9f757a 100644 --- a/plugins/inputs/kube_inventory/persistentvolumeclaim_test.go +++ b/plugins/inputs/kube_inventory/persistentvolumeclaim_test.go @@ -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 { diff --git a/plugins/inputs/kube_inventory/statefulset.go b/plugins/inputs/kube_inventory/statefulset.go index 22b235116b22c..06335fc612a1e 100644 --- a/plugins/inputs/kube_inventory/statefulset.go +++ b/plugins/inputs/kube_inventory/statefulset.go @@ -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 + } } } diff --git a/plugins/inputs/kube_inventory/statefulset_test.go b/plugins/inputs/kube_inventory/statefulset_test.go index cbbc453f58f35..6f30acc8b7435 100644 --- a/plugins/inputs/kube_inventory/statefulset_test.go +++ b/plugins/inputs/kube_inventory/statefulset_test.go @@ -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 {