Skip to content

Commit

Permalink
add getTagsWithCardinality
Browse files Browse the repository at this point in the history
  • Loading branch information
zhuminyi committed Oct 10, 2024
1 parent 81e640e commit 1bbc6a6
Show file tree
Hide file tree
Showing 22 changed files with 161 additions and 25 deletions.
5 changes: 5 additions & 0 deletions comp/core/autodiscovery/autodiscoveryimpl/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ func (s *dummyService) GetTags() ([]string, error) {
return nil, nil
}

// GetTagsWithCardinality returns the tags for this service
func (s *dummyService) GetTagsWithCardinality(_ string) ([]string, error) {
return s.GetTags()
}

// GetPid return a dummy pid
func (s *dummyService) GetPid(context.Context) (int, error) {
return s.Pid, nil
Expand Down
11 changes: 8 additions & 3 deletions comp/core/autodiscovery/common/utils/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
logsConfigPath = "logs"
checksPath = "checks"
checkIDPath = "check.id"
checkTagCardinality = "check_tag_cardinality"
)

// ExtractTemplatesFromMap looks for autodiscovery configurations in a given
Expand Down Expand Up @@ -76,7 +77,10 @@ func extractCheckTemplatesFromMap(key string, input map[string]string, prefix st
}
// ParseBool returns `true` only on success cases
ignoreAdTags, _ := strconv.ParseBool(input[prefix+ignoreAutodiscoveryTags])
return BuildTemplates(key, checkNames, initConfigs, instances, ignoreAdTags), nil

cardinality := input[prefix+checkTagCardinality]

return BuildTemplates(key, checkNames, initConfigs, instances, ignoreAdTags, cardinality), nil
}

// extractLogsTemplatesFromMap returns the logs configuration from a given map,
Expand Down Expand Up @@ -166,8 +170,8 @@ func ParseJSONValue(value string) ([][]integration.Data, error) {

// BuildTemplates returns check configurations configured according to the
// passed in AD identifier, check names, init, instance configs and their
// `ignoreAutoDiscoveryTags` field.
func BuildTemplates(adID string, checkNames []string, initConfigs, instances [][]integration.Data, ignoreAutodiscoveryTags bool) []integration.Config {
// `ignoreAutoDiscoveryTags`, `CheckTagCardinality` fields.
func BuildTemplates(adID string, checkNames []string, initConfigs, instances [][]integration.Data, ignoreAutodiscoveryTags bool, checkCard string) []integration.Config {
templates := make([]integration.Config, 0)

// sanity checks
Expand All @@ -192,6 +196,7 @@ func BuildTemplates(adID string, checkNames []string, initConfigs, instances [][
Instances: []integration.Data{instance},
ADIdentifiers: []string{adID},
IgnoreAutodiscoveryTags: ignoreAutodiscoveryTags,
CheckTagCardinality: checkCard,
})
}
}
Expand Down
45 changes: 38 additions & 7 deletions comp/core/autodiscovery/common/utils/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,12 +344,13 @@ func TestParseCheckNames(t *testing.T) {
func TestBuildTemplates(t *testing.T) {
key := "id"
tests := []struct {
name string
inputCheckNames []string
inputInitConfig [][]integration.Data
inputInstances [][]integration.Data
expectedConfigs []integration.Config
ignoreAdTags bool
name string
inputCheckNames []string
inputInitConfig [][]integration.Data
inputInstances [][]integration.Data
expectedConfigs []integration.Config
ignoreAdTags bool
checkTagCardinality string
}{
{
name: "wrong number of checkNames",
Expand Down Expand Up @@ -434,10 +435,40 @@ func TestBuildTemplates(t *testing.T) {
},
},
},
{
name: "valid inputs with list and checkCardinality",
inputCheckNames: []string{"a", "b"},
inputInitConfig: [][]integration.Data{{integration.Data("{\"test\": 1}")}, {integration.Data("{}")}},
inputInstances: [][]integration.Data{{integration.Data("{\"foo\": 1}"), integration.Data("{\"foo\": 2}")}, {integration.Data("{1:2}")}},
checkTagCardinality: "low",
expectedConfigs: []integration.Config{
{
Name: "a",
ADIdentifiers: []string{key},
InitConfig: integration.Data("{\"test\": 1}"),
Instances: []integration.Data{integration.Data("{\"foo\": 1}")},
CheckTagCardinality: "low",
},
{
Name: "a",
ADIdentifiers: []string{key},
InitConfig: integration.Data("{\"test\": 1}"),
Instances: []integration.Data{integration.Data("{\"foo\": 2}")},
CheckTagCardinality: "low",
},
{
Name: "b",
ADIdentifiers: []string{key},
InitConfig: integration.Data("{}"),
Instances: []integration.Data{integration.Data("{1:2}")},
CheckTagCardinality: "low",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.expectedConfigs, BuildTemplates(key, tt.inputCheckNames, tt.inputInitConfig, tt.inputInstances, tt.ignoreAdTags))
assert.Equal(t, tt.expectedConfigs, BuildTemplates(key, tt.inputCheckNames, tt.inputInitConfig, tt.inputInstances, tt.ignoreAdTags, tt.checkTagCardinality))
})
}
}
3 changes: 3 additions & 0 deletions comp/core/autodiscovery/common/utils/pod_annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func parseChecksJSON(adIdentifier string, checksJSON string) ([]integration.Conf
Instances []interface{} `json:"instances"`
Logs json.RawMessage `json:"logs"`
IgnoreAutodiscoveryTags bool `json:"ignore_autodiscovery_tags"`
CheckTagCardinality string `json:"check_tag_cardinality"`
}

err := json.Unmarshal([]byte(checksJSON), &namedChecks)
Expand All @@ -84,6 +85,8 @@ func parseChecksJSON(adIdentifier string, checksJSON string) ([]integration.Conf
IgnoreAutodiscoveryTags: config.IgnoreAutodiscoveryTags,
}

c.CheckTagCardinality = config.CheckTagCardinality

if len(config.Logs) > 0 {
c.LogsConfig = integration.Data(config.Logs)
}
Expand Down
26 changes: 26 additions & 0 deletions comp/core/autodiscovery/common/utils/pod_annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,32 @@ func TestExtractTemplatesFromAnnotations(t *testing.T) {
},
},
},
{
name: "Nominal case with two templates and check tag cardinality",
annotations: map[string]string{
"ad.datadoghq.com/foobar.check_names": "[\"apache\",\"http_check\"]",
"ad.datadoghq.com/foobar.init_configs": "[{},{}]",
"ad.datadoghq.com/foobar.instances": "[{\"apache_status_url\":\"http://%%host%%/server-status?auto\"},{\"name\":\"My service\",\"timeout\":1,\"url\":\"http://%%host%%\"}]",
"ad.datadoghq.com/foobar.check_tag_cardinality": "low",
},
adIdentifier: "foobar",
output: []integration.Config{
{
Name: "apache",
Instances: []integration.Data{integration.Data("{\"apache_status_url\":\"http://%%host%%/server-status?auto\"}")},
InitConfig: integration.Data("{}"),
ADIdentifiers: []string{adID},
CheckTagCardinality: "low",
},
{
Name: "http_check",
Instances: []integration.Data{integration.Data("{\"name\":\"My service\",\"timeout\":1,\"url\":\"http://%%host%%\"}")},
InitConfig: integration.Data("{}"),
ADIdentifiers: []string{adID},
CheckTagCardinality: "low",
},
},
},
{
name: "Take one, ignore one",
annotations: map[string]string{
Expand Down
8 changes: 7 additions & 1 deletion comp/core/autodiscovery/configresolver/configresolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,13 @@ func Resolve(tpl integration.Config, svc listeners.Service) (integration.Config,
return resolvedConfig, errors.New("unable to resolve, service not ready")
}

tags, err := svc.GetTags()
var tags []string
var err error
if tpl.CheckTagCardinality != "" {
tags, err = svc.GetTagsWithCardinality(tpl.CheckTagCardinality)
} else {
tags, err = svc.GetTags()
}
if err != nil {
return resolvedConfig, fmt.Errorf("couldn't get tags for service '%s', err: %w", svc.GetServiceID(), err)
}
Expand Down
5 changes: 5 additions & 0 deletions comp/core/autodiscovery/configresolver/configresolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ func (s *dummyService) GetTags() ([]string, error) {
return []string{"foo:bar"}, nil
}

// GetTagsWithCardinality returns the tags for this service
func (s *dummyService) GetTagsWithCardinality(_ string) ([]string, error) {
return s.GetTags()
}

// GetPid return a dummy pid
func (s *dummyService) GetPid(context.Context) (int, error) {
return s.Pid, nil
Expand Down
3 changes: 3 additions & 0 deletions comp/core/autodiscovery/integration/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ type Config struct {
// IgnoreAutodiscoveryTags is used to ignore tags coming from autodiscovery
IgnoreAutodiscoveryTags bool `json:"ignore_autodiscovery_tags"` // (include in digest: true)

// CheckTagCardinality is used to override the default tag cardinality in the agent configuration
CheckTagCardinality string `json:"check_tag_cardinality"` // (include in digest: false)

// MetricsExcluded is whether metrics collection is disabled (set by
// container listeners only)
MetricsExcluded bool `json:"metrics_excluded"` // (include in digest: false)
Expand Down
5 changes: 5 additions & 0 deletions comp/core/autodiscovery/listeners/cloudfoundry.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ func (s *CloudFoundryService) GetTags() ([]string, error) {
return s.tags, nil
}

// GetTagsWithCardinality returns the tags with given cardinality. Not supported in CF
func (s *CloudFoundryService) GetTagsWithCardinality(cardinality string) ([]string, error) {
return s.GetTags()
}

// GetPid returns nil and an error because pids are currently not supported in CF
func (s *CloudFoundryService) GetPid(context.Context) (int, error) {
return -1, ErrNotSupported
Expand Down
5 changes: 5 additions & 0 deletions comp/core/autodiscovery/listeners/dbm_aurora.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,11 @@ func (d *DBMAuroraService) GetTags() ([]string, error) {
return []string{}, nil
}

// GetTagsWithCardinality returns the tags with given cardinality. Not supported in DBMAuroraService
func (d *DBMAuroraService) GetTagsWithCardinality(_ string) ([]string, error) {
return s.GetTags()

Check failure on line 244 in comp/core/autodiscovery/listeners/dbm_aurora.go

View workflow job for this annotation

GitHub Actions / CodeQL-Build (javascript)

undefined: s

Check failure on line 244 in comp/core/autodiscovery/listeners/dbm_aurora.go

View workflow job for this annotation

GitHub Actions / CodeQL-Build (python)

undefined: s

Check failure on line 244 in comp/core/autodiscovery/listeners/dbm_aurora.go

View workflow job for this annotation

GitHub Actions / CodeQL-Build (cpp)

undefined: s
}

// GetPid returns nil and an error because pids are currently not supported
func (d *DBMAuroraService) GetPid(context.Context) (int, error) {
return -1, ErrNotSupported
Expand Down
5 changes: 5 additions & 0 deletions comp/core/autodiscovery/listeners/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ func (s *EnvironmentService) GetTags() ([]string, error) {
return nil, nil
}

// GetTagsWithCardinality returns the tags with given cardinality. Not supported in EnvironmentService
func (s *EnvironmentService) GetTagsWithCardinality(_ string) ([]string, error) {
return s.GetTags()
}

// GetPid inspect the container and return its pid
// Not relevant in this listener
func (s *EnvironmentService) GetPid(context.Context) (int, error) {
Expand Down
5 changes: 5 additions & 0 deletions comp/core/autodiscovery/listeners/kube_endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,11 @@ func (s *KubeEndpointService) GetTags() ([]string, error) {
return s.tags, nil
}

// GetTagsWithCardinality returns the tags with given cardinality.
func (s *KubeEndpointService) GetTagsWithCardinality(_ string) ([]string, error) {
return s.GetTags()
}

// GetHostname returns nil and an error because port is not supported in Kubelet
func (s *KubeEndpointService) GetHostname(context.Context) (string, error) {
return "", ErrNotSupported
Expand Down
5 changes: 5 additions & 0 deletions comp/core/autodiscovery/listeners/kube_services.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ func (s *KubeServiceService) GetTags() ([]string, error) {
return s.tags, nil
}

// GetTagsWithCardinality returns the tags with given cardinality.
func (s *KubeServiceService) GetTagsWithCardinality(_ string) ([]string, error) {
return s.GetTags()
}

// GetHostname returns nil and an error because port is not supported in Kubelet
func (s *KubeServiceService) GetHostname(context.Context) (string, error) {
return "", ErrNotSupported
Expand Down
11 changes: 11 additions & 0 deletions comp/core/autodiscovery/listeners/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/DataDog/datadog-agent/comp/core/autodiscovery/providers/names"
"github.com/DataDog/datadog-agent/comp/core/tagger"
taggercommon "github.com/DataDog/datadog-agent/comp/core/tagger/common"
"github.com/DataDog/datadog-agent/comp/core/tagger/types"
workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def"
pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup"
"github.com/DataDog/datadog-agent/pkg/util/containers"
Expand Down Expand Up @@ -92,6 +93,16 @@ func (s *service) GetTags() ([]string, error) {
return tagger.Tag(taggercommon.BuildTaggerEntityID(s.entity.GetID()).String(), tagger.ChecksCardinality())
}

// GetTagsWithCardinality returns the tags with given cardinality.
func (s *service) GetTagsWithCardinality(cardinality string) ([]string, error) {
checkCard, err := types.StringToTagCardinality(cardinality)
if err == nil {
return tagger.Tag(taggercommon.BuildTaggerEntityID(s.entity.GetID()).String(), checkCard)
}
log.Warnf("error converting cardinality %s to TagCardinality: %v", cardinality, err)
return s.GetTags()
}

// GetPid returns the process ID of the service.
func (s *service) GetPid(_ context.Context) (int, error) {
return s.pid, nil
Expand Down
5 changes: 5 additions & 0 deletions comp/core/autodiscovery/listeners/snmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,11 @@ func (s *SNMPService) GetTags() ([]string, error) {
return []string{}, nil
}

// GetTagsWithCardinality returns the tags with given cardinality.
func (s *SNMPService) GetTagsWithCardinality(_ string) ([]string, error) {
return s.GetTags()
}

// GetPid returns nil and an error because pids are currently not supported
func (s *SNMPService) GetPid(context.Context) (int, error) {
return -1, ErrNotSupported
Expand Down
5 changes: 5 additions & 0 deletions comp/core/autodiscovery/listeners/staticconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ func (s *StaticConfigService) GetTags() ([]string, error) {
return nil, nil
}

// GetTagsWithCardinality returns the tags with given cardinality.
func (s *StaticConfigService) GetTagsWithCardinality(_ string) ([]string, error) {
return s.GetTags()
}

// GetPid inspect the container and return its pid
// Not relevant in this listener
func (s *StaticConfigService) GetPid(context.Context) (int, error) {
Expand Down
23 changes: 12 additions & 11 deletions comp/core/autodiscovery/listeners/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,18 @@ type ContainerPort struct {
// It should be matched with a check template by the ConfigResolver using the
// ADIdentifiers field.
type Service interface {
Equal(Service) bool // compare two services
GetServiceID() string // unique service name
GetADIdentifiers(context.Context) ([]string, error) // identifiers on which templates will be matched
GetHosts(context.Context) (map[string]string, error) // network --> IP address
GetPorts(context.Context) ([]ContainerPort, error) // network ports
GetTags() ([]string, error) // tags
GetPid(context.Context) (int, error) // process identifier
GetHostname(context.Context) (string, error) // hostname.domainname for the entity
IsReady(context.Context) bool // is the service ready
HasFilter(containers.FilterType) bool // whether the service is excluded by metrics or logs exclusion config
GetExtraConfig(string) (string, error) // Extra configuration values
Equal(Service) bool // compare two services
GetServiceID() string // unique service name
GetADIdentifiers(context.Context) ([]string, error) // identifiers on which templates will be matched
GetHosts(context.Context) (map[string]string, error) // network --> IP address
GetPorts(context.Context) ([]ContainerPort, error) // network ports
GetTags() ([]string, error) // tags
GetTagsWithCardinality(cardinality string) ([]string, error) // tags with given cardinality
GetPid(context.Context) (int, error) // process identifier
GetHostname(context.Context) (string, error) // hostname.domainname for the entity
IsReady(context.Context) bool // is the service ready
HasFilter(containers.FilterType) bool // whether the service is excluded by metrics or logs exclusion config
GetExtraConfig(string) (string, error) // Extra configuration values

// FilterTemplates filters the templates which will be resolved against
// this service, in a map keyed by template digest.
Expand Down
4 changes: 4 additions & 0 deletions comp/core/autodiscovery/providers/config_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type configFormat struct {
Instances []integration.RawMap
DockerImages []string `yaml:"docker_images"` // Only imported for deprecation warning
IgnoreAutodiscoveryTags bool `yaml:"ignore_autodiscovery_tags"` // Use to ignore tags coming from autodiscovery
CheckTagCardinality string `yaml:"check_tag_cardinality"` // Use to set the tag cardinality override for the check
}

type configPkg struct {
Expand Down Expand Up @@ -430,6 +431,9 @@ func GetIntegrationConfigFromFile(name, fpath string) (integration.Config, error
// Copy ignore_autodiscovery_tags parameter
conf.IgnoreAutodiscoveryTags = cf.IgnoreAutodiscoveryTags

// Copy check_tag_cardinality parameter
conf.CheckTagCardinality = cf.CheckTagCardinality

// DockerImages entry was found: we ignore it if no ADIdentifiers has been found
if len(cf.DockerImages) > 0 && len(cf.ADIdentifiers) == 0 {
return conf, errors.New("the 'docker_images' section is deprecated, please use 'ad_identifiers' instead")
Expand Down
2 changes: 1 addition & 1 deletion comp/core/autodiscovery/providers/consul.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func (p *ConsulConfigProvider) getTemplates(ctx context.Context, key string) []i
log.Errorf("Failed to retrieve instances at %s. Error: %s", instanceKey, err)
return templates
}
return utils.BuildTemplates(key, checkNames, initConfigs, instances, false)
return utils.BuildTemplates(key, checkNames, initConfigs, instances, false, "")
}

// getValue returns value, error
Expand Down
2 changes: 1 addition & 1 deletion comp/core/autodiscovery/providers/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func (p *EtcdConfigProvider) getTemplates(ctx context.Context, key string) []int
return nil
}

return utils.BuildTemplates(key, checkNames, initConfigs, instances, false)
return utils.BuildTemplates(key, checkNames, initConfigs, instances, false, "")
}

// getEtcdValue retrieves content from etcd
Expand Down
1 change: 1 addition & 0 deletions comp/core/autodiscovery/providers/kube_endpoints_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ func endpointChecksFromTemplate(tpl integration.Config, ep *v1.Endpoints) []inte
Provider: names.KubeEndpointsFile,
Source: tpl.Source,
IgnoreAutodiscoveryTags: tpl.IgnoreAutodiscoveryTags,
CheckTagCardinality: tpl.CheckTagCardinality,
}

utils.ResolveEndpointConfigAuto(config, ep.Subsets[i].Addresses[j])
Expand Down
2 changes: 1 addition & 1 deletion comp/core/autodiscovery/providers/zookeeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func (z *ZookeeperConfigProvider) getTemplates(key string) []integration.Config
return nil
}

return utils.BuildTemplates(key, checkNames, initConfigs, instances, false)
return utils.BuildTemplates(key, checkNames, initConfigs, instances, false, "")
}

func (z *ZookeeperConfigProvider) getJSONValue(key string) ([][]integration.Data, error) {
Expand Down

0 comments on commit 1bbc6a6

Please sign in to comment.