<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:og="http://ogp.me/ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:schema="http://schema.org/" xmlns:sioc="http://rdfs.org/sioc/ns#" xmlns:sioct="http://rdfs.org/sioc/types#" xmlns:skos="http://www.w3.org/2004/02/skos/core#" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" version="2.0" xml:base="http://badzilla.co.uk/">
  <channel>
    <title>bash</title>
    <link>http://badzilla.co.uk/</link>
    <description/>
    <language>en</language>
    
    <item>
  <title>AWS Fargate Static Analysis with PHP</title>
  <link>http://badzilla.co.uk/aws-fargate-static-analysis-php</link>
  <description>
&lt;span&gt;AWS Fargate Static Analysis with PHP&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Mon, 13/01/2020 - 14:28&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;In my earlier blog on &lt;a href="http://badzilla.co.uk/aws-fargate-automated-testing-cucumber-gherkin-java-maven-selenium-grid-hub-and-chrome-and-firefox"&gt;AWS Fargate Automated Testing&lt;/a&gt; I spoke about creating an AWS Fargate task definition which would include a web app's codebase and the Cucumber / Gherkin / maven / Java runtime stack. This tutorial is an opportunity to look at the static analysis stage of the pipeline where code is inspected for vulnerabilities, coding standards, compilation errors, copy and paste detection amongst others. Since my background is in Drupal and PHP, my tests will be focused around the PHP language and will use the excellent &lt;a href="https://github.com/jakzal/phpqa"&gt;Static Analysis Tools for PHP repo&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Looking at the jakzal/phpqa repo, it is clear there is a great deal of tooling available. The purpose of this tutorial is take a small sample of these tools and create a Fargate task to run them against my codebase. My somewhat arbitrary selection is:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;phpcpd - Copy/paste detection&lt;/li&gt;
	&lt;li&gt;phpcs - Codesniffer that detects coding standards violations&lt;/li&gt;
	&lt;li&gt;phplint - PHP syntax error checker. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok - let's get started. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Create the Dockerfile and the Entrypoint&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;As I have previously mentioned, Fargate is a black box and it doesn't lend itself to command line invocation of the tooling. Typically locally on a laptop we would run the jakzal/phpqa Docker image like: 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$  docker run &lt;span style="color: #660033;"&gt;-it&lt;/span&gt; &lt;span style="color: #660033;"&gt;--rm&lt;/span&gt; &lt;span style="color: #660033;"&gt;-v&lt;/span&gt; $&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;PWD&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;:&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;project &lt;span style="color: #660033;"&gt;-w&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;project  jakzal&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;phpqa phpcpd web&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;core&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;modules&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;views&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;src
$  docker run &lt;span style="color: #660033;"&gt;-it&lt;/span&gt; &lt;span style="color: #660033;"&gt;--rm&lt;/span&gt; &lt;span style="color: #660033;"&gt;-v&lt;/span&gt; $&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;PWD&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;:&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;project &lt;span style="color: #660033;"&gt;-w&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;project  jakzal&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;phpqa phpcs web&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;core&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;modules&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;views&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;src
$  docker run &lt;span style="color: #660033;"&gt;-it&lt;/span&gt; &lt;span style="color: #660033;"&gt;--rm&lt;/span&gt; &lt;span style="color: #660033;"&gt;-v&lt;/span&gt; $&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;PWD&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;:&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;project &lt;span style="color: #660033;"&gt;-w&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;project  jakzal&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;phpqa phplint web&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;core&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;modules&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;views&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;src&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
This could obviously be placed in a shell script. Now in Fargate we don't have access to the command line and we have to create a Fargate definition up front before that can be provisioned and then run. So it's a little bit more involved. &lt;br /&gt;&lt;br /&gt;
The simplest approach is to create a Dockerfile based on the jakzal/phpqa repo, and an extrypoint script that will run each one of the tools I have identified. &lt;br /&gt;&lt;br /&gt;The Dockerfile is defined below. Note that I have selected PHP version 7.2. This is the closest supported version of PHP to what I'm running on my production box. Think I need to upgrade that at some point..
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;FROM jakzal&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;phpqa:1.28.1-php7.2
ADD entry.sh &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;entry.sh
RUN &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;bash&lt;/span&gt; &lt;span style="color: #660033;"&gt;-c&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'chmod +x /entry.sh'&lt;/span&gt;
ENTRYPOINT &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"/entry.sh"&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Next up is the entry.sh file. First thing to note is I have added the &lt;strong&gt;set +e&lt;/strong&gt; flag, which is default anyway. This is included to ensure that even if I get some pernickety error messages the script won't terminate immediately, and it acts as an aide memoire that we don't want error termination so don't accidentally copy paste in a competing &lt;strong&gt;set -e&lt;/strong&gt; flag. &lt;br /&gt;&lt;br /&gt;There is then a check whether the shared ECS volume has been loaded - this is the responsibility of the codebase container, but because containers can start at varying times, I have to ensure I don't run the PHP analysis before the volume is ready. &lt;br /&gt;&lt;br /&gt;The path to the source code to perform the analysis on is defined as /var/static_tests/web/core/modules/views/src. This has two components. The first part /var/static_tests/ is the mount point which will correspond to my codebase top level directory. The second component, web/core/modules/views/src points to the core contributed Drupal Views module. This is purely there as a reference to some arbitrary code. I am using the codebase to my own Badzilla which is a site build with no custom code and thus I have none of my own code to use in this sample. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;#!/usr/bin/env sh&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;set&lt;/span&gt; +e
 
&lt;span style="color: #000000; font-weight: bold;"&gt;while&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;!&lt;/span&gt; &lt;span style="color: #660033;"&gt;-d&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;static_tests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;web &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;do&lt;/span&gt;
  &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sleep&lt;/span&gt; &lt;span style="color: #000000;"&gt;5&lt;/span&gt;
  &lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Waiting for volume to be mounted and files copied into position"&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;done&lt;/span&gt;
 
phpcpd &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;static_tests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;web&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;core&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;modules&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;views&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;src
phpcs &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;static_tests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;web&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;core&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;modules&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;views&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;src
phplint &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;static_tests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;web&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;core&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;modules&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;views&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;src&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Building the Docker image locally&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;It isn't mandatory to test everything works before constructing the Fargate task definition, but it makes sense to me to test my work locally first. If the Fargate task subsequently fails then I know the problem area will be localised to the AWS eco-system, and probably to Fargate. So I always build locally and run locally first. To build I cd into my Dockerfile / entry.sh entry and issue:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;docker build &lt;span style="color: #660033;"&gt;-f&lt;/span&gt; Dockerfile &lt;span style="color: #660033;"&gt;-t&lt;/span&gt; static-fargate  .&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
To run it's 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;docker run &lt;span style="color: #660033;"&gt;-it&lt;/span&gt; &lt;span style="color: #660033;"&gt;--rm&lt;/span&gt; &lt;span style="color: #660033;"&gt;-v&lt;/span&gt; $&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;PWD&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;:&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;static_tests  static-fargate &lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
You can see above I am establishing the Docker volume which will be shared with my codebase.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The Docker Hub repo for this is at &lt;a href="https://hub.docker.com/repository/docker/sanddevil/static-fargate"&gt;https://hub.docker.com/repository/docker/sanddevil/static-fargate&lt;/a&gt; and the GitHub repo for the code is at &lt;a href="https://github.com/sanddevil/devops-static-php"&gt;https://github.com/sanddevil/devops-static-php&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Define the Fargate task&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;With everything working locally it's time to build the Fargate task. This is very similar to the script I created in my earlier automated testing blog. There are a few differences obviously. My container stack comprises of a combined PHP + Apache + my own codebase image, and the PHP static analysis  jakzal/phpqa obviously. I use the shell script heredoc convention to define each container. You should note I have now expanded my codebase container to include two shared volumes - one for the automated tests (not discussed here but discussed previously) and the static tests. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;#!/bin/bash&lt;/span&gt;
 
 
&lt;span style="color: #007800;"&gt;BRANCH&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"master"&lt;/span&gt;
&lt;span style="color: #007800;"&gt;REPO&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"php7.0-apache/&lt;span style="color: #007800;"&gt;${BRANCH}&lt;/span&gt;"&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Repo account and repo&lt;/span&gt;
&lt;span style="color: #007800;"&gt;ECR_ACCOUNT&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"xxxxxxxxxxx.dkr.ecr.eu-west-2.amazonaws.com"&lt;/span&gt;
&lt;span style="color: #007800;"&gt;ECR_REPO&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${ECR_ACCOUNT}&lt;/span&gt;/&lt;span style="color: #007800;"&gt;${REPO,,}&lt;/span&gt;"&lt;/span&gt;
&lt;span style="color: #007800;"&gt;ECS_CLUSTER&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"FargatePrototype"&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Get the Task Role ARN for executing the task&lt;/span&gt;
&lt;span style="color: #007800;"&gt;TASK_ARN&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws iam get-role &lt;span style="color: #660033;"&gt;--role-name&lt;/span&gt; ecsTaskExecutionRole &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq .Role.Arn -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Execution ARN appears to be the same as the Task ARN&lt;/span&gt;
&lt;span style="color: #007800;"&gt;EXECUTION_ARN&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${TASK_ARN}&lt;/span&gt;"&lt;/span&gt;
 
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Determine if the log group already exists: NOTE: "aws ecs register-task-definition" will not create the log group for you!&lt;/span&gt;
&lt;span style="color: #007800;"&gt;LOG_EXISTS&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws logs describe-log-groups &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #ff0000;"&gt;".logGroups[] | select(.logGroupName == &lt;span style="color: #000099; font-weight: bold;"&gt;\"&lt;/span&gt;/ecs/"&lt;/span&gt;&lt;span style="color: #800000;"&gt;${BRANCH}&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #000099; font-weight: bold;"&gt;\"&lt;/span&gt;) | .logGroupName"&lt;/span&gt; &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;wc&lt;/span&gt; -l&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${LOG_EXISTS}&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #660033;"&gt;-eq&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	aws logs create-log-group &lt;span style="color: #660033;"&gt;--log-group-name&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"/ecs/&lt;span style="color: #007800;"&gt;${BRANCH}&lt;/span&gt;"&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;CONTAINER_CODEBASE&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOF
	{
		"dnsSearchDomains": [],
		"logConfiguration": {
			"logDriver": "awslogs",
			"options": {
				"awslogs-group": "/ecs/${BRANCH}",
				"awslogs-region": "eu-west-2",
				"awslogs-stream-prefix": "ecs"
			}
		},
		"entryPoint": [
			"/usr/local/bin/entry.sh"
		],
		"portMappings": [{
			"hostPort": 80,
			"protocol": "tcp",
			"containerPort": 80
		}],
		"command": [],
		"cpu": 0,
		"image": "${ECR_REPO}",
		"name": "PHPApacheCodebase",
		"mountPoints": [{
			"sourceVolume": "automated_tests",
			"containerPath": "/var/automated_tests",
			"readOnly": false
		},{
			"sourceVolume": "static_tests",
			"containerPath": "/var/static_tests",
			"readOnly": false
		}]
	}
EOF&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;CONTAINER_STATIC_PHP&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOF
	{
		"dnsSearchDomains": [],
		"logConfiguration": {
			"logDriver": "awslogs",
			"options": {
				"awslogs-group": "/ecs/${BRANCH}",
				"awslogs-region": "eu-west-2",
				"awslogs-stream-prefix": "ecs"
			}
		},
		"entryPoint": [],
		"portMappings": [],
		"command": [],
		"cpu": 0,
		"image": "registry.hub.docker.com/sanddevil/static-fargate",
		"name": "StaticPHP",
		"essential": true,
		"mountPoints": [{
			"sourceVolume": "static_tests",
			"containerPath": "/var/static_tests"
		}]
	}
EOF&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
 
&lt;span style="color: #007800;"&gt;CONTAINERS_STATIC&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOF
[
${CONTAINER_CODEBASE},
${CONTAINER_STATIC_PHP}
]
EOF&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
 
aws ecs register-task-definition \
  &lt;span style="color: #660033;"&gt;--family&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"STATIC-&lt;span style="color: #007800;"&gt;${BRANCH}&lt;/span&gt;"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--volumes&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"name=static_tests,host={}"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"name=automated_tests,host={}"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--task-role-arn&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$TASK_ARN&lt;/span&gt;"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--execution-role-arn&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${EXECUTION_ARN}&lt;/span&gt;"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--network-mode&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"awsvpc"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--container-definitions&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${CONTAINERS_STATIC}&lt;/span&gt;"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--cpu&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"256"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--memory&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"512"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--requires-compatibilities&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"FARGATE"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
I'm not quite done yet though. Somehow I need to copy my codebase into the shared Docker volume so that the PHP static analysis container can see it. This is done in the entry.sh script of my PHP + Apache + Codebase image (not discussed here) but the entry.sh file is shown below for completeness. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;#!/bin/bash&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;set&lt;/span&gt; &lt;span style="color: #660033;"&gt;-e&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Copy the automated tests into a shared area accessible to maven&lt;/span&gt;
&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cp&lt;/span&gt; &lt;span style="color: #660033;"&gt;-R&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;test&lt;/span&gt;  &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;automated_tests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;.
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Copy the PHP codebase into a shared area accessible to the PHP static analysis container&lt;/span&gt;
&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cp&lt;/span&gt; &lt;span style="color: #660033;"&gt;-R&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;web  &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;static_tests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;.
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Run Apache in the foreground to prevent the container from quitting&lt;/span&gt;
apache2-foreground&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Here you can see the copying I do for both the automated tests and the static analysis.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Running the Fargate task&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2020-01/Screenshot_2020-01-14_at_14_54_17-edited.png?itok=SEUKoW46 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2020-01/Screenshot_2020-01-14_at_14_54_17-edited.png?itok=H29PqVpt 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2020-01/Screenshot_2020-01-14_at_14_54_17-edited.png?itok=vDraWtWi 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2020-01/Screenshot_2020-01-14_at_14_54_17-edited.png?itok=9FcxZ4b4 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2020-01/Screenshot_2020-01-14_at_14_54_17-edited.png?itok=SEUKoW46" alt="Task Running" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2020-01/Screenshot_2020-01-14_at_14_54_37-edited.png?itok=dd27IZ5a 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2020-01/Screenshot_2020-01-14_at_14_54_37-edited.png?itok=pt6QQe2a 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2020-01/Screenshot_2020-01-14_at_14_54_37-edited.png?itok=sCz9YTr5 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2020-01/Screenshot_2020-01-14_at_14_54_37-edited.png?itok=eTY4vp7U 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2020-01/Screenshot_2020-01-14_at_14_54_37-edited.png?itok=dd27IZ5a" alt="CloudWatch Logs" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Normally I would invoke the Fargate task programmatically using AWS CLI but since that leads to a rather dry image-free blog, I will use the console in this instance. My previous blog shows how to navigate around the ECS dashboard to run the task, then you can see the task running in the first screenshot above. It will only run until the entrypoint script terminates as per the rules on how Docker works, so to capture that scrennshot I had to be quick. The second screenshot shows the CloudWatch logs for the task, and you can see there are a few copy/paste errors detected. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/aws" hreflang="en"&gt;AWS&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/awscli" hreflang="en"&gt;AWS CLI&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/ecs" hreflang="en"&gt;ECS&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/docker" hreflang="en"&gt;Docker&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/bash" hreflang="en"&gt;bash&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Mon, 13 Jan 2020 14:28:49 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">176 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>AWS Fargate Automated Testing with Cucumber, Gherkin, Java, Maven, Selenium Grid Hub and Chrome and Firefox Nodes</title>
  <link>http://badzilla.co.uk/aws-fargate-automated-testing-cucumber-gherkin-java-maven-selenium-grid-hub-and-chrome-and-firefox</link>
  <description>
&lt;span&gt;AWS Fargate Automated Testing with Cucumber, Gherkin, Java, Maven, Selenium Grid Hub and Chrome and Firefox Nodes&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Mon, 09/12/2019 - 08:37&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Tutorial for creating an automated testing AWS Fargate task that will include Docker containers for a full testing framework:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Maven for build automation&lt;/li&gt;
	&lt;li&gt;Java Runtime to enable the execution of maven and the junit unit testing framework&lt;/li&gt;
	&lt;li&gt;Java Cucumber - a tool for BDD testing&lt;/li&gt;
	&lt;li&gt;Gherkin to define behaviours in the English language&lt;/li&gt;
	&lt;li&gt;Selenium Hub being the central loading point for the tests&lt;/li&gt;
	&lt;li&gt;Selenium Chrome - one of the nodes&lt;/li&gt;
	&lt;li&gt;Selenium Firefox - a second node&lt;/li&gt;
	&lt;li&gt;Apache / PHP - the web app and web server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a trivial exercise but by the end of the blog I will have a working automated testing environment which can be slotted into a DevOps pipeline. Please note this blog is not a tutorial on how to write Cucumber / Gherkin tests, however I will create a few sample Gherkin behaviours and their respective Java Cucumber stepdefs as a starting point. These can then be expanded out by your QA team. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Starting Point&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The starting point will be the simple PHP/Apache web app I put together in my previous blog &lt;a href="http://badzilla.co.uk/programmatically-create-aws-ecr-repository-and-commit-docker-image-ecr"&gt;here&lt;/a&gt; - this is a single url website which merely shows the phpinfo() status page. But it's ideal for our automated testing because our testing framework is plenty complex already, and we can still run a few tests against this simple landing page such as whether the additional PHP extensions I included in the Dockerfile are loaded correctly. &lt;/p&gt;

&lt;p&gt;Now we need to build out our testing tree structure. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;At a sibling level to the docroot directory I created in the previous blog, create the following:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; &lt;span style="color: #660033;"&gt;-p&lt;/span&gt; mytests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;test&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;java&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;mytests
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; &lt;span style="color: #660033;"&gt;-p&lt;/span&gt; mytests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;test&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;resources&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;mytests&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now it's time to create the files I need
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; mytests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; pom.xml
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;test&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;java&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;mytests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;RunCucumberTest.java
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;test&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;java&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;mytests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Stepdefs.java
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;test&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;java&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;mytests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;SetupTestDriver.java
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;test&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;resources&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;mytests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;home_page.feature&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
This will create a tree structure like this:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;tree&lt;/span&gt;
.
&lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;-- pom.xml
&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;-- src
    &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;-- &lt;span style="color: #7a0874; font-weight: bold;"&gt;test&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;-- &lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;   &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;-- mytests
        &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;       &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;-- RunCucumberTest.java
        &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;       &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;-- SetupTestDriver.java
        &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;       &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;-- Stepdefs.java
        &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;-- resources
            &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;-- mytests
                &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;-- home_page.feature
 
&lt;span style="color: #000000;"&gt;6&lt;/span&gt; directories, &lt;span style="color: #000000;"&gt;5&lt;/span&gt; files&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now we need to flesh out those files we created. Firstly the pom file which contains a list of the project's dependencies. Careful inspection will show you that I used the hellocucumber template as my starting point.&lt;br /&gt;
&lt;strong&gt;pom.xml&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="xml geshifilter-xml" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;?xml&lt;/span&gt; &lt;span style="color: #000066;"&gt;version&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"1.0"&lt;/span&gt; &lt;span style="color: #000066;"&gt;encoding&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"UTF-8"&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;project&lt;/span&gt; &lt;span style="color: #000066;"&gt;xmlns&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"http://maven.apache.org/POM/4.0.0"&lt;/span&gt;&lt;/span&gt;
&lt;span style="color: #009900;"&gt;         &lt;span style="color: #000066;"&gt;xmlns:xsi&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;&lt;/span&gt;
&lt;span style="color: #009900;"&gt;         &lt;span style="color: #000066;"&gt;xsi:schemaLocation&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;modelVersion&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;4.0.0&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/modelVersion&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;hellocucumber&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;mytests&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;1.0.0-SNAPSHOT&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;packaging&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;jar&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/packaging&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;properties&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;cucumber.version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;4.2.6&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/cucumber.version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;project.build.sourceEncoding&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;UTF-8&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/project.build.sourceEncoding&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/properties&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;dependencies&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;io.cucumber&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;cucumber-java&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;${cucumber.version}&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;scope&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;test&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/scope&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;io.cucumber&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;cucumber-junit&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;${cucumber.version}&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;scope&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;test&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/scope&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;junit&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;junit&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;4.12&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;scope&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;test&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/scope&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
    &lt;span style="color: #808080; font-style: italic;"&gt;&lt;!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager --&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;io.github.bonigarcia&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;webdrivermanager&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;3.7.1&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
	&lt;span style="color: #808080; font-style: italic;"&gt;&lt;!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java --&gt;&lt;/span&gt;
	&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    		&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;org.seleniumhq.selenium&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    		&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;selenium-java&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    		&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;3.141.59&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
    &lt;span style="color: #808080; font-style: italic;"&gt;&lt;!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-chrome-driver --&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;org.seleniumhq.selenium&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;selenium-chrome-driver&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;3.141.59&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
    &lt;span style="color: #808080; font-style: italic;"&gt;&lt;!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-surefire-plugin --&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;org.apache.maven.plugins&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;maven-surefire-plugin&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;2.22.2&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 
 
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;org.slf4j&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;slf4j-api&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;1.5.6&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;org.slf4j&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;slf4j-log4j12&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;1.5.6&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/dependency&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 
 
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/dependencies&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;build&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;plugins&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;plugin&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;org.apache.maven.plugins&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/groupId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;maven-compiler-plugin&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/artifactId&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;3.7.0&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/version&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;configuration&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
                    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;encoding&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;UTF-8&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/encoding&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
                    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;source&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;1.8&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/source&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
                    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;target&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;1.8&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/target&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/configuration&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/plugin&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/plugins&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/build&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style="color: #009900;"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;/project&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Now my Gherkin tests themselves. These are rather simple - I am checking for whether my GD and Memecached PHP extensions have been loaded, i.e. they are listed on the front page which just shows the entire PHP configuration. Under normal circumstances Gherkin test tend to be GIVEN..WHEN..THEN constructs, but since I am not actually doing anything (e.g. clicking a button to go somewhere) I only need WHEN..THEN&lt;br /&gt;
&lt;strong&gt;home_page.feature&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;Feature: Are we on the Home Page?
 
 
  Scenario: On the home page
    When User is on the Home Page
    Then Message Displayed Memcached
 
    When User is on the Home Page
    Then Message Displayed GD&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Next is the StepDef file where I convert the Gherkin into Cucumber Java containing the actual business logic behind the quasi-English Gherkin. I don't pretend to be an expert Java coder - I have the sum total of about 4 days experience. Therefore my code is probably sub-optimal, but it does the job and an in-house Java professional could whip it into shape. I have defined two browsers - Firefox and Chrome as per our Selenium configuration, although please note there is currently no semblance of parallel running of the tests in here. That again has been left to more talented Java practitioners than myself. &lt;br /&gt;
&lt;strong&gt;StepDefs.java&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="java geshifilter-java" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;package&lt;/span&gt; &lt;span style="color: #006699;"&gt;mytests&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;base.SetupTestDriver&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;java.util.concurrent.TimeUnit&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.By&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.WebDriver&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.chrome.ChromeDriver&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.firefox.FirefoxDriver&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;io.github.bonigarcia.wdm.WebDriverManager&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;cucumber.api.java.en.Given&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;cucumber.api.java.en.Then&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;cucumber.api.java.en.When&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;java.net.MalformedURLException&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;static&lt;/span&gt; org.&lt;span style="color: #006633;"&gt;junit&lt;/span&gt;.&lt;span style="color: #000000; font-weight: bold;"&gt;Assert&lt;/span&gt;.&lt;span style="color: #339933;"&gt;*;&lt;/span&gt;
 
 
&lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;class&lt;/span&gt; Stepdefs &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
 
	&lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;static&lt;/span&gt; WebDriver&lt;span style="color: #009900;"&gt;[&lt;/span&gt;&lt;span style="color: #009900;"&gt;]&lt;/span&gt; drivers&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;static&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt;&lt;span style="color: #009900;"&gt;[&lt;/span&gt;&lt;span style="color: #009900;"&gt;]&lt;/span&gt;&lt;span style="color: #009900;"&gt;[&lt;/span&gt;&lt;span style="color: #009900;"&gt;]&lt;/span&gt; browsers&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
    @When&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"User is on the Home Page"&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;
    &lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #000066; font-weight: bold;"&gt;void&lt;/span&gt; user_is_on_Home_Page&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;throws&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+throwable"&gt;&lt;span style="color: #003399;"&gt;Throwable&lt;/span&gt;&lt;/a&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
       	browsers &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt;&lt;span style="color: #009900;"&gt;[&lt;/span&gt;&lt;span style="color: #009900;"&gt;]&lt;/span&gt;&lt;span style="color: #009900;"&gt;[&lt;/span&gt;&lt;span style="color: #009900;"&gt;]&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
       		&lt;span style="color: #009900;"&gt;{&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"linux"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;"firefox"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;"http://127.0.0.1"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;"http://127.0.0.1:4444"&lt;/span&gt;&lt;span style="color: #009900;"&gt;}&lt;/span&gt;,
            &lt;span style="color: #009900;"&gt;{&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"linux"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;"chrome"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;"http://127.0.0.1"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;"http://127.0.0.1:4444"&lt;/span&gt;&lt;span style="color: #009900;"&gt;}&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;}&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
		drivers &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; WebDriver&lt;span style="color: #009900;"&gt;[&lt;/span&gt;browsers.&lt;span style="color: #006633;"&gt;length&lt;/span&gt;&lt;span style="color: #009900;"&gt;]&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;for&lt;/span&gt; &lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #000066; font-weight: bold;"&gt;int&lt;/span&gt; i &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #cc66cc;"&gt;0&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt; i &lt;span style="color: #339933;"&gt;&lt;&lt;/span&gt; browsers.&lt;span style="color: #006633;"&gt;length&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt; i&lt;span style="color: #339933;"&gt;++&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
        	drivers&lt;span style="color: #009900;"&gt;[&lt;/span&gt;i&lt;span style="color: #009900;"&gt;]&lt;/span&gt; &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; SetupTestDriver&lt;span style="color: #009900;"&gt;(&lt;/span&gt;browsers&lt;span style="color: #009900;"&gt;[&lt;/span&gt;i&lt;span style="color: #009900;"&gt;]&lt;/span&gt;&lt;span style="color: #009900;"&gt;[&lt;/span&gt;&lt;span style="color: #cc66cc;"&gt;0&lt;/span&gt;&lt;span style="color: #009900;"&gt;]&lt;/span&gt;, browsers&lt;span style="color: #009900;"&gt;[&lt;/span&gt;i&lt;span style="color: #009900;"&gt;]&lt;/span&gt;&lt;span style="color: #009900;"&gt;[&lt;/span&gt;&lt;span style="color: #cc66cc;"&gt;1&lt;/span&gt;&lt;span style="color: #009900;"&gt;]&lt;/span&gt;, browsers&lt;span style="color: #009900;"&gt;[&lt;/span&gt;i&lt;span style="color: #009900;"&gt;]&lt;/span&gt;&lt;span style="color: #009900;"&gt;[&lt;/span&gt;&lt;span style="color: #cc66cc;"&gt;2&lt;/span&gt;&lt;span style="color: #009900;"&gt;]&lt;/span&gt;, browsers&lt;span style="color: #009900;"&gt;[&lt;/span&gt;i&lt;span style="color: #009900;"&gt;]&lt;/span&gt;&lt;span style="color: #009900;"&gt;[&lt;/span&gt;&lt;span style="color: #cc66cc;"&gt;3&lt;/span&gt;&lt;span style="color: #009900;"&gt;]&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;.&lt;span style="color: #006633;"&gt;getDriver&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
 
    @Then&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"Message Displayed Memcached"&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;
    &lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #000066; font-weight: bold;"&gt;void&lt;/span&gt; message_displayed_memcached&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;throws&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+throwable"&gt;&lt;span style="color: #003399;"&gt;Throwable&lt;/span&gt;&lt;/a&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;for&lt;/span&gt; &lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #000066; font-weight: bold;"&gt;int&lt;/span&gt; i &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #cc66cc;"&gt;0&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt; i &lt;span style="color: #339933;"&gt;&lt;&lt;/span&gt; drivers.&lt;span style="color: #006633;"&gt;length&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt; i&lt;span style="color: #339933;"&gt;++&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
        	&lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+boolean"&gt;&lt;span style="color: #003399;"&gt;Boolean&lt;/span&gt;&lt;/a&gt; exists &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #339933;"&gt;!&lt;/span&gt;drivers&lt;span style="color: #009900;"&gt;[&lt;/span&gt;i&lt;span style="color: #009900;"&gt;]&lt;/span&gt;.&lt;span style="color: #006633;"&gt;findElements&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;By.&lt;span style="color: #006633;"&gt;name&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"module_memcached"&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;.&lt;span style="color: #006633;"&gt;isEmpty&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        	drivers&lt;span style="color: #009900;"&gt;[&lt;/span&gt;i&lt;span style="color: #009900;"&gt;]&lt;/span&gt;.&lt;span style="color: #006633;"&gt;quit&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        	assertTrue&lt;span style="color: #009900;"&gt;(&lt;/span&gt;exists&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
 
	@Then&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"Message Displayed GD"&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #000066; font-weight: bold;"&gt;void&lt;/span&gt; gd&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;throws&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+throwable"&gt;&lt;span style="color: #003399;"&gt;Throwable&lt;/span&gt;&lt;/a&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;for&lt;/span&gt; &lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #000066; font-weight: bold;"&gt;int&lt;/span&gt; i &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #cc66cc;"&gt;0&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt; i &lt;span style="color: #339933;"&gt;&lt;&lt;/span&gt; drivers.&lt;span style="color: #006633;"&gt;length&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt; i&lt;span style="color: #339933;"&gt;++&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
			&lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+boolean"&gt;&lt;span style="color: #003399;"&gt;Boolean&lt;/span&gt;&lt;/a&gt; exists &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #339933;"&gt;!&lt;/span&gt;drivers&lt;span style="color: #009900;"&gt;[&lt;/span&gt;i&lt;span style="color: #009900;"&gt;]&lt;/span&gt;.&lt;span style="color: #006633;"&gt;findElements&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;By.&lt;span style="color: #006633;"&gt;name&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"module_gd"&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;.&lt;span style="color: #006633;"&gt;isEmpty&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        	drivers&lt;span style="color: #009900;"&gt;[&lt;/span&gt;i&lt;span style="color: #009900;"&gt;]&lt;/span&gt;.&lt;span style="color: #006633;"&gt;quit&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        	assertTrue&lt;span style="color: #009900;"&gt;(&lt;/span&gt;exists&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
	&lt;span style="color: #009900;"&gt;}&lt;/span&gt;
&lt;span style="color: #009900;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The StepDef file doesn't contain any Firefox or Chrome webdriver startup configuration. This has been placed in a separate Java class.&lt;br /&gt;
&lt;strong&gt;SetupTestDriver.java&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="java geshifilter-java" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;// src/main/java/base/SetupTestDriver.java&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;package&lt;/span&gt; &lt;span style="color: #006699;"&gt;base&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.Platform&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.WebDriver&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.chrome.ChromeOptions&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.firefox.FirefoxOptions&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.firefox.FirefoxProfile&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.firefox.FirefoxDriverLogLevel&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.remote.RemoteWebDriver&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.openqa.selenium.Dimension&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;java.net.MalformedURLException&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;java.net.URL&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;java.util.concurrent.TimeUnit&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;class&lt;/span&gt; SetupTestDriver &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
    &lt;span style="color: #000000; font-weight: bold;"&gt;private&lt;/span&gt; WebDriver driver &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000066; font-weight: bold;"&gt;null&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #000000; font-weight: bold;"&gt;private&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; browser &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000066; font-weight: bold;"&gt;null&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #000000; font-weight: bold;"&gt;private&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; baseUrl &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000066; font-weight: bold;"&gt;null&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #000000; font-weight: bold;"&gt;private&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; os &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000066; font-weight: bold;"&gt;null&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #000000; font-weight: bold;"&gt;private&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; node &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000066; font-weight: bold;"&gt;null&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
    &lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; SetupTestDriver&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; os, &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; browser, &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; baseUrl, &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; node&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;throws&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+malformedurlexception"&gt;&lt;span style="color: #003399;"&gt;MalformedURLException&lt;/span&gt;&lt;/a&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;browser&lt;/span&gt; &lt;span style="color: #339933;"&gt;=&lt;/span&gt; browser&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;os&lt;/span&gt; &lt;span style="color: #339933;"&gt;=&lt;/span&gt; os&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;baseUrl&lt;/span&gt; &lt;span style="color: #339933;"&gt;=&lt;/span&gt; baseUrl&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;node&lt;/span&gt; &lt;span style="color: #339933;"&gt;=&lt;/span&gt; node&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
        Platform platform &lt;span style="color: #339933;"&gt;=&lt;/span&gt; Platform.&lt;span style="color: #006633;"&gt;fromString&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;os.&lt;span style="color: #006633;"&gt;toUpperCase&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;browser.&lt;span style="color: #006633;"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"chrome"&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
            ChromeOptions chromeOptions &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; ChromeOptions&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
            chromeOptions.&lt;span style="color: #006633;"&gt;addArguments&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"--headless"&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
            chromeOptions.&lt;span style="color: #006633;"&gt;setCapability&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"platform"&lt;/span&gt;, platform&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
            &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;driver&lt;/span&gt; &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; RemoteWebDriver&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+url"&gt;&lt;span style="color: #003399;"&gt;URL&lt;/span&gt;&lt;/a&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;node &lt;span style="color: #339933;"&gt;+&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;"/wd/hub"&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;, chromeOptions&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;}&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;else&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #009900;"&gt;(&lt;/span&gt;browser.&lt;span style="color: #006633;"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"firefox"&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
            FirefoxOptions firefoxOptions &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; FirefoxOptions&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
            firefoxOptions.&lt;span style="color: #006633;"&gt;setProfile&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; FirefoxProfile&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
            firefoxOptions.&lt;span style="color: #006633;"&gt;setCapability&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"platform"&lt;/span&gt;, platform&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
            firefoxOptions.&lt;span style="color: #006633;"&gt;setHeadless&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #000066; font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
            &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;driver&lt;/span&gt; &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; RemoteWebDriver&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+url"&gt;&lt;span style="color: #003399;"&gt;URL&lt;/span&gt;&lt;/a&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;node &lt;span style="color: #339933;"&gt;+&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;"/wd/hub"&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;, firefoxOptions&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
 
        &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;driver&lt;/span&gt;.&lt;span style="color: #006633;"&gt;manage&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;.&lt;span style="color: #006633;"&gt;timeouts&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;.&lt;span style="color: #006633;"&gt;implicitlyWait&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #cc66cc;"&gt;10&lt;/span&gt;, TimeUnit.&lt;span style="color: #006633;"&gt;SECONDS&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #666666; font-style: italic;"&gt;// Maximizing the screen doesn't appear to work.&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;driver&lt;/span&gt;.&lt;span style="color: #006633;"&gt;manage&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;.&lt;span style="color: #006633;"&gt;window&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;.&lt;span style="color: #006633;"&gt;setSize&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;new&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+dimension"&gt;&lt;span style="color: #003399;"&gt;Dimension&lt;/span&gt;&lt;/a&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #cc66cc;"&gt;1600&lt;/span&gt;,&lt;span style="color: #cc66cc;"&gt;900&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;driver&lt;/span&gt;.&lt;span style="color: #006633;"&gt;get&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;baseUrl&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
    &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
 
    &lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; getOs&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;return&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;os&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
 
    &lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; getBrowser&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;return&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;browser&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
 
    &lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; getBaseUrl&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;return&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;baseUrl&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
 
    &lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string"&gt;&lt;span style="color: #003399;"&gt;String&lt;/span&gt;&lt;/a&gt; getNode&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;return&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;node&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
 
    &lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; WebDriver getDriver&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
        &lt;span style="color: #000000; font-weight: bold;"&gt;return&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;this&lt;/span&gt;.&lt;span style="color: #006633;"&gt;driver&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
    &lt;span style="color: #009900;"&gt;}&lt;/span&gt;
&lt;span style="color: #009900;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Finally there's some code to perform the glue between Gherkin and Cucumber.&lt;br /&gt;
&lt;strong&gt;RunCucumberTest.java&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="java geshifilter-java" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;package&lt;/span&gt; &lt;span style="color: #006699;"&gt;mytests&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;cucumber.api.CucumberOptions&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;cucumber.api.junit.Cucumber&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: #006699;"&gt;org.junit.runner.RunWith&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
 
@RunWith&lt;span style="color: #009900;"&gt;(&lt;/span&gt;Cucumber.&lt;span style="color: #000000; font-weight: bold;"&gt;class&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;
@CucumberOptions&lt;span style="color: #009900;"&gt;(&lt;/span&gt;plugin &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"pretty"&lt;/span&gt;&lt;span style="color: #009900;"&gt;}&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;class&lt;/span&gt; RunCucumberTest &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
&lt;span style="color: #009900;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Build the Docker Codebase + PHP/Apache&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;In my previous blog &lt;a href="http://badzilla.co.uk/programmatically-create-aws-ecr-repository-and-commit-docker-image-ecr"&gt;here&lt;/a&gt; I showed how to add the codebase to the php:7.2-apache image. The codebase has now changed, and I now have two top level sibling directories &lt;em&gt;docroot&lt;/em&gt; and &lt;em&gt;mytests &lt;/em&gt;- which contains the automated test code I've just added. There is a change we need to make to the &lt;em&gt;Dockerfile&lt;/em&gt; in this revision, and the inclusion of an entrypoint script called &lt;em&gt;entry.sh&lt;/em&gt;. The &lt;em&gt;entry.sh &lt;/em&gt;file will copy the test code suite into a shared Fargate non-persistent drive so that the Maven container can access the codebase and run the tests against it. Once the copy of files has been completed, Apache must be run in foreground mode to prevent the container from quitting. Below we have the new version of the &lt;em&gt;Dockerfile&lt;/em&gt;, and the &lt;em&gt;entry.sh&lt;/em&gt; file. The image needs to be rebuilt, but since that was covered in the previous blog, it is omitted here. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;FROM php:&lt;span style="color: #000000;"&gt;7.2&lt;/span&gt;-apache
RUN &lt;span style="color: #c20cb9; font-weight: bold;"&gt;apt-get update&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;apt-get install&lt;/span&gt; &lt;span style="color: #660033;"&gt;-y&lt;/span&gt; libmemcached-dev zlib1g-dev \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    libpng-dev \
    libwebp-dev \
    &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; pecl &lt;span style="color: #c20cb9; font-weight: bold;"&gt;install&lt;/span&gt; memcached \
    &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; docker-php-ext-enable memcached \
    &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; docker-php-ext-configure gd &lt;span style="color: #660033;"&gt;--with-gd&lt;/span&gt; &lt;span style="color: #660033;"&gt;--with-webp-dir&lt;/span&gt; &lt;span style="color: #660033;"&gt;--with-jpeg-dir&lt;/span&gt; \
       &lt;span style="color: #660033;"&gt;--with-png-dir&lt;/span&gt; &lt;span style="color: #660033;"&gt;--with-zlib-dir&lt;/span&gt; &lt;span style="color: #660033;"&gt;--with-freetype-dir&lt;/span&gt; \
    &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; docker-php-ext-install gd
COPY &lt;span style="color: #660033;"&gt;--chown&lt;/span&gt;=www-data:www-data .&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;.
COPY entry.sh &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;local&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;.
ENV AH_SITE_ENVIRONMENT devops
ENV APACHE_DOCUMENT_ROOT &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;docroot
RUN &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sed&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ri&lt;/span&gt; &lt;span style="color: #660033;"&gt;-e&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'s!/var/www/html!${APACHE_DOCUMENT_ROOT}!g'&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;etc&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;apache2&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;sites-available&lt;span style="color: #000000; font-weight: bold;"&gt;/*&lt;/span&gt;.conf
RUN &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sed&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ri&lt;/span&gt; &lt;span style="color: #660033;"&gt;-e&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'s!/var/www/!${APACHE_DOCUMENT_ROOT}!g'&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;etc&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;apache2&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;apache2.conf &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;etc&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;apache2&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;conf-available&lt;span style="color: #000000; font-weight: bold;"&gt;/*&lt;/span&gt;.conf
RUN &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;bash&lt;/span&gt; &lt;span style="color: #660033;"&gt;-c&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'chmod +x /usr/local/bin/entry.sh'&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;strong&gt;entry.sh&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;#!/bin/bash&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;set&lt;/span&gt; &lt;span style="color: #660033;"&gt;-e&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Copy the automated tests into a shared areaaccessible to maven&lt;/span&gt;
&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cp&lt;/span&gt; &lt;span style="color: #660033;"&gt;-R&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;mytests  &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;automated_tests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;.
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Run Apache in the foreground to prevent the container from quitting&lt;/span&gt;
apache2-foreground&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Maven:3.6.2-jdk-13&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The Java runtime is bundled with the Maven image if the correct tag is selected. I have opted for maven:3.6.2-jdk-13 which is up to date and supported. This requires a small amount of customisation, so again a Dockerfile will be needed. In this instance I want to put a wait loop in the entrypoint script to ensure that there's no attempt to run the tests before the non-persistent shared drive containing the test suite has been mounted by the d8codebase container. At the end I exec the &lt;em&gt;mvn clean install&lt;/em&gt; command to run the tests. &lt;/p&gt;

&lt;p&gt;The easiest way of achieving this is to edit the &lt;em&gt;mvn-entrypoint.sh &lt;/em&gt;script which is in &lt;em&gt;/usrlocal/bin.&lt;/em&gt; I copied out of the image to edit and the Dockerfile copies it back into place. &lt;/p&gt;

&lt;p&gt;Using my previous blog I built this, tagged and pushed to ECR using the image name &lt;em&gt;d8maven. &lt;/em&gt;The instructions aren't copied here for brevity reasons - please refer to my previous blog if you need to. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;FROM maven:3.6.2-jdk-&lt;span style="color: #000000;"&gt;13&lt;/span&gt;
COPY mvn-entrypoint.sh &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;local&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;mvn-entrypoint.sh
RUN &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;bash&lt;/span&gt; &lt;span style="color: #660033;"&gt;-c&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'chmod +x /usr/local/bin/mvn-entrypoint.sh'&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;strong&gt;mvn-entrypoint.sh&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;#! /bin/sh -eu&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Copy files from /usr/share/maven/ref into ${MAVEN_CONFIG}&lt;/span&gt;
&lt;span style="color: #666666; font-style: italic;"&gt;# So the initial ~/.m2 is set with expected content.&lt;/span&gt;
&lt;span style="color: #666666; font-style: italic;"&gt;# Don't override, as this is just a reference setup&lt;/span&gt;
 
copy_reference_files&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
  &lt;span style="color: #7a0874; font-weight: bold;"&gt;local&lt;/span&gt; &lt;span style="color: #007800;"&gt;log&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$MAVEN_CONFIG&lt;/span&gt;/copy_reference_file.log"&lt;/span&gt;
  &lt;span style="color: #7a0874; font-weight: bold;"&gt;local&lt;/span&gt; &lt;span style="color: #007800;"&gt;ref&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"/usr/share/maven/ref"&lt;/span&gt;
 
  &lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; &lt;span style="color: #660033;"&gt;-p&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${MAVEN_CONFIG}&lt;/span&gt;/repository"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${log}&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dev&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;null &lt;span style="color: #000000;"&gt;2&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt; ; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
      &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${ref}&lt;/span&gt;"&lt;/span&gt;
      &lt;span style="color: #7a0874; font-weight: bold;"&gt;local&lt;/span&gt; &lt;span style="color: #007800;"&gt;reflink&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;""&lt;/span&gt;
      &lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;cp&lt;/span&gt; &lt;span style="color: #660033;"&gt;--help&lt;/span&gt; &lt;span style="color: #000000;"&gt;2&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; &lt;span style="color: #660033;"&gt;-q&lt;/span&gt; reflink ; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
          &lt;span style="color: #007800;"&gt;reflink&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"--reflink=auto"&lt;/span&gt;
      &lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
      &lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-n&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$(find "${MAVEN_CONFIG}/repository" -maxdepth 0 -type d -empty 2&gt;/dev/null)&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt; ; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;# destination is empty...&lt;/span&gt;
          &lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"--- Copying all files to &lt;span style="color: #007800;"&gt;${MAVEN_CONFIG}&lt;/span&gt; at &lt;span style="color: #007800;"&gt;$(date)&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&gt;&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${log}&lt;/span&gt;"&lt;/span&gt;
          &lt;span style="color: #c20cb9; font-weight: bold;"&gt;cp&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rv&lt;/span&gt; &lt;span style="color: #800000;"&gt;${reflink}&lt;/span&gt; . &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${MAVEN_CONFIG}&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&gt;&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${log}&lt;/span&gt;"&lt;/span&gt;
      &lt;span style="color: #000000; font-weight: bold;"&gt;else&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;# destination is non-empty, copy file-by-file&lt;/span&gt;
          &lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"--- Copying individual files to &lt;span style="color: #007800;"&gt;${MAVEN_CONFIG}&lt;/span&gt; at &lt;span style="color: #007800;"&gt;$(date)&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&gt;&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${log}&lt;/span&gt;"&lt;/span&gt;
          &lt;span style="color: #c20cb9; font-weight: bold;"&gt;find&lt;/span&gt; . &lt;span style="color: #660033;"&gt;-type&lt;/span&gt; f &lt;span style="color: #660033;"&gt;-exec&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sh&lt;/span&gt; &lt;span style="color: #660033;"&gt;-eu&lt;/span&gt; &lt;span style="color: #660033;"&gt;-c&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'
              log="${1}"
              shift
              reflink="${1}"
              shift
              for f in "$@" ; do
                  if [ ! -e "${MAVEN_CONFIG}/${f}" ] || [ -e "${f}.override" ] ; then
                      mkdir -p "${MAVEN_CONFIG}/$(dirname "${f}")"
                      cp -rv ${reflink} "${f}" "${MAVEN_CONFIG}/${f}" &gt;&gt; "${log}"
                  fi
              done
          '&lt;/span&gt; _ &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${log}&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${reflink}&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt; +
      &lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
      &lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&gt;&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${log}&lt;/span&gt;"&lt;/span&gt;
  &lt;span style="color: #000000; font-weight: bold;"&gt;else&lt;/span&gt;
    &lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Can not write to &lt;span style="color: #007800;"&gt;${log}&lt;/span&gt;. Wrong volume permissions? Carrying on ..."&lt;/span&gt;
  &lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Wait until we see the test files that are being copied from the PHP/Apache/Codebase container to a shared volume.&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;while&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;!&lt;/span&gt; &lt;span style="color: #660033;"&gt;-d&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;automated_tests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;mytests &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;do&lt;/span&gt;
  &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sleep&lt;/span&gt; &lt;span style="color: #000000;"&gt;2&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;done&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;owd&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$(pwd)&lt;/span&gt;"&lt;/span&gt;
copy_reference_files
&lt;span style="color: #7a0874; font-weight: bold;"&gt;unset&lt;/span&gt; MAVEN_CONFIG
 
&lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${owd}&lt;/span&gt;"&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;unset&lt;/span&gt; owd
 
&lt;span style="color: #7a0874; font-weight: bold;"&gt;exec&lt;/span&gt; mvn &lt;span style="color: #660033;"&gt;-f&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;automated_tests&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;mytests &lt;span style="color: #660033;"&gt;-q&lt;/span&gt; clean &lt;span style="color: #c20cb9; font-weight: bold;"&gt;install&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Define the Fargate Task&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;I now have all parts I need apart from a shell script to actually define the Fargate task which will contain all the config for the containers. I have made extensive use of the heredoc convention in the shell script - one per container definition - which makes it easier to read, and also means when I come to make up other tasks (such as static analysis, and persistent playground) I can simple swap out those containers I don't need.&lt;br /&gt;
&lt;br /&gt;
There are a few comments here to note. &lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;You cannot create a Fargate Task without the IAM ecsTaskExecutionRole, but that will not be created for you. It is however created when you manually create your first Fargate task in the AWS console. Of course ecsTaskExecutionRole can be created programmatically too - and will be the subject of a block at another time.&lt;/li&gt;
	&lt;li&gt;The Fargate task definition will not create your CloudFront log group for you! Therefore I do a check in the script to see if it already exists, and if not then create.&lt;/li&gt;
	&lt;li&gt;I have defined a mount point to where I copy the test suite. This is because the test suite is in the code repository which is copied into the PHP/Apache container, but is needed by the Maven container also.&lt;/li&gt;
	&lt;li&gt;The Selenium Chrome browser is using a non-standard port 5556. This is because it would clash with Firefox otherwise which also defaults to port 5555. You must remember to use an environmental variable NODE_PORT to change the port as well as the hostPort and containerPort.&lt;/li&gt;
	&lt;li&gt;I have defaulted the task's compute to extremely high cpu and memory. They should be reduced using trial and error to avoid incurring high compute fees.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;#!/bin/bash&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Rewrite branch name so no feature/ hotfix/ forward slash&lt;/span&gt;
&lt;span style="color: #007800;"&gt;BRANCH&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"selenium-testing"&lt;/span&gt;
&lt;span style="color: #007800;"&gt;REPO&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"d8codebase"&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Repo account and repo&lt;/span&gt;
&lt;span style="color: #007800;"&gt;ECR_ACCOUNT&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"XXXXXXXXXXX.dkr.ecr.eu-west-2.amazonaws.com"&lt;/span&gt;
&lt;span style="color: #007800;"&gt;ECR_REPO&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${ECR_ACCOUNT}&lt;/span&gt;/&lt;span style="color: #007800;"&gt;${REPO,,}&lt;/span&gt;"&lt;/span&gt;
&lt;span style="color: #007800;"&gt;ECS_CLUSTER&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"default"&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Get the Task Role ARN for executing the task&lt;/span&gt;
&lt;span style="color: #007800;"&gt;TASK_ARN&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws iam get-role &lt;span style="color: #660033;"&gt;--role-name&lt;/span&gt; ecsTaskExecutionRole &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq .Role.Arn -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Execution ARN appears to be the same as the Task ARN&lt;/span&gt;
&lt;span style="color: #007800;"&gt;EXECUTION_ARN&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${TASK_ARN}&lt;/span&gt;"&lt;/span&gt;
 
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Determine if the log group already exists: NOTE: "aws ecs register-task-definition" will not create the log group for you!&lt;/span&gt;
&lt;span style="color: #007800;"&gt;LOG_EXISTS&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws logs describe-log-groups &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #ff0000;"&gt;".logGroups[] | select(.logGroupName == &lt;span style="color: #000099; font-weight: bold;"&gt;\"&lt;/span&gt;/ecs/"&lt;/span&gt;&lt;span style="color: #800000;"&gt;${BRANCH}&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #000099; font-weight: bold;"&gt;\"&lt;/span&gt;) | .logGroupName"&lt;/span&gt; &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;wc&lt;/span&gt; -l&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${LOG_EXISTS}&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #660033;"&gt;-eq&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	aws logs create-log-group &lt;span style="color: #660033;"&gt;--log-group-name&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"/ecs/&lt;span style="color: #007800;"&gt;${BRANCH}&lt;/span&gt;"&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;CONTAINER_CODEBASE&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOF
	{
		"dnsSearchDomains": [],
		"logConfiguration": {
			"logDriver": "awslogs",
			"options": {
				"awslogs-group": "/ecs/${BRANCH}",
				"awslogs-region": "eu-west-2",
				"awslogs-stream-prefix": "ecs"
			}
		},
		"entryPoint": [
			"/usr/local/bin/entry.sh"
		],
		"portMappings": [{
			"hostPort": 80,
			"protocol": "tcp",
			"containerPort": 80
		}],
		"command": [],
		"cpu": 0,
		"image": "${ECR_REPO}",
		"name": "d8codebase",
		"mountPoints": [{
			"sourceVolume": "automated_tests",
			"containerPath": "/var/automated_tests",
			"readOnly": false
		}]
	}
EOF&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;CONTAINER_SELENIUM_HUB&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOF
	{
		"dnsSearchDomains": [],
		"logConfiguration": {
			"logDriver": "awslogs",
			"options": {
				"awslogs-group": "/ecs/${BRANCH}",
				"awslogs-region": "eu-west-2",
				"awslogs-stream-prefix": "ecs"
			}
		},
		"entryPoint": [],
		"portMappings": [{
			"hostPort": 4444,
			"protocol": "tcp",
			"containerPort": 4444
		}],
		"command": [],
		"cpu": 0,
		"environment": [{
			"name": "SE_OPTS","value": "-debug"
		}],
		"image": "registry.hub.docker.com/selenium/hub:3.141.59-uranium",
		"name": "selenium-hub"
	}
EOF&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;CONTAINER_SELENIUM_FIREFOX&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOF
	{
		"dnsSearchDomains": [],
		"logConfiguration": {
			"logDriver": "awslogs",
			"options": {
				"awslogs-group": "/ecs/${BRANCH}",
				"awslogs-region": "eu-west-2",
				"awslogs-stream-prefix": "ecs"
			}
		},
		"entryPoint": [],
		"portMappings": [{
			"hostPort": 5555,
			"protocol": "tcp",
			"containerPort": 5555
		}],
		"command": [],
		"cpu": 0,
		"environment": [{
			"name": "NODE_MAX_INSTANCES", "value": "5"
		},{
			"name": "NODE_MAX_SESSIONS", "value": "5"
		},{
			"name": "HUB_HOST", "value": "127.0.0.1"
		},{
			"name": "HUB_PORT", "value": "4444"
		}],
		"image": "registry.hub.docker.com/selenium/node-firefox:3.141.59-uranium",
		"name": "SeleniumNodeFirefox"
	}
EOF&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;CONTAINER_SELENIUM_CHROME&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOF
 	{
 		"dnsSearchDomains": [],
 		"logConfiguration": {
 			"logDriver": "awslogs",
 			"options": {
 				"awslogs-group": "/ecs/${BRANCH}",
 				"awslogs-region": "eu-west-2",
 				"awslogs-stream-prefix": "ecs"
 			}
 		},
 		"entryPoint": [],
 		"portMappings": [{
 			"hostPort": 5556,
 			"protocol": "tcp",
 			"containerPort": 5556
 		}],
 		"command": [],
 		"cpu": 0,
 		"environment": [{
 			"name": "NODE_MAX_INSTANCES", "value": "5"
 		},{
 			"name": "NODE_MAX_SESSIONS", "value": "5"
 		},{
 			"name": "HUB_HOST", "value": "127.0.0.1"
 		},{
 			"name": "HUB_PORT", "value": "4444"
 		},{
 			"name": "NODE_PORT", "value": "5556"
 		}],
 		"image": "registry.hub.docker.com/selenium/node-chrome:3.141.59-uranium",
 		"name": "SeleniumNodeChrome"
 	}
EOF&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;CONTAINER_MAVEN&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOF
	{
		"dnsSearchDomains": [],
		"logConfiguration": {
			"logDriver": "awslogs",
			"options": {
				"awslogs-group": "/ecs/${BRANCH}",
				"awslogs-region": "eu-west-2",
				"awslogs-stream-prefix": "ecs"
			}
		},
		"entryPoint": [],
		"portMappings": [],
		"command": [],
		"cpu": 0,
		"image": "${ECR_ACCOUNT}/d8maven",
		"name": "Maven",
		"essential": true,
		"mountPoints": [{
			"sourceVolume": "automated_tests",
			"containerPath": "/var/automated_tests"
		}]
	}
EOF&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
 
&lt;span style="color: #007800;"&gt;CONTAINERS_AUTOMATIC&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOF
[
${CONTAINER_CODEBASE},
${CONTAINER_SELENIUM_HUB},
${CONTAINER_SELENIUM_FIREFOX},
${CONTAINER_MAVEN},
${CONTAINER_SELENIUM_CHROME}
]
EOF&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
 
aws ecs register-task-definition \
  &lt;span style="color: #660033;"&gt;--family&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"AUTOMATION-&lt;span style="color: #007800;"&gt;${BRANCH}&lt;/span&gt;"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--volumes&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"name=automated_tests,host={}"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--task-role-arn&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$TASK_ARN&lt;/span&gt;"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--execution-role-arn&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${EXECUTION_ARN}&lt;/span&gt;"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--network-mode&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"awsvpc"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--container-definitions&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${CONTAINERS_AUTOMATIC}&lt;/span&gt;"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--cpu&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"4096"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--memory&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"30720"&lt;/span&gt; \
  &lt;span style="color: #660033;"&gt;--requires-compatibilities&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"FARGATE"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Running the Fargate Task&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/screencapture-eu-west-2-console-aws-amazon-ecs-home-2019-12-10-16_40_01.png?itok=Fffyjmc5 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-12/screencapture-eu-west-2-console-aws-amazon-ecs-home-2019-12-10-16_40_01.png?itok=-mwj0Mh3 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-12/screencapture-eu-west-2-console-aws-amazon-ecs-home-2019-12-10-16_40_01.png?itok=-pRD2LfJ 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-12/screencapture-eu-west-2-console-aws-amazon-ecs-home-2019-12-10-16_40_01.png?itok=9NKHks8i 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/screencapture-eu-west-2-console-aws-amazon-ecs-home-2019-12-10-16_40_01.png?itok=Fffyjmc5" alt="Run Task" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-10%20at%2016.45.09.png?itok=JCu8fCFw 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-12/Screenshot%202019-12-10%20at%2016.45.09.png?itok=nNzZaByc 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-12/Screenshot%202019-12-10%20at%2016.45.09.png?itok=p62Fu_Dl 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-12/Screenshot%202019-12-10%20at%2016.45.09.png?itok=c3o8LhZS 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-10%20at%2016.45.09.png?itok=JCu8fCFw" alt="Running Task" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-10%20at%2016.45.19.png?itok=O0_8h9c6 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-12/Screenshot%202019-12-10%20at%2016.45.19.png?itok=rtPVZ1nd 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-12/Screenshot%202019-12-10%20at%2016.45.19.png?itok=8oFSBSK5 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-12/Screenshot%202019-12-10%20at%2016.45.19.png?itok=b8-KpJnf 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-10%20at%2016.45.19.png?itok=O0_8h9c6" alt="All containers running" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-10%20at%2016.46.10.png?itok=HtC-w96y 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-12/Screenshot%202019-12-10%20at%2016.46.10.png?itok=adcaUdoh 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-12/Screenshot%202019-12-10%20at%2016.46.10.png?itok=G5h9B1j2 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-12/Screenshot%202019-12-10%20at%2016.46.10.png?itok=E1G0Wpgh 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-10%20at%2016.46.10.png?itok=HtC-w96y" alt="All containers stopped" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Once the script is executed, the task will be defined and ready to run. This can be run by creating a new shell script (or extending the one above) or by using the console. Since this blog is becoming too code focused, I'll document the running of tasks programmatically in another blog later. For now you should be able to see your task in the console and run it. See screenshot 1 above.&lt;/p&gt;

&lt;p&gt;Screenshot 2 show that the task has reached RUNNING state. If you are quick you can click on the task identifier and be taken to the more detailed screen shown in image 3 which shows all the containers that are running. &lt;/p&gt;

&lt;p&gt;Once one of the Docker images completes its activity, a signal will be sent to all the other containers to stop. In the task described in this blog, the first task to complete is the running of the automated tests. Once the tests complete, then all other containers will stop. See image 4. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Did the Tests Actually Succeed?&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/screencapture-eu-west-2-console-aws-amazon-cloudwatch-home-2019-12-10-16_55_13.png?itok=E8ySuBsU 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-12/screencapture-eu-west-2-console-aws-amazon-cloudwatch-home-2019-12-10-16_55_13.png?itok=TvSbKodT 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-12/screencapture-eu-west-2-console-aws-amazon-cloudwatch-home-2019-12-10-16_55_13.png?itok=kMWLfPE5 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-12/screencapture-eu-west-2-console-aws-amazon-cloudwatch-home-2019-12-10-16_55_13.png?itok=PnCz6kAM 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/screencapture-eu-west-2-console-aws-amazon-cloudwatch-home-2019-12-10-16_55_13.png?itok=E8ySuBsU" alt="CloudWatch success" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;A valid question! The output of the Maven container is written to a CloudWatch log stream which can be parsed and echoed back to the screen, or sent to a Slack channel (more on this in a later blog). For now I have created a sequence of commands using pipes which includes the open source &lt;strong&gt;awslogs&lt;/strong&gt; utility.&lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ aws logs describe-log-streams &lt;span style="color: #660033;"&gt;--log-group-name&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"/ecs/selenium-testing"&lt;/span&gt; &lt;span style="color: #660033;"&gt;--log-stream-name-prefix&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"ecs/Maven"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #ff0000;"&gt;'.logStreams|=sort_by(-.creationTime)|.logStreams[0].logeamName'&lt;/span&gt; &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;xargs&lt;/span&gt; -I&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt; awslogs get &lt;span style="color: #ff0000;"&gt;"/ecs/selenium-testing"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt; &lt;span style="color: #660033;"&gt;-s1d&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;cut&lt;/span&gt; &lt;span style="color: #660033;"&gt;-d&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;' '&lt;/span&gt; &lt;span style="color: #660033;"&gt;-f&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;,&lt;span style="color: #000000;"&gt;2&lt;/span&gt; &lt;span style="color: #660033;"&gt;--complement&lt;/span&gt;
mvn
&lt;span style="color: #660033;"&gt;-------------------------------------------------------&lt;/span&gt;
 T E S T S
&lt;span style="color: #660033;"&gt;-------------------------------------------------------&lt;/span&gt;
Running mytests.RunCucumberTest
Dec &lt;span style="color: #000000;"&gt;10&lt;/span&gt;, &lt;span style="color: #000000;"&gt;2019&lt;/span&gt; &lt;span style="color: #000000;"&gt;3&lt;/span&gt;:&lt;span style="color: #000000;"&gt;43&lt;/span&gt;:&lt;span style="color: #000000;"&gt;46&lt;/span&gt; PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
Dec &lt;span style="color: #000000;"&gt;10&lt;/span&gt;, &lt;span style="color: #000000;"&gt;2019&lt;/span&gt; &lt;span style="color: #000000;"&gt;3&lt;/span&gt;:&lt;span style="color: #000000;"&gt;43&lt;/span&gt;:&lt;span style="color: #000000;"&gt;47&lt;/span&gt; PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
Dec &lt;span style="color: #000000;"&gt;10&lt;/span&gt;, &lt;span style="color: #000000;"&gt;2019&lt;/span&gt; &lt;span style="color: #000000;"&gt;3&lt;/span&gt;:&lt;span style="color: #000000;"&gt;43&lt;/span&gt;:&lt;span style="color: #000000;"&gt;49&lt;/span&gt; PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
Dec &lt;span style="color: #000000;"&gt;10&lt;/span&gt;, &lt;span style="color: #000000;"&gt;2019&lt;/span&gt; &lt;span style="color: #000000;"&gt;3&lt;/span&gt;:&lt;span style="color: #000000;"&gt;43&lt;/span&gt;:&lt;span style="color: #000000;"&gt;50&lt;/span&gt; PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
Feature: Are we on the Home Page?
  Scenario: On the home page         &lt;span style="color: #666666; font-style: italic;"&gt;# mytests/home_page.feature:4&lt;/span&gt;
    When User is on the Home Page    &lt;span style="color: #666666; font-style: italic;"&gt;# Stepdefs.user_is_on_Home_Page()&lt;/span&gt;
    Then Message Displayed Memcached &lt;span style="color: #666666; font-style: italic;"&gt;# Stepdefs.message_displayed_memcached()&lt;/span&gt;
    When User is on the Home Page    &lt;span style="color: #666666; font-style: italic;"&gt;# Stepdefs.user_is_on_Home_Page()&lt;/span&gt;
    Then Message Displayed GD        &lt;span style="color: #666666; font-style: italic;"&gt;# Stepdefs.gd()&lt;/span&gt;
&lt;span style="color: #000000;"&gt;1&lt;/span&gt; Scenarios &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt; passed&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; Steps &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;4&lt;/span&gt; passed&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
0m6.835s
Tests run: &lt;span style="color: #000000;"&gt;1&lt;/span&gt;, Failures: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, Errors: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, Skipped: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, Time elapsed: &lt;span style="color: #000000;"&gt;7.055&lt;/span&gt; sec
Results :
Tests run: &lt;span style="color: #000000;"&gt;1&lt;/span&gt;, Failures: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, Errors: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, Skipped: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Troubleshooting Selenium Grid&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-10%20at%2017.17.52.png?itok=CyMh5g8X 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-12/Screenshot%202019-12-10%20at%2017.17.52.png?itok=uKKQA2e6 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-12/Screenshot%202019-12-10%20at%2017.17.52.png?itok=XEv9FUiO 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-12/Screenshot%202019-12-10%20at%2017.17.52.png?itok=UcTRu0a3 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-10%20at%2017.17.52.png?itok=CyMh5g8X" alt="Custom Rule" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-10%20at%2017.18.24.png?itok=3Jg4RYn9 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-12/Screenshot%202019-12-10%20at%2017.18.24.png?itok=xTq_OE_n 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-12/Screenshot%202019-12-10%20at%2017.18.24.png?itok=aNF-w9z5 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-12/Screenshot%202019-12-10%20at%2017.18.24.png?itok=EuDe0bIn 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-10%20at%2017.18.24.png?itok=3Jg4RYn9" alt="Selenium Grid" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Getting the Selenium stack working can be fiddly, although the CloudWatch logs are a very good way of diagnosing problems. If you want to satisy yourself that Selenium Hub and its two nodes (Firefox and Chrome) are actually there and available, there is a way but you'll have to work fast on the console since the Fargate tasks completes and shuts down once the tests are complete. &lt;/p&gt;

&lt;p&gt;When the Fargate task transitions from PENDING to RUNNING, click on the task identifier. Copy the public IP address into your clipboard - you'll need it shortly. Now click on the ENI (Elastic Network Interface) link which will launch a new tab. Then click on the security group. Now you need to create a new rule. By default port 4444 is blocked on the public IP address - and to see Selenium working I need that to be open. &lt;/p&gt;

&lt;p&gt;Edit the rules, create a new custom TCP/IP rule, add 4444 as the port and select anywhere for the CIDR, then save. See screenshot 1 above. &lt;/p&gt;

&lt;p&gt;You now instantly have an open port 4444. Open a new browser tab, then paste the IP address you copied a few steps ago, then append /grid/console to it and enter. You should see your Grid + Node configuration as per the second screenshot above. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/ecs" hreflang="en"&gt;ECS&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/aws" hreflang="en"&gt;AWS&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/awscli" hreflang="en"&gt;AWS CLI&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/development" hreflang="en"&gt;Development&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/docker" hreflang="en"&gt;Docker&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/bash" hreflang="en"&gt;bash&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Mon, 09 Dec 2019 08:37:50 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">173 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>Programmatically Create AWS ECR Repository and Commit Docker Image to ECR</title>
  <link>http://badzilla.co.uk/programmatically-create-aws-ecr-repository-and-commit-docker-image-ecr</link>
  <description>
&lt;span&gt;Programmatically Create AWS ECR Repository and Commit Docker Image to ECR&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Sat, 07/12/2019 - 07:56&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;This is a tutorial for using AWS CLI to programmatically create an AWS ECR repository and then commit a Docker image to that repository. This is the first step in a series of tutorials for creating an automated testing framework in AWS Fargate which can be one step of a DevOps pipeline. &lt;/p&gt;

&lt;p&gt;As an example I am going to use the Docker php:7.2-apache image and to make it a little more complex, add a few more PHP extensions using a new Dockerfile so that my new image will be Drupal 8 compliant. &lt;/p&gt;

&lt;p&gt;Let's get started. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Pull Base Image and Define Dockerfile&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The base php:7.2-apache image needs to be pulled from Docker Hub. Issue the following command. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ docker pull php:&lt;span style="color: #000000;"&gt;7.2&lt;/span&gt;-apache
&lt;span style="color: #000000;"&gt;7.2&lt;/span&gt;-apache: Pulling from library&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;php
000eee12ec04: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
8ae4f9fcfeea: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
60f22fbbd07a: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
ccc7a63ad75f: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
a2427b8dd6e7: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
91cac3b30184: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
d6e40015fc10: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
240e21c03bb4: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
504858e1e4aa: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
9a0523b2d73f: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
e3acb84829f4: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
28a372733f87: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
62ee66cdb80a: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
c3f368ddc7aa: Pull &lt;span style="color: #7a0874; font-weight: bold;"&gt;complete&lt;/span&gt; 
Digest: sha256:602bef9acc8d54527ae5b7ee0f16e5cdb6ab81364310f5123b93b95e357f608d
Status: Downloaded newer image &lt;span style="color: #000000; font-weight: bold;"&gt;for&lt;/span&gt; php:&lt;span style="color: #000000;"&gt;7.2&lt;/span&gt;-apache
docker.io&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;library&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;php:&lt;span style="color: #000000;"&gt;7.2&lt;/span&gt;-apache
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
php                 &lt;span style="color: #000000;"&gt;7.2&lt;/span&gt;-apache          fec8a1aaffb8        &lt;span style="color: #000000;"&gt;31&lt;/span&gt; hours ago        410MB
lambci&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;lambda       go1.x               8d962cde7e27        &lt;span style="color: #000000;"&gt;3&lt;/span&gt; months ago        707MB
sls-docker          latest              8d962cde7e27        &lt;span style="color: #000000;"&gt;3&lt;/span&gt; months ago        707MB&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Yes the docker image is there. Now I need to create a directory for the Dockerfile and a sample index.php file which will prove our image is working. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; automated &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; automated&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
By default the Docker php image uses /var/www/html as Apache's docroot. However, I'm going to alter this to something more standard for Drupal web apps - a directory called docroot will be created and will contain a simple index.php containing a call to phpinfo();
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; docroot &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;?php phpinfo();"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt; docroot&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;index.php&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
The Dockerfile should now be created and populated. There a number of activities that need to be performed on it. 
&lt;ul&gt;
&lt;li&gt;Reference the base image with a FROM instruction&lt;/li&gt;
&lt;li&gt;Install the libraries that support memcached and graphics manipulation&lt;/li&gt;
&lt;li&gt;Enable memcached PHP extension&lt;/li&gt;
&lt;li&gt;Configure the graphics PHP extension&lt;/li&gt;
&lt;li&gt;Install the graphics PHP extension&lt;/li&gt;
&lt;li&gt;Copy the files in the current directory and below into the Docker image at the /var/www/html ensuring the permissions are correct for the apache user and group&lt;/li&gt;
&lt;li&gt;Set the environment variable AH_SITE_ENVIRONMENT to devops - this is an Acquia Cloud environment variable and only of any significance for those using Acquia as their host - or need a setting in my case to denote that devops is not running on Acquia&lt;/li&gt;
&lt;li&gt;Change the default location for the docroot - that means setting an environment variable and using the sed editor to change the configuration in the sites files&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;Dockerfile&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;FROM php:&lt;span style="color: #000000;"&gt;7.2&lt;/span&gt;-apache
RUN &lt;span style="color: #c20cb9; font-weight: bold;"&gt;apt-get update&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;apt-get install&lt;/span&gt; &lt;span style="color: #660033;"&gt;-y&lt;/span&gt; libmemcached-dev zlib1g-dev \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    libpng-dev \
    libwebp-dev \
    &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; pecl &lt;span style="color: #c20cb9; font-weight: bold;"&gt;install&lt;/span&gt; memcached \
    &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; docker-php-ext-enable memcached \
    &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; docker-php-ext-configure gd &lt;span style="color: #660033;"&gt;--with-gd&lt;/span&gt; &lt;span style="color: #660033;"&gt;--with-webp-dir&lt;/span&gt; &lt;span style="color: #660033;"&gt;--with-jpeg-dir&lt;/span&gt; \
       &lt;span style="color: #660033;"&gt;--with-png-dir&lt;/span&gt; &lt;span style="color: #660033;"&gt;--with-zlib-dir&lt;/span&gt; &lt;span style="color: #660033;"&gt;--with-freetype-dir&lt;/span&gt; \
    &lt;span style="color: #000000; font-weight: bold;"&gt;&amp;&amp;&lt;/span&gt; docker-php-ext-install gd
COPY &lt;span style="color: #660033;"&gt;--chown&lt;/span&gt;=www-data:www-data .&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;.
ENV AH_SITE_ENVIRONMENT devops
ENV APACHE_DOCUMENT_ROOT &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;docroot
RUN &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sed&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ri&lt;/span&gt; &lt;span style="color: #660033;"&gt;-e&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'s!/var/www/html!${APACHE_DOCUMENT_ROOT}!g'&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;etc&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;apache2&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;sites-available&lt;span style="color: #000000; font-weight: bold;"&gt;/*&lt;/span&gt;.conf
RUN &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sed&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ri&lt;/span&gt; &lt;span style="color: #660033;"&gt;-e&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'s!/var/www/!${APACHE_DOCUMENT_ROOT}!g'&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;etc&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;apache2&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;apache2.conf &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;etc&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;apache2&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;conf-available&lt;span style="color: #000000; font-weight: bold;"&gt;/*&lt;/span&gt;.conf&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Build the Image, Run the Container&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-07%20at%2012.17.34.png?itok=jwU0kVpn 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-12/Screenshot%202019-12-07%20at%2012.17.34.png?itok=XLFrcLyd 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-12/Screenshot%202019-12-07%20at%2012.17.34.png?itok=7J5O5LHx 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-12/Screenshot%202019-12-07%20at%2012.17.34.png?itok=eCD6F2Tg 2310w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot%202019-12-07%20at%2012.17.34.png?itok=jwU0kVpn" alt="phpinfo" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Once the Dockerfile is complete, it is built with
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;docker build &lt;span style="color: #660033;"&gt;-t&lt;/span&gt; d8codebase .&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
and to confirm it's built correctly:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
d8codebase          latest              c2193f9778a6        &lt;span style="color: #000000;"&gt;33&lt;/span&gt; minutes ago      439MB
&lt;span style="color: #000000; font-weight: bold;"&gt;&lt;&lt;/span&gt;none&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;              &lt;span style="color: #000000; font-weight: bold;"&gt;&lt;&lt;/span&gt;none&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;              2a71964685e0        &lt;span style="color: #000000;"&gt;2&lt;/span&gt; hours ago         432MB
php                 &lt;span style="color: #000000;"&gt;7.2&lt;/span&gt;-apache          fec8a1aaffb8        &lt;span style="color: #000000;"&gt;35&lt;/span&gt; hours ago        410MB
lambci&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;lambda       go1.x               8d962cde7e27        &lt;span style="color: #000000;"&gt;3&lt;/span&gt; months ago        707MB
sls-docker          latest              8d962cde7e27        &lt;span style="color: #000000;"&gt;3&lt;/span&gt; months ago        707MB&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Great it's there. Now to spin up the container. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;docker run &lt;span style="color: #660033;"&gt;-d&lt;/span&gt; &lt;span style="color: #660033;"&gt;-p&lt;/span&gt; &lt;span style="color: #000000;"&gt;8080&lt;/span&gt;:&lt;span style="color: #000000;"&gt;80&lt;/span&gt; d8codebase&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Note I am mapping port 8080 to the container's port 80 which probably won't be pertinent to you. Long story I will try to make short. I write my blogs on my Macbook on a local network in the 192.168 range assigned by my ISP's hub. But I develop and test all the practical work in my blogs in a VM in the IP 10. range. Routing between 192.168 and 10. is difficult without port forwarding - so I port forward 127.0.0.1 8080 to my VM's 10.0.2.15 8080, so when I run my Docker Apache container I must remember incoming is on port 8080 and map that against the container's port 80. Hope that makes sense!&lt;br /&gt;&lt;br /&gt;Now check it's running:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ docker &lt;span style="color: #c20cb9; font-weight: bold;"&gt;ps&lt;/span&gt;
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
9a6dc2fb88ff        d8codebase          &lt;span style="color: #ff0000;"&gt;"docker-php-entrypoi…"&lt;/span&gt;   &lt;span style="color: #000000;"&gt;44&lt;/span&gt; minutes ago      Up &lt;span style="color: #000000;"&gt;44&lt;/span&gt; minutes       0.0.0.0:&lt;span style="color: #000000;"&gt;8080&lt;/span&gt;-&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;80&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;tcp   agitated_feistel&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Yes, and we can see from the screenshot above that it's picking up the memcached and the gd graphics extensions. Success.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Programmatically Create the AWS ECR Repository&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot_2019-12-07_at_13_16_14-edited.png?itok=eiXr6OXC 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-12/Screenshot_2019-12-07_at_13_16_14-edited.png?itok=6-TIckwl 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-12/Screenshot_2019-12-07_at_13_16_14-edited.png?itok=inIVYe9n 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-12/Screenshot_2019-12-07_at_13_16_14-edited.png?itok=cBSia9gB 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot_2019-12-07_at_13_16_14-edited.png?itok=eiXr6OXC" alt="ECR Repository" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;This is quite easy and I've put it into a shell script that requires one parameter - the repo name to be created. The work is done by the aws ecr create-repository call. The rest of the code is simply checking for error conditions. The screenshot above was taken on the AWS console after the shell script below was successfully run with a parameter of d8codebase.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;#!/bin/bash&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;#Programmatically create an ECR repo&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Check whether we have the args&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; $&lt;span style="color: #000000; font-weight: bold;"&gt;@&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"usage: [repo_name]"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Create the repo&lt;/span&gt;
&lt;span style="color: #007800;"&gt;REPO_NAME&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ecr create-repository &lt;span style="color: #660033;"&gt;--repository-name&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"$1"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq .repository.repositoryName -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Check it was created ok. We already get a quality stderr msg from aws cli so just quit on error.&lt;/span&gt;
&lt;span style="color: #666666; font-style: italic;"&gt;# Similarly, if already exists it will tell us&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${REPO_NAME}&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;!&lt;/span&gt;= &lt;span style="color: #007800;"&gt;$1&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;2&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Successfully created &lt;span style="color: #007800;"&gt;${REPO_NAME}&lt;/span&gt;"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Login to Docker and Push Image to ECR&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot_2019-12-08_at_10_20_26-edited.png?itok=sv0QPbaX 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-12/Screenshot_2019-12-08_at_10_20_26-edited.png?itok=AEUf4O-_ 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-12/Screenshot_2019-12-08_at_10_20_26-edited.png?itok=z9aPZ3kh 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-12/Screenshot_2019-12-08_at_10_20_26-edited.png?itok=JirTlXB0 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-12/Screenshot_2019-12-08_at_10_20_26-edited.png?itok=sv0QPbaX" alt="Docker Push" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Now the script to automatically login to Docker and push the image to ECR. Note that AWS ECR does require you to use the docker login command, and therefore provides a AWS CLI ECR command get-login which returns a token than can be piped into the docker login command. The token retrieved from ECR has a large payload, and it is top and tailed with other metadata beyond just the password. Therefore that needs to be removed, and if you look closely at the script below, you can see that I pipe the entire returned payload through sed with a regex, and then the result is piped onwards to docker login. Hopefully the rest is quite self explanatory - and you can see the screenshot above that the push has worked and the image can now be included in ECS / Fargate task definitions. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;#!/bin/bash&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;#Programmatically push to an ECR repo&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Check whether we have the args&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; $&lt;span style="color: #000000; font-weight: bold;"&gt;@&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"usage: [repo_name]"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;REPO_NAME&lt;/span&gt;=&lt;span style="color: #007800;"&gt;$1&lt;/span&gt;
&lt;span style="color: #007800;"&gt;ECR_ACCOUNT&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"XXXXXXXXXX.dkr.ecr.eu-west-2.amazonaws.com"&lt;/span&gt;
&lt;span style="color: #007800;"&gt;ECR_REPO&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${ECR_ACCOUNT}&lt;/span&gt;/$1"&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# AWS Authentication - since we need to use docker push&lt;/span&gt;
&lt;span style="color: #666666; font-style: italic;"&gt;# The sed regex will top and tail the additional meta data sent by the aws login request.&lt;/span&gt;
aws ecr get-login &lt;span style="color: #660033;"&gt;--region&lt;/span&gt; eu-west-&lt;span style="color: #000000;"&gt;2&lt;/span&gt;  &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sed&lt;/span&gt; &lt;span style="color: #660033;"&gt;-e&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'s/^.*-p \(.*\)\s\-\e.*$/\1/'&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt;  docker &lt;span style="color: #c20cb9; font-weight: bold;"&gt;login&lt;/span&gt; &lt;span style="color: #660033;"&gt;--password-stdin&lt;/span&gt; &lt;span style="color: #660033;"&gt;-u&lt;/span&gt; AWS &lt;span style="color: #800000;"&gt;${ECR_ACCOUNT}&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Get the image id of the Docker build. If there is a "latest" use that else get the first without latest&lt;/span&gt;
&lt;span style="color: #007800;"&gt;TAG&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;docker images &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; &lt;span style="color: #660033;"&gt;-w&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${REPO_NAME}&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; latest &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;awk&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'{ print $3; }'&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #800000;"&gt;${TAG}&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
        &lt;span style="color: #007800;"&gt;TAG&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;docker images &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; &lt;span style="color: #660033;"&gt;-w&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${REPO_NAME}&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;awk&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'{ print $3; }'&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
docker tag &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$TAG&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${ECR_REPO}&lt;/span&gt;"&lt;/span&gt;
docker push &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;${ECR_REPO}&lt;/span&gt;"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/aws" hreflang="en"&gt;AWS&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/awscli" hreflang="en"&gt;AWS CLI&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/docker" hreflang="en"&gt;Docker&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/fargate" hreflang="en"&gt;Fargate&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/ecs" hreflang="en"&gt;ECS&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/development" hreflang="en"&gt;Development&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/bash" hreflang="en"&gt;bash&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Sat, 07 Dec 2019 07:56:15 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">172 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>Create Arbitrary Subdomains for AWS Fargate Tasks using AWS CLI</title>
  <link>http://badzilla.co.uk/create-arbitrary-subdomains-aws-fargate-tasks-using-aws-cli</link>
  <description>
&lt;span&gt;Create Arbitrary Subdomains for AWS Fargate Tasks using AWS CLI&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Fri, 01/11/2019 - 15:03&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-11/Screenshot_2019-11-03_at_11_24_32-edited1.png?itok=t3-00HWu 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-11/Screenshot_2019-11-03_at_11_24_32-edited1.png?itok=dcZAK-DY 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-11/Screenshot_2019-11-03_at_11_24_32-edited1.png?itok=aY5EToiP 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-11/Screenshot_2019-11-03_at_11_24_32-edited1.png?itok=MUHYEW-M 1695w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-11/Screenshot_2019-11-03_at_11_24_32-edited1.png?itok=t3-00HWu" alt="Success" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;AWS Fargate is a relatively new product offering the capability of running Docker bundles as an ECS compute service on EC2 without the necessity for the user to have to orchestrate the underlying EC2 infrastructure. It is perfect for DevOps, and was the technology I chose as DevOps Architect at my current client. The client wanted standard CI/CD capabilities such as spinning up containerised copies of their website environment per feature branch to perform static analysis, automated testing, and also significantly, a persisting playground that QA or development personnel could use for manual testing and troubleshooting a feature (or hotfix) branch they are currently working on.&lt;/p&gt;

&lt;p&gt;This is similar to the offering of both Platform.sh and Amazee Labs hosting solutions - developers can spin up their feature branches. Alas my client is locked into another host yet needed on-the-fly feature branch Docker bundles.&lt;/p&gt;

&lt;p&gt;AWS Fargate tasks can achieve this, but out of the box it isn't possible to create public domain registration via ECS Service Discovery. The Fargate task is issued a bare IPv4 address which will obviously work but our requirement is to have a subdomain created per branch that would be of the format {hotfix|feature}--{jira ticket}-{suitable branch name}.{top level domain}.  So an example would be:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;feature--doi-746-my-whizzy-new-feature.clientdomain.dev&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So whilst we can't create a subdomain like that natively, we can do it by retrieving the IP address from the ECS Fargate task, then add that IP to a public Route 53 Hosted Zone. Furthermore, since the Fargate task is run via a Jenkins pipeline job that uses shell scripts populated with AWS CLI, the good news is we can indeed complete the registration of subdomain also using the AWS CLI *and* have the DNS propagate within 60 seconds! Amazing! Let's dive into how we achieve this. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Requirements + Assumptions&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The solution will be built using the standard httpd Apache2 server sample Fargate task described on the AWS blog &lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_AWSCLI_Fargate.html"&gt;Tutorial: Creating a Cluster with a Fargate Task Using the AWS CLI&lt;/a&gt;. I added the task definition into the console, although it is also possible create a shell script and use AWS CLI. I have used the default cluster for brevity's sake, and the AWS account default VPC. I have also transferred a spare domain I had, &lt;em&gt;saasidate.com&lt;/em&gt;, into Route 53 before I started the blog. This will be my tld and all the subdomains will be added off it. It's important that the ownership of the domain is transferred into Route 53 since otherwise subdomains will have authority issues if the parent domain is still registered to other domain providers such as GoDaddy or 123-Reg. &lt;/p&gt;
&lt;p&gt;The solution I am putting together will use AWS CLI which by default returns JSON structured data. It is absolutely essential to use the Linux command line utility &lt;strong&gt;jq&lt;/strong&gt; for parsing the JSON. Documentation on jq is readily available on the net. &lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Steps&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The solution will need the following steps:&lt;/p&gt;

&lt;ol&gt;
	&lt;li&gt;Get the user's default VPC (or create a custom VPC if preferred. We'll need this at a few points in the code. &lt;/li&gt;
	&lt;li&gt;Get a subnet from the VPC. Three subnets are created for use with the default VPC. I pick the first which is arbitrary.&lt;/li&gt;
	&lt;li&gt;Get a security group. A new security group is created per task when using the console but that is unnecessary for the shell scripts we will be building. So in our script, check whether our 'standard' security group has been created. If so use it, if not then create a security group with an ingress port of 80 and a CIDR of 0.0.0.0/0 which allows access worldwide on TCP port 80.&lt;/li&gt;
	&lt;li&gt;Run the Fargate task and loop / sleep until the task has a status of RUNNING. &lt;/li&gt;
	&lt;li&gt;Get the network interface id of the task and interrogate it for the IP address. &lt;/li&gt;
	&lt;li&gt;Get the hosted zone for the parent domain.&lt;/li&gt;
	&lt;li&gt;Add a record set containing the feature branch subdomain to the parent domain's hosted zone.&lt;/li&gt;
	&lt;li&gt;Create a new hosted zone using the feature branch. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ok - let's crack on and put this into AWS CLI shell scripts. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Get the VPC&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;I'm using the default VPC so I can filter the list I get back from AWS using the IsDefault attribute. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #007800;"&gt;VPC&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ec2 describe-vpcs &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #ff0000;"&gt;'.Vpcs[] | select(.IsDefault == true) | .VpcId'&lt;/span&gt; -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Note the use of the jq select statement. This is a familiar construct and will be used throughout this blog. Also note the -r flag - this removes the double quotes from the response.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Get the First Subnet in the Default VPC&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Here I am using jq again but piping the results through head to get the first subnet. There wasn't an obvious jq query to do this natively within jq. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;# Get the first subnet of the VPC&lt;/span&gt;
&lt;span style="color: #007800;"&gt;SUBNET&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ec2 describe-subnets &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #660033;"&gt;--arg&lt;/span&gt; VPC &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$VPC&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'.Subnets[] | select(.VpcId == $VPC) | .SubnetId'&lt;/span&gt; &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;head&lt;/span&gt; &lt;span style="color: #660033;"&gt;-n&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Get the Security Group&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Here I check whether we already have a dedicated security group which gives us worldwide access to port 80. I search first for a unique security group description and if it doesn't exist, then create it.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;# Check if our security group for port 80 webserver already exists. Search for our funky unique description&lt;/span&gt;
&lt;span style="color: #007800;"&gt;SECURITY&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ec2 describe-security-groups &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #ff0000;"&gt;' .SecurityGroups[] | select (.Description == "Ingress Port 80 Anywhere") | .GroupId'&lt;/span&gt; -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Let's inspect what we got back.&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ne&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-security-groups failed with code $?"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# If we didn't get a security group then create&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$SECURITY&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #007800;"&gt;SECURITY&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ec2 create-security-group \
		&lt;span style="color: #660033;"&gt;--description&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Ingress Port 80 Anywhere"&lt;/span&gt; \
		&lt;span style="color: #660033;"&gt;--group-name&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Fargate Webserver Port 80"&lt;/span&gt; \
		&lt;span style="color: #660033;"&gt;--vpc-id&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$VPC&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq .GroupId &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
 
	aws ec2 authorize-security-group-ingress \
		&lt;span style="color: #660033;"&gt;--group-id&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$SECURITY&lt;/span&gt;"&lt;/span&gt; \
		&lt;span style="color: #660033;"&gt;--ip-permissions&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"FromPort=80,ToPort=80,IpProtocol=TCP,IpRanges=[{CidrIp=0.0.0.0/0}]"&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Run the Fargate Task&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Next I run the Fargate task. This is the sample Fargate task covered in the AWS documentation and uses the httpd docker image. When I created it in the console I called it "first-run-task-definition" - for the life of me I can't remember why I chose such a crazy name! Note I am piping the result through jq as per normal and then onwards through sed to get the task id without all the arn information that precedes it. The sed command looks for the final forward slash in the task arn and crops anything before it. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;# Run the task and parse the task ARN for polling later to determine its status&lt;/span&gt;
&lt;span style="color: #007800;"&gt;TASK&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ecs run-task \
	&lt;span style="color: #660033;"&gt;--cluster&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"default"&lt;/span&gt; \
	&lt;span style="color: #660033;"&gt;--task-definition&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"first-run-task-definition"&lt;/span&gt; \
	&lt;span style="color: #660033;"&gt;--network-configuration&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"awsvpcConfiguration={subnets=[&lt;span style="color: #007800;"&gt;${SUBNET}&lt;/span&gt;],securityGroups=[&lt;span style="color: #007800;"&gt;${SECURITY}&lt;/span&gt;],assignPublicIp=ENABLED}"&lt;/span&gt; \
	&lt;span style="color: #660033;"&gt;--launch-type&lt;/span&gt; FARGATE  &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq .tasks&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #000000;"&gt;0&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;.taskArn &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sed&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"s/.*\///"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Let's inspect what we got back. There should be a task identifier.&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ne&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"task-run failed with code $?"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$TASK&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"task-run could not create task"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Loop and Wait for Fargate Task to get to RUNNING Status&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Next I have to wait for the task to acquire RUNNING status, However I can't wait for ever, and thus I have wrapped a shell script rule into a timeout mechanism. I have allowed for 5 minutes for the task to get to RUNNING status and that should be more than enough.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;# Loop around until we see a RUNNING status or timeout after 10 x 30 second sleeps&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;for&lt;/span&gt; i &lt;span style="color: #000000; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;3&lt;/span&gt; &lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #000000;"&gt;5&lt;/span&gt; &lt;span style="color: #000000;"&gt;6&lt;/span&gt; &lt;span style="color: #000000;"&gt;7&lt;/span&gt; &lt;span style="color: #000000;"&gt;8&lt;/span&gt; &lt;span style="color: #000000;"&gt;9&lt;/span&gt; &lt;span style="color: #000000;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;do&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$i&lt;/span&gt; &lt;span style="color: #660033;"&gt;-eq&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
		&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Timed out before could establish task is running"&lt;/span&gt;
		&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
	&lt;span style="color: #007800;"&gt;STATUS&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ecs describe-tasks &lt;span style="color: #660033;"&gt;--cluster&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"default"&lt;/span&gt; &lt;span style="color: #660033;"&gt;--tasks&lt;/span&gt; &lt;span style="color: #007800;"&gt;$TASK&lt;/span&gt;  &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq .tasks&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #000000;"&gt;0&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;.lastStatus -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
	&lt;span style="color: #666666; font-style: italic;"&gt;# Did it exit unexpectedly?&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ne&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
		&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-tasks failed with code $?"&lt;/span&gt;
		&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
	&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$STATUS&lt;/span&gt;"&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;"RUNNING"&lt;/span&gt;  &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
		&lt;span style="color: #7a0874; font-weight: bold;"&gt;break&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
	&lt;span style="color: #c20cb9; font-weight: bold;"&gt;sleep&lt;/span&gt; &lt;span style="color: #000000;"&gt;30&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;done&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Obtain the Network Interface Id&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The ENI is available in the Fargate task's description so I needed to parse this on my quest to get the public IP. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;# Get the network Interface id&lt;/span&gt;
&lt;span style="color: #007800;"&gt;ENI&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ecs describe-tasks &lt;span style="color: #660033;"&gt;--cluster&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"default"&lt;/span&gt; &lt;span style="color: #660033;"&gt;--tasks&lt;/span&gt; &lt;span style="color: #007800;"&gt;$TASK&lt;/span&gt;  &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #ff0000;"&gt;'.tasks[0].attachments[0].details[] | select(.name == "networkInterfaceId") | .value'&lt;/span&gt; &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Let's inspect what we got back. There should be a network interface id.&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ne&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-tasks failed with code $?"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$ENI&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-tasks could not establish eni"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Get the Public IP Address&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;With the ENI it is possible to parse the the descriptions of all the network interfaces for the public IP address. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #007800;"&gt;PUBLIC_IP&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ec2 describe-network-interfaces &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #660033;"&gt;--arg&lt;/span&gt; ENI &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$ENI&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'.NetworkInterfaces[] | select(.NetworkInterfaceId == $ENI) | .PrivateIpAddresses[0].Association.PublicIp'&lt;/span&gt; -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Did we get an IP address?&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ne&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-network-interfaces failed with code $?"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$PUBLIC_IP&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-network-interfaces could not retrieve public IP address"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Get the Parent Domain's Hosted Zone Id&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The shell script needs to know about the parent domain and the subdomain name (which in my case is a feature branch name) - so those need to be retrieved from runtime arguments. This will go at the top of the shell script.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #007800;"&gt;$1&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;||&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #007800;"&gt;$2&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"usage: parent_domain_name feature_branch_name"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;BRANCH&lt;/span&gt;=&lt;span style="color: #007800;"&gt;$2&lt;/span&gt;.&lt;span style="color: #007800;"&gt;$1&lt;/span&gt;
&lt;span style="color: #007800;"&gt;PARENT&lt;/span&gt;=&lt;span style="color: #007800;"&gt;$1&lt;/span&gt;.&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Then continuing at the end of the codebase, the following gets the parent domain
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #007800;"&gt;PARENT_ZONE&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws route53 list-hosted-zones-by-name &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #660033;"&gt;--arg&lt;/span&gt; PARENT &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$PARENT&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'.HostedZones[] | select(.Name == $PARENT) | .Id'&lt;/span&gt; &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sed&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"s/.*\///"&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Add the Feature Branch Name and Public IP Address to the Parent Hosted Zone&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Now I created a new record set for the parent domain's hosted zone. This uses the AWS CLI command change-resource-record-sets which allows for insert, upsert and delete. I needed a DNS A record adding. The easiest way of providing the runtime parameters is via a JSON structure and that is created in shell script heredoc format to simplify shell script escaping. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #007800;"&gt;BATCH&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOT
{
  "Comment":"CREATE/DELETE/UPSERT a record",
  "Changes":[{
    "Action": "UPSERT",
    		  "ResourceRecordSet": {
    		  	"Name": "${BRANCH}",
    		  	"Type": "A",
    		  	"TTL": 300,
    		  	"ResourceRecords": [{ "Value": "${PUBLIC_IP}"}]
    		  }
  }]
}
EOT&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Use the hosted zone of the tld&lt;/span&gt;
aws route53 change-resource-record-sets \
	&lt;span style="color: #660033;"&gt;--hosted-zone-id&lt;/span&gt; &lt;span style="color: #007800;"&gt;$PARENT_ZONE&lt;/span&gt; \
	&lt;span style="color: #660033;"&gt;--change-batch&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$BATCH&lt;/span&gt;"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Create the Feature Branch Hosted Zone&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The final AWS CLI call is to use create-hosted-zone, and here I needed to provide the feature branch name and an arbitrary unique caller reference for which I used a timestamp. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #007800;"&gt;timestamp&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;date&lt;/span&gt; +&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;s&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Now create a new hosted zone of the feature branch&lt;/span&gt;
aws route53 create-hosted-zone \
	&lt;span style="color: #660033;"&gt;--name&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$BRANCH&lt;/span&gt;"&lt;/span&gt; \
	&lt;span style="color: #660033;"&gt;--caller-reference&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$timestamp&lt;/span&gt;"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;The Complete Script&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The complete script is listed below. Note that for brevity and easy reading I have cut a few coding standards. There is repetition in the error condition checking. This should be rewritten with calls to shell script functions in a separate file. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;#!/bin/bash&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Script to assign a public IP address issued by a Fargate task to a subdomain&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #007800;"&gt;$1&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;||&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #007800;"&gt;$2&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"usage: parent_domain_name feature_branch_name"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;BRANCH&lt;/span&gt;=&lt;span style="color: #007800;"&gt;$2&lt;/span&gt;.&lt;span style="color: #007800;"&gt;$1&lt;/span&gt;
&lt;span style="color: #007800;"&gt;PARENT&lt;/span&gt;=&lt;span style="color: #007800;"&gt;$1&lt;/span&gt;.
 
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Get the default VPC.&lt;/span&gt;
&lt;span style="color: #007800;"&gt;VPC&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ec2 describe-vpcs &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #ff0000;"&gt;'.Vpcs[] | select(.IsDefault == true) | .VpcId'&lt;/span&gt; -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Get the first subnet of the VPC&lt;/span&gt;
&lt;span style="color: #007800;"&gt;SUBNET&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ec2 describe-subnets &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #660033;"&gt;--arg&lt;/span&gt; VPC &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$VPC&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'.Subnets[] | select(.VpcId == $VPC) | .SubnetId'&lt;/span&gt; &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;head&lt;/span&gt; &lt;span style="color: #660033;"&gt;-n&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Check if our security group for port 80 webserver already exists. Search for our funky unique description&lt;/span&gt;
&lt;span style="color: #007800;"&gt;SECURITY&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ec2 describe-security-groups &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #ff0000;"&gt;' .SecurityGroups[] | select (.Description == "Ingress Port 80 Anywhere") | .GroupId'&lt;/span&gt; -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Let's inspect what we got back.&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ne&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-security-groups failed with code $?"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# If we didn't get a security group then create&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$SECURITY&lt;/span&gt;"&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;""&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #007800;"&gt;SECURITY&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ec2 create-security-group \
		&lt;span style="color: #660033;"&gt;--description&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Ingress Port 80 Anywhere"&lt;/span&gt; \
		&lt;span style="color: #660033;"&gt;--group-name&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Fargate Webserver Port 80"&lt;/span&gt; \
		&lt;span style="color: #660033;"&gt;--vpc-id&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$VPC&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq .GroupId &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
 
	aws ec2 authorize-security-group-ingress \
		&lt;span style="color: #660033;"&gt;--group-id&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$SECURITY&lt;/span&gt;"&lt;/span&gt; \
		&lt;span style="color: #660033;"&gt;--ip-permissions&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"FromPort=80,ToPort=80,IpProtocol=TCP,IpRanges=[{CidrIp=0.0.0.0/0}]"&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Run the task and parse the task ARN for polling later to determine its status&lt;/span&gt;
&lt;span style="color: #007800;"&gt;TASK&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ecs run-task \
	&lt;span style="color: #660033;"&gt;--cluster&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"default"&lt;/span&gt; \
	&lt;span style="color: #660033;"&gt;--task-definition&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"first-run-task-definition"&lt;/span&gt; \
	&lt;span style="color: #660033;"&gt;--network-configuration&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"awsvpcConfiguration={subnets=[&lt;span style="color: #007800;"&gt;${SUBNET}&lt;/span&gt;],securityGroups=[&lt;span style="color: #007800;"&gt;${SECURITY}&lt;/span&gt;],assignPublicIp=ENABLED}"&lt;/span&gt; \
	&lt;span style="color: #660033;"&gt;--launch-type&lt;/span&gt; FARGATE  &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq .tasks&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #000000;"&gt;0&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;.taskArn &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sed&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"s/.*\///"&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Let's inspect what we got back. There should be a task identifier.&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ne&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"task-run failed with code $?"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$TASK&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"task-run could not create task"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Loop around until we see a RUNNING status or timeout after 10 x 30 second sleeps&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;for&lt;/span&gt; i &lt;span style="color: #000000; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;3&lt;/span&gt; &lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #000000;"&gt;5&lt;/span&gt; &lt;span style="color: #000000;"&gt;6&lt;/span&gt; &lt;span style="color: #000000;"&gt;7&lt;/span&gt; &lt;span style="color: #000000;"&gt;8&lt;/span&gt; &lt;span style="color: #000000;"&gt;9&lt;/span&gt; &lt;span style="color: #000000;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;do&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$i&lt;/span&gt; &lt;span style="color: #660033;"&gt;-eq&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
		&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Timed out before could establish task is running"&lt;/span&gt;
		&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
	&lt;span style="color: #007800;"&gt;STATUS&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ecs describe-tasks &lt;span style="color: #660033;"&gt;--cluster&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"default"&lt;/span&gt; &lt;span style="color: #660033;"&gt;--tasks&lt;/span&gt; &lt;span style="color: #007800;"&gt;$TASK&lt;/span&gt;  &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq .tasks&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #000000;"&gt;0&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;.lastStatus -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
	&lt;span style="color: #666666; font-style: italic;"&gt;# Did it exit unexpectedly?&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ne&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
		&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-tasks failed with code $?"&lt;/span&gt;
		&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
	&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$STATUS&lt;/span&gt;"&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;"RUNNING"&lt;/span&gt;  &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
		&lt;span style="color: #7a0874; font-weight: bold;"&gt;break&lt;/span&gt;
	&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
	&lt;span style="color: #c20cb9; font-weight: bold;"&gt;sleep&lt;/span&gt; &lt;span style="color: #000000;"&gt;30&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;done&lt;/span&gt;
 
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Get the network Interface id&lt;/span&gt;
&lt;span style="color: #007800;"&gt;ENI&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ecs describe-tasks &lt;span style="color: #660033;"&gt;--cluster&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"default"&lt;/span&gt; &lt;span style="color: #660033;"&gt;--tasks&lt;/span&gt; &lt;span style="color: #007800;"&gt;$TASK&lt;/span&gt;  &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #ff0000;"&gt;'.tasks[0].attachments[0].details[] | select(.name == "networkInterfaceId") | .value'&lt;/span&gt; &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Let's inspect what we got back. There should be a network interface id.&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ne&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-tasks failed with code $?"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$ENI&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-tasks could not establish eni"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Get the Public IP Address&lt;/span&gt;
&lt;span style="color: #007800;"&gt;PUBLIC_IP&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws ec2 describe-network-interfaces &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #660033;"&gt;--arg&lt;/span&gt; ENI &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$ENI&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'.NetworkInterfaces[] | select(.NetworkInterfaceId == $ENI) | .PrivateIpAddresses[0].Association.PublicIp'&lt;/span&gt; -r&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Did we get an IP address?&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ne&lt;/span&gt; &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-network-interfaces failed with code $?"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #007800;"&gt;$?&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #000000; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; &lt;span style="color: #660033;"&gt;-z&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$PUBLIC_IP&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;; &lt;span style="color: #000000; font-weight: bold;"&gt;then&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"describe-network-interfaces could not retrieve public IP address"&lt;/span&gt;
	&lt;span style="color: #7a0874; font-weight: bold;"&gt;exit&lt;/span&gt; &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;fi&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;BATCH&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; &lt;span style="color: #cc0000; font-style: italic;"&gt;&lt;&lt;EOT
{
  "Comment":"CREATE/DELETE/UPSERT a record",
  "Changes":[{
    "Action": "UPSERT",
    		  "ResourceRecordSet": {
    		  	"Name": "${BRANCH}",
    		  	"Type": "A",
    		  	"TTL": 300,
    		  	"ResourceRecords": [{ "Value": "${PUBLIC_IP}"}]
    		  }
  }]
}
EOT&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
&lt;span style="color: #007800;"&gt;PARENT_ZONE&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;aws route53 list-hosted-zones-by-name &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; jq &lt;span style="color: #660033;"&gt;--arg&lt;/span&gt; PARENT &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$PARENT&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'.HostedZones[] | select(.Name == $PARENT) | .Id'&lt;/span&gt; &lt;span style="color: #660033;"&gt;-r&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sed&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"s/.*\///"&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;`&lt;/span&gt;
 
aws route53 change-resource-record-sets \
	&lt;span style="color: #660033;"&gt;--hosted-zone-id&lt;/span&gt; &lt;span style="color: #007800;"&gt;$PARENT_ZONE&lt;/span&gt; \
	&lt;span style="color: #660033;"&gt;--change-batch&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$BATCH&lt;/span&gt;"&lt;/span&gt;
 
 
&lt;span style="color: #007800;"&gt;timestamp&lt;/span&gt;=$&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;date&lt;/span&gt; +&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;s&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
 
&lt;span style="color: #666666; font-style: italic;"&gt;# Now create a new hosted zone of the feature branch&lt;/span&gt;
aws route53 create-hosted-zone \
	&lt;span style="color: #660033;"&gt;--name&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$BRANCH&lt;/span&gt;"&lt;/span&gt; \
	&lt;span style="color: #660033;"&gt;--caller-reference&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"&lt;span style="color: #007800;"&gt;$timestamp&lt;/span&gt;"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Invoking the Script&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-11/Screenshot_2019-11-03_at_11_25_07-edited1.png?itok=6zDl28OV 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-11/Screenshot_2019-11-03_at_11_25_07-edited1.png?itok=PtA97zAh 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-11/Screenshot_2019-11-03_at_11_25_07-edited1.png?itok=onEwER9j 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-11/Screenshot_2019-11-03_at_11_25_07-edited1.png?itok=3pXhsRib 1362w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-11/Screenshot_2019-11-03_at_11_25_07-edited1.png?itok=6zDl28OV" alt="Full Domain Name" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The script requires two parameters as previous discussed. Here's my example for the blog:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;.&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;feature-branch.sh saasidate.com feature--doi-&lt;span style="color: #000000;"&gt;746&lt;/span&gt;-my-whizzy-new-feature&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Currently the output of the script is the response from the AWS CLI route53 create-hosted-zone call, and here you can detect the full domain name.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Checking the Outcome&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-11/Screenshot%202019-11-03%20at%2011.58.11.png?itok=J7vAfmhk 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-11/Screenshot%202019-11-03%20at%2011.58.11.png?itok=UyDrsDoT 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-11/Screenshot%202019-11-03%20at%2011.58.11.png?itok=vqKiRvSi 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-11/Screenshot%202019-11-03%20at%2011.58.11.png?itok=YUAatBcF 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-11/Screenshot%202019-11-03%20at%2011.58.11.png?itok=J7vAfmhk" alt="Tasks Running" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-11/Screenshot%202019-11-03%20at%2012.00.56.png?itok=d-SSfTq- 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-11/Screenshot%202019-11-03%20at%2012.00.56.png?itok=N4C40cpp 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-11/Screenshot%202019-11-03%20at%2012.00.56.png?itok=oHvt2vUZ 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-11/Screenshot%202019-11-03%20at%2012.00.56.png?itok=wa9icCup 2254w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-11/Screenshot%202019-11-03%20at%2012.00.56.png?itok=d-SSfTq-" alt="Route 53" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Obviously the first check is to copy and paste the url of the feature branch into a browser and see if it loads. An example of this is the blog heading image at the top of the page. &lt;/p&gt;

&lt;p&gt;Also the AWS console is the place to check everything is as required. Navigate to ECS -&gt; default -&gt; Tasks and you should see a screenshot similar to the first one immediately above. This is the task we invoked from inside our shell script. Now navigate to Route 53 -&gt; Hosted Zones -&gt; {domain name} and you can see the feature branch and its IP address.&lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Steps left to do&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;New hosted zones will normally propagate in 60 seconds in Route 53 - but it would be good if the script above polls Route 53 every 10 seconds or so and reports back the subdomain url and the IP address once the propagation has completed. This should be surfaced on the command line as a minimum, but perhaps a notification on Slack would be even better. Both options are trivial. &lt;/p&gt;

&lt;p&gt;Whilst the idea is that the Fargate tasks should persist, they shouldn't be around forever. Therefore there needs to be clear up activities to remove the feature subdomain from the parent domain's hosted zone, and the subdomain hosted zone. Also there obviously needs a step to stop the Fargate task. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Caveats&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;There are caveats to this solution - but for my use case, it's one of those rare occurrences in life that the caveats don't apply to me. &lt;/p&gt;

&lt;p&gt;Firstly, this solution will only work with a Fargate &lt;strong&gt;task&lt;/strong&gt; and not an ECS &lt;strong&gt;service&lt;/strong&gt; running a Fargate task. Tasks should be run as services for production environments since services give you great things like replication, and health percentages against number of running tasks. There is therefore no scaling, no load balancing, no DDOS protection in what I'm offering here.&lt;/p&gt;

&lt;p&gt;Fargate tasks run in isolation are perfect for spun up short living environments such as playgrounds for devs and QAs to run manual tests against or troubleshoot development issues - which is exactly my use case. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/aws" hreflang="en"&gt;AWS&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/awscli" hreflang="en"&gt;AWS CLI&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/docker" hreflang="en"&gt;Docker&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/fargate" hreflang="en"&gt;Fargate&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/ecs" hreflang="en"&gt;ECS&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/development" hreflang="en"&gt;Development&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/Route53" hreflang="en"&gt;Route 53&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/bash" hreflang="en"&gt;bash&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Fri, 01 Nov 2019 15:03:02 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">171 at http://badzilla.co.uk</guid>
    </item>

  </channel>
</rss>
