// Copyright 2020 The Prometheus Authors // Licensed 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 moby import ( "context" "fmt" "net" "strconv" "github.com/docker/docker/api/types" "github.com/prometheus/common/model" "github.com/prometheus/prometheus/discovery/targetgroup" "github.com/prometheus/prometheus/util/strutil" ) const ( swarmLabelNodePrefix = swarmLabel + "node_" swarmLabelNodeAddress = swarmLabelNodePrefix + "address" swarmLabelNodeAvailability = swarmLabelNodePrefix + "availability" swarmLabelNodeEngineVersion = swarmLabelNodePrefix + "engine_version" swarmLabelNodeHostname = swarmLabelNodePrefix + "hostname" swarmLabelNodeID = swarmLabelNodePrefix + "id" swarmLabelNodeLabelPrefix = swarmLabelNodePrefix + "label_" swarmLabelNodeManagerAddr = swarmLabelNodePrefix + "manager_address" swarmLabelNodeManagerLeader = swarmLabelNodePrefix + "manager_leader" swarmLabelNodeManagerReachability = swarmLabelNodePrefix + "manager_reachability" swarmLabelNodePlatformArchitecture = swarmLabelNodePrefix + "platform_architecture" swarmLabelNodePlatformOS = swarmLabelNodePrefix + "platform_os" swarmLabelNodeRole = swarmLabelNodePrefix + "role" swarmLabelNodeStatus = swarmLabelNodePrefix + "status" ) func (d *Discovery) refreshNodes(ctx context.Context) ([]*targetgroup.Group, error) { tg := &targetgroup.Group{ Source: "DockerSwarm", } nodes, err := d.client.NodeList(ctx, types.NodeListOptions{Filters: d.filters}) if err != nil { return nil, fmt.Errorf("error while listing swarm nodes: %w", err) } for _, n := range nodes { labels := model.LabelSet{ swarmLabelNodeID: model.LabelValue(n.ID), swarmLabelNodeRole: model.LabelValue(n.Spec.Role), swarmLabelNodeAvailability: model.LabelValue(n.Spec.Availability), swarmLabelNodeHostname: model.LabelValue(n.Description.Hostname), swarmLabelNodePlatformArchitecture: model.LabelValue(n.Description.Platform.Architecture), swarmLabelNodePlatformOS: model.LabelValue(n.Description.Platform.OS), swarmLabelNodeEngineVersion: model.LabelValue(n.Description.Engine.EngineVersion), swarmLabelNodeStatus: model.LabelValue(n.Status.State), swarmLabelNodeAddress: model.LabelValue(n.Status.Addr), } if n.ManagerStatus != nil { labels[swarmLabelNodeManagerLeader] = model.LabelValue(strconv.FormatBool(n.ManagerStatus.Leader)) labels[swarmLabelNodeManagerReachability] = model.LabelValue(n.ManagerStatus.Reachability) labels[swarmLabelNodeManagerAddr] = model.LabelValue(n.ManagerStatus.Addr) } for k, v := range n.Spec.Labels { ln := strutil.SanitizeLabelName(k) labels[model.LabelName(swarmLabelNodeLabelPrefix+ln)] = model.LabelValue(v) } addr := net.JoinHostPort(n.Status.Addr, strconv.FormatUint(uint64(d.port), 10)) labels[model.AddressLabel] = model.LabelValue(addr) tg.Targets = append(tg.Targets, labels) } return []*targetgroup.Group{tg}, nil } func (d *Discovery) getNodesLabels(ctx context.Context) (map[string]map[string]string, error) { nodes, err := d.client.NodeList(ctx, types.NodeListOptions{}) if err != nil { return nil, fmt.Errorf("error while listing swarm nodes: %w", err) } labels := make(map[string]map[string]string, len(nodes)) for _, n := range nodes { labels[n.ID] = map[string]string{ swarmLabelNodeID: n.ID, swarmLabelNodeRole: string(n.Spec.Role), swarmLabelNodeAddress: n.Status.Addr, swarmLabelNodeAvailability: string(n.Spec.Availability), swarmLabelNodeHostname: n.Description.Hostname, swarmLabelNodePlatformArchitecture: n.Description.Platform.Architecture, swarmLabelNodePlatformOS: n.Description.Platform.OS, swarmLabelNodeStatus: string(n.Status.State), } for k, v := range n.Spec.Labels { ln := strutil.SanitizeLabelName(k) labels[n.ID][swarmLabelNodeLabelPrefix+ln] = v } } return labels, nil }