Exception
10 months ago
AbstractMonitoringMiddleware.php
10 months ago
ApiCallAttemptMonitoringMiddleware.php
10 months ago
ApiCallMonitoringMiddleware.php
10 months ago
Configuration.php
10 months ago
ConfigurationInterface.php
10 months ago
ConfigurationProvider.php
10 months ago
MonitoringMiddlewareInterface.php
10 months ago
ConfigurationProvider.php
237 lines
| 1 | <?php |
| 2 | namespace Aws\ClientSideMonitoring; |
| 3 | |
| 4 | use Aws\AbstractConfigurationProvider; |
| 5 | use Aws\CacheInterface; |
| 6 | use Aws\ClientSideMonitoring\Exception\ConfigurationException; |
| 7 | use Aws\ConfigurationProviderInterface; |
| 8 | use GuzzleHttp\Promise; |
| 9 | use GuzzleHttp\Promise\PromiseInterface; |
| 10 | |
| 11 | /** |
| 12 | * A configuration provider is a function that accepts no arguments and returns |
| 13 | * a promise that is fulfilled with a {@see \Aws\ClientSideMonitoring\ConfigurationInterface} |
| 14 | * or rejected with an {@see \Aws\ClientSideMonitoring\Exception\ConfigurationException}. |
| 15 | * |
| 16 | * <code> |
| 17 | * use Aws\ClientSideMonitoring\ConfigurationProvider; |
| 18 | * $provider = ConfigurationProvider::defaultProvider(); |
| 19 | * // Returns a ConfigurationInterface or throws. |
| 20 | * $config = $provider()->wait(); |
| 21 | * </code> |
| 22 | * |
| 23 | * Configuration providers can be composed to create configuration using |
| 24 | * conditional logic that can create different configurations in different |
| 25 | * environments. You can compose multiple providers into a single provider using |
| 26 | * {@see Aws\ClientSideMonitoring\ConfigurationProvider::chain}. This function |
| 27 | * accepts providers as variadic arguments and returns a new function that will |
| 28 | * invoke each provider until a successful configuration is returned. |
| 29 | * |
| 30 | * <code> |
| 31 | * // First try an INI file at this location. |
| 32 | * $a = ConfigurationProvider::ini(null, '/path/to/file.ini'); |
| 33 | * // Then try an INI file at this location. |
| 34 | * $b = ConfigurationProvider::ini(null, '/path/to/other-file.ini'); |
| 35 | * // Then try loading from environment variables. |
| 36 | * $c = ConfigurationProvider::env(); |
| 37 | * // Combine the three providers together. |
| 38 | * $composed = ConfigurationProvider::chain($a, $b, $c); |
| 39 | * // Returns a promise that is fulfilled with a configuration or throws. |
| 40 | * $promise = $composed(); |
| 41 | * // Wait on the configuration to resolve. |
| 42 | * $config = $promise->wait(); |
| 43 | * </code> |
| 44 | */ |
| 45 | class ConfigurationProvider extends AbstractConfigurationProvider |
| 46 | implements ConfigurationProviderInterface |
| 47 | { |
| 48 | const DEFAULT_CLIENT_ID = ''; |
| 49 | const DEFAULT_ENABLED = false; |
| 50 | const DEFAULT_HOST = '127.0.0.1'; |
| 51 | const DEFAULT_PORT = 31000; |
| 52 | const ENV_CLIENT_ID = 'AWS_CSM_CLIENT_ID'; |
| 53 | const ENV_ENABLED = 'AWS_CSM_ENABLED'; |
| 54 | const ENV_HOST = 'AWS_CSM_HOST'; |
| 55 | const ENV_PORT = 'AWS_CSM_PORT'; |
| 56 | const ENV_PROFILE = 'AWS_PROFILE'; |
| 57 | |
| 58 | public static $cacheKey = 'aws_cached_csm_config'; |
| 59 | |
| 60 | protected static $interfaceClass = ConfigurationInterface::class; |
| 61 | protected static $exceptionClass = ConfigurationException::class; |
| 62 | |
| 63 | /** |
| 64 | * Create a default config provider that first checks for environment |
| 65 | * variables, then checks for a specified profile in the environment-defined |
| 66 | * config file location (env variable is 'AWS_CONFIG_FILE', file location |
| 67 | * defaults to ~/.aws/config), then checks for the "default" profile in the |
| 68 | * environment-defined config file location, and failing those uses a default |
| 69 | * fallback set of configuration options. |
| 70 | * |
| 71 | * This provider is automatically wrapped in a memoize function that caches |
| 72 | * previously provided config options. |
| 73 | * |
| 74 | * @param array $config |
| 75 | * |
| 76 | * @return callable |
| 77 | */ |
| 78 | public static function defaultProvider(array $config = []) |
| 79 | { |
| 80 | $configProviders = [self::env()]; |
| 81 | if ( |
| 82 | !isset($config['use_aws_shared_config_files']) |
| 83 | || $config['use_aws_shared_config_files'] != false |
| 84 | ) { |
| 85 | $configProviders[] = self::ini(); |
| 86 | } |
| 87 | $configProviders[] = self::fallback(); |
| 88 | |
| 89 | $memo = self::memoize( |
| 90 | call_user_func_array([ConfigurationProvider::class, 'chain'], $configProviders) |
| 91 | ); |
| 92 | |
| 93 | if (isset($config['csm']) && $config['csm'] instanceof CacheInterface) { |
| 94 | return self::cache($memo, $config['csm'], self::$cacheKey); |
| 95 | } |
| 96 | |
| 97 | return $memo; |
| 98 | } |
| 99 | |
| 100 | /** |
| 101 | * Provider that creates CSM config from environment variables. |
| 102 | * |
| 103 | * @return callable |
| 104 | */ |
| 105 | public static function env() |
| 106 | { |
| 107 | return function () { |
| 108 | // Use credentials from environment variables, if available |
| 109 | $enabled = getenv(self::ENV_ENABLED); |
| 110 | if ($enabled !== false) { |
| 111 | return Promise\Create::promiseFor( |
| 112 | new Configuration( |
| 113 | $enabled, |
| 114 | getenv(self::ENV_HOST) ?: self::DEFAULT_HOST, |
| 115 | getenv(self::ENV_PORT) ?: self::DEFAULT_PORT, |
| 116 | getenv(self:: ENV_CLIENT_ID) ?: self::DEFAULT_CLIENT_ID |
| 117 | ) |
| 118 | ); |
| 119 | } |
| 120 | |
| 121 | return self::reject('Could not find environment variable CSM config' |
| 122 | . ' in ' . self::ENV_ENABLED. '/' . self::ENV_HOST . '/' |
| 123 | . self::ENV_PORT . '/' . self::ENV_CLIENT_ID); |
| 124 | }; |
| 125 | } |
| 126 | |
| 127 | /** |
| 128 | * Fallback config options when other sources are not set. |
| 129 | * |
| 130 | * @return callable |
| 131 | */ |
| 132 | public static function fallback() |
| 133 | { |
| 134 | return function() { |
| 135 | return Promise\Create::promiseFor( |
| 136 | new Configuration( |
| 137 | self::DEFAULT_ENABLED, |
| 138 | self::DEFAULT_HOST, |
| 139 | self::DEFAULT_PORT, |
| 140 | self::DEFAULT_CLIENT_ID |
| 141 | ) |
| 142 | ); |
| 143 | }; |
| 144 | } |
| 145 | |
| 146 | /** |
| 147 | * Config provider that creates config using a config file whose location |
| 148 | * is specified by an environment variable 'AWS_CONFIG_FILE', defaulting to |
| 149 | * ~/.aws/config if not specified |
| 150 | * |
| 151 | * @param string|null $profile Profile to use. If not specified will use |
| 152 | * the "default" profile. |
| 153 | * @param string|null $filename If provided, uses a custom filename rather |
| 154 | * than looking in the default directory. |
| 155 | * |
| 156 | * @return callable |
| 157 | */ |
| 158 | public static function ini($profile = null, $filename = null) |
| 159 | { |
| 160 | $filename = $filename ?: (self::getDefaultConfigFilename()); |
| 161 | $profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'aws_csm'); |
| 162 | |
| 163 | return function () use ($profile, $filename) { |
| 164 | if (!@is_readable($filename)) { |
| 165 | return self::reject("Cannot read CSM config from $filename"); |
| 166 | } |
| 167 | $data = \Aws\parse_ini_file($filename, true); |
| 168 | if ($data === false) { |
| 169 | return self::reject("Invalid config file: $filename"); |
| 170 | } |
| 171 | if (!isset($data[$profile])) { |
| 172 | return self::reject("'$profile' not found in config file"); |
| 173 | } |
| 174 | if (!isset($data[$profile]['csm_enabled'])) { |
| 175 | return self::reject("Required CSM config values not present in |
| 176 | INI profile '{$profile}' ({$filename})"); |
| 177 | } |
| 178 | |
| 179 | // host is optional |
| 180 | if (empty($data[$profile]['csm_host'])) { |
| 181 | $data[$profile]['csm_host'] = self::DEFAULT_HOST; |
| 182 | } |
| 183 | |
| 184 | // port is optional |
| 185 | if (empty($data[$profile]['csm_port'])) { |
| 186 | $data[$profile]['csm_port'] = self::DEFAULT_PORT; |
| 187 | } |
| 188 | |
| 189 | // client_id is optional |
| 190 | if (empty($data[$profile]['csm_client_id'])) { |
| 191 | $data[$profile]['csm_client_id'] = self::DEFAULT_CLIENT_ID; |
| 192 | } |
| 193 | |
| 194 | return Promise\Create::promiseFor( |
| 195 | new Configuration( |
| 196 | $data[$profile]['csm_enabled'], |
| 197 | $data[$profile]['csm_host'], |
| 198 | $data[$profile]['csm_port'], |
| 199 | $data[$profile]['csm_client_id'] |
| 200 | ) |
| 201 | ); |
| 202 | }; |
| 203 | } |
| 204 | |
| 205 | /** |
| 206 | * Unwraps a configuration object in whatever valid form it is in, |
| 207 | * always returning a ConfigurationInterface object. |
| 208 | * |
| 209 | * @param mixed $config |
| 210 | * @return ConfigurationInterface |
| 211 | * @throws \InvalidArgumentException |
| 212 | */ |
| 213 | public static function unwrap($config) |
| 214 | { |
| 215 | if (is_callable($config)) { |
| 216 | $config = $config(); |
| 217 | } |
| 218 | if ($config instanceof PromiseInterface) { |
| 219 | $config = $config->wait(); |
| 220 | } |
| 221 | if ($config instanceof ConfigurationInterface) { |
| 222 | return $config; |
| 223 | } elseif (is_array($config) && isset($config['enabled'])) { |
| 224 | $client_id = isset($config['client_id']) ? $config['client_id'] |
| 225 | : self::DEFAULT_CLIENT_ID; |
| 226 | $host = isset($config['host']) ? $config['host'] |
| 227 | : self::DEFAULT_HOST; |
| 228 | $port = isset($config['port']) ? $config['port'] |
| 229 | : self::DEFAULT_PORT; |
| 230 | return new Configuration($config['enabled'], $host, $port, $client_id); |
| 231 | } |
| 232 | |
| 233 | throw new \InvalidArgumentException('Not a valid CSM configuration ' |
| 234 | . 'argument.'); |
| 235 | } |
| 236 | } |
| 237 |