X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fconfig%2FEtcdConfig.php;h=6605c38d5a5924ec921d06c6cf7150d7f9c2d923;hb=faf7cc4a09848c538320bd2b9067b1a77c0a0183;hp=ae3df4996fba1a5bed932e854b3dfc33b764aced;hpb=e143e3ebe4f2a2b796179d33b2b366c852f74249;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/config/EtcdConfig.php b/includes/config/EtcdConfig.php index ae3df4996f..3811da325c 100644 --- a/includes/config/EtcdConfig.php +++ b/includes/config/EtcdConfig.php @@ -1,7 +1,5 @@ http->run( [ 'method' => 'GET', - 'url' => "{$this->protocol}://{$address}/v2/keys/{$this->directory}/", + 'url' => "{$this->protocol}://{$address}/v2/keys/{$this->directory}/?recursive=true", 'headers' => [ 'content-type' => 'application/json' ] ] ); @@ -243,28 +241,65 @@ class EtcdConfig implements Config, LoggerAwareInterface { empty( $terminalCodes[$rcode] ) ]; } + try { + return [ $this->parseResponse( $rbody ), null, false ]; + } catch ( EtcdConfigParseError $e ) { + return [ null, $e->getMessage(), false ]; + } + } + /** + * Parse a response body, throwing EtcdConfigParseError if there is a validation error + * + * @param string $rbody + * @return array + */ + protected function parseResponse( $rbody ) { $info = json_decode( $rbody, true ); - if ( $info === null || !isset( $info['node']['nodes'] ) ) { - return [ null, $rcode, "Unexpected JSON response; missing 'nodes' list.", false ]; + if ( $info === null ) { + throw new EtcdConfigParseError( "Error unserializing JSON response." ); + } + if ( !isset( $info['node'] ) || !is_array( $info['node'] ) ) { + throw new EtcdConfigParseError( + "Unexpected JSON response: Missing or invalid node at top level." ); } - $config = []; - foreach ( $info['node']['nodes'] as $node ) { + $this->parseDirectory( '', $info['node'], $config ); + return $config; + } + + /** + * Recursively parse a directory node and populate the array passed by + * reference, throwing EtcdConfigParseError if there is a validation error + * + * @param string $dirName The relative directory name + * @param array $dirNode The decoded directory node + * @param array &$config The output array + */ + protected function parseDirectory( $dirName, $dirNode, &$config ) { + if ( !isset( $dirNode['nodes'] ) ) { + throw new EtcdConfigParseError( + "Unexpected JSON response in dir '$dirName'; missing 'nodes' list." ); + } + if ( !is_array( $dirNode['nodes'] ) ) { + throw new EtcdConfigParseError( + "Unexpected JSON response in dir '$dirName'; 'nodes' is not an array." ); + } + + foreach ( $dirNode['nodes'] as $node ) { + $baseName = basename( $node['key'] ); + $fullName = $dirName === '' ? $baseName : "$dirName/$baseName"; if ( !empty( $node['dir'] ) ) { - continue; // skip directories - } + $this->parseDirectory( $fullName, $node, $config ); + } else { + $value = $this->unserialize( $node['value'] ); + if ( !is_array( $value ) || !array_key_exists( 'val', $value ) ) { + throw new EtcdConfigParseError( "Failed to parse value for '$fullName'." ); + } - $name = basename( $node['key'] ); - $value = $this->unserialize( $node['value'] ); - if ( !is_array( $value ) || !array_key_exists( 'val', $value ) ) { - return [ null, "Failed to parse value for '$name'.", false ]; + $config[$fullName] = $value['val']; } - - $config[$name] = $value['val']; } - - return [ $config, null, false ]; } /**