Самый простой способ создать AWS лямбда-зип для java проекта с использованием sbt? - PullRequest
0 голосов
/ 11 марта 2020

Постановка проблемы

Один из лямбда-форматов, который принимает AWS, - это zip-файл со следующими

Все скомпилированные файлы классов и файлы ресурсов на уровне root .

Все необходимые файлы jar для запуска кода в каталоге / lib.

Какой самый простой способ упаковать проект java в этот формат с использованием sbt?

Рабочий пример в Gradle

AWS предоставляет пример в gradle который выполняет эту настройку.

Например, со следующим макетом проекта:

.
├── build.gradle
└── src
   └── main
      └── java
         └── example
            └── HelloWorldLambda.java

И HelloWorldLambda.java:

package example;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;

public class HelloWorldLambda implements RequestHandler<SQSEvent, SomeResult> {
  @Override
  public SomeResult handleRequest(SQSEvent event, Context ctx) {
    for (var record: event.getRecords()) {
      System.out.println("Found message: " + record.getBody());
    }
    return new SomeResult("OK");
  }
}

final class SomeResult {
  private String result;

  SomeResult(String result) {
    this.result = result;
  }

  public String getResult() {
    return this.result;
  }
}

Тогда это build.gradle со следующим приведет к правильному zip:

apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    compile (
        'com.amazonaws:aws-lambda-java-core:1.2.0',
        'com.amazonaws:aws-lambda-java-events:2.2.7'
    )
}

task buildZip(type: Zip) {
    from compileJava
    from processResources
    into('lib') {
        from configurations.runtimeClasspath
    }
}

build.dependsOn buildZip

Рабочий пример в SBT с использованием native-packager

Мне удалось получить следующую работу с использованием sbt и sbt-native-packager.

Макет проекта:

.
├── build.sbt
├── project
│  ├── build.properties
│  ├── plugins.sbt
│  └── project
└── src
   └── main
      └── java
         └── example
            └── HelloWorldLambda.java

build.properties:

sbt.version=1.3.8

plugins.sbt:

addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.6.1")

build.sbt:

import com.typesafe.sbt.SbtNativePackager.Universal
import com.typesafe.sbt.packager.MappingsHelper._
import sbt.File
val LambdaZip = config("lambdaZip")

lazy val root = project.in(file("."))
  .enablePlugins(JavaAppPackaging)
  .configs(LambdaZip)
  .settings(Seq(
    libraryDependencies ++= Seq(
      "com.amazonaws" % "aws-lambda-java-core" % "1.2.0",
      "com.amazonaws" % "aws-lambda-java-events" % "2.2.7",
    ),
    topLevelDirectory := None,
    maintainer := "maintainer@example.com"
  ) ++ inConfig(LambdaZip)(Seq(
    (target in Universal) := {
      target.value / "lambdaZip"
    },
    (mappings in Universal) := {
      val deps = (mappings in Universal).value.flatMap {
        case (file, name) if name != "lib/root.root-0.1.0-SNAPSHOT.jar" => Seq(file -> name)
        case (jarToExtract, name) =>
          val extractDir = (target in Universal).value / "extract"
          val unzipped = IO.unzip(jarToExtract, extractDir).toSeq
          relative(unzipped, Seq(extractDir))
      }
      deps
    },
    packageBin := {
      val zip = (packageBin in Universal).value
      zip
    }
  )))

Это работает, но я вижу следующие проблемы с ним:

  • Требуется использование плагина
  • Требуется вручную извлечь исходную флягу, разархивировать ее во временную папку каталог и создание сопоставления для них
  • Требуется использование строкового фильтра для всех jar-файлов проекта, то есть g можно по ошибке распаковать архив с зависимостями, если фильтр недостаточно плотный.

Есть ли более чистый способ реализовать это?

Примечание: AWS Lambda также принимает толстые банки и есть плагины, такие как sbt-assembly, которые могут создавать такие толстые фляги. Я не спрашиваю, как построить толстую банку в sbt для использования с лямбдой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...