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", Role: "instance",
Region: "RegionOne", Region: "RegionOne",
Port: 80, Port: 80,
Availability: "public",
RefreshInterval: model.Duration(60 * time.Second), RefreshInterval: model.Duration(60 * time.Second),
TLSConfig: config_util.TLSConfig{ TLSConfig: config_util.TLSConfig{
CAFile: "testdata/valid_ca_file", CAFile: "testdata/valid_ca_file",
@ -846,6 +847,9 @@ var expectedErrors = []struct {
}, { }, {
filename: "openstack_role.bad.yml", filename: "openstack_role.bad.yml",
errMsg: "unknown OpenStack SD role", 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", filename: "url_in_targetgroup.bad.yml",
errMsg: "\"http://bad\" is not a valid hostname", 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. // HypervisorDiscovery discovers OpenStack hypervisors.
type HypervisorDiscovery struct { type HypervisorDiscovery struct {
provider *gophercloud.ProviderClient provider *gophercloud.ProviderClient
authOpts *gophercloud.AuthOptions authOpts *gophercloud.AuthOptions
region string region string
logger log.Logger logger log.Logger
port int port int
availability gophercloud.Availability
} }
// newHypervisorDiscovery returns a new hypervisor discovery. // newHypervisorDiscovery returns a new hypervisor discovery.
func newHypervisorDiscovery(provider *gophercloud.ProviderClient, opts *gophercloud.AuthOptions, 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, 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) { 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 { if err != nil {
return nil, errors.Wrap(err, "could not authenticate to OpenStack") return nil, errors.Wrap(err, "could not authenticate to OpenStack")
} }
client, err := openstack.NewComputeV2(h.provider, gophercloud.EndpointOpts{ client, err := openstack.NewComputeV2(h.provider, gophercloud.EndpointOpts{
Region: h.region, Region: h.region, Availability: h.availability,
}) })
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not create OpenStack compute session") return nil, errors.Wrap(err, "could not create OpenStack compute session")

View file

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

View file

@ -15,6 +15,7 @@ package openstack
import ( import (
"context" "context"
"fmt"
"net/http" "net/http"
"time" "time"
@ -34,6 +35,7 @@ import (
var DefaultSDConfig = SDConfig{ var DefaultSDConfig = SDConfig{
Port: 80, Port: 80,
RefreshInterval: model.Duration(60 * time.Second), RefreshInterval: model.Duration(60 * time.Second),
Availability: "public",
} }
// SDConfig is the configuration for OpenStack based service discovery. // SDConfig is the configuration for OpenStack based service discovery.
@ -55,6 +57,7 @@ type SDConfig struct {
Port int `yaml:"port"` Port int `yaml:"port"`
AllTenants bool `yaml:"all_tenants,omitempty"` AllTenants bool `yaml:"all_tenants,omitempty"`
TLSConfig config_util.TLSConfig `yaml:"tls_config,omitempty"` TLSConfig config_util.TLSConfig `yaml:"tls_config,omitempty"`
Availability string `yaml:"availability,omitempty"`
} }
// Role is the role of the target in OpenStack. // 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 { if err != nil {
return err 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 == "" { if c.Role == "" {
return errors.New("role missing (one of: instance, hypervisor)") return errors.New("role missing (one of: instance, hypervisor)")
} }
if c.Region == "" { if c.Region == "" {
return errors.New("openstack SD configuration requires a region") return errors.New("openstack SD configuration requires a region")
} }
return nil return nil
} }
@ -161,11 +172,12 @@ func newRefresher(conf *SDConfig, l log.Logger) (refresher, error) {
}, },
Timeout: 5 * time.Duration(conf.RefreshInterval), Timeout: 5 * time.Duration(conf.RefreshInterval),
} }
availability := gophercloud.Availability(conf.Availability)
switch conf.Role { switch conf.Role {
case OpenStackRoleHypervisor: 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: 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") return nil, errors.New("unknown OpenStack discovery role")
} }

View file

@ -773,6 +773,9 @@ region: <string>
# instead be specified in the relabeling rule. # instead be specified in the relabeling rule.
[ port: <int> | default = 80 ] [ 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 configuration.
tls_config: tls_config:
[ <tls_config> ] [ <tls_config> ]