Skip to content
This repository was archived by the owner on Sep 12, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/StackFormation/Helper/Div.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,17 @@ public static function isProgramInstalled($program)
@exec('which ' . $program, $out, $return);
return $return === 0;
}

/**
* @param string $string
* @return bool
*/
public static function isJson($string) {
$string = trim($string);

// TODO just a workaround to check if the string is a valid JSON
// we could not check that with json_decode because, it could be that the JSON file has some comments inside
// and the StringPreProcessor/StripComments is invoked after that check!!
return preg_match('/\A\{(.*)/', $string);
}
}
8 changes: 8 additions & 0 deletions src/StackFormation/Helper/Pipeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ public function addStage(callable $stage)
return $this;
}

/**
* @return \callable[]
*/
public function getStages()
{
return $this->stages;
}

/**
* Process the payload.
*
Expand Down
82 changes: 82 additions & 0 deletions src/StackFormation/PreProcessor/RecursiveArrayObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace StackFormation\PreProcessor;

/**
* Class RecursiveArrayObject
*
* PHP's ArrayObject isn't recursive (nested arrays will remain regular arrays),
* this one will transform nested arrays into ArrayObjects...
*/
class RecursiveArrayObject extends \ArrayObject {

/**
* @param null $input
* @param int $flags
* @param string $iterator_class
*/
public function __construct($input = null, $flags = self::ARRAY_AS_PROPS, $iterator_class = "ArrayIterator") {
foreach ($input as $k=>$v) {
$this->__set($k, $v);
}
}

/**
* @param string $name
* @param mixed $value
*/
public function __set($name, $value){
if (is_array($value) || is_object($value)) {
$this->offsetSet($name, (new self($value)));
} else {
$this->offsetSet($name, $value);
}
}

/**
* @param string $name
* @return mixed
*/
public function __get($name){
if ($this->offsetExists($name)) {
return $this->offsetGet($name);
} elseif (array_key_exists($name, $this)) {
return $this[$name];
} else {
throw new \InvalidArgumentException(sprintf('$this have not prop `%s`',$name));
}
}

/**
* @return array
*/
public function getArrayCopy()
{
$array = parent::getArrayCopy();
$assocArray = false;
foreach ($array as $key => $value) {
if (is_string($key)) {
$assocArray = true;
}
if ($value instanceof RecursiveArrayObject) {
$array[$key] = $value->getArrayCopy();
}
}
return $assocArray ? $array : array_values($array);
}

/**
* @param string $name
* @return bool
*/
public function __isset($name){
return array_key_exists($name, $this);
}

/**
* @param string $name
*/
public function __unset($name){
unset($this[$name]);
}
}
44 changes: 44 additions & 0 deletions src/StackFormation/PreProcessor/Rootline.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace StackFormation\PreProcessor;

/**
* Class Rootline
*
* The rootline shows gives the transformers access to the parent objects (all generations)
* since sometimes you need to change things outside of the current value (e.g. when replacing the whole node)
*/
class Rootline extends \ArrayObject {

/**
* @return array
*/
protected function getKeys() {
return array_keys($this->getArrayCopy());
}

/**
* @param $index
* @return mixed
*/
public function indexGet($index) {
$keys = $this->getKeys();
return $this->offsetGet($keys[$index]);
}

public function removeLast() {
$keys = $this->getKeys();

// TODO
@$this->offsetUnset($keys[$this->count()]);
}

/**
* @param int $generation
* @return mixed
*/
public function parent($generation = 1) {
$keys = $this->getKeys();
return $this->offsetGet($keys[$this->count() - $generation]);
}
}
38 changes: 38 additions & 0 deletions src/StackFormation/PreProcessor/RootlineItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace StackFormation\PreProcessor;

/**
* Class RootlineItem
*
* Since you not only need the reference to the parent(s) but also their key in relation to their parent
* (e.g. in case you need to delete them), this rootline item represents the item itself (value) and the position (key)
*/
class RootlineItem {

protected $key;
protected $value;

/**
* @param string $key
* @param mixed $value
*/
public function __construct($key, $value) {
$this->key = $key;
$this->value = $value;
}

/**
* @return string
*/
public function getKey() {
return $this->key;
}

/**
* @return mixed
*/
public function getValue() {
return $this->value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace StackFormation\PreProcessor\Stage;

abstract class AbstractStringPreProcessorStage
{
protected $stringPreProcessor; // reference to parent

/**
* @param \StackFormation\PreProcessor\StringPreProcessor $stringPreProcessor
*/
public function __construct(\StackFormation\PreProcessor\StringPreProcessor $stringPreProcessor) {
$this->stringPreProcessor = $stringPreProcessor;
}

/**
* @param string $content
* @throws \StackFormation\Exception\StringPreProcessorException
*/
public function __invoke($content)
{
try {
return $this->invoke($content);
} catch (\Exception $e) {

throw new \Exception('TODO create StringPreProcessorException');
// TODO
//throw new \StackFormation\Exception\StringPreProcessorException($content, $e);
}
}

/**
* @param string $content
*/
abstract function invoke($content);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace StackFormation\PreProcessor\Stage;

use StackFormation\PreProcessor\Rootline;

abstract class AbstractTreePreProcessorStage
{
protected $treePreProcessor;
protected $basePath;

/**
* @param \StackFormation\PreProcessor\TreePreProcessor $treePreProcessor
* @param string $basePath
*/
public function __construct(\StackFormation\PreProcessor\TreePreProcessor $treePreProcessor, $basePath = '') {
$this->treePreProcessor = $treePreProcessor;
$this->basePath = $basePath;
}

public function __invoke() {}

/**
* @param string $path
* @param string $value
* @param Rootline $rootLineReferences
* @return mixed
*/
abstract function invoke($path, $value, Rootline $rootLineReferences);
}
24 changes: 24 additions & 0 deletions src/StackFormation/PreProcessor/Stage/String/StripComments.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace StackFormation\PreProcessor\Stage\String;

use StackFormation\PreProcessor\Stage\AbstractStringPreProcessorStage;

class StripComments extends AbstractStringPreProcessorStage {

/**
* @param string $content
* @return string
*/
public function invoke($content)
{
// there's a problem with '"http://example.com"' being converted to '"http:'
// $content = preg_replace('~//[^\r\n]*|/\*.*?\*/~s', '', $content);

// there's a problem with "arn:aws:s3:::my-bucket/*"
// $content = preg_replace('~/\*.*?\*/~s', '', $content);

// quick workaround: don't allow quotes
return preg_replace('~/\*[^"]*?\*/~s', '', $content);
}
}
43 changes: 43 additions & 0 deletions src/StackFormation/PreProcessor/Stage/Tree/ExpandCidrIp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace StackFormation\PreProcessor\Stage\Tree;

use StackFormation\PreProcessor\Stage\AbstractTreePreProcessorStage;
use StackFormation\PreProcessor\Rootline;
use StackFormation\PreProcessor\RootlineItem;
use StackFormation\PreProcessor\RecursiveArrayObject;

class ExpandCidrIp extends AbstractTreePreProcessorStage
{
/**
* This one will resolve comma-separated list of IP addresses
*
* @param string $path
* @param string $value
* @param Rootline $rootLineReferences
* @return bool
*/
function invoke($path, $value, Rootline $rootLineReferences) {
if (!preg_match('+/SecurityGroupIngress/.*/CidrIp+', $path) || strpos($value, ',') === false) {
return false; // indicate that nothing has been touched
}

$parentRootlineItem = $rootLineReferences->parent(1); /* @var $parentRootlineItem RootlineItem */
$parent = $parentRootlineItem->getValue(); /* @var $parent RecursiveArrayObject */

$grandParentRootlineItem = $rootLineReferences->parent(2); /* @var $grandParentRootlineItem RootlineItem */
$grandParent = $grandParentRootlineItem->getValue(); /* @var $grandParent RecursiveArrayObject */

// remove original item
$grandParent->offsetUnset($parentRootlineItem->getKey());

// add a new line for every csl item
foreach (explode(',', $value) as $cidrIp) {
$newItem = clone $parent;
$newItem->CidrIp = $cidrIp;
$grandParent->append($newItem);
}

return true; // indicate that something has changed
}
}
45 changes: 45 additions & 0 deletions src/StackFormation/PreProcessor/Stage/Tree/ExpandCslPort.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace StackFormation\PreProcessor\Stage\Tree;

use StackFormation\PreProcessor\Stage\AbstractTreePreProcessorStage;
use StackFormation\PreProcessor\Rootline;
use StackFormation\PreProcessor\RootlineItem;
use StackFormation\PreProcessor\RecursiveArrayObject;

class ExpandCslPort extends AbstractTreePreProcessorStage
{
/**
* This one converts "Port" into "FromPort" and "ToPort" and will resolve comma-separated lists
*
* @param string $path
* @param string $value
* @param Rootline $rootLineReferences
* @return bool
*/
function invoke($path, $value, Rootline $rootLineReferences) {
if (!preg_match('+/SecurityGroupIngress/.*/Port$+', $path)) {
return false; // indicate that nothing has been touched
}

$parentRootlineItem = $rootLineReferences->parent(1); /* @var $parentRootlineItem RootlineItem */
$parent = $parentRootlineItem->getValue(); /* @var $parent RecursiveArrayObject */

$grandParentRootlineItem = $rootLineReferences->parent(2); /* @var $grandParentRootlineItem RootlineItem */
$grandParent = $grandParentRootlineItem->getValue(); /* @var $grandParent RecursiveArrayObject */

// remove original item
$grandParent->offsetUnset($parentRootlineItem->getKey());

// add a new line for every csl item
foreach (explode(',', $value) as $port) {
$newItem = clone $parent;
$newItem->FromPort = $port;
$newItem->ToPort = $port;
$newItem->offsetUnset('Port');
$grandParent->append($newItem);
}

return true; // indicate that something has changed
}
}
Loading