From 41fd3e1de3198110a02869d59d2d89acfa66164e Mon Sep 17 00:00:00 2001 From: Julian Kleinhans Date: Tue, 13 Dec 2016 16:12:05 +0100 Subject: [PATCH] #45 Remove obsolete PreProcessor --- src/StackFormation/Preprocessor.php | 228 ---------------------- tests/StackFormation/PreprocessorTest.php | 90 --------- 2 files changed, 318 deletions(-) delete mode 100644 src/StackFormation/Preprocessor.php delete mode 100644 tests/StackFormation/PreprocessorTest.php diff --git a/src/StackFormation/Preprocessor.php b/src/StackFormation/Preprocessor.php deleted file mode 100644 index f1bd545..0000000 --- a/src/StackFormation/Preprocessor.php +++ /dev/null @@ -1,228 +0,0 @@ -stripComments($json); - $json = $this->parseRefInDoubleQuotedStrings($json); - $json = $this->expandPort($json); - $json = $this->injectFilecontent($json, $basePath); - $json = $this->base64encodedJson($json); - $json = $this->split($json); - $json = $this->replaceFnGetAttr($json); - $json = $this->replaceRef($json); - $json = $this->replaceMarkers($json); - return $json; - } - - protected function stripComments($json) - { - // there's a problem with '"http://example.com"' being converted to '"http:' - // $json = preg_replace('~//[^\r\n]*|/\*.*?\*/~s', '', $json); - - // there's a problem with "arn:aws:s3:::my-bucket/*" - // $json = preg_replace('~/\*.*?\*/~s', '', $json); - - // quick workaround: don't allow quotes - $json = preg_replace('~/\*[^"]*?\*/~s', '', $json); - return $json; - } - - protected function parseRefInDoubleQuotedStrings($json) - { - $json = preg_replace_callback( - '/"([^"]*){Ref:(.+?)}([^"]*)"/', - function ($matches) { - $snippet = $matches[0]; - $snippet = trim($snippet, '"'); - $pieces = preg_split('/({Ref:.+})/U', $snippet, -1, PREG_SPLIT_DELIM_CAPTURE); - $processedPieces = []; - foreach ($pieces as $piece) { - if (empty($piece)) { - continue; - } - if (substr($piece, 0, 5) == '{Ref:') { - $processedPieces[] = preg_replace('/{Ref:(.+)}/', '{"Ref":"$1"}', $piece); - } else { - $processedPieces[] = '"' . $piece . '"'; - } - } - return '{"Fn::Join": ["", [' . implode(', ', $processedPieces) . ']]}'; - }, - $json - ); - return $json; - } - - protected function replaceMarkers($json) - { - $markers = [ - '###TIMESTAMP###' => date(\DateTime::ISO8601), - ]; - $json = str_replace(array_keys($markers), array_values($markers), $json); - - $json = preg_replace_callback( - '/###ENV:([^#:]+)###/', - function ($matches) { - if (!getenv($matches[1])) { - throw new \Exception("Environment variable '{$matches[1]}' not found"); - } - - return getenv($matches[1]); - }, - $json - ); - - return $json; - } - - protected function expandPort($jsonString) - { - return preg_replace('/([\{,]\s*)"Port"\s*:\s*"(\d+)"/', '\1"FromPort": "\2", "ToPort": "\2"', $jsonString); - } - - protected function injectFilecontent($jsonString, $basePath) - { - $jsonString = preg_replace_callback( - '/(\s*)(.*){\s*"Fn::FileContent(Unpretty|TrimLines|Minify)?"\s*:\s*"(.+?)"\s*}/', - function (array $matches) use ($basePath) { - $file = $basePath . '/' . end($matches); - if (!is_file($file)) { - throw new FileNotFoundException("File '$file' not found"); - } - $ext = pathinfo($file, PATHINFO_EXTENSION); - if ($matches[3] == 'Minify' && $ext != 'js') { - throw new \Exception('Fn::FileContentMinify is only supported for *.js files. (File: ' . $file . ')'); - } - - $fileContent = file_get_contents($file); - $fileContent = $this->injectInclude($fileContent, dirname(realpath($file))); - - if ($ext === 'js') { - if ($matches[3] == 'Minify') { - $fileContent = \JShrink\Minifier::minify($fileContent, ['flaggedComments' => false]); - } - - $size = strlen($fileContent); - if ($size > self::MAX_JS_FILE_INCLUDE_SIZE) { - // this is assuming you are uploading an inline JS file to AWS Lambda - throw new \Exception(sprintf("JS file is larger than %s bytes (actual size: %s bytes)", self::MAX_JS_FILE_INCLUDE_SIZE, $size)); - } - } - - // TODO: this isn't optimal. Why are we processing this here in between? - $fileContent = $this->base64encodedJson($fileContent); - - $lines = explode("\n", $fileContent); - foreach ($lines as $key => &$line) { - if ($matches[3] == 'TrimLines') { - $line = trim($line); - if (empty($line)) { - unset($lines[$key]); - } - } - $line .= "\n"; - } - - if ($matches[3] == 'Unpretty') { - $result = ' {"Fn::Join": ["", ' . json_encode(array_values($lines)) . ']}'; - } else { - $result = ' {"Fn::Join": ["", ' . json_encode(array_values($lines), JSON_PRETTY_PRINT) . ']}'; - } - - $whitespace = trim($matches[1], "\n"); - $result = str_replace("\n", "\n" . $whitespace, $result); - - return $matches[1] . $matches[2] . $result; - }, - $jsonString - ); - - return $jsonString; - } - - protected function split($jsonString) - { - return preg_replace_callback( - '/(\s*)(.*){\s*"Fn::Split"\s*:\s*\[\s*"(.*?)"\s*,\s*"(.*?)"\s*\]\s*}/', - function (array $matches) { - if (empty($matches[3])) { - throw new \Exception('Delimiter cannot be empty'); - } - if (empty($matches[4])) { - throw new \Exception('String cannot be empty'); - } - $pieces = explode($matches[3], $matches[4]); - return $matches[1] . $matches[2] . '["' . implode('", "', $pieces).'"]'; - }, - $jsonString - ); - } - - protected function injectInclude($string, $basePath) - { - return preg_replace_callback( - '/###INCLUDE:(.+)/', - function (array $matches) use ($basePath) { - $file = $basePath . '/' . $matches[1]; - - # Parse ENV vars in file names... - $file = $this->replaceMarkers($file); - - if (!is_file($file)) { - throw new FileNotFoundException("File $file not found"); - } - - $fileContent = file_get_contents($file); - $fileContent = trim($fileContent); - - return $fileContent; - }, - $string - ); - } - - protected function replaceRef($jsonString) - { - return preg_replace('/\{\s*Ref\s*:\s*([a-zA-Z0-9:]+?)\s*\}/', '", {"Ref": "$1"}, "', $jsonString); - } - - /** - * @param $jsonString - * @return mixed - */ - protected function base64encodedJson($jsonString) - { - $jsonString = preg_replace_callback( - '/###JSON###(.+?)######/', - function (array $m) { - return '", ' . base64_decode($m[1]) . ', "'; - }, - $jsonString - ); - return $jsonString; - } - - /** - * transforms {Fn::GetAtt:[resource,attribute]} to inline statement - * - * @param $jsonstring - * @return mixed - */ - protected function replaceFnGetAttr($jsonstring) - { - return preg_replace('/\{\s*Fn\s*::\s*GetAtt\s*:\s*\[\s*([a-zA-Z0-9:]+?)\s*,\s*([a-zA-Z0-9:]+?)\s*\]\s*\}/', - '", {"Fn::GetAtt": ["$1", "$2"]} ,"', $jsonstring); - } -} diff --git a/tests/StackFormation/PreprocessorTest.php b/tests/StackFormation/PreprocessorTest.php deleted file mode 100644 index ceb116e..0000000 --- a/tests/StackFormation/PreprocessorTest.php +++ /dev/null @@ -1,90 +0,0 @@ -preprocessor = new \StackFormation\Preprocessor(); - } - - /** - * @param string $fixtureDirectory - * @throws \Exception - * @test - * @dataProvider processFileDataProvider - */ - public function processFile($fixtureDirectory) - { - $prefix = FIXTURE_ROOT . 'Preprocessor/'; - $prefix .= $fixtureDirectory . '/'; - $templatePath = $prefix . 'blueprint/input.template'; - $fileContent = file_get_contents($templatePath); - $this->assertEquals( - $this->preprocessor->processJson($fileContent, dirname($templatePath)), - file_get_contents($prefix. 'blueprint/expected.template') - ); - } - - public function processFileDataProvider() - { - $prefix = FIXTURE_ROOT . 'Preprocessor/'; - $directories = glob($prefix.'*', GLOB_ONLYDIR); - array_walk($directories, function(&$directory) use ($prefix) { - $directory = [ str_replace($prefix, '', $directory)]; - }); - return $directories; - } - - /** - * @param string $inputJson - * @param string $expectedJson - * @throws \Exception - * @test - * @dataProvider processJsonDataProvider - */ - public function processJson($inputJson, $expectedJson) - { - $this->assertEquals( - $this->preprocessor->processJson($inputJson, sys_get_temp_dir()), - $expectedJson - ); - } - - /** - * @return array - */ - public function processJsonDataProvider() - { - return [ - // strip comments - ['Hello World /* Comment */', 'Hello World '], - ['Hello World /* Comment */ Hello World', 'Hello World Hello World'], - ['/* Comment */ Hello World', ' Hello World'], - // support single quotes - ["Hello World /* 'Comment' */ Hello World", 'Hello World Hello World'], - // ignore double quotes - ['Hello World /* "Comment" */', 'Hello World /* "Comment" */'], - ['Hello World /* "Comment */', 'Hello World /* "Comment */'], - // multi-line - ["Hello World /* Multiline\nComment */ Hello World", 'Hello World Hello World'], - // parseRefInDoubleQuotedStrings - ['"Key": "Name", "Value": "magento-{Ref:Environment}-{Ref:Build}-instance"', '"Key": "Name", "Value": {"Fn::Join": ["", ["magento-", {"Ref":"Environment"}, "-", {"Ref":"Build"}, "-instance"]]}'], - // expandPort - ['{"IpProtocol": "tcp", "Port": "80", "CidrIp": "1.2.3.4/32"},', '{"IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "1.2.3.4/32"},'], - // replace ref - ["WAIT_CONDITION_HANDLE='{Ref:WaitConditionHandle}'", "WAIT_CONDITION_HANDLE='\", {\"Ref\": \"WaitConditionHandle\"}, \"'"], - ["REGION='{Ref:AWS::Region}'", "REGION='\", {\"Ref\": \"AWS::Region\"}, \"'"], - ['"Aliases": { "Fn::Split": [",", "a,b,c"] }', '"Aliases": ["a", "b", "c"]'], - ['"Aliases": { "Fn::Split": ["+", "a,b,c"] }', '"Aliases": ["a,b,c"]'], - ['"Aliases": { "Fn::Split": ["+", "a+b+c"] }', '"Aliases": ["a", "b", "c"]'], - ]; - } -}