pkg/process/finders/kubernetes/template.go (152 lines of code) (raw):
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) 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 (
"fmt"
"strconv"
"strings"
"github.com/apache/skywalking-rover/pkg/process/finders/base"
"github.com/shirou/gopsutil/process"
"k8s.io/apimachinery/pkg/labels"
)
func executeFilter(builders []*base.TemplateBuilder, p *process.Process, pc *PodContainer, finder *ProcessFinder) (bool, error) {
if len(builders) == 0 {
return true, nil
}
moduleManager := finder.manager.GetModuleManager()
for _, b := range builders {
result, err := b.Execute(&FilterContext{
Process: base.NewTemplateProcess(moduleManager, p),
Pod: &TemplatePodJudgment{&TemplatePod{pc, finder}},
Container: &TemplateContainer{pc},
})
if err != nil {
return false, err
}
success, err := strconv.ParseBool(result)
if err != nil {
return false, err
}
// must all filtering success
// if have any false, just short circuit
if !success {
return false, nil
}
}
return true, nil
}
func renderTemplate(builder *base.TemplateBuilder, p *process.Process, pc *PodContainer, finder *ProcessFinder) (string, error) {
moduleManager := finder.manager.GetModuleManager()
return builder.Execute(&EntityRenderContext{
Rover: base.NewTemplateRover(moduleManager),
Process: base.NewTemplateProcess(moduleManager, p),
Pod: &TemplatePod{pc, finder},
Container: &TemplateContainer{pc},
})
}
type FilterContext struct {
Process *base.TemplateProcess
Pod *TemplatePodJudgment
Container *TemplateContainer
}
type EntityRenderContext struct {
Rover *base.TemplateRover
Process *base.TemplateProcess
Pod *TemplatePod
Container *TemplateContainer
}
type TemplatePod struct {
pc *PodContainer
finder *ProcessFinder
}
func (p *TemplatePod) Name() string {
return p.pc.Pod.Name
}
func (p *TemplatePod) Namespace() string {
return p.pc.Pod.Namespace
}
func (p *TemplatePod) Node() string {
return p.pc.Pod.Spec.NodeName
}
func (p *TemplatePod) FindContainer(name string) (*TemplateContainer, error) {
container := p.pc.FindContainerFromSamePod(name)
if container == nil {
return nil, fmt.Errorf("could not found the container")
}
return &TemplateContainer{pc: container}, nil
}
func (p *TemplatePod) LabelValue(names, def string) (string, error) {
namesArray := strings.Split(names, ",")
for _, name := range namesArray {
val := p.pc.Pod.Labels[name]
if val != "" {
return val, nil
}
}
return def, nil
}
func (p *TemplatePod) ServiceName() string {
return p.pc.ServiceName()
}
func (p *TemplatePod) OwnerName(kindNames string) (string, error) {
kindNameArray := strings.Split(kindNames, ",")
for _, name := range kindNameArray {
if strings.EqualFold(name, "service") {
if s := p.ServiceName(); s != "" {
return s, nil
}
continue
}
if owner, err := p.pc.FindOwner(p.finder.ctx, name, p.finder.k8sConfig); err != nil {
return "", err
} else if owner != nil {
return owner.Name, nil
}
}
return "", fmt.Errorf("could not found owner in %v", kindNameArray)
}
type TemplatePodJudgment struct {
*TemplatePod
}
func (t *TemplatePodJudgment) HasContainer(name string) bool {
// nolint
for _, c := range t.pc.Pod.Spec.Containers {
if c.Name == name {
return true
}
}
return false
}
func (t *TemplatePodJudgment) LabelSelector(selector string) (bool, error) {
labelsMap, err := labels.ConvertSelectorToLabelsMap(selector)
if err != nil {
return false, err
}
return labelsMap.AsSelector().Matches(labels.Set(t.pc.Pod.Labels)), nil
}
func (t *TemplatePodJudgment) HasServiceName() bool {
return t.ServiceName() != ""
}
func (t *TemplatePodJudgment) HasOwnerName(names string) bool {
name, err := t.OwnerName(names)
return err == nil && name != ""
}
type TemplateContainer struct {
pc *PodContainer
}
func (c *TemplateContainer) Name() string {
return c.pc.ContainerSpec.Name
}
func (c *TemplateContainer) ID() string {
return c.pc.ContainerStatus.ContainerID
}
func (c *TemplateContainer) EnvValue(names string) (string, error) {
namesArray := strings.Split(names, ",")
for _, e := range c.pc.ContainerSpec.Env {
for _, needName := range namesArray {
if e.Name == needName {
return e.Value, nil
}
}
}
actualNames := make([]string, 0)
for _, e := range c.pc.ContainerSpec.Env {
actualNames = append(actualNames, e.Name)
}
return "", fmt.Errorf("could not found matches environment, want names: %v, actual names: %v", namesArray, actualNames)
}