VictoriaMetrics/lib/promscrape/discovery/kubernetes/api.go
Aliaksandr Valialkin 855436efd2
lib/promauth: refactor NewConfig in order to improve maintainability
1. Split NewConfig into smaller functions
2. Introduce Options struct for simplifying construction of the Config with various options

This commit is based on https://github.com/VictoriaMetrics/VictoriaMetrics/pull/2684
2022-07-04 14:31:12 +03:00

98 lines
3.2 KiB
Go

package kubernetes
import (
"fmt"
"net"
"os"
"strings"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
)
func newAPIConfig(sdc *SDConfig, baseDir string, swcFunc ScrapeWorkConstructorFunc) (*apiConfig, error) {
role := sdc.role()
switch role {
case "node", "pod", "service", "endpoints", "endpointslice", "ingress":
default:
return nil, fmt.Errorf("unexpected `role`: %q; must be one of `node`, `pod`, `service`, `endpoints`, `endpointslice` or `ingress`", role)
}
cc := &sdc.HTTPClientConfig
ac, err := cc.NewConfig(baseDir)
if err != nil {
return nil, fmt.Errorf("cannot parse auth config: %w", err)
}
apiServer := sdc.APIServer
if len(sdc.KubeConfigFile) > 0 {
if len(apiServer) > 0 {
return nil, fmt.Errorf("`api_server: %q` and `kubeconfig_file: %q` options cannot be set simultaneously", apiServer, sdc.KubeConfigFile)
}
kc, err := newKubeConfig(sdc.KubeConfigFile)
if err != nil {
return nil, fmt.Errorf("cannot build kube config from the specified `kubeconfig_file` config option: %w", err)
}
opts := &promauth.Options{
BaseDir: baseDir,
BasicAuth: kc.basicAuth,
BearerToken: kc.token,
BearerTokenFile: kc.tokenFile,
OAuth2: cc.OAuth2,
TLSConfig: kc.tlsConfig,
Headers: cc.Headers,
}
acNew, err := opts.NewConfig()
if err != nil {
return nil, fmt.Errorf("cannot initialize auth config from `kubeconfig_file: %q`: %w", sdc.KubeConfigFile, err)
}
ac = acNew
apiServer = kc.server
sdc.ProxyURL = kc.proxyURL
}
if len(apiServer) == 0 {
// Assume we run at k8s pod.
// Discover apiServer and auth config according to k8s docs.
// See https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#service-account-admission-controller
host := os.Getenv("KUBERNETES_SERVICE_HOST")
port := os.Getenv("KUBERNETES_SERVICE_PORT")
if len(host) == 0 {
return nil, fmt.Errorf("cannot find KUBERNETES_SERVICE_HOST env var; it must be defined when running in k8s; " +
"probably, `kubernetes_sd_config->api_server` is missing in Prometheus configs?")
}
if len(port) == 0 {
return nil, fmt.Errorf("cannot find KUBERNETES_SERVICE_PORT env var; it must be defined when running in k8s; "+
"KUBERNETES_SERVICE_HOST=%q", host)
}
apiServer = "https://" + net.JoinHostPort(host, port)
tlsConfig := promauth.TLSConfig{
CAFile: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
}
opts := &promauth.Options{
BaseDir: baseDir,
BearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token",
OAuth2: cc.OAuth2,
TLSConfig: &tlsConfig,
Headers: cc.Headers,
}
acNew, err := opts.NewConfig()
if err != nil {
return nil, fmt.Errorf("cannot initialize service account auth: %w; probably, `kubernetes_sd_config->api_server` is missing in Prometheus configs?", err)
}
ac = acNew
}
if !strings.Contains(apiServer, "://") {
proto := "http"
if sdc.HTTPClientConfig.TLSConfig != nil {
proto = "https"
}
apiServer = proto + "://" + apiServer
}
for strings.HasSuffix(apiServer, "/") {
apiServer = apiServer[:len(apiServer)-1]
}
aw := newAPIWatcher(apiServer, ac, sdc, swcFunc)
cfg := &apiConfig{
aw: aw,
}
return cfg, nil
}