[JAVA] About testing web applications using DynamoDB and automating deployment to Fargate

Introduction

Article summary

What are you automating

image.png

What kind of technology are you using

How do you do it

image.png


Practical edition

Use DynamoDB locally

Automate tests to access DynamoDB

jcabi-dynamodb-maven-plugin

Flow of downloading, starting, inputting DDL, testing, and stopping DynamoDB Local

pom.xml


<plugins>
    <plugin>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.8</version>
        <executions>
            <execution>
                <id>unpack-dynamodb-local</id>
                <goals>
                    <goal>unpack</goal>
                </goals>
                <configuration>
                    <artifactItems>
                        <artifactItem>
                            <groupId>com.jcabi</groupId>
                            <artifactId>DynamoDBLocal</artifactId>
                            <version>2015-07-16</version>
                            <type>zip</type>
                            <outputDirectory>${project.build.directory}/dynamodb-dist</outputDirectory>
                            <overWrite>false</overWrite>
                        </artifactItem>
                    </artifactItems>
                </configuration>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>com.jcabi</groupId>
        <artifactId>jcabi-dynamodb-maven-plugin</artifactId>
        <version>0.9.1</version>
        <executions>
            <execution>
                <goals>
                    <goal>start</goal>
                    <goal>create-tables</goal>
                    <goal>stop</goal>
                </goals>
                <configuration>
                    <port>${dynamodb.port}</port>
                    <dist>${project.build.directory}/dynamodb-dist</dist>
                    <arguments>
                        <argument>-inMemory</argument>
                        <argument>-sharedDb</argument>
                    </arguments>
                    <tables>
                        <table>${basedir}/src/main/resources/ddl/Asset.json</table>
                        <table>${basedir}/src/main/resources/ddl/AssetGroup.json</table>
                        <table>${basedir}/src/main/resources/ddl/AssetRole.json</table>
                        <table>${basedir}/src/main/resources/ddl/Contract.json</table>
                        <table>${basedir}/src/main/resources/ddl/Invitation.json</table>
                        <table>${basedir}/src/main/resources/ddl/Member.json</table>
                        <table>${basedir}/src/main/resources/ddl/Organization.json</table>
                        <table>${basedir}/src/main/resources/ddl/OrgKey.json</table>
                        <table>${basedir}/src/main/resources/ddl/OrgMember.json</table>
                        <table>${basedir}/src/main/resources/ddl/Role.json</table>
                        <table>${basedir}/src/main/resources/ddl/Service.json</table>
                        <table>${basedir}/src/main/resources/ddl/Tag.json</table>
                    </tables>
                </configuration>
            </execution>
        </executions>
    </plugin>
<plugins>
mvn verify

E2E test automation

Launch the Spring Boot application

pom.xml


<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <mainClass>jp.gr.java_conf.uzresk.puzzle.web.WebApplication</mainClass>
            <profiles>
                <!-- application-integration.Launch the application using yml-->
                <profile>integration</profile>
            </profiles>
        </configuration>
        <executions>
            <execution>
                <id>pre-integration-test</id>
                <goals>
                    <goal>start</goal>
                </goals>
            </execution>
            <execution>
                <id>post-integration-test</id>
                <goals>
                    <goal>stop</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

application-integration.yml


server:
  port: 18080
settings:
  dynamodb:
    host: localhost
    port: 10000
    region: ap-northeast-1

Absorb the environmental difference between the local environment and CI

environment Startup port Chrome
local 8080 Headless=false
Jenkins 1800 Headless=true
    @BeforeClass
    public static void beforeClass() {

        //Change the base URL(Default:http://localhost:8080)
        String webApplicationPort = System.getProperty("webapp.port", "8080");
        Configuration.baseUrl = String.format("http://localhost:%s/app/",webApplicationPort);

        //Make the default driver Chrome Driver
        Configuration.browser = System.getProperty("selenide.browser", WebDriverRunner.CHROME);
        System.setProperty("webdriver.chromedriver", System.getProperty("webdriver.chromedriver", "./drivers/chromedriver.exe"));

        // headless
        Configuration.headless = Boolean.parseBoolean(System.getProperty("selenide.headless", "false"));
    }

pom.xml


<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.11</version>
        <configuration>
            <includes>
                <include>**/*.class</include>
            </includes>
            <groups>
                jp.gr.java_conf.uzresk.puzzle.web.test.IntegrationTest
            </groups>
            <summaryFile>${report.dir}/failsafe-summary.xml</summaryFile>
            <reportsDirectory>${report.dir}</reportsDirectory>
            <!--Settings for CI-->
            <systemPropertyVariables>
                <webapp.port>18080</webapp.port>
                <selenide.headless>true</selenide.headless>
                <webdriver.chromedriver>./drivers/chromedriver</webdriver.chromedriver>
            </systemPropertyVariables>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>integration-test</goal>
                    <goal>verify</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
<plugins>

Install Chrome on Amazon Linux


By the way, I started DynamoDB locally and tested it, and I was able to test around the screen. Let's deploy it.


Deploy

Prepare a Dockerfile

FROM openjdk:8u131-jdk-alpine

LABEL maintainer "uzresk"

RUN apk --update add tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    apk del tzdata && \
    rm -rf /var/cache/apk/*

VOLUME /tmp

ARG JAR_FILE
ADD ${JAR_FILE} xxx-web.jar
ENTRYPOINT ["java","-jar","/xxx-web.jar"]

push to docker build and ECR

            <!--Create a container from Dockerfile and deploy it to ECR--> 
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.3.6</version>
                <configuration>
                    <repository>xxxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxx-web</repository>
                    <tag>${project.version}</tag>
                    <buildArgs>
                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                </configuration>
                <executions>
                    <execution>
                        <id>default</id>
                        <phase>install</phase>
                        <goals>
                            <goal>build</goal>
                            <goal>push</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

Where it gets stuck


Deploy to Fargate


Jenkins settings

docker logout xxxx.dkr.ecr.ap-northeast-1.amazonaws.com
eval $(aws ecr get-login --no-include-email --region ap-northeast-1)

# dockerfile-maven-config with plugin.https to json://Fail without
sed -i 's/xxxx/https:\/\/xxxx/' ~/.docker/config.json
mvn install
chmod +x $WORKSPACE/web/bin/ecs-deploy
$WORKSPACE/web/bin/ecs-deploy -c web-cluster -n web-service -i xxxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxxxxx-web:0.0.1-SNAPSHOT -t 600 -r us-east-1
docker images | grep "[image name]" | grep "<none>"  | awk '{print $3}' | xargs docker rmi

at the end

Recommended Posts

About testing web applications using DynamoDB and automating deployment to Fargate
Perspectives to worry about when doing code reviews of web applications (Rails)