Einführung
- Der Bildschirm ist Java (Spring Boot) + DynamoDB, eine Webanwendung, das Client-Tool ist Go und der API-Teil ist API Gateway + Lambda (Python).
- Dieses Mal möchte ich einen Teil der Automatisierung des Testens und Bereitstellens von Webanwendungen mit SpringBoot + DynamoDB in dieser Architektur vorstellen.
- Ich frage mich, ob es ein Referenzteil gibt, auch wenn Sie kein Java-Ingenieur sind. Wenn Sie möchten, lesen Sie bitte nur die Zusammenfassung des Artikels.
Artikelübersicht
Was automatisieren Sie?
Welche Art von Technologie verwenden Sie?
- ** Internetanwendung **
- SpringBoot 1.5.6 + Thymeleaf
- DB verwendet nur DynamoDB. Ich habe das DynamoDB-Zugriffsframework selbst implementiert.
- DynamoDBLocal
- Sie können DynamoDB lokal starten.
- Da es im Speicher gestartet werden kann, ist es gut, dass Sie die Daten nicht bereinigen müssen, indem Sie sie mit CI starten und am Ende löschen.
- Selenide
- Selenium Wrapper Bibliothek. Ich mag diesen Ort und benutze ihn.
- Kann mit CSS Selector geschrieben werden (die Anzahl der Beschreibungen wird trotzdem reduziert)
- Testcode und CSS Selector-Beschreibung können schnell getrennt werden
- Sie können Treiber usw. einfach mit Umgebungsvariablen wechseln. (Einige werden von uns selbst implementiert)
- Keine detaillierten Wartezeiten beim Laden des Bildschirms, keine Bildschirmaufnahmen, wenn der Test fehlschlägt, oder Teile, die von Ihnen selbst erweitert wurden
- ** Browser für E2E-Tests **
- Als ich die Nachricht sah, dass der Haupt-Committer von PhantomJS fehlte, wagte ich den Sprung und begann, ** Chrome Headless ** zu verwenden.
- Referenz: Phantom.js Betreuer, der die Zukunft des Projekts in Frage stellt und zurücktritt
- Der Chrome-Treiber verwendet 2.33, kann jedoch problemlos verwendet werden.
- Ich werde später darauf zurückkommen, aber ** Gut, jeder ist zu faul, um Chrome unter Amazon Linux kopflos auszuführen, also lasst uns aufhören. ** ** **
- ** Im Container verwendetes Betriebssystem-Image **
- Ich dachte, ich könnte CentOS wegen der langen Erstellungszeit nicht verwenden, also wechselte ich zu ** Alpine Linux **.
- Die Entwicklungsumgebung basiert auf openjdk alpine linux und die Gebietsschemaeinstellungen werden festgelegt.
- Ich habe auch die Einstellungen des Protokolltreibers (fließend) hinzugefügt, aber da es sich um eine Entwicklungsumgebung handelt, verwende ich CloudWatch-Protokolle, die Fargate für mich festlegt.
- ** Docker-Repository **
- ** Verwenden Sie ECR **
- Docker Hub kann nur ein privates Repository haben. Es wird keine Automatisierung erstellt.
- Ich habe auch artifactory auf EC2 eingerichtet, aber als ich dachte, dass ich es bedienen muss, habe ich aufgehört, weil es ein bisschen albern war. Ich tat.
- Der entscheidende Faktor ist, dass Sie ID / PW verwalten müssen, wenn Sie diese externen Container verwenden. AWS verfügt jedoch über einen wunderbaren Mechanismus namens STS. Daher habe ich beschlossen, dass es besser ist, weiterzumachen.
- ** Container-Orchestrierungssoftware **
- ** Ich habe angefangen, [AWS Fargate] zu verwenden (https://aws.amazon.com/jp/fargate/?nc2=h_mo) **.
- Ich habe ECS (EC2) bis letzten Monat mit Spot Fleet verwendet, aber ich habe meine Neugier auf Fargate verloren. (Natürlich ist der Preis für Fargate höher)
- ECS (Fargate) läuft auf us-east-1.
- Ich versuche, ap-northeast-1 in der Produktion zu verwenden, aber da DynamoDB kein Konzept wie ein Schema hat, kann ich nicht dieselbe Tabelle in derselben Region platzieren. Aber ich denke, es ist in Ordnung, Fargate deswegen zu berühren.
- ** Skript für ECS (Fargate) bereitstellen **
- Zum Zeitpunkt von ECS (EC2) habe ich die Bereitstellung mit silinternational / ecs-deploy durchgeführt, aber ich habe mich gegabelt, weil Fargate nicht unterstützt wurde. Ich benutze es, nachdem ich es repariert habe.
- ecs-deploy ist nur eine Shell, daher ist es bequem zu tragen. Klicken Sie hier für eine Fargate-kompatible Version.
* AWS Fargate BlueGreenDeployment
* https://github.com/uzresk/ecs-deploy.git
Wie machst du das
- Beim Ausführen dieser Aufgaben von Jenkins aus habe ich zuerst in Shell geschrieben, aber es ist mehr als ich erwartet hatte.
- Ich habe viele Versuche und Irrtümer durchgeführt, aber ** Abgesehen von der Bereitstellung in Fargate können Sie dies mit nur "mvn install" tun. ** ** **
Praktische Ausgabe
Verwenden Sie DynamoDB lokal
- Um DynamoDB lokal zu verwenden, verwenden Sie das offizielle Modul DynamoDB Local.
- Ich benutze es schwebend auf Docker. Wenn Sie diese Seite googeln, werden verschiedene Artikel angezeigt, und es gibt keine besonderen Punkte, von denen Sie abhängig sein könnten. Deshalb werde ich sie weglassen.
- Übrigens ist auch die GUI enthalten, aber ich benutze sie nicht, weil ich sie in den Knoten schreiben muss.
Automatisieren Sie Tests, um auf DynamoDB zuzugreifen
- Wenn man sich das AWS-Handbuch von DynamoDBLocal ansieht, scheint es im Speicher wie H2 betrieben werden zu können ** ** .. ** ** **
- Wenn Sie es in den Speicher verschieben können, werden Sie nicht vergessen, die Daten zu löschen. Es gibt also keine Möglichkeit, dies nicht zu verwenden.
- Ich fragte mich, ob ich es mit diesem Verfahren verschieben könnte.
-
- Starten Sie DynamoDB im Speicher
-
- Erstellen Sie eine Tabelle
-
- Führen Sie den Test aus
-
- DynamoDB stoppen (Daten verschwinden)
- Da die zu verwendende Umgebung eine Mischung aus Windows und Linux ist, dachte ich, ich möchte vermeiden, etwas mit Shell oder Bat zu tun, um eine Tabellendefinition zu starten oder zu erstellen.
- Ich habe angefangen, leise Maven-Plug-Ins zu erstellen, aber es ist zu langweilig. Das war's. ..
jcabi-dynamodb-maven-plugin
Ablauf beim Herunterladen, Starten, Eingeben von DDL, Testen und Stoppen von DynamoDB Local
- Wenn Sie etwas genauer erklären, wird der Ablauf so sein.
-
- Laden Sie DynamoDBLocal mit dem Maven-Dependency-Plugin herunter und platzieren Sie es in dynamodb-dist
-
- Starten Sie DynamoDB von dynamodb-dist an dem durch $ {dynamodb.port} angegebenen Port mit dem jcabi-dynamodb-maven-plugin.
-
- Nach dem Start wird das in geschriebene Skript zur Tabellenerstellung ausgeführt.
- Wenn Sie json schnell am Tisch haben möchten, verwenden Sie dies bitte
- Referenz: Ein Liner zum Konvertieren vorhandener DynamoDB-Tabellen in das JSON-Format
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>
- Da es mit der Integrationsaufgabe funktioniert, können Sie DynamoDB starten, testen und stoppen, indem Sie den folgenden Befehl ausführen.
mvn verify
E2E-Testautomatisierung
- Ich möchte den E2E-Test mit dem Integrationstest durchführen.
- Ich benutze Selenide. Ich mag diesen Ort.
- Einstellungen können in den Systemeigenschaften vorgenommen werden (Konfiguration)
- Headless Switching konnte nicht durch Einstellen der Systemeigenschaften durchgeführt werden, wurde jedoch ein wenig verbessert, damit dies möglich ist.
- Wenn Sie statisch importieren, können Sie es mit CSS Selector wie "$ (" # id ")" implementieren, sodass die Anzahl der Beschreibungen im Vergleich zu Selen drastisch reduziert wird.
- Ich mag das Seitenmuster
- Es ist leicht zu verstehen, was Sie testen, da Sie die CSSSelector-Beschreibung aus der JUnit-Testklasse entfernen können.
Starten Sie die Spring Boot-Anwendung
- Wenn Sie das Spring-Boot-Maven-Plugin verwenden, beginnt es mit der Vorintegration und endet mit der Nachintegration. Das können Sie leicht tun.
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.Starten Sie eine Anwendung mit 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>
- Ich habe auch ein Profil für die Integration vorbereitet und im Falle der Integration so eingestellt, dass es auf Port 18080 startet.
application-integration.yml
server:
port: 18080
settings:
dynamodb:
host: localhost
port: 10000
region: ap-northeast-1
Absorbieren Sie den Umweltunterschied zwischen der lokalen Umgebung und CI
- Wenn Sie Selenide-Code in JUnit schreiben und ausführen, funktioniert dies, es gibt jedoch Unterschiede in der Umgebung.
Umgebung |
Startport |
Chrome |
lokal |
8080 |
Headless=false |
Jenkins |
1800 |
Headless=true |
- In
@ BeforeClass
vor dem Ausführen von Selenide können verschiedene Einstellungen mit -D (Systemeigenschaft) vorgenommen werden.
@BeforeClass
public static void beforeClass() {
//Ändern Sie die Basis-URL(Standard:http://localhost:8080)
String webApplicationPort = System.getProperty("webapp.port", "8080");
Configuration.baseUrl = String.format("http://localhost:%s/app/",webApplicationPort);
//Machen Sie den Standardtreiber Chrome-Treiber
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"));
}
- Der Integrationstest wird vom Maven-Failsafe-Plugin festgelegt, aber hier werden der Port, der ChromeDriver-Speicherort und Headless oder nicht umgeschaltet.
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>
<!--Einstellungen für 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>
Installieren Sie Chrome unter Amazon Linux
- Eigentlich hat das am längsten gedauert.
- Da Amazon Linux ein Betriebssystem ist, für das CUI erforderlich ist, enthält es keine GUI-Module und kann nicht aus dem Yum-Repository von Amazon abgerufen werden. Daher kann es von einem anderen Speicherort abgerufen werden, um Abhängigkeiten nacheinander aufzulösen. Ich muss es tun. Dies kann nicht durch Auflösen der Abhängigkeit dieses Moduls behoben werden. Die Wiederholung dauerte sehr lange.
- ** Die Schlussfolgerung ist ... **
- ** Ich bin süchtig danach, Chrome unter Amazon Linux auszuführen. ** ** **
- ** Verwenden Sie Debian oder CentOS7 / Redhat7. ** ** **
- ** Auch wenn Sie Amazon Linux verwenden und die Cloud verwenden, setzen Sie Jenkins Slave auf CentOS 7 und führen Sie JOB aus. ** ** **
- Wenn Sie es dennoch versuchen möchten, lesen Sie bitte diese Seite.
- Das hier vorgestellte Chrome ist alt, also musst du doch den harten Weg gehen.
- AWS-Konto erforderlich.
Übrigens habe ich DynamoDB lokal gestartet und getestet, und ich konnte auf dem Bildschirm testen.
Lassen Sie es uns bereitstellen.
Bereitstellen
Bereiten Sie eine Docker-Datei vor
- Bereiten Sie eine Docker-Datei vor. Ich denke, es ist gut, auf den offiziellen Blog von Spring Boot zu verweisen, aber ich denke, dass es kein Problem gibt, wenn Sie mindestens so viel verwenden.
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"]
Docker bauen und auf ECR drücken
- Verwenden Sie spotify / dockerfile-maven, um einen Container mit Dockerfile zu erstellen.
- Erstellen Sie einen Container mit dem von build als Argument von Dockerfile erstellten JAR und verschieben Sie ihn an den in
<Repository>
angegebenen Speicherort.
- Wenn eine Authentifizierung erforderlich ist, muss diese in settings.xml festgelegt werden, aber meine Umgebung hat eine Rolle, damit die EC2-Instanz, auf der Jenkins ausgeführt wird, auf ECR pushen und sich anmelden kann Sie müssen es nicht einstellen, da es von Jenkins im Voraus ausgeführt wird.
<!--Erstellen Sie einen Container aus Dockerfile und stellen Sie ihn für ECR bereit-->
<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>
Wo es stecken bleibt
Bereitstellung in Fargate
- Zum Zeitpunkt von ECS (LaunchType EC2) habe ich eine Shell namens ecs-deploy verwendet, die jedoch nicht mit Fargate kompatibel ist.
- Fork unterstützt die Bereitstellung in Fargate. Verwenden Sie es daher, wenn Sie möchten. Die Verwendung entspricht genau der von ecs-deploy.
- https://qiita.com/uzresk/items/02f378f31e6f496b41a0
Jenkins Einstellungen
- Machen Sie als vorbereitende Vorbereitung ein Docker-Login.
- Wenn Sie aws ecs get-login ... drücken, wird der Docker-Anmeldebefehl zurückgegeben, sodass er wie bei eval ausgeführt wird.
- Vergessen Sie nicht, dass Docker 17.06 und höher die Option --no-include-email erfordert.
* http://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/ECR_AWSCLI.html
docker logout xxxx.dkr.ecr.ap-northeast-1.amazonaws.com
eval $(aws ecr get-login --no-include-email --region ap-northeast-1)
# dockerfile-maven-Konfiguration mit Plugin.https zu json://Scheitern ohne
sed -i 's/xxxx/https:\/\/xxxx/' ~/.docker/config.json
mvn install
- Führen Sie ecs-deploy aus
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
- Da es neu markiert ist, löschen Sie das Docker-Image ohne Tags
docker images | grep "[image name]" | grep "<none>" | awk '{print $3}' | xargs docker rmi
schließlich
- Ich führe diesen Zyklus zum Zeitpunkt des Drückens aus, aber es dauert ungefähr 3 Minuten und 30 Sekunden, um den Test abzuschließen, sodass ich ihn bisher ohne Probleme bedienen kann.
- Ich frage mich, ob der E2E-Testteil, der einige Zeit in Anspruch nimmt, wenn die App etwas älter wird, mit Slave von Jenkins ausgeführt werden kann. Es wäre interessant, wenn wir dies auf Fargate parallel verschieben könnten.