mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
lib/promscrape/discovery/kubernetes: properly discover targets in multiple namespaces
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1170
This commit is contained in:
parent
4e685fb0df
commit
eee860f83d
10 changed files with 164 additions and 145 deletions
|
@ -6,6 +6,7 @@
|
||||||
* FEATURE: vmagent: reduce memory usage when `-remoteWrite.queues` is set to a big value. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1167).
|
* FEATURE: vmagent: reduce memory usage when `-remoteWrite.queues` is set to a big value. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1167).
|
||||||
* FEATURE: vmagent: add AWS IAM roles for tasks support for EC2 service discovery according to [these docs](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html).
|
* FEATURE: vmagent: add AWS IAM roles for tasks support for EC2 service discovery according to [these docs](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html).
|
||||||
|
|
||||||
|
* BUGFIX: vmagent: properly discovery targets if multiple namespace selectors are put inside `kubernetes_sd_config`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1170).
|
||||||
* BUGFIX: properly generate filename for `*.tar.gz` archive inside `_checksums.txt` file posted at [releases page](https://github.com/VictoriaMetrics/VictoriaMetrics/releases). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1171).
|
* BUGFIX: properly generate filename for `*.tar.gz` archive inside `_checksums.txt` file posted at [releases page](https://github.com/VictoriaMetrics/VictoriaMetrics/releases). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1171).
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ type WatchEvent struct {
|
||||||
|
|
||||||
// object is any Kubernetes object.
|
// object is any Kubernetes object.
|
||||||
type object interface {
|
type object interface {
|
||||||
key() string
|
name() string
|
||||||
getTargetLabels(gw *groupWatcher) []map[string]string
|
getTargetLabels(gw *groupWatcher) []map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,9 +51,9 @@ type apiWatcher struct {
|
||||||
|
|
||||||
gw *groupWatcher
|
gw *groupWatcher
|
||||||
|
|
||||||
// swos contains a map of ScrapeWork objects for the given apiWatcher
|
// swos contains per-namepsace maps of ScrapeWork objects for the given apiWatcher
|
||||||
swosByKey map[string][]interface{}
|
swosByNamespace map[string]map[string][]interface{}
|
||||||
swosByKeyLock sync.Mutex
|
swosByNamespaceLock sync.Mutex
|
||||||
|
|
||||||
swosCount *metrics.Counter
|
swosCount *metrics.Counter
|
||||||
}
|
}
|
||||||
|
@ -64,44 +64,54 @@ func newAPIWatcher(apiServer string, ac *promauth.Config, sdc *SDConfig, swcFunc
|
||||||
proxyURL := sdc.ProxyURL.URL()
|
proxyURL := sdc.ProxyURL.URL()
|
||||||
gw := getGroupWatcher(apiServer, ac, namespaces, selectors, proxyURL)
|
gw := getGroupWatcher(apiServer, ac, namespaces, selectors, proxyURL)
|
||||||
return &apiWatcher{
|
return &apiWatcher{
|
||||||
role: sdc.Role,
|
role: sdc.Role,
|
||||||
swcFunc: swcFunc,
|
swcFunc: swcFunc,
|
||||||
gw: gw,
|
gw: gw,
|
||||||
swosByKey: make(map[string][]interface{}),
|
swosByNamespace: make(map[string]map[string][]interface{}),
|
||||||
swosCount: metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_scrape_works{role=%q}`, sdc.Role)),
|
swosCount: metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_scrape_works{role=%q}`, sdc.Role)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aw *apiWatcher) mustStop() {
|
func (aw *apiWatcher) mustStop() {
|
||||||
aw.gw.unsubscribeAPIWatcher(aw)
|
aw.gw.unsubscribeAPIWatcher(aw)
|
||||||
aw.reloadScrapeWorks(make(map[string][]interface{}))
|
aw.swosByNamespaceLock.Lock()
|
||||||
|
aw.swosByNamespace = make(map[string]map[string][]interface{})
|
||||||
|
aw.swosByNamespaceLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aw *apiWatcher) reloadScrapeWorks(swosByKey map[string][]interface{}) {
|
func (aw *apiWatcher) reloadScrapeWorks(namespace string, swosByName map[string][]interface{}) {
|
||||||
aw.swosByKeyLock.Lock()
|
aw.swosByNamespaceLock.Lock()
|
||||||
aw.swosCount.Add(len(swosByKey) - len(aw.swosByKey))
|
aw.swosCount.Add(len(swosByName) - len(aw.swosByNamespace[namespace]))
|
||||||
aw.swosByKey = swosByKey
|
aw.swosByNamespace[namespace] = swosByName
|
||||||
aw.swosByKeyLock.Unlock()
|
aw.swosByNamespaceLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aw *apiWatcher) setScrapeWorks(key string, labels []map[string]string) {
|
func (aw *apiWatcher) setScrapeWorks(namespace, name string, labels []map[string]string) {
|
||||||
swos := getScrapeWorkObjectsForLabels(aw.swcFunc, labels)
|
swos := getScrapeWorkObjectsForLabels(aw.swcFunc, labels)
|
||||||
aw.swosByKeyLock.Lock()
|
aw.swosByNamespaceLock.Lock()
|
||||||
if len(swos) > 0 {
|
swosByName := aw.swosByNamespace[namespace]
|
||||||
aw.swosCount.Add(len(swos) - len(aw.swosByKey[key]))
|
if swosByName == nil {
|
||||||
aw.swosByKey[key] = swos
|
swosByName = make(map[string][]interface{})
|
||||||
} else {
|
aw.swosByNamespace[namespace] = swosByName
|
||||||
aw.swosCount.Add(-len(aw.swosByKey[key]))
|
|
||||||
delete(aw.swosByKey, key)
|
|
||||||
}
|
}
|
||||||
aw.swosByKeyLock.Unlock()
|
if len(swos) > 0 {
|
||||||
|
aw.swosCount.Add(len(swos) - len(swosByName[name]))
|
||||||
|
swosByName[name] = swos
|
||||||
|
} else {
|
||||||
|
aw.swosCount.Add(-len(swosByName[name]))
|
||||||
|
delete(swosByName, name)
|
||||||
|
}
|
||||||
|
aw.swosByNamespaceLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aw *apiWatcher) removeScrapeWorks(key string) {
|
func (aw *apiWatcher) removeScrapeWorks(namespace, name string) {
|
||||||
aw.swosByKeyLock.Lock()
|
aw.swosByNamespaceLock.Lock()
|
||||||
aw.swosCount.Add(-len(aw.swosByKey[key]))
|
swosByName := aw.swosByNamespace[namespace]
|
||||||
delete(aw.swosByKey, key)
|
if len(swosByName) > 0 {
|
||||||
aw.swosByKeyLock.Unlock()
|
aw.swosCount.Add(-len(swosByName[name]))
|
||||||
|
delete(swosByName, name)
|
||||||
|
}
|
||||||
|
aw.swosByNamespaceLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getScrapeWorkObjectsForLabels(swcFunc ScrapeWorkConstructorFunc, labelss []map[string]string) []interface{} {
|
func getScrapeWorkObjectsForLabels(swcFunc ScrapeWorkConstructorFunc, labelss []map[string]string) []interface{} {
|
||||||
|
@ -119,16 +129,20 @@ func getScrapeWorkObjectsForLabels(swcFunc ScrapeWorkConstructorFunc, labelss []
|
||||||
// getScrapeWorkObjects returns all the ScrapeWork objects for the given aw.
|
// getScrapeWorkObjects returns all the ScrapeWork objects for the given aw.
|
||||||
func (aw *apiWatcher) getScrapeWorkObjects() []interface{} {
|
func (aw *apiWatcher) getScrapeWorkObjects() []interface{} {
|
||||||
aw.gw.startWatchersForRole(aw.role, aw)
|
aw.gw.startWatchersForRole(aw.role, aw)
|
||||||
aw.swosByKeyLock.Lock()
|
aw.swosByNamespaceLock.Lock()
|
||||||
defer aw.swosByKeyLock.Unlock()
|
defer aw.swosByNamespaceLock.Unlock()
|
||||||
|
|
||||||
size := 0
|
size := 0
|
||||||
for _, swosLocal := range aw.swosByKey {
|
for _, swosByName := range aw.swosByNamespace {
|
||||||
size += len(swosLocal)
|
for _, swosLocal := range swosByName {
|
||||||
|
size += len(swosLocal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
swos := make([]interface{}, 0, size)
|
swos := make([]interface{}, 0, size)
|
||||||
for _, swosLocal := range aw.swosByKey {
|
for _, swosByName := range aw.swosByNamespace {
|
||||||
swos = append(swos, swosLocal...)
|
for _, swosLocal := range swosByName {
|
||||||
|
swos = append(swos, swosLocal...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return swos
|
return swos
|
||||||
}
|
}
|
||||||
|
@ -209,17 +223,21 @@ func (gw *groupWatcher) getObjectByRole(role, namespace, name string) object {
|
||||||
// this is needed for testing
|
// this is needed for testing
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
key := namespace + "/" + name
|
|
||||||
gw.startWatchersForRole(role, nil)
|
gw.startWatchersForRole(role, nil)
|
||||||
gw.mu.Lock()
|
gw.mu.Lock()
|
||||||
defer gw.mu.Unlock()
|
defer gw.mu.Unlock()
|
||||||
|
|
||||||
for _, uw := range gw.m {
|
for _, uw := range gw.m {
|
||||||
if uw.role != role {
|
if uw.role != role {
|
||||||
|
// Role mismatch
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if uw.namespace != "" && uw.namespace != namespace {
|
||||||
|
// Namespace mismatch
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
uw.mu.Lock()
|
uw.mu.Lock()
|
||||||
o := uw.objectsByKey[key]
|
o := uw.objectsByName[name]
|
||||||
uw.mu.Unlock()
|
uw.mu.Unlock()
|
||||||
if o != nil {
|
if o != nil {
|
||||||
return o
|
return o
|
||||||
|
@ -229,13 +247,13 @@ func (gw *groupWatcher) getObjectByRole(role, namespace, name string) object {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gw *groupWatcher) startWatchersForRole(role string, aw *apiWatcher) {
|
func (gw *groupWatcher) startWatchersForRole(role string, aw *apiWatcher) {
|
||||||
paths := getAPIPaths(role, gw.namespaces, gw.selectors)
|
paths, namespaces := getAPIPathsWithNamespaces(role, gw.namespaces, gw.selectors)
|
||||||
for _, path := range paths {
|
for i, path := range paths {
|
||||||
apiURL := gw.apiServer + path
|
apiURL := gw.apiServer + path
|
||||||
gw.mu.Lock()
|
gw.mu.Lock()
|
||||||
uw := gw.m[apiURL]
|
uw := gw.m[apiURL]
|
||||||
if uw == nil {
|
if uw == nil {
|
||||||
uw = newURLWatcher(role, apiURL, gw)
|
uw = newURLWatcher(role, namespaces[i], apiURL, gw)
|
||||||
gw.m[apiURL] = uw
|
gw.m[apiURL] = uw
|
||||||
}
|
}
|
||||||
gw.mu.Unlock()
|
gw.mu.Unlock()
|
||||||
|
@ -243,25 +261,25 @@ func (gw *groupWatcher) startWatchersForRole(role string, aw *apiWatcher) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gw *groupWatcher) reloadScrapeWorksForAPIWatchers(aws []*apiWatcher, objectsByKey map[string]object) {
|
func (gw *groupWatcher) reloadScrapeWorksForAPIWatchers(namespace string, aws []*apiWatcher, objectsByName map[string]object) {
|
||||||
if len(aws) == 0 {
|
if len(aws) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
swosByKey := make([]map[string][]interface{}, len(aws))
|
swosByName := make([]map[string][]interface{}, len(aws))
|
||||||
for i := range aws {
|
for i := range aws {
|
||||||
swosByKey[i] = make(map[string][]interface{})
|
swosByName[i] = make(map[string][]interface{})
|
||||||
}
|
}
|
||||||
for key, o := range objectsByKey {
|
for name, o := range objectsByName {
|
||||||
labels := o.getTargetLabels(gw)
|
labels := o.getTargetLabels(gw)
|
||||||
for i, aw := range aws {
|
for i, aw := range aws {
|
||||||
swos := getScrapeWorkObjectsForLabels(aw.swcFunc, labels)
|
swos := getScrapeWorkObjectsForLabels(aw.swcFunc, labels)
|
||||||
if len(swos) > 0 {
|
if len(swos) > 0 {
|
||||||
swosByKey[i][key] = swos
|
swosByName[i][name] = swos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, aw := range aws {
|
for i, aw := range aws {
|
||||||
aw.reloadScrapeWorks(swosByKey[i])
|
aw.reloadScrapeWorks(namespace, swosByName[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,16 +303,17 @@ func (gw *groupWatcher) unsubscribeAPIWatcher(aw *apiWatcher) {
|
||||||
gw.mu.Unlock()
|
gw.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// urlWatcher watches for an apiURL and updates object states in objectsByKey.
|
// urlWatcher watches for an apiURL and updates object states in objectsByName.
|
||||||
type urlWatcher struct {
|
type urlWatcher struct {
|
||||||
role string
|
role string
|
||||||
apiURL string
|
namespace string
|
||||||
gw *groupWatcher
|
apiURL string
|
||||||
|
gw *groupWatcher
|
||||||
|
|
||||||
parseObject parseObjectFunc
|
parseObject parseObjectFunc
|
||||||
parseObjectList parseObjectListFunc
|
parseObjectList parseObjectListFunc
|
||||||
|
|
||||||
// mu protects aws, awsPending, objectsByKey and resourceVersion
|
// mu protects aws, awsPending, objectsByName and resourceVersion
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
||||||
// aws contains registered apiWatcher objects
|
// aws contains registered apiWatcher objects
|
||||||
|
@ -303,8 +322,8 @@ type urlWatcher struct {
|
||||||
// awsPending contains pending apiWatcher objects, which must be moved to aws in a batch
|
// awsPending contains pending apiWatcher objects, which must be moved to aws in a batch
|
||||||
awsPending map[*apiWatcher]struct{}
|
awsPending map[*apiWatcher]struct{}
|
||||||
|
|
||||||
// objectsByKey contains the latest state for objects obtained from apiURL
|
// objectsByName contains the latest state for objects obtained from apiURL
|
||||||
objectsByKey map[string]object
|
objectsByName map[string]object
|
||||||
|
|
||||||
resourceVersion string
|
resourceVersion string
|
||||||
|
|
||||||
|
@ -315,20 +334,21 @@ type urlWatcher struct {
|
||||||
staleResourceVersions *metrics.Counter
|
staleResourceVersions *metrics.Counter
|
||||||
}
|
}
|
||||||
|
|
||||||
func newURLWatcher(role, apiURL string, gw *groupWatcher) *urlWatcher {
|
func newURLWatcher(role, namespace, apiURL string, gw *groupWatcher) *urlWatcher {
|
||||||
parseObject, parseObjectList := getObjectParsersForRole(role)
|
parseObject, parseObjectList := getObjectParsersForRole(role)
|
||||||
metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_url_watchers{role=%q}`, role)).Inc()
|
metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_url_watchers{role=%q}`, role)).Inc()
|
||||||
uw := &urlWatcher{
|
uw := &urlWatcher{
|
||||||
role: role,
|
role: role,
|
||||||
apiURL: apiURL,
|
namespace: namespace,
|
||||||
gw: gw,
|
apiURL: apiURL,
|
||||||
|
gw: gw,
|
||||||
|
|
||||||
parseObject: parseObject,
|
parseObject: parseObject,
|
||||||
parseObjectList: parseObjectList,
|
parseObjectList: parseObjectList,
|
||||||
|
|
||||||
aws: make(map[*apiWatcher]struct{}),
|
aws: make(map[*apiWatcher]struct{}),
|
||||||
awsPending: make(map[*apiWatcher]struct{}),
|
awsPending: make(map[*apiWatcher]struct{}),
|
||||||
objectsByKey: make(map[string]object),
|
objectsByName: make(map[string]object),
|
||||||
|
|
||||||
objectsCount: metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_objects{role=%q}`, role)),
|
objectsCount: metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_objects{role=%q}`, role)),
|
||||||
objectsAdded: metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_objects_added_total{role=%q}`, role)),
|
objectsAdded: metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_objects_added_total{role=%q}`, role)),
|
||||||
|
@ -372,7 +392,7 @@ func (uw *urlWatcher) processPendingSubscribers() {
|
||||||
t := time.NewTicker(time.Second)
|
t := time.NewTicker(time.Second)
|
||||||
for range t.C {
|
for range t.C {
|
||||||
var awsPending []*apiWatcher
|
var awsPending []*apiWatcher
|
||||||
var objectsByKey map[string]object
|
var objectsByName map[string]object
|
||||||
|
|
||||||
uw.mu.Lock()
|
uw.mu.Lock()
|
||||||
if len(uw.awsPending) > 0 {
|
if len(uw.awsPending) > 0 {
|
||||||
|
@ -384,16 +404,16 @@ func (uw *urlWatcher) processPendingSubscribers() {
|
||||||
uw.aws[aw] = struct{}{}
|
uw.aws[aw] = struct{}{}
|
||||||
delete(uw.awsPending, aw)
|
delete(uw.awsPending, aw)
|
||||||
}
|
}
|
||||||
objectsByKey = make(map[string]object, len(uw.objectsByKey))
|
objectsByName = make(map[string]object, len(uw.objectsByName))
|
||||||
for key, o := range uw.objectsByKey {
|
for name, o := range uw.objectsByName {
|
||||||
objectsByKey[key] = o
|
objectsByName[name] = o
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_subscibers{role=%q,type="pending"}`, uw.role)).Add(-len(awsPending))
|
metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_subscibers{role=%q,type="pending"}`, uw.role)).Add(-len(awsPending))
|
||||||
metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_subscibers{role=%q,type="permanent"}`, uw.role)).Add(len(awsPending))
|
metrics.GetOrCreateCounter(fmt.Sprintf(`vm_promscrape_discovery_kubernetes_subscibers{role=%q,type="permanent"}`, uw.role)).Add(len(awsPending))
|
||||||
uw.mu.Unlock()
|
uw.mu.Unlock()
|
||||||
|
|
||||||
uw.gw.reloadScrapeWorksForAPIWatchers(awsPending, objectsByKey)
|
uw.gw.reloadScrapeWorksForAPIWatchers(uw.namespace, awsPending, objectsByName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,7 +445,7 @@ func (uw *urlWatcher) reloadObjects() string {
|
||||||
logger.Errorf("unexpected status code for request to %q: %d; want %d; response: %q", requestURL, resp.StatusCode, http.StatusOK, body)
|
logger.Errorf("unexpected status code for request to %q: %d; want %d; response: %q", requestURL, resp.StatusCode, http.StatusOK, body)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
objectsByKey, metadata, err := uw.parseObjectList(resp.Body)
|
objectsByName, metadata, err := uw.parseObjectList(resp.Body)
|
||||||
_ = resp.Body.Close()
|
_ = resp.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("cannot parse objects from %q: %s", requestURL, err)
|
logger.Errorf("cannot parse objects from %q: %s", requestURL, err)
|
||||||
|
@ -434,18 +454,18 @@ func (uw *urlWatcher) reloadObjects() string {
|
||||||
|
|
||||||
uw.mu.Lock()
|
uw.mu.Lock()
|
||||||
var updated, removed, added int
|
var updated, removed, added int
|
||||||
for key := range uw.objectsByKey {
|
for name := range uw.objectsByName {
|
||||||
if o, ok := objectsByKey[key]; ok {
|
if o, ok := objectsByName[name]; ok {
|
||||||
uw.objectsByKey[key] = o
|
uw.objectsByName[name] = o
|
||||||
updated++
|
updated++
|
||||||
} else {
|
} else {
|
||||||
delete(uw.objectsByKey, key)
|
delete(uw.objectsByName, name)
|
||||||
removed++
|
removed++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for key, o := range objectsByKey {
|
for name, o := range objectsByName {
|
||||||
if _, ok := uw.objectsByKey[key]; !ok {
|
if _, ok := uw.objectsByName[name]; !ok {
|
||||||
uw.objectsByKey[key] = o
|
uw.objectsByName[name] = o
|
||||||
added++
|
added++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,8 +477,8 @@ func (uw *urlWatcher) reloadObjects() string {
|
||||||
aws := getAPIWatchers(uw.aws)
|
aws := getAPIWatchers(uw.aws)
|
||||||
uw.mu.Unlock()
|
uw.mu.Unlock()
|
||||||
|
|
||||||
uw.gw.reloadScrapeWorksForAPIWatchers(aws, objectsByKey)
|
uw.gw.reloadScrapeWorksForAPIWatchers(uw.namespace, aws, objectsByName)
|
||||||
logger.Infof("reloaded %d objects from %q", len(objectsByKey), requestURL)
|
logger.Infof("reloaded %d objects from %q", len(objectsByName), requestURL)
|
||||||
return metadata.ResourceVersion
|
return metadata.ResourceVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,37 +564,37 @@ func (uw *urlWatcher) readObjectUpdateStream(r io.Reader) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
key := o.key()
|
name := o.name()
|
||||||
uw.mu.Lock()
|
uw.mu.Lock()
|
||||||
if _, ok := uw.objectsByKey[key]; !ok {
|
if _, ok := uw.objectsByName[name]; !ok {
|
||||||
uw.objectsCount.Inc()
|
uw.objectsCount.Inc()
|
||||||
uw.objectsAdded.Inc()
|
uw.objectsAdded.Inc()
|
||||||
} else {
|
} else {
|
||||||
uw.objectsUpdated.Inc()
|
uw.objectsUpdated.Inc()
|
||||||
}
|
}
|
||||||
uw.objectsByKey[key] = o
|
uw.objectsByName[name] = o
|
||||||
aws := getAPIWatchers(uw.aws)
|
aws := getAPIWatchers(uw.aws)
|
||||||
uw.mu.Unlock()
|
uw.mu.Unlock()
|
||||||
labels := o.getTargetLabels(uw.gw)
|
labels := o.getTargetLabels(uw.gw)
|
||||||
for _, aw := range aws {
|
for _, aw := range aws {
|
||||||
aw.setScrapeWorks(key, labels)
|
aw.setScrapeWorks(uw.namespace, name, labels)
|
||||||
}
|
}
|
||||||
case "DELETED":
|
case "DELETED":
|
||||||
o, err := uw.parseObject(we.Object)
|
o, err := uw.parseObject(we.Object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
key := o.key()
|
name := o.name()
|
||||||
uw.mu.Lock()
|
uw.mu.Lock()
|
||||||
if _, ok := uw.objectsByKey[key]; ok {
|
if _, ok := uw.objectsByName[name]; ok {
|
||||||
uw.objectsCount.Dec()
|
uw.objectsCount.Dec()
|
||||||
uw.objectsRemoved.Inc()
|
uw.objectsRemoved.Inc()
|
||||||
delete(uw.objectsByKey, key)
|
delete(uw.objectsByName, name)
|
||||||
}
|
}
|
||||||
aws := getAPIWatchers(uw.aws)
|
aws := getAPIWatchers(uw.aws)
|
||||||
uw.mu.Unlock()
|
uw.mu.Unlock()
|
||||||
for _, aw := range aws {
|
for _, aw := range aws {
|
||||||
aw.removeScrapeWorks(key)
|
aw.removeScrapeWorks(uw.namespace, name)
|
||||||
}
|
}
|
||||||
case "BOOKMARK":
|
case "BOOKMARK":
|
||||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#watch-bookmarks
|
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#watch-bookmarks
|
||||||
|
@ -630,19 +650,19 @@ func parseError(data []byte) (*Error, error) {
|
||||||
return &em, nil
|
return &em, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAPIPaths(role string, namespaces []string, selectors []Selector) []string {
|
func getAPIPathsWithNamespaces(role string, namespaces []string, selectors []Selector) ([]string, []string) {
|
||||||
objectName := getObjectNameByRole(role)
|
objectName := getObjectNameByRole(role)
|
||||||
if objectName == "nodes" || len(namespaces) == 0 {
|
if objectName == "nodes" || len(namespaces) == 0 {
|
||||||
query := joinSelectors(role, selectors)
|
query := joinSelectors(role, selectors)
|
||||||
path := getAPIPath(objectName, "", query)
|
path := getAPIPath(objectName, "", query)
|
||||||
return []string{path}
|
return []string{path}, []string{""}
|
||||||
}
|
}
|
||||||
query := joinSelectors(role, selectors)
|
query := joinSelectors(role, selectors)
|
||||||
paths := make([]string, len(namespaces))
|
paths := make([]string, len(namespaces))
|
||||||
for i, namespace := range namespaces {
|
for i, namespace := range namespaces {
|
||||||
paths[i] = getAPIPath(objectName, namespace, query)
|
paths[i] = getAPIPath(objectName, namespace, query)
|
||||||
}
|
}
|
||||||
return paths
|
return paths, namespaces
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAPIPath(objectName, namespace, query string) string {
|
func getAPIPath(objectName, namespace, query string) string {
|
||||||
|
|
|
@ -5,52 +5,55 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetAPIPaths(t *testing.T) {
|
func TestGetAPIPathsWithNamespaces(t *testing.T) {
|
||||||
f := func(role string, namespaces []string, selectors []Selector, expectedPaths []string) {
|
f := func(role string, namespaces []string, selectors []Selector, expectedPaths, expectedNamespaces []string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
paths := getAPIPaths(role, namespaces, selectors)
|
paths, resultNamespaces := getAPIPathsWithNamespaces(role, namespaces, selectors)
|
||||||
if !reflect.DeepEqual(paths, expectedPaths) {
|
if !reflect.DeepEqual(paths, expectedPaths) {
|
||||||
t.Fatalf("unexpected paths; got\n%q\nwant\n%q", paths, expectedPaths)
|
t.Fatalf("unexpected paths; got\n%q\nwant\n%q", paths, expectedPaths)
|
||||||
}
|
}
|
||||||
|
if !reflect.DeepEqual(resultNamespaces, expectedNamespaces) {
|
||||||
|
t.Fatalf("unexpected namespaces; got\n%q\nwant\n%q", resultNamespaces, expectedNamespaces)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// role=node
|
// role=node
|
||||||
f("node", nil, nil, []string{"/api/v1/nodes"})
|
f("node", nil, nil, []string{"/api/v1/nodes"}, []string{""})
|
||||||
f("node", []string{"foo", "bar"}, nil, []string{"/api/v1/nodes"})
|
f("node", []string{"foo", "bar"}, nil, []string{"/api/v1/nodes"}, []string{""})
|
||||||
f("node", nil, []Selector{
|
f("node", nil, []Selector{
|
||||||
{
|
{
|
||||||
Role: "pod",
|
Role: "pod",
|
||||||
Label: "foo",
|
Label: "foo",
|
||||||
Field: "bar",
|
Field: "bar",
|
||||||
},
|
},
|
||||||
}, []string{"/api/v1/nodes"})
|
}, []string{"/api/v1/nodes"}, []string{""})
|
||||||
f("node", nil, []Selector{
|
f("node", nil, []Selector{
|
||||||
{
|
{
|
||||||
Role: "node",
|
Role: "node",
|
||||||
Label: "foo",
|
Label: "foo",
|
||||||
Field: "bar",
|
Field: "bar",
|
||||||
},
|
},
|
||||||
}, []string{"/api/v1/nodes?labelSelector=foo&fieldSelector=bar"})
|
}, []string{"/api/v1/nodes?labelSelector=foo&fieldSelector=bar"}, []string{""})
|
||||||
f("node", []string{"x", "y"}, []Selector{
|
f("node", []string{"x", "y"}, []Selector{
|
||||||
{
|
{
|
||||||
Role: "node",
|
Role: "node",
|
||||||
Label: "foo",
|
Label: "foo",
|
||||||
Field: "bar",
|
Field: "bar",
|
||||||
},
|
},
|
||||||
}, []string{"/api/v1/nodes?labelSelector=foo&fieldSelector=bar"})
|
}, []string{"/api/v1/nodes?labelSelector=foo&fieldSelector=bar"}, []string{""})
|
||||||
|
|
||||||
// role=pod
|
// role=pod
|
||||||
f("pod", nil, nil, []string{"/api/v1/pods"})
|
f("pod", nil, nil, []string{"/api/v1/pods"}, []string{""})
|
||||||
f("pod", []string{"foo", "bar"}, nil, []string{
|
f("pod", []string{"foo", "bar"}, nil, []string{
|
||||||
"/api/v1/namespaces/foo/pods",
|
"/api/v1/namespaces/foo/pods",
|
||||||
"/api/v1/namespaces/bar/pods",
|
"/api/v1/namespaces/bar/pods",
|
||||||
})
|
}, []string{"foo", "bar"})
|
||||||
f("pod", nil, []Selector{
|
f("pod", nil, []Selector{
|
||||||
{
|
{
|
||||||
Role: "node",
|
Role: "node",
|
||||||
Label: "foo",
|
Label: "foo",
|
||||||
},
|
},
|
||||||
}, []string{"/api/v1/pods"})
|
}, []string{"/api/v1/pods"}, []string{""})
|
||||||
f("pod", nil, []Selector{
|
f("pod", nil, []Selector{
|
||||||
{
|
{
|
||||||
Role: "pod",
|
Role: "pod",
|
||||||
|
@ -61,7 +64,7 @@ func TestGetAPIPaths(t *testing.T) {
|
||||||
Label: "x",
|
Label: "x",
|
||||||
Field: "y",
|
Field: "y",
|
||||||
},
|
},
|
||||||
}, []string{"/api/v1/pods?labelSelector=foo%2Cx&fieldSelector=y"})
|
}, []string{"/api/v1/pods?labelSelector=foo%2Cx&fieldSelector=y"}, []string{""})
|
||||||
f("pod", []string{"x", "y"}, []Selector{
|
f("pod", []string{"x", "y"}, []Selector{
|
||||||
{
|
{
|
||||||
Role: "pod",
|
Role: "pod",
|
||||||
|
@ -75,14 +78,14 @@ func TestGetAPIPaths(t *testing.T) {
|
||||||
}, []string{
|
}, []string{
|
||||||
"/api/v1/namespaces/x/pods?labelSelector=foo%2Cx&fieldSelector=y",
|
"/api/v1/namespaces/x/pods?labelSelector=foo%2Cx&fieldSelector=y",
|
||||||
"/api/v1/namespaces/y/pods?labelSelector=foo%2Cx&fieldSelector=y",
|
"/api/v1/namespaces/y/pods?labelSelector=foo%2Cx&fieldSelector=y",
|
||||||
})
|
}, []string{"x", "y"})
|
||||||
|
|
||||||
// role=service
|
// role=service
|
||||||
f("service", nil, nil, []string{"/api/v1/services"})
|
f("service", nil, nil, []string{"/api/v1/services"}, []string{""})
|
||||||
f("service", []string{"x", "y"}, nil, []string{
|
f("service", []string{"x", "y"}, nil, []string{
|
||||||
"/api/v1/namespaces/x/services",
|
"/api/v1/namespaces/x/services",
|
||||||
"/api/v1/namespaces/y/services",
|
"/api/v1/namespaces/y/services",
|
||||||
})
|
}, []string{"x", "y"})
|
||||||
f("service", nil, []Selector{
|
f("service", nil, []Selector{
|
||||||
{
|
{
|
||||||
Role: "node",
|
Role: "node",
|
||||||
|
@ -92,7 +95,7 @@ func TestGetAPIPaths(t *testing.T) {
|
||||||
Role: "service",
|
Role: "service",
|
||||||
Field: "bar",
|
Field: "bar",
|
||||||
},
|
},
|
||||||
}, []string{"/api/v1/services?fieldSelector=bar"})
|
}, []string{"/api/v1/services?fieldSelector=bar"}, []string{""})
|
||||||
f("service", []string{"x", "y"}, []Selector{
|
f("service", []string{"x", "y"}, []Selector{
|
||||||
{
|
{
|
||||||
Role: "service",
|
Role: "service",
|
||||||
|
@ -101,14 +104,14 @@ func TestGetAPIPaths(t *testing.T) {
|
||||||
}, []string{
|
}, []string{
|
||||||
"/api/v1/namespaces/x/services?labelSelector=abc%3Dde",
|
"/api/v1/namespaces/x/services?labelSelector=abc%3Dde",
|
||||||
"/api/v1/namespaces/y/services?labelSelector=abc%3Dde",
|
"/api/v1/namespaces/y/services?labelSelector=abc%3Dde",
|
||||||
})
|
}, []string{"x", "y"})
|
||||||
|
|
||||||
// role=endpoints
|
// role=endpoints
|
||||||
f("endpoints", nil, nil, []string{"/api/v1/endpoints"})
|
f("endpoints", nil, nil, []string{"/api/v1/endpoints"}, []string{""})
|
||||||
f("endpoints", []string{"x", "y"}, nil, []string{
|
f("endpoints", []string{"x", "y"}, nil, []string{
|
||||||
"/api/v1/namespaces/x/endpoints",
|
"/api/v1/namespaces/x/endpoints",
|
||||||
"/api/v1/namespaces/y/endpoints",
|
"/api/v1/namespaces/y/endpoints",
|
||||||
})
|
}, []string{"x", "y"})
|
||||||
f("endpoints", []string{"x", "y"}, []Selector{
|
f("endpoints", []string{"x", "y"}, []Selector{
|
||||||
{
|
{
|
||||||
Role: "endpoints",
|
Role: "endpoints",
|
||||||
|
@ -121,10 +124,10 @@ func TestGetAPIPaths(t *testing.T) {
|
||||||
}, []string{
|
}, []string{
|
||||||
"/api/v1/namespaces/x/endpoints?labelSelector=bbb",
|
"/api/v1/namespaces/x/endpoints?labelSelector=bbb",
|
||||||
"/api/v1/namespaces/y/endpoints?labelSelector=bbb",
|
"/api/v1/namespaces/y/endpoints?labelSelector=bbb",
|
||||||
})
|
}, []string{"x", "y"})
|
||||||
|
|
||||||
// role=endpointslices
|
// role=endpointslices
|
||||||
f("endpointslices", nil, nil, []string{"/apis/discovery.k8s.io/v1beta1/endpointslices"})
|
f("endpointslices", nil, nil, []string{"/apis/discovery.k8s.io/v1beta1/endpointslices"}, []string{""})
|
||||||
f("endpointslices", []string{"x", "y"}, []Selector{
|
f("endpointslices", []string{"x", "y"}, []Selector{
|
||||||
{
|
{
|
||||||
Role: "endpointslices",
|
Role: "endpointslices",
|
||||||
|
@ -134,10 +137,10 @@ func TestGetAPIPaths(t *testing.T) {
|
||||||
}, []string{
|
}, []string{
|
||||||
"/apis/discovery.k8s.io/v1beta1/namespaces/x/endpointslices?labelSelector=label&fieldSelector=field",
|
"/apis/discovery.k8s.io/v1beta1/namespaces/x/endpointslices?labelSelector=label&fieldSelector=field",
|
||||||
"/apis/discovery.k8s.io/v1beta1/namespaces/y/endpointslices?labelSelector=label&fieldSelector=field",
|
"/apis/discovery.k8s.io/v1beta1/namespaces/y/endpointslices?labelSelector=label&fieldSelector=field",
|
||||||
})
|
}, []string{"x", "y"})
|
||||||
|
|
||||||
// role=ingress
|
// role=ingress
|
||||||
f("ingress", nil, nil, []string{"/apis/networking.k8s.io/v1beta1/ingresses"})
|
f("ingress", nil, nil, []string{"/apis/networking.k8s.io/v1beta1/ingresses"}, []string{""})
|
||||||
f("ingress", []string{"x", "y"}, []Selector{
|
f("ingress", []string{"x", "y"}, []Selector{
|
||||||
{
|
{
|
||||||
Role: "node",
|
Role: "node",
|
||||||
|
@ -158,7 +161,7 @@ func TestGetAPIPaths(t *testing.T) {
|
||||||
}, []string{
|
}, []string{
|
||||||
"/apis/networking.k8s.io/v1beta1/namespaces/x/ingresses?labelSelector=cde%2Cbaaa&fieldSelector=abc",
|
"/apis/networking.k8s.io/v1beta1/namespaces/x/ingresses?labelSelector=cde%2Cbaaa&fieldSelector=abc",
|
||||||
"/apis/networking.k8s.io/v1beta1/namespaces/y/ingresses?labelSelector=cde%2Cbaaa&fieldSelector=abc",
|
"/apis/networking.k8s.io/v1beta1/namespaces/y/ingresses?labelSelector=cde%2Cbaaa&fieldSelector=abc",
|
||||||
})
|
}, []string{"x", "y"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseBookmark(t *testing.T) {
|
func TestParseBookmark(t *testing.T) {
|
||||||
|
|
|
@ -16,10 +16,6 @@ type ObjectMeta struct {
|
||||||
OwnerReferences []OwnerReference
|
OwnerReferences []OwnerReference
|
||||||
}
|
}
|
||||||
|
|
||||||
func (om *ObjectMeta) key() string {
|
|
||||||
return om.Namespace + "/" + om.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListMeta is a Kubernetes list metadata
|
// ListMeta is a Kubernetes list metadata
|
||||||
// https://v1-17.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#listmeta-v1-meta
|
// https://v1-17.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#listmeta-v1-meta
|
||||||
type ListMeta struct {
|
type ListMeta struct {
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (eps *Endpoints) key() string {
|
func (eps *Endpoints) name() string {
|
||||||
return eps.Metadata.key()
|
return eps.Metadata.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseEndpointsList(r io.Reader) (map[string]object, ListMeta, error) {
|
func parseEndpointsList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
|
@ -18,11 +18,11 @@ func parseEndpointsList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
if err := d.Decode(&epsl); err != nil {
|
if err := d.Decode(&epsl); err != nil {
|
||||||
return nil, epsl.Metadata, fmt.Errorf("cannot unmarshal EndpointsList: %w", err)
|
return nil, epsl.Metadata, fmt.Errorf("cannot unmarshal EndpointsList: %w", err)
|
||||||
}
|
}
|
||||||
objectsByKey := make(map[string]object)
|
objectsByName := make(map[string]object)
|
||||||
for _, eps := range epsl.Items {
|
for _, eps := range epsl.Items {
|
||||||
objectsByKey[eps.key()] = eps
|
objectsByName[eps.name()] = eps
|
||||||
}
|
}
|
||||||
return objectsByKey, epsl.Metadata, nil
|
return objectsByName, epsl.Metadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseEndpoints(data []byte) (object, error) {
|
func parseEndpoints(data []byte) (object, error) {
|
||||||
|
|
|
@ -9,8 +9,8 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (eps *EndpointSlice) key() string {
|
func (eps *EndpointSlice) name() string {
|
||||||
return eps.Metadata.key()
|
return eps.Metadata.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseEndpointSliceList(r io.Reader) (map[string]object, ListMeta, error) {
|
func parseEndpointSliceList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
|
@ -19,11 +19,11 @@ func parseEndpointSliceList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
if err := d.Decode(&epsl); err != nil {
|
if err := d.Decode(&epsl); err != nil {
|
||||||
return nil, epsl.Metadata, fmt.Errorf("cannot unmarshal EndpointSliceList: %w", err)
|
return nil, epsl.Metadata, fmt.Errorf("cannot unmarshal EndpointSliceList: %w", err)
|
||||||
}
|
}
|
||||||
objectsByKey := make(map[string]object)
|
objectsByName := make(map[string]object)
|
||||||
for _, eps := range epsl.Items {
|
for _, eps := range epsl.Items {
|
||||||
objectsByKey[eps.key()] = eps
|
objectsByName[eps.name()] = eps
|
||||||
}
|
}
|
||||||
return objectsByKey, epsl.Metadata, nil
|
return objectsByName, epsl.Metadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseEndpointSlice(data []byte) (object, error) {
|
func parseEndpointSlice(data []byte) (object, error) {
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ig *Ingress) key() string {
|
func (ig *Ingress) name() string {
|
||||||
return ig.Metadata.key()
|
return ig.Metadata.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseIngressList(r io.Reader) (map[string]object, ListMeta, error) {
|
func parseIngressList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
|
@ -16,11 +16,11 @@ func parseIngressList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
if err := d.Decode(&igl); err != nil {
|
if err := d.Decode(&igl); err != nil {
|
||||||
return nil, igl.Metadata, fmt.Errorf("cannot unmarshal IngressList: %w", err)
|
return nil, igl.Metadata, fmt.Errorf("cannot unmarshal IngressList: %w", err)
|
||||||
}
|
}
|
||||||
objectsByKey := make(map[string]object)
|
objectsByName := make(map[string]object)
|
||||||
for _, ig := range igl.Items {
|
for _, ig := range igl.Items {
|
||||||
objectsByKey[ig.key()] = ig
|
objectsByName[ig.name()] = ig
|
||||||
}
|
}
|
||||||
return objectsByKey, igl.Metadata, nil
|
return objectsByName, igl.Metadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseIngress(data []byte) (object, error) {
|
func parseIngress(data []byte) (object, error) {
|
||||||
|
|
|
@ -8,9 +8,8 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getNodesLabels returns labels for k8s nodes obtained from the given cfg
|
func (n *Node) name() string {
|
||||||
func (n *Node) key() string {
|
return n.Metadata.Name
|
||||||
return n.Metadata.key()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNodeList(r io.Reader) (map[string]object, ListMeta, error) {
|
func parseNodeList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
|
@ -19,11 +18,11 @@ func parseNodeList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
if err := d.Decode(&nl); err != nil {
|
if err := d.Decode(&nl); err != nil {
|
||||||
return nil, nl.Metadata, fmt.Errorf("cannot unmarshal NodeList: %w", err)
|
return nil, nl.Metadata, fmt.Errorf("cannot unmarshal NodeList: %w", err)
|
||||||
}
|
}
|
||||||
objectsByKey := make(map[string]object)
|
objectsByName := make(map[string]object)
|
||||||
for _, n := range nl.Items {
|
for _, n := range nl.Items {
|
||||||
objectsByKey[n.key()] = n
|
objectsByName[n.name()] = n
|
||||||
}
|
}
|
||||||
return objectsByKey, nl.Metadata, nil
|
return objectsByName, nl.Metadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNode(data []byte) (object, error) {
|
func parseNode(data []byte) (object, error) {
|
||||||
|
|
|
@ -10,8 +10,8 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *Pod) key() string {
|
func (p *Pod) name() string {
|
||||||
return p.Metadata.key()
|
return p.Metadata.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePodList(r io.Reader) (map[string]object, ListMeta, error) {
|
func parsePodList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
|
@ -20,11 +20,11 @@ func parsePodList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
if err := d.Decode(&pl); err != nil {
|
if err := d.Decode(&pl); err != nil {
|
||||||
return nil, pl.Metadata, fmt.Errorf("cannot unmarshal PodList: %w", err)
|
return nil, pl.Metadata, fmt.Errorf("cannot unmarshal PodList: %w", err)
|
||||||
}
|
}
|
||||||
objectsByKey := make(map[string]object)
|
objectsByName := make(map[string]object)
|
||||||
for _, p := range pl.Items {
|
for _, p := range pl.Items {
|
||||||
objectsByKey[p.key()] = p
|
objectsByName[p.name()] = p
|
||||||
}
|
}
|
||||||
return objectsByKey, pl.Metadata, nil
|
return objectsByName, pl.Metadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePod(data []byte) (object, error) {
|
func parsePod(data []byte) (object, error) {
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) key() string {
|
func (s *Service) name() string {
|
||||||
return s.Metadata.key()
|
return s.Metadata.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseServiceList(r io.Reader) (map[string]object, ListMeta, error) {
|
func parseServiceList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
|
@ -18,11 +18,11 @@ func parseServiceList(r io.Reader) (map[string]object, ListMeta, error) {
|
||||||
if err := d.Decode(&sl); err != nil {
|
if err := d.Decode(&sl); err != nil {
|
||||||
return nil, sl.Metadata, fmt.Errorf("cannot unmarshal ServiceList: %w", err)
|
return nil, sl.Metadata, fmt.Errorf("cannot unmarshal ServiceList: %w", err)
|
||||||
}
|
}
|
||||||
objectsByKey := make(map[string]object)
|
objectsByName := make(map[string]object)
|
||||||
for _, s := range sl.Items {
|
for _, s := range sl.Items {
|
||||||
objectsByKey[s.key()] = s
|
objectsByName[s.name()] = s
|
||||||
}
|
}
|
||||||
return objectsByKey, sl.Metadata, nil
|
return objectsByName, sl.Metadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseService(data []byte) (object, error) {
|
func parseService(data []byte) (object, error) {
|
||||||
|
|
Loading…
Reference in a new issue