AWS CodeArtifact, GA en juin 2020, pour les grands projets, je veux un référentiel local pour gérer une bibliothèque commune, mais je ne veux pas prendre la peine de configurer EC2 ou un conteneur pour cela ... Cela semble très simple à utiliser.
Donc, cette fois, je toucherai en fait à AWS CodeArtifact pour gérer la bibliothèque Java. Comme c'est un gros problème, je vais essayer de l'exécuter avec Maven et Gradle, et même essayer CI / CD de la bibliothèque liée à CodeArtifact. Vous pouvez toujours accompagner le Guide de l'utilisateur officiel (Au moment de la rédaction de cet article, il est toujours en japonais. Il n'y a pas de manuel)
De plus, comme indiqué dans le guide de l'utilisateur, veuillez noter que la CLI ne peut être utilisée que si elle est mise à jour vers la dernière version.
Recherchez `` CodeArtifact '' dans la sélection de service, allez à l'écran supérieur et appuyez sur le bouton "Créer un référentiel". Ensuite, il vous sera demandé le nom du référentiel comme indiqué ci-dessous, alors donnez-lui un nom textuel.
Ensuite, créez un domaine. Je ne ferai pas de comptes croisés cette fois, donc pour le moment, sélectionnez "ce compte AWS" et donnez-lui un nom de domaine textuel. Définissez une clé principale client pour la sécurité.
Ne faites rien sur l'écran de confirmation et "créez un référentiel"!
Ceci termine la création. Ensuite, connectons-nous. Pour les paramètres de connexion, appuyez sur "Afficher la procédure de connexion" sur l'écran des détails du référentiel créé.
Lorsque vous sélectionnez le client du gestionnaire de packages, ce qui suit s'affiche. Pour une raison quelconque, les tirets de «« id »» sont doublés. Je ne sais pas si c'est quelque chose comme ça ou un bug. Un mystère.
Obtenez le premier jeton et enregistrez le mot de passe long qui apparaît à l'écran. La date d'expiration du jeton est jusqu'à 12 heures et peut être raccourcie, mais il semble qu'elle ne peut pas être plus longue. Un peu gênant ...
Créons la bibliothèque suivante dans le projet Maven.
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>[URL du référentiel]</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>[↑ Jetons payés en acquérant des jetons]</password>
</server>
</servers>
</settings>
Maintenant, si vous mvn déployez et réussissez avec cela ...
Le référentiel a été ajouté avec succès!
Le code côté utilisateur doit ressembler à ce qui suit. setting.xml peut être identique à ↑. Il est censé fonctionner avec Lambda, donc il fait quelque chose de bizarre.
Dans la fonction handler de Lambda, de la classe définie dans la bibliothèque de ↑
Greeting greetingBody = new Greeting("Hello", "Taro", null);
Utilise.
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;
}
}
La clé est la partie suivante de pom.xml. Définition de la dépendance de la bibliothèque stockée dans CodeArtifact et paramètre de connexion.
<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>[URL du référentiel]</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>[URL du référentiel]</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>
Maintenant, lorsque vous mvn package, la bibliothèque est fermement importée et la construction est terminée. Si vous avez modifié settings.xml à partir du chemin par défaut, veillez à spécifier l'option `` -s```.
Maintenant, portons ce qui a été construit avec Maven avec la version Gradle. Ne modifiez pas le contenu de la source Java.
Créez le build.gradle suivant et `` 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 '[URL du référentiel]'
credentials {
username "aws"
password "[↑ Jetons payés en acquérant des jetons]"
}
}
}
}
L'erreur suivante s'affiche, mais le téléchargement lui-même semble fonctionner.
> 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
L'utilisateur de la bibliothèque définit build.gradle comme suit. Comme pour le côté bibliothèque, la source Java n'a pas besoin d'être modifiée.
Pour créer FatJar, exécutez-le avec
gradlew shadowJar au lieu de `` `` gradle build
.
build.gradle
plugins {
id 'com.github.johnrengelman.shadow' version '2.0.3'
id 'java-library'
}
repositories {
jcenter()
maven {
url '[URL du référentiel]'
credentials {
username "aws"
password "[↑ Jetons payés en acquérant des jetons]"
}
}
}
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"
}
}
Il peut être confirmé que cela fonctionne non seulement avec Maven mais aussi avec Gradle.
Je ne sais pas s'il y a une demande. Bien entendu, Code Artifact peut également être incorporé dans Code Build.
L'intégration avec CodeBuild est décrite dans Cette section du guide de l'utilisateur. Comme indiqué, attachez les autorisations suivantes au rôle de service CodeBuild pour publier:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codeartifact:GetAuthorizationToken",
"codeartifact:ReadFromRepository",
"codeartifact:GetRepositoryEndpoint",
"codeartifact:PublishPackageVersion",
"codeartifact:PutPackageMetadata",
"sts:GetServiceBearerToken"
],
"Resource": "*"
}
]
}
Le point est buildspec.yml, mais avant cela, passons en revue le settings.xml que nous avons créé cette fois. Ce n'est pas tant que vous devez obtenir manuellement le jeton à chaque fois que vous activez CI / CI, alors créez la balise `` mot de passe '' comme suit.
<password>${env.CODEARTIFACT_TOKEN}</password>
Ensuite, définissons buildspec.yml comme suit.
Au fait, la partie aws code artifact
ne fonctionne pas si vous l'exécutez comme décrit dans le guide de l'utilisateur. Notez que cela ne fonctionnera pas sans
--query authorisationToken```. Cette option n'est même pas répertoriée dans la documentation de la CLI (https://docs.aws.amazon.com/cli/latest/reference/codeartifact/get-authorization-token.html), ce qui est assez mystérieux ... .. Pour le moment, si cette option n'est pas ajoutée, l'horodatage sera affiché et ce ne sera pas la variable d'environnement attendue.
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 [identifiant de compte] --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/**/*'
Le pipeline CI / CD de la bibliothèque est maintenant terminé!
Recommended Posts