code.dwrz.net

Go monorepo.
Log | Files | Refs

config.go (7142B)


      1 package config
      2 
      3 import (
      4 	"context"
      5 
      6 	"github.com/aws/aws-sdk-go-v2/aws"
      7 )
      8 
      9 // defaultLoaders are a slice of functions that will read external configuration
     10 // sources for configuration values. These values are read by the AWSConfigResolvers
     11 // using interfaces to extract specific information from the external configuration.
     12 var defaultLoaders = []loader{
     13 	loadEnvConfig,
     14 	loadSharedConfigIgnoreNotExist,
     15 }
     16 
     17 // defaultAWSConfigResolvers are a slice of functions that will resolve external
     18 // configuration values into AWS configuration values.
     19 //
     20 // This will setup the AWS configuration's Region,
     21 var defaultAWSConfigResolvers = []awsConfigResolver{
     22 	// Resolves the default configuration the SDK's aws.Config will be
     23 	// initialized with.
     24 	resolveDefaultAWSConfig,
     25 
     26 	// Sets the logger to be used. Could be user provided logger, and client
     27 	// logging mode.
     28 	resolveLogger,
     29 	resolveClientLogMode,
     30 
     31 	// Sets the HTTP client and configuration to use for making requests using
     32 	// the HTTP transport.
     33 	resolveHTTPClient,
     34 	resolveCustomCABundle,
     35 
     36 	// Sets the endpoint resolving behavior the API Clients will use for making
     37 	// requests to. Clients default to their own clients this allows overrides
     38 	// to be specified. The resolveEndpointResolver option is deprecated, but
     39 	// we still need to set it for backwards compatibility on config
     40 	// construction.
     41 	resolveEndpointResolver,
     42 	resolveEndpointResolverWithOptions,
     43 
     44 	// Sets the retry behavior API clients will use within their retry attempt
     45 	// middleware. Defaults to unset, allowing API clients to define their own
     46 	// retry behavior.
     47 	resolveRetryer,
     48 
     49 	// Sets the region the API Clients should use for making requests to.
     50 	resolveRegion,
     51 	resolveEC2IMDSRegion,
     52 	resolveDefaultRegion,
     53 
     54 	// Sets the additional set of middleware stack mutators that will custom
     55 	// API client request pipeline middleware.
     56 	resolveAPIOptions,
     57 
     58 	// Resolves the DefaultsMode that should be used by SDK clients. If this
     59 	// mode is set to DefaultsModeAuto.
     60 	//
     61 	// Comes after HTTPClient and CustomCABundle to ensure the HTTP client is
     62 	// configured if provided before invoking IMDS if mode is auto. Comes
     63 	// before resolving credentials so that those subsequent clients use the
     64 	// configured auto mode.
     65 	resolveDefaultsModeOptions,
     66 
     67 	// Sets the resolved credentials the API clients will use for
     68 	// authentication. Provides the SDK's default credential chain.
     69 	//
     70 	// Should probably be the last step in the resolve chain to ensure that all
     71 	// other configurations are resolved first in case downstream credentials
     72 	// implementations depend on or can be configured with earlier resolved
     73 	// configuration options.
     74 	resolveCredentials,
     75 
     76 	// Sets the resolved bearer authentication token API clients will use for
     77 	// httpBearerAuth authentication scheme.
     78 	resolveBearerAuthToken,
     79 }
     80 
     81 // A Config represents a generic configuration value or set of values. This type
     82 // will be used by the AWSConfigResolvers to extract
     83 //
     84 // General the Config type will use type assertion against the Provider interfaces
     85 // to extract specific data from the Config.
     86 type Config interface{}
     87 
     88 // A loader is used to load external configuration data and returns it as
     89 // a generic Config type.
     90 //
     91 // The loader should return an error if it fails to load the external configuration
     92 // or the configuration data is malformed, or required components missing.
     93 type loader func(context.Context, configs) (Config, error)
     94 
     95 // An awsConfigResolver will extract configuration data from the configs slice
     96 // using the provider interfaces to extract specific functionality. The extracted
     97 // configuration values will be written to the AWS Config value.
     98 //
     99 // The resolver should return an error if it it fails to extract the data, the
    100 // data is malformed, or incomplete.
    101 type awsConfigResolver func(ctx context.Context, cfg *aws.Config, configs configs) error
    102 
    103 // configs is a slice of Config values. These values will be used by the
    104 // AWSConfigResolvers to extract external configuration values to populate the
    105 // AWS Config type.
    106 //
    107 // Use AppendFromLoaders to add additional external Config values that are
    108 // loaded from external sources.
    109 //
    110 // Use ResolveAWSConfig after external Config values have been added or loaded
    111 // to extract the loaded configuration values into the AWS Config.
    112 type configs []Config
    113 
    114 // AppendFromLoaders iterates over the slice of loaders passed in calling each
    115 // loader function in order. The external config value returned by the loader
    116 // will be added to the returned configs slice.
    117 //
    118 // If a loader returns an error this method will stop iterating and return
    119 // that error.
    120 func (cs configs) AppendFromLoaders(ctx context.Context, loaders []loader) (configs, error) {
    121 	for _, fn := range loaders {
    122 		cfg, err := fn(ctx, cs)
    123 		if err != nil {
    124 			return nil, err
    125 		}
    126 
    127 		cs = append(cs, cfg)
    128 	}
    129 
    130 	return cs, nil
    131 }
    132 
    133 // ResolveAWSConfig returns a AWS configuration populated with values by calling
    134 // the resolvers slice passed in. Each resolver is called in order. Any resolver
    135 // may overwrite the AWS Configuration value of a previous resolver.
    136 //
    137 // If an resolver returns an error this method will return that error, and stop
    138 // iterating over the resolvers.
    139 func (cs configs) ResolveAWSConfig(ctx context.Context, resolvers []awsConfigResolver) (aws.Config, error) {
    140 	var cfg aws.Config
    141 
    142 	for _, fn := range resolvers {
    143 		if err := fn(ctx, &cfg, cs); err != nil {
    144 			return aws.Config{}, err
    145 		}
    146 	}
    147 
    148 	return cfg, nil
    149 }
    150 
    151 // ResolveConfig calls the provide function passing slice of configuration sources.
    152 // This implements the aws.ConfigResolver interface.
    153 func (cs configs) ResolveConfig(f func(configs []interface{}) error) error {
    154 	var cfgs []interface{}
    155 	for i := range cs {
    156 		cfgs = append(cfgs, cs[i])
    157 	}
    158 	return f(cfgs)
    159 }
    160 
    161 // LoadDefaultConfig reads the SDK's default external configurations, and
    162 // populates an AWS Config with the values from the external configurations.
    163 //
    164 // An optional variadic set of additional Config values can be provided as input
    165 // that will be prepended to the configs slice. Use this to add custom configuration.
    166 // The custom configurations must satisfy the respective providers for their data
    167 // or the custom data will be ignored by the resolvers and config loaders.
    168 //
    169 //	cfg, err := config.LoadDefaultConfig( context.TODO(),
    170 //	   WithSharedConfigProfile("test-profile"),
    171 //	)
    172 //	if err != nil {
    173 //	   panic(fmt.Sprintf("failed loading config, %v", err))
    174 //	}
    175 //
    176 // The default configuration sources are:
    177 // * Environment Variables
    178 // * Shared Configuration and Shared Credentials files.
    179 func LoadDefaultConfig(ctx context.Context, optFns ...func(*LoadOptions) error) (cfg aws.Config, err error) {
    180 	var options LoadOptions
    181 	for _, optFn := range optFns {
    182 		if err := optFn(&options); err != nil {
    183 			return aws.Config{}, err
    184 		}
    185 	}
    186 
    187 	// assign Load Options to configs
    188 	var cfgCpy = configs{options}
    189 
    190 	cfgCpy, err = cfgCpy.AppendFromLoaders(ctx, defaultLoaders)
    191 	if err != nil {
    192 		return aws.Config{}, err
    193 	}
    194 
    195 	cfg, err = cfgCpy.ResolveAWSConfig(ctx, defaultAWSConfigResolvers)
    196 	if err != nil {
    197 		return aws.Config{}, err
    198 	}
    199 
    200 	return cfg, nil
    201 }