AWS CodeArtifact, GA, im Juni 2020, für große Projekte möchte ich, dass ein lokales Repository eine gemeinsame Bibliothek verwaltet, aber ich möchte nicht die Mühe machen, EC2 oder einen Container dafür einzurichten ... Es scheint sehr einfach zu bedienen zu sein.
Dieses Mal werde ich also AWS CodeArtifact berühren, um die Java-Bibliothek zu verwalten. Da es eine große Sache ist, werde ich versuchen, es mit Maven und Gradle auszuführen, und sogar CI / CD der mit CodeArtifact verknüpften Bibliothek ausprobieren. Sie können jederzeit Official User Guide begleiten. (Zum Zeitpunkt des Schreibens dieses Artikels ist er noch auf Japanisch. Es gibt kein Handbuch)
Beachten Sie außerdem, wie im Benutzerhandbuch angegeben, dass die CLI nur verwendet werden kann, wenn sie auf die neueste Version aktualisiert wurde.
Suchen Sie in der Dienstauswahl nach `` `CodeArtifact```, gehen Sie zum oberen Bildschirm und klicken Sie auf die Schaltfläche" Repository erstellen ". Anschließend werden Sie wie unten gezeigt nach dem Namen des Repositorys gefragt. Geben Sie ihm daher einen Textnamen.
Erstellen Sie als Nächstes eine Domain. Ich werde diesmal kein Cross-Account erstellen. Wählen Sie daher vorerst "dieses AWS-Konto" aus und geben Sie ihm einen textuellen Domainnamen. Legen Sie aus Sicherheitsgründen einen Kundenstammschlüssel fest.
Machen Sie nichts auf dem Bestätigungsbildschirm und "erstellen Sie ein Repository"!
Damit ist die Erstellung abgeschlossen. Als nächstes verbinden wir uns. Für Verbindungseinstellungen klicken Sie im Detailbild des erstellten Repositorys auf "Verbindungsverfahren anzeigen".
Wenn Sie den Paketmanager-Client auswählen, wird Folgendes angezeigt. Aus irgendeinem Grund werden die Bindestriche von "id" verdoppelt. Ich weiß nicht, ob es so etwas oder ein Fehler ist. Ein Geheimnis.
Erhalten Sie das erste Token und speichern Sie das lange Kennwort, das auf dem Bildschirm angezeigt wird. Das Ablaufdatum des Tokens beträgt bis zu 12 Stunden und kann verkürzt werden, aber es scheint, dass es nicht länger sein kann. Ein wenig unpraktisch ...
Lassen Sie uns die folgende Bibliothek im Maven-Projekt erstellen.
Greeting.java
package com.amazonaws.lambda.demo;
public class Greeting {
private String greetings;
private String name = null;
private String version = null;
public String getGreetings() {
return greetings;
}
public void setGreetings(String greetings) {
this.greetings = greetings;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public Greeting(String greetings, String name, String version) {
this.greetings = greetings;
if(name != null) {
this.name = name;
}
if(version != null) {
this.version = version;
}
else {
this.version = "1.0";
}
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.amazonaws.lambda</groupId>
<artifactId>Greeting</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>Greeting</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>test-domain-TestRepository</id>
<name>test-domain-TestRepository</name>
<url>[Repository-URL]</url>
</repository>
</distributionManagement>
</project>
settings.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<servers>
<server>
<id>test-domain-TestRepository</id>
<username>aws</username>
<password>[↑ Token werden durch den Erwerb von Token ausgezahlt]</password>
</server>
</servers>
</settings>
Nun, wenn Sie mvn bereitstellen und damit Erfolg haben ...
Das Repository wurde erfolgreich hinzugefügt!
Der Code auf der Benutzerseite sollte wie folgt aussehen. settings.xml kann mit ↑ identisch sein. Es soll mit Lambda funktionieren, also macht es etwas Seltsames.
In der Handlerfunktion von Lambda der in der Bibliothek von ↑ definierten Klasse
Greeting greetingBody = new Greeting("Hello", "Taro", null);
Benutzt.
LambdaFunctionHandler.java
package com.amazonaws.lambda.demo;
import java.util.logging.Logger;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import java.util.Map;
import java.util.HashMap;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class LambdaFunctionHandler implements RequestHandler<Map<String, Object> , Response> {
private static final Logger LOG = Logger.getLogger(LambdaFunctionHandler.class.getName());
@Override
public Response handleRequest(Map<String, Object> input, Context context) {
LambdaLogger logger = context.getLogger();
logger.log("received: " + input);
Greeting greetingBody = new Greeting("Hello", "Taro", null);
// TODO: implement your handler
return new Response.Builder()
.setStatusCode(200)
.setHeaders(new HashMap<String, String>(){{put("Content-Type","application/json");}})
.setObjectBody(greetingBody)
.build();
}
}
Response.java
package com.amazonaws.lambda.demo;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Collections;
import java.util.Map;
//import org.apache.log4j.Logger;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonInclude;
public class Response {
private final int statusCode;
private final Map<String, String> headers;
private final boolean isBase64Encoded;
private final String body;
public int getStatusCode() {
return statusCode;
}
public String getBody() {
return body;
}
public Map<String, String> getHeaders() {
return headers;
}
// API Gateway expects the property to be called "isBase64Encoded" => isIs
public boolean isIsBase64Encoded() {
return isBase64Encoded;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
// private static final Logger LOG = Logger.getLogger(Response.Builder.class);
private static final ObjectMapper objectMapper = new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
private int statusCode = 200;
private Map<String, String> headers = Collections.emptyMap();
private String rawBody;
private Object objectBody;
private byte[] binaryBody;
private boolean base64Encoded;
public Builder setStatusCode(int statusCode) {
this.statusCode = statusCode;
return this;
}
public Builder setHeaders(Map<String, String> headers) {
this.headers = headers;
return this;
}
/**
* Builds the {@link Response} using the passed raw body string.
*/
public Builder setRawBody(String rawBody) {
this.rawBody = rawBody;
return this;
}
/**
* Builds the {@link Response} using the passed object body
* converted to JSON.
*/
public Builder setObjectBody(Object objectBody) {
this.objectBody = objectBody;
return this;
}
/**
* Builds the {@link Response} using the passed binary body
* encoded as base64. {@link #setBase64Encoded(boolean)
* setBase64Encoded(true)} will be in invoked automatically.
*/
public Builder setBinaryBody(byte[] binaryBody) {
this.binaryBody = binaryBody;
setBase64Encoded(true);
return this;
}
/**
* A binary or rather a base64encoded responses requires
* <ol>
* <li>"Binary Media Types" to be configured in API Gateway
* <li>a request with an "Accept" header set to one of the "Binary Media
* Types"
* </ol>
*/
public Builder setBase64Encoded(boolean base64Encoded) {
this.base64Encoded = base64Encoded;
return this;
}
public Response build() {
String body = null;
if (rawBody != null) {
body = rawBody;
} else if (objectBody != null) {
try {
body = objectMapper.writeValueAsString(objectBody);
} catch (JsonProcessingException e) {
// LOG.error("failed to serialize object", e);
throw new RuntimeException(e);
}
} else if (binaryBody != null) {
body = new String(Base64.getEncoder().encode(binaryBody), StandardCharsets.UTF_8);
}
return new Response(statusCode, headers, base64Encoded, body);
}
}
public Response(int statusCode, Map<String, String> headers, boolean isBase64Encoded, String body) {
this.statusCode = statusCode;
this.headers = headers;
this.isBase64Encoded = isBase64Encoded;
this.body = body;
}
}
Der Schlüssel ist der folgende Teil von pom.xml. Definition der in CodeArtifact gespeicherten Bibliotheksabhängigkeiten und Verbindungseinstellungen.
<dependency>
<groupId>com.amazonaws.lambda</groupId>
<artifactId>Greeting</artifactId>
<version>1.0.0</version>
</dependency>
<profiles>
<profile>
<id>test-domain-TestRepository</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>test-domain-TestRepository</id>
<name>test-domain-TestRepository</name>
<url>[Repository-URL]</url>
</repository>
</repositories>
</profile>
</profiles>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.amazonaws.lambda</groupId>
<artifactId>LambdaTest3</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>LambdaTest3</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<profiles>
<profile>
<id>test-domain-TestRepository</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>test-domain-TestRepository</id>
<name>test-domain-TestRepository</name>
<url>[Repository-URL]</url>
</repository>
</repositories>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-bom</artifactId>
<version>1.11.256</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws.lambda</groupId>
<artifactId>Greeting</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
Wenn Sie nun ein mvn-Paket erstellen, wird die Bibliothek fest importiert und der Build ist abgeschlossen. Wenn Sie settings.xml vom Standardpfad geändert haben, müssen Sie die Option `` `-s``` angeben.
Lassen Sie uns nun portieren, was mit Maven mit Gradle Build erstellt wurde. Ändern Sie nicht den Inhalt der Java-Quelle.
Erstellen Sie das folgende build.gradle und `` `gradlew Publish```.
build.gradle
plugins {
id 'maven-publish'
id 'java-library'
}
repositories {
jcenter()
}
dependencies {
testImplementation 'junit:junit:4.12'
}
publishing {
publications {
mavenJava(MavenPublication) {
groupId = 'com.amazonaws.lambda'
artifactId = 'Greeting'
version = '1.0.1'
from components.java
}
}
repositories {
maven {
url '[Repository-URL]'
credentials {
username "aws"
password "[↑ Token werden durch den Erwerb von Token ausgezahlt]"
}
}
}
}
Der folgende Fehler wird angezeigt, aber der Upload selbst scheint zu funktionieren.
> Task :publishMavenJavaPublicationToMavenRepository
Cannot upload checksum for module-maven-metadata.xml. Remote repository doesn't support sha-512. Error: Could not PUT 'https://test-domain-xxxxxxxxxxx.d.codeartifact.ap-northeast-1.amazonaws.com/maven/TestRepository/com/amazonaws/lambda/Greeting/maven-metadata.xml.sha512'. Received status code 400 from server: Bad Request
Der Bibliotheksbenutzer legt build.gradle wie folgt fest. Wie bei der Bibliothek muss die Java-Quelle nicht geändert werden.
Um FatJar zu erstellen, führen Sie es mit `gradlew shadowJar``` anstelle von`
gradle build``` aus.
build.gradle
plugins {
id 'com.github.johnrengelman.shadow' version '2.0.3'
id 'java-library'
}
repositories {
jcenter()
maven {
url '[Repository-URL]'
credentials {
username "aws"
password "[↑ Token werden durch den Erwerb von Token ausgezahlt]"
}
}
}
dependencies {
implementation platform('com.amazonaws:aws-java-sdk-bom:1.11.256')
implementation 'com.amazonaws:aws-lambda-java-events:1.3.0'
implementation 'com.amazonaws:aws-lambda-java-core:1.1.0'
runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.2.0'
implementation 'com.amazonaws.lambda:Greeting:1.0.0'
testImplementation 'junit:junit:4.12'
}
jar {
manifest {
attributes "Main-Class" : "LambdaFunctionHandler.java"
}
}
Es kann bestätigt werden, dass es nicht nur mit Maven, sondern auch mit Gradle funktioniert.
Ich weiß nicht, ob es eine Anfrage gibt. Natürlich kann Code Artifact auch in Code Build integriert werden.
Die Integration mit CodeBuild wird in Dieser Abschnitt des Benutzerhandbuchs beschrieben. Fügen Sie der CodeBuild-Servicerolle zum Veröffentlichen die folgenden Berechtigungen hinzu.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codeartifact:GetAuthorizationToken",
"codeartifact:ReadFromRepository",
"codeartifact:GetRepositoryEndpoint",
"codeartifact:PublishPackageVersion",
"codeartifact:PutPackageMetadata",
"sts:GetServiceBearerToken"
],
"Resource": "*"
}
]
}
Der Punkt ist buildspec.yml, aber vorher wollen wir die settings.xml überprüfen, die wir dieses Mal erstellt haben. Es ist nicht so sehr so, dass Sie das Token jedes Mal manuell abrufen müssen, wenn Sie CI / CI aktivieren. Machen Sie also das `` `password``` -Tag wie folgt.
<password>${env.CODEARTIFACT_TOKEN}</password>
Definieren wir dann buildspec.yml wie folgt.
Übrigens funktioniert der Teil `aws codeartifact``` nicht, wenn Sie ihn wie im Benutzerhandbuch beschrieben ausführen. Beachten Sie, dass es ohne
`--query authorisationToken``` nicht funktioniert. Diese Option ist nicht einmal in der CLI-Dokumentation aufgeführt (https://docs.aws.amazon.com/cli/latest/reference/codeartifact/get-authorization-token.html), was ein ziemliches Rätsel ist ... .. Wenn diese Option nicht hinzugefügt wird, wird vorerst der Zeitstempel ausgegeben und es handelt sich nicht um die erwartete Umgebungsvariable.
buildspec.yml
version: 0.2
phases:
install:
runtime-versions:
java: corretto8
commands:
- pip install --upgrade pip
- pip install --upgrade awscli
pre_build:
commands:
- export CODEARTIFACT_TOKEN=$(aws codeartifact get-authorization-token --domain test-domain --domain-owner [Konto-ID] --query authorizationToken --output text)
build:
commands:
- echo Build started on `date`
- mvn -s ./settings.xml deploy
- echo Build ended on `date`
cache:
paths:
- '/root/.m2/**/*'
Die CI / CD-Pipeline der Bibliothek ist jetzt abgeschlossen!
Recommended Posts