From dea47441e343afbb9cd9ba3a8c260879f75c8e74 Mon Sep 17 00:00:00 2001 From: Tarun Menon Date: Thu, 5 Oct 2023 10:11:54 +1100 Subject: [PATCH] Fix tests & update to shared workflow --- .github/workflows/cftest.yaml | 25 ---- .github/workflows/rspec.yaml | 8 ++ spec/schedule_spec.rb | 216 ++++++++++++++++++++++++---------- 3 files changed, 164 insertions(+), 85 deletions(-) delete mode 100644 .github/workflows/cftest.yaml create mode 100644 .github/workflows/rspec.yaml diff --git a/.github/workflows/cftest.yaml b/.github/workflows/cftest.yaml deleted file mode 100644 index b1ee9a7..0000000 --- a/.github/workflows/cftest.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: cftest - -on: [push, pull_request] - -jobs: - test: - name: test - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: set up ruby 2.7 - uses: actions/setup-ruby@v1 - with: - ruby-version: 2.7.x - - name: install gems - run: gem install cfhighlander rspec - - name: set cfndsl spec - run: cfndsl -u - - name: cftest - run: rspec - env: - AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_REGION: ap-southeast-2 \ No newline at end of file diff --git a/.github/workflows/rspec.yaml b/.github/workflows/rspec.yaml new file mode 100644 index 0000000..d0a2ef8 --- /dev/null +++ b/.github/workflows/rspec.yaml @@ -0,0 +1,8 @@ +name: cftest + +on: [push, pull_request] + +jobs: + rspec: + uses: theonestack/shared-workflows/.github/workflows/rspec.yaml@main + secrets: inherit \ No newline at end of file diff --git a/spec/schedule_spec.rb b/spec/schedule_spec.rb index 1a20b90..acc3c57 100644 --- a/spec/schedule_spec.rb +++ b/spec/schedule_spec.rb @@ -1,77 +1,173 @@ require 'yaml' -describe 'should fail without a task_definition' do +describe 'compiled component ecs-runtask' do context 'cftest' do it 'compiles test' do expect(system("cfhighlander cftest #{@validate} --tests tests/schedule.test.yaml")).to be_truthy - end + end end - + let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/schedule/ecs-runtask.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 - - end - - context 'Resource StateMachine' do - let(:properties) { template["Resources"]["StateMachine"]["Properties"] } - - it 'has property StateMachineName' do - expect(properties["StateMachineName"]).to eq({"Fn::Sub"=>"${EnvironmentName}-ecs-runtask-RunTask"}) + + context "Resource" do + + + context "StepFunctionRole" do + let(:resource) { template["Resources"]["StepFunctionRole"] } + + 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({"Statement"=>[{"Effect"=>"Allow", "Principal"=>{"Service"=>["states.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"=>"run_task", "PolicyDocument"=>{"Statement"=>[{"Sid"=>"runtask", "Action"=>["ecs:RunTask", "iam:PassRole"], "Resource"=>"*", "Effect"=>"Allow"}]}}, {"PolicyName"=>"manage_task", "PolicyDocument"=>{"Statement"=>[{"Sid"=>"managetask", "Action"=>["ecs:StopTask", "ecs:DescribeTasks"], "Resource"=>"*", "Effect"=>"Allow"}]}}, {"PolicyName"=>"task_events", "PolicyDocument"=>{"Statement"=>[{"Sid"=>"taskevents", "Action"=>["events:PutTargets", "events:PutRule", "events:DescribeRule"], "Resource"=>[{"Fn::Sub"=>"arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForECSTaskRule"}], "Effect"=>"Allow"}]}}]) + end + end - - it 'has property RoleArn' do - expect(properties["RoleArn"]).to eq({"Fn::GetAtt" => ["StepFunctionRole", "Arn"]}) + + context "StateMachine" do + let(:resource) { template["Resources"]["StateMachine"] } + + it "is of type AWS::StepFunctions::StateMachine" do + expect(resource["Type"]).to eq("AWS::StepFunctions::StateMachine") + end + + it "to have property StateMachineName" do + expect(resource["Properties"]["StateMachineName"]).to eq({"Fn::Sub"=>"${EnvironmentName}-ecs-runtask-RunTask"}) + end + + it "to have property RoleArn" do + expect(resource["Properties"]["RoleArn"]).to eq({"Fn::GetAtt"=>["StepFunctionRole", "Arn"]}) + end + + it "to have property DefinitionString" do + expect(resource["Properties"]["DefinitionString"]).to eq({"Fn::Sub"=>["{\n \"Comment\": \"\",\n \"StartAt\": \"Run Task\",\n \"TimeoutSeconds\": 3600,\n \"States\": {\n \"Run Task\": {\n \"Type\": \"Task\",\n \"Resource\": \"arn:aws:states:::ecs:runTask.sync\",\n \"Parameters\": {\n \"LaunchType\": \"FARGATE\",\n \"Cluster\": \"${EcsCluster}\",\n \"TaskDefinition\": \"${Task}\",\n \"NetworkConfiguration\": {\n \"AwsvpcConfiguration\": {\n \"Subnets\": [\"${SubnetId}\"],\n \"SecurityGroups\": [\"${SecurityGroup}\"],\n \"AssignPublicIp\": \"DISABLED\"\n }\n }\n },\n \"Next\": \"Success\",\n \"Catch\": [\n {\n \"ErrorEquals\": [ \"States.ALL\" ],\n \"Next\": \"Failure\"\n }\n ]\n },\n \"Success\": {\n \"Type\": \"Succeed\"\n },\n \"Failure\": {\n \"Type\": \"Fail\"\n }\n }\n}", {"SubnetId"=>{"Fn::Select"=>[0, {"Ref"=>"SubnetIds"}]}, "Task"=>{"Ref"=>"Task"}}]}) + end + end - - it 'has property DefinitionString' do - expect(properties["DefinitionString"]).not_to be_nil + + context "SecurityGroup" do + let(:resource) { template["Resources"]["SecurityGroup"] } + + it "is of type AWS::EC2::SecurityGroup" do + expect(resource["Type"]).to eq("AWS::EC2::SecurityGroup") + end + + it "to have property VpcId" do + expect(resource["Properties"]["VpcId"]).to eq({"Ref"=>"VPCId"}) + end + + it "to have property GroupDescription" do + expect(resource["Properties"]["GroupDescription"]).to eq({"Fn::Sub"=>"${EnvironmentName}-ecs-runtask ecs runtask"}) + end + end - end - - context 'Resource Schedule' do - let(:properties) { template["Resources"]["Schedule"]["Properties"] } - - it 'has property Name' do - expect(properties["Name"]).to eq({"Fn::Sub"=>"${EnvironmentName}-ecs-runtask-eventrule"}) + + context "EventBridgeInvokeRole" do + let(:resource) { template["Resources"]["EventBridgeInvokeRole"] } + + 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({"Statement"=>[{"Effect"=>"Allow", "Principal"=>{"Service"=>["events.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"=>"event_schedule", "PolicyDocument"=>{"Statement"=>[{"Sid"=>"eventschedule", "Action"=>["states:StartExecution"], "Resource"=>[{"Fn::Sub"=>"${StateMachine}"}], "Effect"=>"Allow"}]}}]) + end + end - - it 'has property Description' do - expect(properties["Description"]).to eq({"Fn::Sub"=>"{EnvironmentName} ecs-runtask eventrule"}) + + context "Schedule" do + let(:resource) { template["Resources"]["Schedule"] } + + it "is of type AWS::Events::Rule" do + expect(resource["Type"]).to eq("AWS::Events::Rule") + end + + it "to have property Name" do + expect(resource["Properties"]["Name"]).to eq({"Fn::Sub"=>"${EnvironmentName}-ecs-runtask-eventrule"}) + end + + it "to have property Description" do + expect(resource["Properties"]["Description"]).to eq({"Fn::Sub"=>"{EnvironmentName} ecs-runtask eventrule"}) + end + + it "to have property ScheduleExpression" do + expect(resource["Properties"]["ScheduleExpression"]).to eq("* * * * *") + end + + it "to have property Targets" do + expect(resource["Properties"]["Targets"]).to eq([{"Arn"=>{"Ref"=>"StateMachine"}, "Id"=>{"Fn::Sub"=>"{EnvironmentName}-ecs-runtask-target"}, "RoleArn"=>{"Fn::GetAtt"=>["EventBridgeInvokeRole", "Arn"]}}]) + end + end - - it 'has property ScheduleExpression' do - expect(properties["ScheduleExpression"]).to eq('* * * * *') + + 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 - - it 'has property Targets' do - expect(properties["Targets"]).to eq([{ - "Arn"=>{"Ref"=>"StateMachine"}, - "Id"=> {"Fn::Sub"=>"{EnvironmentName}-ecs-runtask-target"}, - "RoleArn"=>{"Fn::GetAtt"=>["EventBridgeInvokeRole", "Arn"]} - }]) + + 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"=>"dummy", "Image"=>{"Fn::Join"=>["", ["", "apline", ":", {"Ref"=>"ecsruntaskTaskVersion"}]]}, "LogConfiguration"=>{"LogDriver"=>"awslogs", "Options"=>{"awslogs-group"=>{"Ref"=>"LogGroup"}, "awslogs-region"=>{"Ref"=>"AWS::Region"}, "awslogs-stream-prefix"=>"dummy"}}}]) + 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"=>"ecsruntaskTask"}, {"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}}]) + end + end - + end - - -end +end \ No newline at end of file