...

Text file src/go.opentelemetry.io/otel/internal/shared/otlp/envconfig/envconfig.go.tmpl

Documentation: go.opentelemetry.io/otel/internal/shared/otlp/envconfig

     1// Code created by gotmpl. DO NOT MODIFY.
     2// source: internal/shared/otlp/envconfig/envconfig.go.tmpl
     3
     4// Copyright The OpenTelemetry Authors
     5//
     6// Licensed under the Apache License, Version 2.0 (the "License");
     7// you may not use this file except in compliance with the License.
     8// You may obtain a copy of the License at
     9//
    10//     http://www.apache.org/licenses/LICENSE-2.0
    11//
    12// Unless required by applicable law or agreed to in writing, software
    13// distributed under the License is distributed on an "AS IS" BASIS,
    14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15// See the License for the specific language governing permissions and
    16// limitations under the License.
    17
    18package envconfig
    19
    20import (
    21	"crypto/tls"
    22	"crypto/x509"
    23	"errors"
    24	"fmt"
    25	"net/url"
    26	"strconv"
    27	"strings"
    28	"time"
    29
    30	"go.opentelemetry.io/otel/internal/global"
    31)
    32
    33// ConfigFn is the generic function used to set a config.
    34type ConfigFn func(*EnvOptionsReader)
    35
    36// EnvOptionsReader reads the required environment variables.
    37type EnvOptionsReader struct {
    38	GetEnv    func(string) string
    39	ReadFile  func(string) ([]byte, error)
    40	Namespace string
    41}
    42
    43// Apply runs every ConfigFn.
    44func (e *EnvOptionsReader) Apply(opts ...ConfigFn) {
    45	for _, o := range opts {
    46		o(e)
    47	}
    48}
    49
    50// GetEnvValue gets an OTLP environment variable value of the specified key
    51// using the GetEnv function.
    52// This function prepends the OTLP specified namespace to all key lookups.
    53func (e *EnvOptionsReader) GetEnvValue(key string) (string, bool) {
    54	v := strings.TrimSpace(e.GetEnv(keyWithNamespace(e.Namespace, key)))
    55	return v, v != ""
    56}
    57
    58// WithString retrieves the specified config and passes it to ConfigFn as a string.
    59func WithString(n string, fn func(string)) func(e *EnvOptionsReader) {
    60	return func(e *EnvOptionsReader) {
    61		if v, ok := e.GetEnvValue(n); ok {
    62			fn(v)
    63		}
    64	}
    65}
    66
    67// WithBool returns a ConfigFn that reads the environment variable n and if it exists passes its parsed bool value to fn.
    68func WithBool(n string, fn func(bool)) ConfigFn {
    69	return func(e *EnvOptionsReader) {
    70		if v, ok := e.GetEnvValue(n); ok {
    71			b := strings.ToLower(v) == "true"
    72			fn(b)
    73		}
    74	}
    75}
    76
    77// WithDuration retrieves the specified config and passes it to ConfigFn as a duration.
    78func WithDuration(n string, fn func(time.Duration)) func(e *EnvOptionsReader) {
    79	return func(e *EnvOptionsReader) {
    80		if v, ok := e.GetEnvValue(n); ok {
    81			d, err := strconv.Atoi(v)
    82			if err != nil {
    83				global.Error(err, "parse duration", "input", v)
    84				return
    85			}
    86			fn(time.Duration(d) * time.Millisecond)
    87		}
    88	}
    89}
    90
    91// WithHeaders retrieves the specified config and passes it to ConfigFn as a map of HTTP headers.
    92func WithHeaders(n string, fn func(map[string]string)) func(e *EnvOptionsReader) {
    93	return func(e *EnvOptionsReader) {
    94		if v, ok := e.GetEnvValue(n); ok {
    95			fn(stringToHeader(v))
    96		}
    97	}
    98}
    99
   100// WithURL retrieves the specified config and passes it to ConfigFn as a net/url.URL.
   101func WithURL(n string, fn func(*url.URL)) func(e *EnvOptionsReader) {
   102	return func(e *EnvOptionsReader) {
   103		if v, ok := e.GetEnvValue(n); ok {
   104			u, err := url.Parse(v)
   105			if err != nil {
   106				global.Error(err, "parse url", "input", v)
   107				return
   108			}
   109			fn(u)
   110		}
   111	}
   112}
   113
   114// WithCertPool returns a ConfigFn that reads the environment variable n as a filepath to a TLS certificate pool. If it exists, it is parsed as a crypto/x509.CertPool and it is passed to fn.
   115func WithCertPool(n string, fn func(*x509.CertPool)) ConfigFn {
   116	return func(e *EnvOptionsReader) {
   117		if v, ok := e.GetEnvValue(n); ok {
   118			b, err := e.ReadFile(v)
   119			if err != nil {
   120				global.Error(err, "read tls ca cert file", "file", v)
   121				return
   122			}
   123			c, err := createCertPool(b)
   124			if err != nil {
   125				global.Error(err, "create tls cert pool")
   126				return
   127			}
   128			fn(c)
   129		}
   130	}
   131}
   132
   133// WithClientCert returns a ConfigFn that reads the environment variable nc and nk as filepaths to a client certificate and key pair. If they exists, they are parsed as a crypto/tls.Certificate and it is passed to fn.
   134func WithClientCert(nc, nk string, fn func(tls.Certificate)) ConfigFn {
   135	return func(e *EnvOptionsReader) {
   136		vc, okc := e.GetEnvValue(nc)
   137		vk, okk := e.GetEnvValue(nk)
   138		if !okc || !okk {
   139			return
   140		}
   141		cert, err := e.ReadFile(vc)
   142		if err != nil {
   143			global.Error(err, "read tls client cert", "file", vc)
   144			return
   145		}
   146		key, err := e.ReadFile(vk)
   147		if err != nil {
   148			global.Error(err, "read tls client key", "file", vk)
   149			return
   150		}
   151		crt, err := tls.X509KeyPair(cert, key)
   152		if err != nil {
   153			global.Error(err, "create tls client key pair")
   154			return
   155		}
   156		fn(crt)
   157	}
   158}
   159
   160func keyWithNamespace(ns, key string) string {
   161	if ns == "" {
   162		return key
   163	}
   164	return fmt.Sprintf("%s_%s", ns, key)
   165}
   166
   167func stringToHeader(value string) map[string]string {
   168	headersPairs := strings.Split(value, ",")
   169	headers := make(map[string]string)
   170
   171	for _, header := range headersPairs {
   172		n, v, found := strings.Cut(header, "=")
   173		if !found {
   174			global.Error(errors.New("missing '="), "parse headers", "input", header)
   175			continue
   176		}
   177		name, err := url.PathUnescape(n)
   178		if err != nil {
   179			global.Error(err, "escape header key", "key", n)
   180			continue
   181		}
   182		trimmedName := strings.TrimSpace(name)
   183		value, err := url.PathUnescape(v)
   184		if err != nil {
   185			global.Error(err, "escape header value", "value", v)
   186			continue
   187		}
   188		trimmedValue := strings.TrimSpace(value)
   189
   190		headers[trimmedName] = trimmedValue
   191	}
   192
   193	return headers
   194}
   195
   196func createCertPool(certBytes []byte) (*x509.CertPool, error) {
   197	cp := x509.NewCertPool()
   198	if ok := cp.AppendCertsFromPEM(certBytes); !ok {
   199		return nil, errors.New("failed to append certificate to the cert pool")
   200	}
   201	return cp, nil
   202}

View as plain text