src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

config.go (7580B)


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