Skip to content

Commit

Permalink
Configuring httpSD http client from TAs clienthttp, added changelog a…
Browse files Browse the repository at this point in the history
…nd tests
  • Loading branch information
ItielOlenick committed Jul 11, 2024
1 parent 5b290f0 commit 30ed470
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 1 deletion.
28 changes: 28 additions & 0 deletions .chloggen/httpSD-client-config-from-TA-confighttp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: prometheusreceiver

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Use confighttp for httpSD client config


# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [33370]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
84 changes: 83 additions & 1 deletion receiver/prometheusreceiver/metrics_receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package prometheusreceiver // import "github.com/open-telemetry/opentelemetry-co
import (
"bytes"
"context"
"encoding/base64"
"errors"
"fmt"
"io"
Expand All @@ -14,6 +15,7 @@ import (
"os"
"reflect"
"regexp"
"strings"
"sync"
"time"
"unsafe"
Expand Down Expand Up @@ -145,6 +147,80 @@ func (r *pReceiver) startTargetAllocator(allocConf *TargetAllocator, baseCfg *Pr
return nil
}

// ConvertTLSVersion converts a string TLS version to the corresponding config.TLSVersion value in prometheus common.
func convertTLSVersion(version string) (commonconfig.TLSVersion, error) {
normalizedVersion := "TLS" + strings.ReplaceAll(version, ".", "")

if tlsVersion, exists := commonconfig.TLSVersions[normalizedVersion]; exists {
return tlsVersion, nil
}
return 0, fmt.Errorf("unsupported TLS version: %s", version)
}

// configureSDHTTPClientConfig configures the http client for the service discovery manager
// based on the provided TargetAllocator configuration.
func configureSDHTTPClientConfigFromTA(httpSD *promHTTP.SDConfig, allocConf *TargetAllocator) error {
httpSD.HTTPClientConfig.FollowRedirects = false

httpSD.HTTPClientConfig.TLSConfig = commonconfig.TLSConfig{
InsecureSkipVerify: allocConf.TLSSetting.InsecureSkipVerify,
ServerName: allocConf.TLSSetting.ServerName,
CAFile: allocConf.TLSSetting.CAFile,
CertFile: allocConf.TLSSetting.CertFile,
KeyFile: allocConf.TLSSetting.KeyFile,
}

if allocConf.TLSSetting.CAPem != "" {
decodedCA, err := base64.StdEncoding.DecodeString(string(allocConf.TLSSetting.CAPem))
if err != nil {
return fmt.Errorf("failed to decode CA: %w", err)
}
httpSD.HTTPClientConfig.TLSConfig.CA = string(decodedCA)
}

if allocConf.TLSSetting.CertPem != "" {
decodedCert, err := base64.StdEncoding.DecodeString(string(allocConf.TLSSetting.CertPem))
if err != nil {
return fmt.Errorf("failed to decode Cert: %w", err)
}
httpSD.HTTPClientConfig.TLSConfig.Cert = string(decodedCert)
}

if allocConf.TLSSetting.KeyPem != "" {
decodedKey, err := base64.StdEncoding.DecodeString(string(allocConf.TLSSetting.KeyPem))
if err != nil {
return fmt.Errorf("failed to decode Key: %w", err)
}
httpSD.HTTPClientConfig.TLSConfig.Key = commonconfig.Secret(decodedKey)
}

if allocConf.TLSSetting.MinVersion != "" {
minVersion, err := convertTLSVersion(allocConf.TLSSetting.MinVersion)
if err != nil {
return err
}
httpSD.HTTPClientConfig.TLSConfig.MinVersion = minVersion
}

if allocConf.TLSSetting.MaxVersion != "" {
maxVersion, err := convertTLSVersion(allocConf.TLSSetting.MaxVersion)
if err != nil {
return err
}
httpSD.HTTPClientConfig.TLSConfig.MaxVersion = maxVersion
}

if allocConf.ProxyURL != "" {
proxyURL, err := url.Parse(allocConf.ProxyURL)
if err != nil {
return err
}
httpSD.HTTPClientConfig.ProxyURL = commonconfig.URL{URL: proxyURL}
}

return nil
}

// syncTargetAllocator request jobs from targetAllocator and update underlying receiver, if the response does not match the provided compareHash.
// baseDiscoveryCfg can be used to provide additional ScrapeConfigs which will be added to the retrieved jobs.
func (r *pReceiver) syncTargetAllocator(compareHash uint64, allocConf *TargetAllocator, baseCfg *PromConfig) (uint64, error) {
Expand Down Expand Up @@ -179,7 +255,13 @@ func (r *pReceiver) syncTargetAllocator(compareHash uint64, allocConf *TargetAll
}
escapedJob := url.QueryEscape(jobName)
httpSD.URL = fmt.Sprintf("%s/jobs/%s/targets?collector_id=%s", allocConf.Endpoint, escapedJob, allocConf.CollectorID)
httpSD.HTTPClientConfig.FollowRedirects = false

err = configureSDHTTPClientConfigFromTA(&httpSD, allocConf)
if err != nil {
r.settings.Logger.Error("Failed to configure http client config", zap.Error(err))
return 0, err
}

scrapeConfig.ServiceDiscoveryConfigs = discovery.Configs{
&httpSD,
}
Expand Down
54 changes: 54 additions & 0 deletions receiver/prometheusreceiver/metrics_receiver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,25 @@ package prometheusreceiver

import (
"context"
"encoding/base64"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"time"

gokitlog "github.com/go-kit/log"
commonconfig "github.com/prometheus/common/config"
"github.com/prometheus/common/model"
promConfig "github.com/prometheus/prometheus/config"
promHTTP "github.com/prometheus/prometheus/discovery/http"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/config/configopaque"
"go.opentelemetry.io/collector/config/configtls"
"go.opentelemetry.io/collector/consumer/consumertest"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/receiver/receivertest"
Expand Down Expand Up @@ -1640,3 +1646,51 @@ scrape_configs:
require.Contains(t, gotUA, set.BuildInfo.Command)
require.Contains(t, gotUA, set.BuildInfo.Version)
}

func TestConfigureSDHTTPClientConfigFromTA(t *testing.T) {
ta := &TargetAllocator{}
ta.TLSSetting = configtls.ClientConfig{
InsecureSkipVerify: true,
ServerName: "test.server",
Config: configtls.Config{
CAFile: "/path/to/ca",
CertFile: "/path/to/cert",
KeyFile: "/path/to/key",
CAPem: configopaque.String(base64.StdEncoding.EncodeToString([]byte("test-ca"))),
CertPem: configopaque.String(base64.StdEncoding.EncodeToString([]byte("test-cert"))),
KeyPem: configopaque.String(base64.StdEncoding.EncodeToString([]byte("test-key"))),
MinVersion: "1.2",
MaxVersion: "1.3",
},
}
ta.ProxyURL = "http:https://proxy.test"

httpSD := &promHTTP.SDConfig{RefreshInterval: model.Duration(30 * time.Second)}

err := configureSDHTTPClientConfigFromTA(httpSD, ta)

assert.NoError(t, err)

assert.Equal(t, false, httpSD.HTTPClientConfig.FollowRedirects)
assert.Equal(t, true, httpSD.HTTPClientConfig.TLSConfig.InsecureSkipVerify)
assert.Equal(t, "test.server", httpSD.HTTPClientConfig.TLSConfig.ServerName)
assert.Equal(t, "/path/to/ca", httpSD.HTTPClientConfig.TLSConfig.CAFile)
assert.Equal(t, "/path/to/cert", httpSD.HTTPClientConfig.TLSConfig.CertFile)
assert.Equal(t, "/path/to/key", httpSD.HTTPClientConfig.TLSConfig.KeyFile)
assert.Equal(t, "test-ca", httpSD.HTTPClientConfig.TLSConfig.CA)
assert.Equal(t, "test-cert", httpSD.HTTPClientConfig.TLSConfig.Cert)
assert.Equal(t, commonconfig.Secret("test-key"), httpSD.HTTPClientConfig.TLSConfig.Key)
assert.Equal(t, commonconfig.TLSVersions["TLS12"], httpSD.HTTPClientConfig.TLSConfig.MinVersion)
assert.Equal(t, commonconfig.TLSVersions["TLS13"], httpSD.HTTPClientConfig.TLSConfig.MaxVersion)

parsedProxyURL, _ := url.Parse("http:https://proxy.test")
assert.Equal(t, commonconfig.URL{URL: parsedProxyURL}, httpSD.HTTPClientConfig.ProxyURL)

// Test case with empty TargetAllocator
emptyTA := &TargetAllocator{}
emptyHTTPSD := &promHTTP.SDConfig{RefreshInterval: model.Duration(30 * time.Second)}

err = configureSDHTTPClientConfigFromTA(emptyHTTPSD, emptyTA)

assert.NoError(t, err)
}

0 comments on commit 30ed470

Please sign in to comment.