...

Source file src/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig/envconfig.go

Documentation: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/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  
    18  package envconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig"
    19  
    20  import (
    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.
    34  type ConfigFn func(*EnvOptionsReader)
    35  
    36  // EnvOptionsReader reads the required environment variables.
    37  type EnvOptionsReader struct {
    38  	GetEnv    func(string) string
    39  	ReadFile  func(string) ([]byte, error)
    40  	Namespace string
    41  }
    42  
    43  // Apply runs every ConfigFn.
    44  func (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.
    53  func (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.
    59  func 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.
    68  func 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.
    78  func 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.
    92  func 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.
   101  func 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.
   115  func 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.
   134  func 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  
   160  func keyWithNamespace(ns, key string) string {
   161  	if ns == "" {
   162  		return key
   163  	}
   164  	return fmt.Sprintf("%s_%s", ns, key)
   165  }
   166  
   167  func 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  
   196  func 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  }
   203  

View as plain text