Essayez de gérer les bibliothèques Java avec AWS CodeArtifact

introduction

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.

Tout d'abord, essayez de créer un référentiel

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.

キャプチャ1.png

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é.

キャプチャ2.png

Ne faites rien sur l'écran de confirmation et "créez un référentiel"!

キャプチャ3.png

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éé.

キャプチャ4.png

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.

キャプチャ5.png

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 ...

Essayez de l'utiliser dans un projet Maven

Créons la bibliothèque suivante dans le projet Maven.

Stockage de la bibliothèque

Greeting.java

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

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

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 ...

キャプチャ6.png

Le référentiel a été ajouté avec succès!

Utilisation de la bibliothèque

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

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

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

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```.

Essayez de l'utiliser dans un projet Gradle

Maintenant, portons ce qui a été construit avec Maven avec la version Gradle. Ne modifiez pas le contenu de la source Java.

Stockage de la bibliothèque

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

Utilisation de la bibliothèque

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.

Vous voulez CI / CD même une bibliothèque partagée

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

Essayez de gérer les bibliothèques Java avec AWS CodeArtifact
Essayez la connexion DB avec Java
Essayez gRPC avec Java, Maven
Essayez d'utiliser Redis avec Java (jar)
Utilisation de Java avec AWS Lambda-Eclipse Préparation
Essayez la communication bidirectionnelle avec gRPC Java
Essayez d'exécuter AWS X-Ray en Java
Bibliothèques Java
Utilisation de Java avec des arguments CloudWatch AWS Lambda-Implementation-Check
Utilisation de Java avec AWS Lambda-Implementation-Stop / Launch EC2
Essayons WebSocket avec Java et javascript!
Essayez d'utiliser la télécommande Wii en Java
Essayez Java 8 Stream
Essayez d'intégrer Ruby et Java avec Dapr
Comment utiliser le framework Java avec AWS Lambda! ??
Essayez d'implémenter TCP / IP + NIO avec JAVA
Essayez grossièrement Java 9
Essayez de déboguer un programme Java avec VS Code
Soumettre une tâche à AWS Batch avec Java (Eclipse)
Comment déployer Java sur AWS Lambda avec Serverless Framework
Essayez de vous connecter à l'émulateur AzureCosmosDB pour Docker avec Java
Essayez de créer Java dans un module natif avec GraalVM
Essayez DI avec Micronaut
Installez java avec Homebrew
Essayez de créer avec Trailblazer
Changer de siège avec Java
Installez Java avec Ansible
Essayez WebSocket avec jooby
Changer java avec direnv
Téléchargement Java avec Ansible
Raclons avec Java! !!
Construire Java avec Wercker
Essayez la valeur de retour Java
Conversion Endian avec JAVA
Publiez régulièrement des images de tweets sur Twitter avec AWS Lambda + Java
Agrégation et analyse de journaux (utilisation d'AWS Athena en Java)
[Débutant] Essayez de créer un jeu RPG simple avec Java ①
Créer un SlackBot avec AWS lambda et API Gateway en Java
Essayez Spark Submit to EMR à l'aide du kit AWS SDK pour Java