mirror of
				https://github.com/prometheus/prometheus.git
				synced 2025-10-31 16:31:03 +01:00 
			
		
		
		
	This makes it clear that the dockerswarm package does more than docker swarm, but does also docker. I have picked moby as it is the upstream name: https://mobyproject.org/ There is no user-facing change, except in the case of a bad configuration. Previously, a user who would have a bad docker sd config would see an error like: > field xx not found in type dockerswarm.plain Now that error would be turned into: > field xx not found in type moby.plain While not perfect, it should at not be confusing between docker and dockerswarm. Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
		
			
				
	
	
		
			163 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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/docker/docker/api/types/swarm"
 | |
| 	"github.com/prometheus/common/model"
 | |
| 
 | |
| 	"github.com/prometheus/prometheus/discovery/targetgroup"
 | |
| 	"github.com/prometheus/prometheus/util/strutil"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	swarmLabelServicePrefix                  = swarmLabel + "service_"
 | |
| 	swarmLabelServiceEndpointPortName        = swarmLabelServicePrefix + "endpoint_port_name"
 | |
| 	swarmLabelServiceEndpointPortPublishMode = swarmLabelServicePrefix + "endpoint_port_publish_mode"
 | |
| 	swarmLabelServiceID                      = swarmLabelServicePrefix + "id"
 | |
| 	swarmLabelServiceLabelPrefix             = swarmLabelServicePrefix + "label_"
 | |
| 	swarmLabelServiceName                    = swarmLabelServicePrefix + "name"
 | |
| 	swarmLabelServiceMode                    = swarmLabelServicePrefix + "mode"
 | |
| 	swarmLabelServiceUpdatingStatus          = swarmLabelServicePrefix + "updating_status"
 | |
| 	swarmLabelServiceTaskPrefix              = swarmLabelServicePrefix + "task_"
 | |
| 	swarmLabelServiceTaskContainerImage      = swarmLabelServiceTaskPrefix + "container_image"
 | |
| 	swarmLabelServiceTaskContainerHostname   = swarmLabelServiceTaskPrefix + "container_hostname"
 | |
| )
 | |
| 
 | |
| func (d *Discovery) refreshServices(ctx context.Context) ([]*targetgroup.Group, error) {
 | |
| 	tg := &targetgroup.Group{
 | |
| 		Source: "DockerSwarm",
 | |
| 	}
 | |
| 
 | |
| 	services, err := d.client.ServiceList(ctx, types.ServiceListOptions{Filters: d.filters})
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("error while listing swarm services: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	networkLabels, err := getNetworksLabels(ctx, d.client, swarmLabel)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("error while computing swarm network labels: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	for _, s := range services {
 | |
| 		commonLabels := map[string]string{
 | |
| 			swarmLabelServiceID:                    s.ID,
 | |
| 			swarmLabelServiceName:                  s.Spec.Name,
 | |
| 			swarmLabelServiceTaskContainerHostname: s.Spec.TaskTemplate.ContainerSpec.Hostname,
 | |
| 			swarmLabelServiceTaskContainerImage:    s.Spec.TaskTemplate.ContainerSpec.Image,
 | |
| 		}
 | |
| 		commonLabels[swarmLabelServiceMode] = getServiceValueMode(s)
 | |
| 
 | |
| 		if s.UpdateStatus != nil {
 | |
| 			commonLabels[swarmLabelServiceUpdatingStatus] = string(s.UpdateStatus.State)
 | |
| 		}
 | |
| 
 | |
| 		for k, v := range s.Spec.Labels {
 | |
| 			ln := strutil.SanitizeLabelName(k)
 | |
| 			commonLabels[swarmLabelServiceLabelPrefix+ln] = v
 | |
| 		}
 | |
| 
 | |
| 		for _, p := range s.Endpoint.VirtualIPs {
 | |
| 			var added bool
 | |
| 			ip, _, err := net.ParseCIDR(p.Addr)
 | |
| 			if err != nil {
 | |
| 				return nil, fmt.Errorf("error while parsing address %s: %w", p.Addr, err)
 | |
| 			}
 | |
| 
 | |
| 			for _, e := range s.Endpoint.Ports {
 | |
| 				if e.Protocol != swarm.PortConfigProtocolTCP {
 | |
| 					continue
 | |
| 				}
 | |
| 				labels := model.LabelSet{
 | |
| 					swarmLabelServiceEndpointPortName:        model.LabelValue(e.Name),
 | |
| 					swarmLabelServiceEndpointPortPublishMode: model.LabelValue(e.PublishMode),
 | |
| 				}
 | |
| 
 | |
| 				for k, v := range commonLabels {
 | |
| 					labels[model.LabelName(k)] = model.LabelValue(v)
 | |
| 				}
 | |
| 
 | |
| 				for k, v := range networkLabels[p.NetworkID] {
 | |
| 					labels[model.LabelName(k)] = model.LabelValue(v)
 | |
| 				}
 | |
| 
 | |
| 				addr := net.JoinHostPort(ip.String(), strconv.FormatUint(uint64(e.PublishedPort), 10))
 | |
| 				labels[model.AddressLabel] = model.LabelValue(addr)
 | |
| 
 | |
| 				tg.Targets = append(tg.Targets, labels)
 | |
| 				added = true
 | |
| 			}
 | |
| 
 | |
| 			if !added {
 | |
| 				labels := model.LabelSet{}
 | |
| 
 | |
| 				for k, v := range commonLabels {
 | |
| 					labels[model.LabelName(k)] = model.LabelValue(v)
 | |
| 				}
 | |
| 
 | |
| 				for k, v := range networkLabels[p.NetworkID] {
 | |
| 					labels[model.LabelName(k)] = model.LabelValue(v)
 | |
| 				}
 | |
| 
 | |
| 				addr := net.JoinHostPort(ip.String(), fmt.Sprintf("%d", d.port))
 | |
| 				labels[model.AddressLabel] = model.LabelValue(addr)
 | |
| 
 | |
| 				tg.Targets = append(tg.Targets, labels)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return []*targetgroup.Group{tg}, nil
 | |
| }
 | |
| 
 | |
| func (d *Discovery) getServicesLabelsAndPorts(ctx context.Context) (map[string]map[string]string, map[string][]swarm.PortConfig, error) {
 | |
| 	services, err := d.client.ServiceList(ctx, types.ServiceListOptions{})
 | |
| 	if err != nil {
 | |
| 		return nil, nil, err
 | |
| 	}
 | |
| 	servicesLabels := make(map[string]map[string]string, len(services))
 | |
| 	servicesPorts := make(map[string][]swarm.PortConfig, len(services))
 | |
| 	for _, s := range services {
 | |
| 		servicesLabels[s.ID] = map[string]string{
 | |
| 			swarmLabelServiceID:   s.ID,
 | |
| 			swarmLabelServiceName: s.Spec.Name,
 | |
| 		}
 | |
| 
 | |
| 		servicesLabels[s.ID][swarmLabelServiceMode] = getServiceValueMode(s)
 | |
| 
 | |
| 		for k, v := range s.Spec.Labels {
 | |
| 			ln := strutil.SanitizeLabelName(k)
 | |
| 			servicesLabels[s.ID][swarmLabelServiceLabelPrefix+ln] = v
 | |
| 		}
 | |
| 		servicesPorts[s.ID] = s.Endpoint.Ports
 | |
| 	}
 | |
| 
 | |
| 	return servicesLabels, servicesPorts, nil
 | |
| }
 | |
| 
 | |
| func getServiceValueMode(s swarm.Service) string {
 | |
| 	if s.Spec.Mode.Global != nil {
 | |
| 		return "global"
 | |
| 	}
 | |
| 	if s.Spec.Mode.Replicated != nil {
 | |
| 		return "replicated"
 | |
| 	}
 | |
| 	return ""
 | |
| }
 |