diff --git a/docs/functions/customization.md b/docs/functions/customization.md index 81747a8..69e647a 100644 --- a/docs/functions/customization.md +++ b/docs/functions/customization.md @@ -50,7 +50,7 @@ To change the allocated memory of your function, return the number in megabytes. ```php class ExampleFunction extends LambdaFunction { - public function memory() // [tl! focus:4] + public function memory() // [tl! focus:4] { // 2GB of memory return 2048; @@ -227,6 +227,25 @@ You likely won't need to change this, but if you do, *you must include the envir } ``` +## Tags + +A key-value array of strings of tags to be applied to your function, this can be used to organize your functions by owner, project or departement. + +You should note that there are some [restrictions](https://docs.aws.amazon.com/lambda/latest/dg/configuration-tags.html#configuration-tags-restrictions) that apply when adding tags. + +```php +class ExampleFunction extends LambdaFunction +{ + public function tags() // [tl! focus:start] + { + return [ + 'Project' => 'Super Secret Project', + 'Department' => 'Logistics', + ]; + } // [tl! focus:end] +} +``` + ## Description The description is totally up to you, you'll likely not need to change it at all. We have provided a descriptive default. Sidecar doesn't do anything with it. diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1275fa2..04ec51c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -14,5 +14,6 @@ + diff --git a/src/LambdaFunction.php b/src/LambdaFunction.php index 310e56b..5f47ad4 100644 --- a/src/LambdaFunction.php +++ b/src/LambdaFunction.php @@ -319,6 +319,16 @@ public function memory() return config('sidecar.memory'); } + /** + * A list of tags to apply to the function. + * + * @return array + */ + public function tags() + { + return []; + } + /** * The function execution time, in seconds, at which Lambda should terminate the function. * Because the execution time has cost implications, we recommend you set this @@ -427,7 +437,8 @@ public function toDeploymentArray() 'Layers' => $this->layers(), 'Publish' => true, 'PackageType' => $this->packageType(), - 'Architectures' => [$this->architecture()] + 'Architectures' => [$this->architecture()], + 'Tags' => $this->tags(), ]; // For container image packages, we need to remove the Runtime diff --git a/tests/Unit/DeploymentTest.php b/tests/Unit/DeploymentTest.php index 822759c..8bd35e7 100644 --- a/tests/Unit/DeploymentTest.php +++ b/tests/Unit/DeploymentTest.php @@ -14,6 +14,7 @@ use Hammerstone\Sidecar\Events\BeforeFunctionsDeployed; use Hammerstone\Sidecar\Exceptions\NoFunctionsRegisteredException; use Hammerstone\Sidecar\Tests\Unit\Support\DeploymentTestFunction; +use Hammerstone\Sidecar\Tests\Unit\Support\DeploymentTestFunctionWithTags; use Hammerstone\Sidecar\Tests\Unit\Support\DeploymentTestFunctionWithVariables; use Illuminate\Support\Facades\Event; use Mockery; @@ -63,7 +64,8 @@ public function mockCreatingFunction() 'MemorySize' => 'test-MemorySize', 'Layers' => 'test-Layers', 'Publish' => 'test-Publish', - 'Architectures' => ['x86_64'] + 'Architectures' => ['x86_64'], + 'Tags' => [], ]); $this->lambda->shouldNotReceive('updateFunctionConfiguration'); @@ -269,6 +271,59 @@ public function it_doesnt_change_variables_that_havent_changed() $this->assertEvents($deployed = true, $activated = true); } + /** @test */ + public function it_sets_function_tags() + { + $this->lambda->shouldReceive('functionExists')->andReturn(false); + $this->lambda->shouldReceive('getVersions')->andReturn([]); + + $this->lambda->shouldReceive('createFunction')->once()->with([ + 'FunctionName' => 'test-FunctionName', + 'Runtime' => 'test-Runtime', + 'Role' => 'test-Role', + 'Handler' => 'test-Handler', + 'Code' => [ + 'S3Bucket' => 'test-bucket', + 'S3Key' => 'test-key', + ], + 'Description' => 'test-Description', + 'Timeout' => 'test-Timeout', + 'MemorySize' => 'test-MemorySize', + 'EphemeralStorage' => [ + 'Size' => 'test-EphemeralStorage' + ], + 'Layers' => 'test-Layers', + 'Publish' => 'test-Publish', + 'Architectures' => ['x86_64'], + 'Tags' => [ + 'Project' => 'Super Secret Project', + ], + ]); + + $this->lambda->shouldNotReceive('updateFunctionConfiguration'); + $this->lambda->shouldNotReceive('updateFunctionCode'); + + $this->lambda->shouldReceive('getLatestVersion') + ->once() + ->withArgs(function ($function) { + return $function instanceof DeploymentTestFunctionWithTags; + }) + ->andReturn('10'); + + $this->lambda->shouldReceive('aliasVersion') + ->once() + ->withArgs(function ($function, $alias, $version) { + return $function instanceof DeploymentTestFunctionWithTags + && $alias === 'active' + && $version === '10'; + }) + ->andReturn(LambdaClient::CREATED); + + DeploymentTestFunctionWithTags::deploy($activate = true); + + $this->assertEvents($deployed = true, $activated = true); + } + /** @test */ public function it_throws_an_exception_if_there_are_no_functions() { diff --git a/tests/Unit/LambdaClientTest.php b/tests/Unit/LambdaClientTest.php index 76d2511..dfc5743 100644 --- a/tests/Unit/LambdaClientTest.php +++ b/tests/Unit/LambdaClientTest.php @@ -172,7 +172,7 @@ public function update_existing_function() $this->lambda->shouldReceive('functionExists') ->once() ->withArgs(function ($f, $checksum) use ($function) { - return $f === $function && $checksum === 'e827998e'; + return $f === $function && $checksum === '4ec93448'; }) ->andReturn(false); @@ -183,7 +183,7 @@ public function update_existing_function() 'Runtime' => 'test-Runtime', 'Role' => 'test-Role', 'Handler' => 'test-Handler', - 'Description' => 'test-Description [e827998e]', + 'Description' => 'test-Description [4ec93448]', 'Timeout' => 'test-Timeout', 'EphemeralStorage' => [ 'Size' => 'test-EphemeralStorage' @@ -192,7 +192,8 @@ public function update_existing_function() 'Layers' => 'test-Layers', 'Architectures' => [ Architecture::X86_64 - ] + ], + 'Tags' => [], ]); $this->lambda->shouldReceive('updateFunctionCode') @@ -224,7 +225,7 @@ public function update_existing_image_function() ->with([ 'FunctionName' => 'test-FunctionName', 'Role' => null, - 'Description' => 'test-Description [ac420e45]', + 'Description' => 'test-Description [e280b565]', 'Timeout' => 300, 'MemorySize' => 512, 'EphemeralStorage' => [ @@ -234,7 +235,8 @@ public function update_existing_image_function() 'PackageType' => 'Image', 'Architectures' => [ Architecture::X86_64 - ] + ], + 'Tags' => [], ]); $this->lambda->shouldReceive('updateFunctionCode') @@ -259,7 +261,7 @@ public function existing_function_unchanged() $this->lambda->shouldReceive('functionExists') ->once() ->withArgs(function ($f, $checksum) use ($function) { - return $f === $function && $checksum === 'e827998e'; + return $f === $function && $checksum === '4ec93448'; }) ->andReturn(true); diff --git a/tests/Unit/Support/DeploymentTestFunction.php b/tests/Unit/Support/DeploymentTestFunction.php index 114856c..e069602 100644 --- a/tests/Unit/Support/DeploymentTestFunction.php +++ b/tests/Unit/Support/DeploymentTestFunction.php @@ -52,6 +52,7 @@ public function toDeploymentArray() 'Layers' => 'test-Layers', 'Publish' => 'test-Publish', 'Architectures' => ['x86_64'], + 'Tags' => $this->tags(), ]; } } diff --git a/tests/Unit/Support/DeploymentTestFunctionWithTags.php b/tests/Unit/Support/DeploymentTestFunctionWithTags.php new file mode 100644 index 0000000..fee7adf --- /dev/null +++ b/tests/Unit/Support/DeploymentTestFunctionWithTags.php @@ -0,0 +1,16 @@ + + */ + +namespace Hammerstone\Sidecar\Tests\Unit\Support; + +class DeploymentTestFunctionWithTags extends DeploymentTestFunction +{ + public function tags() + { + return [ + 'Project' => 'Super Secret Project' + ]; + } +}