From 2cd8b4ac1cb78d485d53fd621f6d11247600ce0e Mon Sep 17 00:00:00 2001 From: Ray Krishardi Layadi Date: Tue, 14 May 2024 16:42:40 +1000 Subject: [PATCH] Fix/task image subs (#13) * fix: fnsub not working for repo * fix: escape : char * fix: escape : char (2) * fix: need to use FnJoin because if tag_param is there then it will use Ref * fix: spec files --- ecs-task.cfndsl.rb | 4 +- spec/default_spec.rb | 31 +++-- spec/depends_on_spec.rb | 56 ++++++++ spec/ec2_spec.rb | 78 ++++++----- spec/ecs-exec_spec.rb | 118 ++++++++++++++++ spec/ecs_exec_spec.rb | 98 -------------- spec/ephemeral_storage_spec.rb | 97 +++++++------ spec/fargate_spec.rb | 89 ++++++------ spec/secrets_spec.rb | 240 ++++++++++++--------------------- 9 files changed, 425 insertions(+), 386 deletions(-) create mode 100644 spec/depends_on_spec.rb create mode 100644 spec/ecs-exec_spec.rb delete mode 100644 spec/ecs_exec_spec.rb diff --git a/ecs-task.cfndsl.rb b/ecs-task.cfndsl.rb index 92e0ca2..caad7fd 100644 --- a/ecs-task.cfndsl.rb +++ b/ecs-task.cfndsl.rb @@ -30,7 +30,7 @@ name = task.has_key?('name') ? task['name'] : task_name - image_repo = task.has_key?('repo') ? FnSub("#{task['repo']}/") : '' + image_repo = task.has_key?('repo') ? "#{task['repo']}" : '' image_name = task.has_key?('image') ? task['image'] : task_name image_tag = task.has_key?('tag') ? "#{task['tag']}" : 'latest' image_tag = task.has_key?('tag_param') ? Ref("#{task['tag_param']}") : image_tag @@ -38,7 +38,7 @@ # create main definition task_def = { Name: name, - Image: FnJoin('',[ image_repo, image_name, ":", image_tag ]), + Image: FnJoin('', [FnSub("#{image_repo}/#{image_name}"), ":", image_tag]), LogConfiguration: { LogDriver: 'awslogs', Options: { diff --git a/spec/default_spec.rb b/spec/default_spec.rb index 5000b06..c2e4248 100644 --- a/spec/default_spec.rb +++ b/spec/default_spec.rb @@ -1,6 +1,6 @@ require 'yaml' -describe 'compiled component' do +describe 'compiled component ecs-task' do context 'cftest' do it 'compiles test' do @@ -9,18 +9,27 @@ end let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/default/ecs-task.compiled.yaml") } + + context "Resource" do - context 'Resources' do - it 'has No Task ' do - expect(template["Resources"]['Task']).to eq(nil) - end + + context "LogGroup" do + let(:resource) { template["Resources"]["LogGroup"] } - it 'has a Log Group' do - expect(template["Resources"]['LogGroup']).to eq({ - "Type"=>"AWS::Logs::LogGroup", - "Properties"=>{"LogGroupName"=>{"Ref"=>"AWS::StackName"}, "RetentionInDays"=>7} - }) + it "is of type AWS::Logs::LogGroup" do + expect(resource["Type"]).to eq("AWS::Logs::LogGroup") + end + + it "to have property LogGroupName" do + expect(resource["Properties"]["LogGroupName"]).to eq({"Ref"=>"AWS::StackName"}) + end + + it "to have property RetentionInDays" do + expect(resource["Properties"]["RetentionInDays"]).to eq(7) + end + end + end -end +end \ No newline at end of file diff --git a/spec/depends_on_spec.rb b/spec/depends_on_spec.rb new file mode 100644 index 0000000..5ac28db --- /dev/null +++ b/spec/depends_on_spec.rb @@ -0,0 +1,56 @@ +require 'yaml' + +describe 'compiled component ecs-task' do + + context 'cftest' do + it 'compiles test' do + expect(system("cfhighlander cftest #{@validate} --tests tests/depends_on.test.yaml")).to be_truthy + end + end + + let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/depends_on/ecs-task.compiled.yaml") } + + context "Resource" do + + + context "LogGroup" do + let(:resource) { template["Resources"]["LogGroup"] } + + it "is of type AWS::Logs::LogGroup" do + expect(resource["Type"]).to eq("AWS::Logs::LogGroup") + end + + it "to have property LogGroupName" do + expect(resource["Properties"]["LogGroupName"]).to eq({"Ref"=>"AWS::StackName"}) + end + + it "to have property RetentionInDays" do + expect(resource["Properties"]["RetentionInDays"]).to eq(7) + end + + end + + context "Task" do + let(:resource) { template["Resources"]["Task"] } + + it "is of type AWS::ECS::TaskDefinition" do + expect(resource["Type"]).to eq("AWS::ECS::TaskDefinition") + end + + it "to have property ContainerDefinitions" do + expect(resource["Properties"]["ContainerDefinitions"]).to eq([{"Name"=>"nginx", "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"nginx/nginx"}, ":", "latest"]]}, "LogConfiguration"=>{"LogDriver"=>"awslogs", "Options"=>{"awslogs-group"=>{"Ref"=>"LogGroup"}, "awslogs-region"=>{"Ref"=>"AWS::Region"}, "awslogs-stream-prefix"=>"nginx"}}, "DependsOn"=>[{"ContainerName"=>"db", "Condition"=>"START"}]}, {"Name"=>"db", "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"/postgres"}, ":", "latest"]]}, "LogConfiguration"=>{"LogDriver"=>"awslogs", "Options"=>{"awslogs-group"=>{"Ref"=>"LogGroup"}, "awslogs-region"=>{"Ref"=>"AWS::Region"}, "awslogs-stream-prefix"=>"db"}}, "Essential"=>false, "PortMappings"=>[{"ContainerPort"=>5432}]}]) + end + + it "to have property RequiresCompatibilities" do + expect(resource["Properties"]["RequiresCompatibilities"]).to eq(["EC2"]) + end + + it "to have property Tags" do + expect(resource["Properties"]["Tags"]).to eq([{"Key"=>"Name", "Value"=>"ecs-task"}, {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}}]) + end + + end + + end + +end \ No newline at end of file diff --git a/spec/ec2_spec.rb b/spec/ec2_spec.rb index 56a1dcb..43b5d24 100644 --- a/spec/ec2_spec.rb +++ b/spec/ec2_spec.rb @@ -1,6 +1,6 @@ require 'yaml' -describe 'compiled component' do +describe 'compiled component ecs-task' do context 'cftest' do it 'compiles test' do @@ -9,50 +9,48 @@ end let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/ec2/ecs-task.compiled.yaml") } + + context "Resource" do - context 'Resource Task' do - let(:properties) { template["Resources"]["Task"]["Properties"] } - - it 'has property RequiresCompatibilities ' do - expect(properties["RequiresCompatibilities"]).to eq(['EC2']) - end - it 'has property NetworkMode ' do - expect(properties["NetworkMode"]).to eq(nil) - end - - it 'has property CPU ' do - expect(properties["Cpu"]).to eq(nil) - end + context "LogGroup" do + let(:resource) { template["Resources"]["LogGroup"] } - it 'has property Memory ' do - expect(properties["Memory"]).to eq(nil) - end - - it 'has property One container definition ' do - expect(properties["ContainerDefinitions"].count).to eq(1) - expect(properties["ContainerDefinitions"]).to eq([{ - "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"myrepo/"}, "backend", ":", {"Ref"=>"SchemaTag"}]]}, - "LogConfiguration"=> - { - "LogDriver"=>"awslogs", - "Options"=> { - "awslogs-group"=>{"Ref"=>"LogGroup"}, - "awslogs-region"=>{"Ref"=>"AWS::Region"}, - "awslogs-stream-prefix"=>"schema" - } - }, - "Name"=>"schema" - }]) + it "is of type AWS::Logs::LogGroup" do + expect(resource["Type"]).to eq("AWS::Logs::LogGroup") + end + + it "to have property LogGroupName" do + expect(resource["Properties"]["LogGroupName"]).to eq({"Ref"=>"AWS::StackName"}) + end + + it "to have property RetentionInDays" do + expect(resource["Properties"]["RetentionInDays"]).to eq(7) + end + end + + context "Task" do + let(:resource) { template["Resources"]["Task"] } - it 'has property Tags' do - expect(properties["Tags"]).to eq([ - {"Key"=>"Name", "Value"=>"ecs-task"}, - {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, - {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}}, - {"Key"=>"CostCenter", "Value"=>"TeamA"} - ]) + it "is of type AWS::ECS::TaskDefinition" do + expect(resource["Type"]).to eq("AWS::ECS::TaskDefinition") + end + + it "to have property ContainerDefinitions" do + expect(resource["Properties"]["ContainerDefinitions"]).to eq([{"Name"=>"schema", "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"myrepo/backend"}, ":", {"Ref"=>"SchemaTag"}]]}, "LogConfiguration"=>{"LogDriver"=>"awslogs", "Options"=>{"awslogs-group"=>{"Ref"=>"LogGroup"}, "awslogs-region"=>{"Ref"=>"AWS::Region"}, "awslogs-stream-prefix"=>"schema"}}}]) + end + + it "to have property RequiresCompatibilities" do + expect(resource["Properties"]["RequiresCompatibilities"]).to eq(["EC2"]) + end + + it "to have property Tags" do + expect(resource["Properties"]["Tags"]).to eq([{"Key"=>"Name", "Value"=>"ecs-task"}, {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}}, {"Key"=>"CostCenter", "Value"=>"TeamA"}]) + end + end + end + end \ No newline at end of file diff --git a/spec/ecs-exec_spec.rb b/spec/ecs-exec_spec.rb new file mode 100644 index 0000000..9ebac01 --- /dev/null +++ b/spec/ecs-exec_spec.rb @@ -0,0 +1,118 @@ +require 'yaml' + +describe 'compiled component ecs-task' do + + context 'cftest' do + it 'compiles test' do + expect(system("cfhighlander cftest #{@validate} --tests tests/ecs-exec.test.yaml")).to be_truthy + end + end + + let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/ecs-exec/ecs-task.compiled.yaml") } + + context "Resource" do + + + context "LogGroup" do + let(:resource) { template["Resources"]["LogGroup"] } + + it "is of type AWS::Logs::LogGroup" do + expect(resource["Type"]).to eq("AWS::Logs::LogGroup") + end + + it "to have property LogGroupName" do + expect(resource["Properties"]["LogGroupName"]).to eq({"Ref"=>"AWS::StackName"}) + end + + it "to have property RetentionInDays" do + expect(resource["Properties"]["RetentionInDays"]).to eq(7) + end + + end + + context "TaskRole" do + let(:resource) { template["Resources"]["TaskRole"] } + + it "is of type AWS::IAM::Role" do + expect(resource["Type"]).to eq("AWS::IAM::Role") + end + + it "to have property AssumeRolePolicyDocument" do + expect(resource["Properties"]["AssumeRolePolicyDocument"]).to eq({"Version"=>"2012-10-17", "Statement"=>[{"Effect"=>"Allow", "Principal"=>{"Service"=>"ecs-tasks.amazonaws.com"}, "Action"=>"sts:AssumeRole"}, {"Effect"=>"Allow", "Principal"=>{"Service"=>"ssm.amazonaws.com"}, "Action"=>"sts:AssumeRole"}]}) + end + + it "to have property Path" do + expect(resource["Properties"]["Path"]).to eq("/") + end + + it "to have property Policies" do + expect(resource["Properties"]["Policies"]).to eq([{"PolicyName"=>"ssm-session-manager", "PolicyDocument"=>{"Version"=>"2012-10-17", "Statement"=>[{"Sid"=>"ssmsessionmanager", "Action"=>["ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel", "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel"], "Resource"=>["*"], "Effect"=>"Allow"}]}}]) + end + + end + + context "ExecutionRole" do + let(:resource) { template["Resources"]["ExecutionRole"] } + + it "is of type AWS::IAM::Role" do + expect(resource["Type"]).to eq("AWS::IAM::Role") + end + + it "to have property AssumeRolePolicyDocument" do + expect(resource["Properties"]["AssumeRolePolicyDocument"]).to eq({"Version"=>"2012-10-17", "Statement"=>[{"Effect"=>"Allow", "Principal"=>{"Service"=>"ecs-tasks.amazonaws.com"}, "Action"=>"sts:AssumeRole"}, {"Effect"=>"Allow", "Principal"=>{"Service"=>"ssm.amazonaws.com"}, "Action"=>"sts:AssumeRole"}]}) + end + + it "to have property Path" do + expect(resource["Properties"]["Path"]).to eq("/") + end + + it "to have property ManagedPolicyArns" do + expect(resource["Properties"]["ManagedPolicyArns"]).to eq(["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]) + end + + end + + context "Task" do + let(:resource) { template["Resources"]["Task"] } + + it "is of type AWS::ECS::TaskDefinition" do + expect(resource["Type"]).to eq("AWS::ECS::TaskDefinition") + end + + it "to have property ContainerDefinitions" do + expect(resource["Properties"]["ContainerDefinitions"]).to eq([{"Name"=>"schema", "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"myrepo/backend"}, ":", {"Ref"=>"SchemaTag"}]]}, "LogConfiguration"=>{"LogDriver"=>"awslogs", "Options"=>{"awslogs-group"=>{"Ref"=>"LogGroup"}, "awslogs-region"=>{"Ref"=>"AWS::Region"}, "awslogs-stream-prefix"=>"schema"}}}]) + end + + it "to have property RequiresCompatibilities" do + expect(resource["Properties"]["RequiresCompatibilities"]).to eq(["FARGATE"]) + end + + it "to have property Cpu" do + expect(resource["Properties"]["Cpu"]).to eq(256) + end + + it "to have property Memory" do + expect(resource["Properties"]["Memory"]).to eq(512) + end + + it "to have property NetworkMode" do + expect(resource["Properties"]["NetworkMode"]).to eq("awsvpc") + end + + it "to have property TaskRoleArn" do + expect(resource["Properties"]["TaskRoleArn"]).to eq({"Ref"=>"TaskRole"}) + end + + it "to have property ExecutionRoleArn" do + expect(resource["Properties"]["ExecutionRoleArn"]).to eq({"Ref"=>"ExecutionRole"}) + end + + it "to have property Tags" do + expect(resource["Properties"]["Tags"]).to eq([{"Key"=>"Name", "Value"=>"ecs-task"}, {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}}]) + end + + end + + end + +end \ No newline at end of file diff --git a/spec/ecs_exec_spec.rb b/spec/ecs_exec_spec.rb deleted file mode 100644 index 6c30d8f..0000000 --- a/spec/ecs_exec_spec.rb +++ /dev/null @@ -1,98 +0,0 @@ -require 'yaml' - -describe 'compiled component' do - - context 'cftest' do - it 'compiles test' do - expect(system("cfhighlander cftest #{@validate} --tests tests/ecs-exec.test.yaml")).to be_truthy - end - end - - let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/ecs-exec/ecs-task.compiled.yaml") } - - context 'Resource Task' do - let(:properties) { template["Resources"]["Task"]["Properties"] } - - it 'has property RequiresCompatibilities ' do - expect(properties["RequiresCompatibilities"]).to eq(['FARGATE']) - end - - it 'has property NetworkMode ' do - expect(properties["NetworkMode"]).to eq('awsvpc') - end - - it 'has property CPU ' do - expect(properties["Cpu"]).to eq(256) - end - - it 'has property Memory ' do - expect(properties["Memory"]).to eq(512) - end - - it 'has property One container definition ' do - expect(properties["ContainerDefinitions"].count).to eq(1) - expect(properties["ContainerDefinitions"]).to eq([{ - "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"myrepo/"}, "backend", ":", {"Ref"=>"SchemaTag"}]]}, - "LogConfiguration"=> - { - "LogDriver"=>"awslogs", - "Options"=> { - "awslogs-group"=>{"Ref"=>"LogGroup"}, - "awslogs-region"=>{"Ref"=>"AWS::Region"}, - "awslogs-stream-prefix"=>"schema" - } - }, - "Name"=>"schema" - }]) - end - - it 'has property Tags' do - expect(properties["Tags"]).to eq([ - {"Key"=>"Name", "Value"=>"ecs-task"}, - {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, - {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}} - ]) - end - end - - context 'Task Role' do - let(:properties) { template["Resources"]["TaskRole"]["Properties"] } - - it 'has ecs-tasks assume role permissions' do - expect(properties["AssumeRolePolicyDocument"]).to eq({ - "Version" => "2012-10-17", - "Statement" => [ - { - "Action"=>"sts:AssumeRole", - "Effect"=>"Allow", - "Principal"=>{"Service"=>"ecs-tasks.amazonaws.com"} - }, - { - "Action"=>"sts:AssumeRole", - "Effect"=>"Allow", - "Principal"=>{"Service"=>"ssm.amazonaws.com"} - } - ], - }) - end - - it 'has SSM IAM Policies' do - expect(properties["Policies"]).to eq([ - "PolicyName" => "ssm-session-manager", - "PolicyDocument" => { - "Statement" => [{ - "Sid" => "ssmsessionmanager", - "Effect" => "Allow", - "Action" => [ - "ssmmessages:CreateControlChannel", - "ssmmessages:CreateDataChannel", - "ssmmessages:OpenControlChannel", - "ssmmessages:OpenDataChannel" - ], - "Resource" => ["*"], - }] - } - ]) - end - end -end \ No newline at end of file diff --git a/spec/ephemeral_storage_spec.rb b/spec/ephemeral_storage_spec.rb index 05b49f7..be987b3 100644 --- a/spec/ephemeral_storage_spec.rb +++ b/spec/ephemeral_storage_spec.rb @@ -1,6 +1,6 @@ require 'yaml' -describe 'compiled component' do +describe 'compiled component ecs-task' do context 'cftest' do it 'compiles test' do @@ -9,53 +9,64 @@ end let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/ephemeral_storage/ecs-task.compiled.yaml") } + + context "Resource" do - context 'Resource Task' do - let(:properties) { template["Resources"]["Task"]["Properties"] } - - it 'has property RequiresCompatibilities ' do - expect(properties["RequiresCompatibilities"]).to eq(['FARGATE']) - end - it 'has property NetworkMode ' do - expect(properties["NetworkMode"]).to eq('awsvpc') - end + context "LogGroup" do + let(:resource) { template["Resources"]["LogGroup"] } - it 'has property CPU ' do - expect(properties["Cpu"]).to eq(256) - end - - it 'has property Memory ' do - expect(properties["Memory"]).to eq(512) - end - - it "to have property EphemeralStorage" do - expect(properties["EphemeralStorage"]).to eq({"SizeInGiB"=>50}) - end - - it 'has property One container definition ' do - expect(properties["ContainerDefinitions"].count).to eq(1) - expect(properties["ContainerDefinitions"]).to eq([{ - "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"myrepo/"}, "backend", ":", {"Ref"=>"SchemaTag"}]]}, - "LogConfiguration"=> - { - "LogDriver"=>"awslogs", - "Options"=> { - "awslogs-group"=>{"Ref"=>"LogGroup"}, - "awslogs-region"=>{"Ref"=>"AWS::Region"}, - "awslogs-stream-prefix"=>"schema" - } - }, - "Name"=>"schema" - }]) + it "is of type AWS::Logs::LogGroup" do + expect(resource["Type"]).to eq("AWS::Logs::LogGroup") + end + + it "to have property LogGroupName" do + expect(resource["Properties"]["LogGroupName"]).to eq({"Ref"=>"AWS::StackName"}) + end + + it "to have property RetentionInDays" do + expect(resource["Properties"]["RetentionInDays"]).to eq(7) + end + end + + context "Task" do + let(:resource) { template["Resources"]["Task"] } - it 'has property Tags' do - expect(properties["Tags"]).to eq([ - {"Key"=>"Name", "Value"=>"ecs-task"}, - {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, - {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}} - ]) + it "is of type AWS::ECS::TaskDefinition" do + expect(resource["Type"]).to eq("AWS::ECS::TaskDefinition") + end + + it "to have property ContainerDefinitions" do + expect(resource["Properties"]["ContainerDefinitions"]).to eq([{"Name"=>"schema", "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"myrepo/backend"}, ":", {"Ref"=>"SchemaTag"}]]}, "LogConfiguration"=>{"LogDriver"=>"awslogs", "Options"=>{"awslogs-group"=>{"Ref"=>"LogGroup"}, "awslogs-region"=>{"Ref"=>"AWS::Region"}, "awslogs-stream-prefix"=>"schema"}}}]) + end + + it "to have property RequiresCompatibilities" do + expect(resource["Properties"]["RequiresCompatibilities"]).to eq(["FARGATE"]) + end + + it "to have property Cpu" do + expect(resource["Properties"]["Cpu"]).to eq(256) + end + + it "to have property Memory" do + expect(resource["Properties"]["Memory"]).to eq(512) + end + + it "to have property NetworkMode" do + expect(resource["Properties"]["NetworkMode"]).to eq("awsvpc") + end + + it "to have property EphemeralStorage" do + expect(resource["Properties"]["EphemeralStorage"]).to eq({"SizeInGiB"=>50}) + end + + it "to have property Tags" do + expect(resource["Properties"]["Tags"]).to eq([{"Key"=>"Name", "Value"=>"ecs-task"}, {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}}]) + end + end + end + end \ No newline at end of file diff --git a/spec/fargate_spec.rb b/spec/fargate_spec.rb index a82676c..0686210 100644 --- a/spec/fargate_spec.rb +++ b/spec/fargate_spec.rb @@ -1,6 +1,6 @@ require 'yaml' -describe 'compiled component' do +describe 'compiled component ecs-task' do context 'cftest' do it 'compiles test' do @@ -9,49 +9,60 @@ end let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/fargate/ecs-task.compiled.yaml") } + + context "Resource" do - context 'Resource Task' do - let(:properties) { template["Resources"]["Task"]["Properties"] } - - it 'has property RequiresCompatibilities ' do - expect(properties["RequiresCompatibilities"]).to eq(['FARGATE']) - end - it 'has property NetworkMode ' do - expect(properties["NetworkMode"]).to eq('awsvpc') - end - - it 'has property CPU ' do - expect(properties["Cpu"]).to eq(256) - end + context "LogGroup" do + let(:resource) { template["Resources"]["LogGroup"] } - it 'has property Memory ' do - expect(properties["Memory"]).to eq(512) - end - - it 'has property One container definition ' do - expect(properties["ContainerDefinitions"].count).to eq(1) - expect(properties["ContainerDefinitions"]).to eq([{ - "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"myrepo/"}, "backend", ":", {"Ref"=>"SchemaTag"}]]}, - "LogConfiguration"=> - { - "LogDriver"=>"awslogs", - "Options"=> { - "awslogs-group"=>{"Ref"=>"LogGroup"}, - "awslogs-region"=>{"Ref"=>"AWS::Region"}, - "awslogs-stream-prefix"=>"schema" - } - }, - "Name"=>"schema" - }]) + it "is of type AWS::Logs::LogGroup" do + expect(resource["Type"]).to eq("AWS::Logs::LogGroup") + end + + it "to have property LogGroupName" do + expect(resource["Properties"]["LogGroupName"]).to eq({"Ref"=>"AWS::StackName"}) + end + + it "to have property RetentionInDays" do + expect(resource["Properties"]["RetentionInDays"]).to eq(7) + end + end + + context "Task" do + let(:resource) { template["Resources"]["Task"] } - it 'has property Tags' do - expect(properties["Tags"]).to eq([ - {"Key"=>"Name", "Value"=>"ecs-task"}, - {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, - {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}} - ]) + it "is of type AWS::ECS::TaskDefinition" do + expect(resource["Type"]).to eq("AWS::ECS::TaskDefinition") + end + + it "to have property ContainerDefinitions" do + expect(resource["Properties"]["ContainerDefinitions"]).to eq([{"Name"=>"schema", "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"myrepo/backend"}, ":", {"Ref"=>"SchemaTag"}]]}, "LogConfiguration"=>{"LogDriver"=>"awslogs", "Options"=>{"awslogs-group"=>{"Ref"=>"LogGroup"}, "awslogs-region"=>{"Ref"=>"AWS::Region"}, "awslogs-stream-prefix"=>"schema"}}}]) + end + + it "to have property RequiresCompatibilities" do + expect(resource["Properties"]["RequiresCompatibilities"]).to eq(["FARGATE"]) + end + + it "to have property Cpu" do + expect(resource["Properties"]["Cpu"]).to eq(256) + end + + it "to have property Memory" do + expect(resource["Properties"]["Memory"]).to eq(512) + end + + it "to have property NetworkMode" do + expect(resource["Properties"]["NetworkMode"]).to eq("awsvpc") + end + + it "to have property Tags" do + expect(resource["Properties"]["Tags"]).to eq([{"Key"=>"Name", "Value"=>"ecs-task"}, {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}}]) + end + end + end + end \ No newline at end of file diff --git a/spec/secrets_spec.rb b/spec/secrets_spec.rb index 4e8008b..3bd703a 100644 --- a/spec/secrets_spec.rb +++ b/spec/secrets_spec.rb @@ -1,6 +1,6 @@ require 'yaml' -describe 'compiled component' do +describe 'compiled component ecs-task' do context 'cftest' do it 'compiles test' do @@ -9,168 +9,102 @@ end let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/secrets/ecs-task.compiled.yaml") } + + context "Resource" do - context 'Resource Task' do - let(:properties) { template["Resources"]["Task"]["Properties"] } - - it 'has property RequiresCompatibilities ' do - expect(properties["RequiresCompatibilities"]).to eq(['EC2']) - end - it 'has property NetworkMode ' do - expect(properties["NetworkMode"]).to eq(nil) - end + context "LogGroup" do + let(:resource) { template["Resources"]["LogGroup"] } - it 'has property CPU ' do - expect(properties["Cpu"]).to eq(nil) - end - - it 'has property Memory ' do - expect(properties["Memory"]).to eq(nil) + it "is of type AWS::Logs::LogGroup" do + expect(resource["Type"]).to eq("AWS::Logs::LogGroup") + end + + it "to have property LogGroupName" do + expect(resource["Properties"]["LogGroupName"]).to eq({"Ref"=>"AWS::StackName"}) + end + + it "to have property RetentionInDays" do + expect(resource["Properties"]["RetentionInDays"]).to eq(7) + end + end + + context "TaskRole" do + let(:resource) { template["Resources"]["TaskRole"] } - it 'has property One container definition ' do - expect(properties["ContainerDefinitions"].count).to eq(1) - expect(properties["ContainerDefinitions"]).to eq([{ - "Name"=>"nginx", - "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"nginx/"}, "nginx", ":", "latest"]]}, - "LogConfiguration"=> { - "LogDriver"=>"awslogs", - "Options"=> { - "awslogs-group"=>{"Ref"=>"LogGroup"}, - "awslogs-region"=>{"Ref"=>"AWS::Region"}, - "awslogs-stream-prefix"=>"nginx" - } - }, - "Secrets"=> [ - { - "Name"=>"APP_KEY", - "ValueFrom" => { - "Fn::Sub" => "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/app/key" - } - }, - { - "Name"=>"APP_SECRET", - "ValueFrom" => { - "Fn::Sub" => "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/app/secret" - } - }, - { - "Name"=>"ACCESSKEY", - "ValueFrom" => { - "Fn::Sub" => "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:/dont/use/accesskeys" - } - }, - {"Name"=>"SECRETKEY", "ValueFrom"=>{"Ref"=>"EnvironmentName"}}, - { - "Name"=>"API_KEY", - "ValueFrom" => { - "Fn::Sub" => "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/api/key" - } - }, - { - "Name"=>"API_SECRET", - "ValueFrom" => { - "Fn::Sub" => "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/api/secret" - } - } - ] - }]) + it "is of type AWS::IAM::Role" do + expect(resource["Type"]).to eq("AWS::IAM::Role") + end + + it "to have property AssumeRolePolicyDocument" do + expect(resource["Properties"]["AssumeRolePolicyDocument"]).to eq({"Version"=>"2012-10-17", "Statement"=>[{"Effect"=>"Allow", "Principal"=>{"Service"=>"ecs-tasks.amazonaws.com"}, "Action"=>"sts:AssumeRole"}, {"Effect"=>"Allow", "Principal"=>{"Service"=>"ssm.amazonaws.com"}, "Action"=>"sts:AssumeRole"}]}) + end + + it "to have property Path" do + expect(resource["Properties"]["Path"]).to eq("/") + end + + it "to have property Policies" do + expect(resource["Properties"]["Policies"]).to eq([{"PolicyName"=>"s3", "PolicyDocument"=>{"Version"=>"2012-10-17", "Statement"=>[{"Sid"=>"s3", "Action"=>["s3:Get*"], "Resource"=>["*"], "Effect"=>"Allow"}]}}]) + end + end + + context "ExecutionRole" do + let(:resource) { template["Resources"]["ExecutionRole"] } - - - - it 'has property Tags' do - expect(properties["Tags"]).to eq([ - {"Key"=>"Name", "Value"=>"ecs-task"}, - {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, - {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}} - ]) + it "is of type AWS::IAM::Role" do + expect(resource["Type"]).to eq("AWS::IAM::Role") + end + + it "to have property AssumeRolePolicyDocument" do + expect(resource["Properties"]["AssumeRolePolicyDocument"]).to eq({"Version"=>"2012-10-17", "Statement"=>[{"Effect"=>"Allow", "Principal"=>{"Service"=>"ecs-tasks.amazonaws.com"}, "Action"=>"sts:AssumeRole"}, {"Effect"=>"Allow", "Principal"=>{"Service"=>"ssm.amazonaws.com"}, "Action"=>"sts:AssumeRole"}]}) + end + + it "to have property Path" do + expect(resource["Properties"]["Path"]).to eq("/") + end + + it "to have property ManagedPolicyArns" do + expect(resource["Properties"]["ManagedPolicyArns"]).to eq(["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]) + end + + it "to have property Policies" do + expect(resource["Properties"]["Policies"]).to eq([{"PolicyName"=>"ssm-secrets", "PolicyDocument"=>{"Version"=>"2012-10-17", "Statement"=>[{"Sid"=>"ssmsecrets", "Action"=>"ssm:GetParameters", "Resource"=>[{"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/app/key"}, {"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/app/secret"}], "Effect"=>"Allow"}]}}, {"PolicyName"=>"secretsmanager", "PolicyDocument"=>{"Version"=>"2012-10-17", "Statement"=>[{"Sid"=>"secretsmanager", "Action"=>"secretsmanager:GetSecretValue", "Resource"=>[{"Fn::Sub"=>"arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:/dont/use/accesskeys-*"}, {"Ref"=>"EnvironmentName"}], "Effect"=>"Allow"}]}}, {"PolicyName"=>"ssm-secrets-inline", "PolicyDocument"=>{"Version"=>"2012-10-17", "Statement"=>[{"Sid"=>"ssmsecretsinline", "Action"=>"ssm:GetParameters", "Resource"=>[{"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/api/key"}, {"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/api/secret"}], "Effect"=>"Allow"}]}}]) + end + end - end - - context 'Resource TaskRole' do - let(:properties) { template["Resources"]["TaskRole"]["Properties"] } + + context "Task" do + let(:resource) { template["Resources"]["Task"] } - it 'has Task Role' do - expect(properties).to eq({ - "AssumeRolePolicyDocument" => {"Statement"=>[{"Action"=>"sts:AssumeRole", "Effect"=>"Allow", "Principal"=>{"Service"=>"ecs-tasks.amazonaws.com"}}, {"Action"=>"sts:AssumeRole", "Effect"=>"Allow", "Principal"=>{"Service"=>"ssm.amazonaws.com"}}], "Version"=>"2012-10-17"}, - "Path" => "/", - "Policies" => [{"PolicyDocument"=>{"Statement"=>[{"Action"=>["s3:Get*"], "Effect"=>"Allow", "Resource"=>["*"], "Sid"=>"s3"}]}, "PolicyName"=>"s3"}], - }) + it "is of type AWS::ECS::TaskDefinition" do + expect(resource["Type"]).to eq("AWS::ECS::TaskDefinition") end - end - - context 'Resource Execution Role' do - let(:properties) { template["Resources"]["ExecutionRole"]["Properties"] } - - it 'has Execution Role' do - expect(properties).to eq({ - "AssumeRolePolicyDocument" => { - "Statement"=>[ - { - "Action"=>"sts:AssumeRole", - "Effect"=>"Allow", - "Principal"=>{"Service"=>"ecs-tasks.amazonaws.com"} - }, - { - "Action"=>"sts:AssumeRole", - "Effect"=>"Allow", - "Principal"=>{"Service"=>"ssm.amazonaws.com"} - } - ], - "Version"=>"2012-10-17" - }, - "ManagedPolicyArns" => ["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"], - "Path" => "/", - "Policies" => [ - { - "PolicyName"=>"ssm-secrets", - "PolicyDocument"=>{ - "Statement"=>[ - { - "Action"=>"ssm:GetParameters", - "Effect"=>"Allow", - "Resource"=>[ - {"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/app/key"}, - {"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/app/secret"} - ], - "Sid"=>"ssmsecrets" - } - ] - } - }, - { - "PolicyName"=>"secretsmanager", - "PolicyDocument"=>{ - "Statement"=>[ - {"Action"=>"secretsmanager:GetSecretValue", - "Effect"=>"Allow", - "Resource"=>[ - {"Fn::Sub"=>"arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:/dont/use/accesskeys-*"}, - {"Ref"=>"EnvironmentName"} - ], - "Sid"=>"secretsmanager"} - ] - } - }, - { - "PolicyName"=>"ssm-secrets-inline", - "PolicyDocument"=>{ - "Statement"=>[ - {"Action"=>"ssm:GetParameters", - "Effect"=>"Allow", - "Resource"=>[ - {"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/api/key"}, - {"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/api/secret"} - ], - "Sid"=>"ssmsecretsinline"} - ] - } - } - ] - }) + + it "to have property ContainerDefinitions" do + expect(resource["Properties"]["ContainerDefinitions"]).to eq([{"Name"=>"nginx", "Image"=>{"Fn::Join"=>["", [{"Fn::Sub"=>"nginx/nginx"}, ":", "latest"]]}, "LogConfiguration"=>{"LogDriver"=>"awslogs", "Options"=>{"awslogs-group"=>{"Ref"=>"LogGroup"}, "awslogs-region"=>{"Ref"=>"AWS::Region"}, "awslogs-stream-prefix"=>"nginx"}}, "Secrets"=>[{"Name"=>"APP_KEY", "ValueFrom"=>{"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/app/key"}}, {"Name"=>"APP_SECRET", "ValueFrom"=>{"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/app/secret"}}, {"Name"=>"ACCESSKEY", "ValueFrom"=>{"Fn::Sub"=>"arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:/dont/use/accesskeys"}}, {"Name"=>"SECRETKEY", "ValueFrom"=>{"Ref"=>"EnvironmentName"}}, {"Name"=>"API_KEY", "ValueFrom"=>{"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/api/key"}}, {"Name"=>"API_SECRET", "ValueFrom"=>{"Fn::Sub"=>"arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/nginx/${EnvironmentName}/api/secret"}}]}]) + end + + it "to have property RequiresCompatibilities" do + expect(resource["Properties"]["RequiresCompatibilities"]).to eq(["EC2"]) + end + + it "to have property TaskRoleArn" do + expect(resource["Properties"]["TaskRoleArn"]).to eq({"Ref"=>"TaskRole"}) + end + + it "to have property ExecutionRoleArn" do + expect(resource["Properties"]["ExecutionRoleArn"]).to eq({"Ref"=>"ExecutionRole"}) end + + it "to have property Tags" do + expect(resource["Properties"]["Tags"]).to eq([{"Key"=>"Name", "Value"=>"ecs-task"}, {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}}]) + end + + end + end + end \ No newline at end of file