158 lines
4.6 KiB
Go
158 lines
4.6 KiB
Go
// Licensed to Elasticsearch B.V. under one or more contributor
|
|
// license agreements. See the NOTICE file distributed with
|
|
// this work for additional information regarding copyright
|
|
// ownership. Elasticsearch B.V. licenses this file to you under
|
|
// the Apache License, Version 2.0 (the "License"); you may
|
|
// not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
package kubernetes
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/elastic/beats/libbeat/common"
|
|
"github.com/elastic/beats/libbeat/common/safemapstr"
|
|
)
|
|
|
|
// MetaGenerator builds metadata objects for pods and containers
|
|
type MetaGenerator interface {
|
|
// ResourceMetadata generates metadata for the given kubernetes object taking to account certain filters
|
|
ResourceMetadata(obj Resource) common.MapStr
|
|
|
|
// PodMetadata generates metadata for the given pod taking to account certain filters
|
|
PodMetadata(pod *Pod) common.MapStr
|
|
|
|
// Containermetadata generates metadata for the given container of a pod
|
|
ContainerMetadata(pod *Pod, container string) common.MapStr
|
|
}
|
|
|
|
// MetaGeneratorConfig settings
|
|
type MetaGeneratorConfig struct {
|
|
IncludeLabels []string `config:"include_labels"`
|
|
ExcludeLabels []string `config:"exclude_labels"`
|
|
IncludeAnnotations []string `config:"include_annotations"`
|
|
|
|
// Undocumented settings, to be deprecated in favor of `drop_fields` processor:
|
|
IncludePodUID bool `config:"include_pod_uid"`
|
|
IncludeCreatorMetadata bool `config:"include_creator_metadata"`
|
|
}
|
|
|
|
type metaGenerator = MetaGeneratorConfig
|
|
|
|
// NewMetaGenerator initializes and returns a new kubernetes metadata generator
|
|
func NewMetaGenerator(cfg *common.Config) (MetaGenerator, error) {
|
|
// default settings:
|
|
generator := metaGenerator{
|
|
IncludeCreatorMetadata: true,
|
|
}
|
|
|
|
err := cfg.Unpack(&generator)
|
|
return &generator, err
|
|
}
|
|
|
|
// NewMetaGeneratorFromConfig initializes and returns a new kubernetes metadata generator
|
|
func NewMetaGeneratorFromConfig(cfg *MetaGeneratorConfig) MetaGenerator {
|
|
return cfg
|
|
}
|
|
|
|
// ResourceMetadata generates metadata for the given kubernetes object taking to account certain filters
|
|
func (g *metaGenerator) ResourceMetadata(obj Resource) common.MapStr {
|
|
objMeta := obj.GetMetadata()
|
|
labelMap := common.MapStr{}
|
|
if len(g.IncludeLabels) == 0 {
|
|
for k, v := range obj.GetMetadata().Labels {
|
|
safemapstr.Put(labelMap, k, v)
|
|
}
|
|
} else {
|
|
labelMap = generateMapSubset(objMeta.Labels, g.IncludeLabels)
|
|
}
|
|
|
|
// Exclude any labels that are present in the exclude_labels config
|
|
for _, label := range g.ExcludeLabels {
|
|
delete(labelMap, label)
|
|
}
|
|
|
|
annotationsMap := generateMapSubset(objMeta.Annotations, g.IncludeAnnotations)
|
|
meta := common.MapStr{}
|
|
if objMeta.GetNamespace() != "" {
|
|
meta["namespace"] = objMeta.GetNamespace()
|
|
}
|
|
|
|
// Add controller metadata if present
|
|
if g.IncludeCreatorMetadata {
|
|
for _, ref := range objMeta.OwnerReferences {
|
|
if ref.GetController() {
|
|
switch ref.GetKind() {
|
|
// TODO grow this list as we keep adding more `state_*` metricsets
|
|
case "Deployment",
|
|
"ReplicaSet",
|
|
"StatefulSet":
|
|
safemapstr.Put(meta, strings.ToLower(ref.GetKind())+".name", ref.GetName())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(labelMap) != 0 {
|
|
meta["labels"] = labelMap
|
|
}
|
|
|
|
if len(annotationsMap) != 0 {
|
|
meta["annotations"] = annotationsMap
|
|
}
|
|
|
|
return meta
|
|
}
|
|
|
|
// PodMetadata generates metadata for the given pod taking to account certain filters
|
|
func (g *metaGenerator) PodMetadata(pod *Pod) common.MapStr {
|
|
podMeta := g.ResourceMetadata(pod)
|
|
|
|
// Add UID metadata if enabled
|
|
if g.IncludePodUID {
|
|
safemapstr.Put(podMeta, "pod.uid", pod.GetMetadata().GetUid())
|
|
}
|
|
|
|
safemapstr.Put(podMeta, "pod.name", pod.GetMetadata().GetName())
|
|
safemapstr.Put(podMeta, "node.name", pod.Spec.GetNodeName())
|
|
|
|
return podMeta
|
|
}
|
|
|
|
// Containermetadata generates metadata for the given container of a pod
|
|
func (g *metaGenerator) ContainerMetadata(pod *Pod, container string) common.MapStr {
|
|
podMeta := g.PodMetadata(pod)
|
|
|
|
// Add container details
|
|
podMeta["container"] = common.MapStr{
|
|
"name": container,
|
|
}
|
|
|
|
return podMeta
|
|
}
|
|
|
|
func generateMapSubset(input map[string]string, keys []string) common.MapStr {
|
|
output := common.MapStr{}
|
|
if input == nil {
|
|
return output
|
|
}
|
|
|
|
for _, key := range keys {
|
|
value, ok := input[key]
|
|
if ok {
|
|
safemapstr.Put(output, key, value)
|
|
}
|
|
}
|
|
|
|
return output
|
|
}
|