Skip to content
This repository has been archived by the owner on Sep 12, 2022. It is now read-only.

Feature/#45 yml integration #50

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
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