OpenStack SD: Add availability config option, to choose endpoint type (#7494)

* OpenStack SD: Add availability config option, to choose endpoint type

In some environments Prometheus must query OpenStack via an alternative
endpoint type (gophercloud calls this `availability`.

This commit implements this option.

Co-Authored-By: Dennis Kuhn <d.kuhn@syseleven.de>
Signed-off-by: Steffen Neubauer <s.neubauer@syseleven.de>
This commit is contained in:
Steffen Neubauer 2020-07-02 16:17:56 +02:00 committed by GitHub
parent a98be49c52
commit 9c9b872087
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 19 deletions

View file

@ -621,6 +621,7 @@ var expectedConf = &Config{
Role: "instance",
Region: "RegionOne",
Port: 80,
Availability: "public",
RefreshInterval: model.Duration(60 * time.Second),
TLSConfig: config_util.TLSConfig{
CAFile: "testdata/valid_ca_file",
@ -846,6 +847,9 @@ var expectedErrors = []struct {
}, {
filename: "openstack_role.bad.yml",
errMsg: "unknown OpenStack SD role",
}, {
filename: "openstack_availability.bad.yml",
errMsg: "unknown availability invalid, must be one of admin, internal or public",
}, {
filename: "url_in_targetgroup.bad.yml",
errMsg: "\"http://bad\" is not a valid hostname",

View file

@ -0,0 +1,4 @@
scrape_configs:
- openstack_sd_configs:
- availability: invalid

View file

@ -40,18 +40,19 @@ const (
// HypervisorDiscovery discovers OpenStack hypervisors.
type HypervisorDiscovery struct {
provider *gophercloud.ProviderClient
authOpts *gophercloud.AuthOptions
region string
logger log.Logger
port int
provider *gophercloud.ProviderClient
authOpts *gophercloud.AuthOptions
region string
logger log.Logger
port int
availability gophercloud.Availability
}
// newHypervisorDiscovery returns a new hypervisor discovery.
func newHypervisorDiscovery(provider *gophercloud.ProviderClient, opts *gophercloud.AuthOptions,
port int, region string, l log.Logger) *HypervisorDiscovery {
port int, region string, availability gophercloud.Availability, l log.Logger) *HypervisorDiscovery {
return &HypervisorDiscovery{provider: provider, authOpts: opts,
region: region, port: port, logger: l}
region: region, port: port, availability: availability, logger: l}
}
func (h *HypervisorDiscovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
@ -60,8 +61,9 @@ func (h *HypervisorDiscovery) refresh(ctx context.Context) ([]*targetgroup.Group
if err != nil {
return nil, errors.Wrap(err, "could not authenticate to OpenStack")
}
client, err := openstack.NewComputeV2(h.provider, gophercloud.EndpointOpts{
Region: h.region,
Region: h.region, Availability: h.availability,
})
if err != nil {
return nil, errors.Wrap(err, "could not create OpenStack compute session")

View file

@ -47,22 +47,23 @@ const (
// InstanceDiscovery discovers OpenStack instances.
type InstanceDiscovery struct {
provider *gophercloud.ProviderClient
authOpts *gophercloud.AuthOptions
region string
logger log.Logger
port int
allTenants bool
provider *gophercloud.ProviderClient
authOpts *gophercloud.AuthOptions
region string
logger log.Logger
port int
allTenants bool
availability gophercloud.Availability
}
// NewInstanceDiscovery returns a new instance discovery.
func newInstanceDiscovery(provider *gophercloud.ProviderClient, opts *gophercloud.AuthOptions,
port int, region string, allTenants bool, l log.Logger) *InstanceDiscovery {
port int, region string, allTenants bool, availability gophercloud.Availability, l log.Logger) *InstanceDiscovery {
if l == nil {
l = log.NewNopLogger()
}
return &InstanceDiscovery{provider: provider, authOpts: opts,
region: region, port: port, allTenants: allTenants, logger: l}
region: region, port: port, allTenants: allTenants, availability: availability, logger: l}
}
type floatingIPKey struct {
@ -76,8 +77,9 @@ func (i *InstanceDiscovery) refresh(ctx context.Context) ([]*targetgroup.Group,
if err != nil {
return nil, errors.Wrap(err, "could not authenticate to OpenStack")
}
client, err := openstack.NewComputeV2(i.provider, gophercloud.EndpointOpts{
Region: i.region,
Region: i.region, Availability: i.availability,
})
if err != nil {
return nil, errors.Wrap(err, "could not create OpenStack compute session")

View file

@ -15,6 +15,7 @@ package openstack
import (
"context"
"fmt"
"net/http"
"time"
@ -34,6 +35,7 @@ import (
var DefaultSDConfig = SDConfig{
Port: 80,
RefreshInterval: model.Duration(60 * time.Second),
Availability: "public",
}
// SDConfig is the configuration for OpenStack based service discovery.
@ -55,6 +57,7 @@ type SDConfig struct {
Port int `yaml:"port"`
AllTenants bool `yaml:"all_tenants,omitempty"`
TLSConfig config_util.TLSConfig `yaml:"tls_config,omitempty"`
Availability string `yaml:"availability,omitempty"`
}
// Role is the role of the target in OpenStack.
@ -91,12 +94,20 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err != nil {
return err
}
switch c.Availability {
case "public", "internal", "admin":
default:
return fmt.Errorf("unknown availability %s, must be one of admin, internal or public", c.Availability)
}
if c.Role == "" {
return errors.New("role missing (one of: instance, hypervisor)")
}
if c.Region == "" {
return errors.New("openstack SD configuration requires a region")
}
return nil
}
@ -161,11 +172,12 @@ func newRefresher(conf *SDConfig, l log.Logger) (refresher, error) {
},
Timeout: 5 * time.Duration(conf.RefreshInterval),
}
availability := gophercloud.Availability(conf.Availability)
switch conf.Role {
case OpenStackRoleHypervisor:
return newHypervisorDiscovery(client, &opts, conf.Port, conf.Region, l), nil
return newHypervisorDiscovery(client, &opts, conf.Port, conf.Region, availability, l), nil
case OpenStackRoleInstance:
return newInstanceDiscovery(client, &opts, conf.Port, conf.Region, conf.AllTenants, l), nil
return newInstanceDiscovery(client, &opts, conf.Port, conf.Region, conf.AllTenants, availability, l), nil
}
return nil, errors.New("unknown OpenStack discovery role")
}

View file

@ -773,6 +773,9 @@ region: <string>
# instead be specified in the relabeling rule.
[ port: <int> | default = 80 ]
# The availability of the endpoint to connect to. Must be one of public, admin or internal.
[ availability: <string> | default = "public" ]
# TLS configuration.
tls_config:
[ <tls_config> ]