Skip to content

Commit

Permalink
implement query activator (#13)
Browse files Browse the repository at this point in the history
* implement query activator

* update readme
  • Loading branch information
akondas authored Jun 2, 2024
1 parent 67e2466 commit 646de1a
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 9 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ Chaos Monkey for Symfony applications. Try to attack your running Symfony App.
- Repository (not implemented)
- Service (not implemented)

## Activators

- "Query param" - attack only if given query param is present (default `chaos`)

## Symfony

## How to use
Expand Down Expand Up @@ -62,10 +66,12 @@ chaos_monkey:
request:
enabled: true
priority: 0
activators:
query_param: false # if true then chaos monkey will be called only if given query param exist (with any value)
query_param_name: 'chaos'
```

## Roadmap
- [ ] Query param activator
- [ ] Flex recipe
- [ ] Metrics (for example `chaos_monkey_request_count_assaulted`)
- [ ] Assault profiles - each profile can contain different assaults
Expand Down
23 changes: 23 additions & 0 deletions src/Activator/QueryParamActivator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Chaos\Monkey\Symfony\Activator;

use Symfony\Component\HttpFoundation\Request;

final class QueryParamActivator
{
public function __construct(private readonly bool $enabled = false, private readonly string $paramName = 'chaos')
{
}

public function inChaos(Request $request): bool
{
if (!$this->enabled) {
return true;
}

return $request->query->has($this->paramName);
}
}
17 changes: 17 additions & 0 deletions src/DependencyInjection/ChaosMonkeyExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
* },
* watchers: array{
* request: array{enabled: bool, priority: int}
* },
* activators: array{
* query_param: bool,
* query_param_name: string
* }
* }
*/
Expand All @@ -39,6 +43,7 @@ public function load(array $configs, ContainerBuilder $container): void
$config = $this->processConfiguration($configuration, $configs);

$this->setChaosMonkeySettings($container, $config);
$this->setActivators($container, $config);
$this->enableWatchers($container, $config);
}

Expand Down Expand Up @@ -77,4 +82,16 @@ private function enableWatchers(ContainerBuilder $container, array $config): voi
]);
}
}

/**
* @param ConfigArray $config
*/
private function setActivators(ContainerBuilder $container, array $config): void
{
$queryParam = $container->getDefinition('chaos_monkey.activator.query_param');
$queryParam->setArguments([
'$enabled' => $config['activators']['query_param'],
'$paramName' => $config['activators']['query_param_name'],
]);
}
}
7 changes: 7 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->end()
->end()
->arrayNode('activators')
->addDefaultsIfNotSet()
->children()
->booleanNode('query_param')->defaultFalse()->end()
->scalarNode('query_param_name')->defaultValue('chaos')->end()
->end()
->end()
->end();

return $treeBuilder;
Expand Down
4 changes: 4 additions & 0 deletions src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

<service id="chaos_monkey.watcher.request" class="Chaos\Monkey\Symfony\Watcher\RequestWatcher" public="false">
<argument type="service" id="chaos_monkey" />
<argument type="service" id="chaos_monkey.activator.query_param" />
</service>

<service id="chaos_monkey.activator.query_param" class="Chaos\Monkey\Symfony\Activator\QueryParamActivator" public="false">
</service>

<instanceof id="Chaos\Monkey\Assault" autowire="true">
Expand Down
16 changes: 9 additions & 7 deletions src/Watcher/RequestWatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
namespace Chaos\Monkey\Symfony\Watcher;

use Chaos\Monkey\ChaosMonkey;
use Chaos\Monkey\Symfony\Activator\QueryParamActivator;
use Symfony\Component\HttpKernel\Event\RequestEvent;

class RequestWatcher
final class RequestWatcher
{
private ChaosMonkey $chaosMonkey;

public function __construct(ChaosMonkey $chaosMonkey)
{
$this->chaosMonkey = $chaosMonkey;
public function __construct(
private readonly ChaosMonkey $chaosMonkey,
private readonly QueryParamActivator $queryParamActivator
) {
}

public function onKernelRequest(RequestEvent $event): void
Expand All @@ -22,6 +22,8 @@ public function onKernelRequest(RequestEvent $event): void
return;
}

$this->chaosMonkey->call();
if ($this->queryParamActivator->inChaos($event->getRequest())) {
$this->chaosMonkey->call();
}
}
}
33 changes: 33 additions & 0 deletions tests/Activator/QueryParamActivatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Chaos\Monkey\Symfony\Tests\Activator;

use Chaos\Monkey\Symfony\Activator\QueryParamActivator;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;

final class QueryParamActivatorTest extends TestCase
{
public function testItIsInChaosIfDisabled(): void
{
$activator = new QueryParamActivator();

self::assertTrue($activator->inChaos(new Request()));
}

public function testItIsNoInChaosIfEnabledAndParamMissing(): void
{
$activator = new QueryParamActivator(true);

self::assertFalse($activator->inChaos(new Request()));
}

public function testItIsInChaosIfEnabledAndParamExists(): void
{
$activator = new QueryParamActivator(true, 'bye');

self::assertTrue($activator->inChaos(new Request(['bye' => true])));
}
}
25 changes: 24 additions & 1 deletion tests/Controller/SymfonyControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
namespace Chaos\Monkey\Symfony\Tests\Controller;

use Chaos\Monkey\Settings;
use Chaos\Monkey\Symfony\Activator\QueryParamActivator;
use Chaos\Monkey\Symfony\Tests\Symfony\Kernel;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Component\HttpKernel\Exception\LockedHttpException;
use Symfony\Component\Stopwatch\Stopwatch;

class SymfonyControllerTest extends TestCase
Expand Down Expand Up @@ -49,7 +51,22 @@ public function testRequestExceptionAttack(): void
$this->enableExceptionAssault();
$this->client->request('GET', '/hello');

self::assertEquals(500, $this->client->getResponse()->getStatusCode());
self::assertEquals(423, $this->client->getResponse()->getStatusCode());

$this->disableExceptionAssault();
}

public function testRequestExceptionAttackWithQueryParamActivatorEnabled(): void
{
$this->enableQueryParamActivator();
$this->enableExceptionAssault();
$this->client->request('GET', '/hello');

self::assertEquals(200, $this->client->getResponse()->getStatusCode());

$this->client->request('GET', '/hello?chaos=true');

self::assertEquals(423, $this->client->getResponse()->getStatusCode());

$this->disableExceptionAssault();
}
Expand All @@ -58,6 +75,7 @@ private function enableExceptionAssault(): void
{
$this->chaosMonkeySettings()->setEnabled(true);
$this->chaosMonkeySettings()->setExceptionActive(true);
$this->chaosMonkeySettings()->setExceptionClass(LockedHttpException::class);
$this->chaosMonkeySettings()->setProbability(100);
}

Expand All @@ -84,4 +102,9 @@ private function chaosMonkeySettings(): Settings
{
return $this->client->getContainer()->get('chaos_monkey')->settings();
}

private function enableQueryParamActivator(): void
{
$this->client->getContainer()->get('test.service_container')->set('chaos_monkey.activator.query_param', new QueryParamActivator(true));
}
}
1 change: 1 addition & 0 deletions tests/Symfony/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ protected function configureContainer(ContainerConfigurator $container): void
{
$container->extension('framework', [
'secret' => 'S0ME_SECRET',
'test' => true,
]);

$container->services()->set('logger', NullLogger::class);
Expand Down

0 comments on commit 646de1a

Please sign in to comment.