Skip to content

Simplify deployment of ACCP #409

@cloudshiftchris

Description

@cloudshiftchris

We worked through moving from netty-tcnative to ACCP; it wasn't a smooth path, and still has a few rough edges.

For Netty TcNative we had pulled in the native dependencies via build.gradle.kts as:

    val nettyTcnativeClassifiers = setOf("osx-aarch_64", "osx-x86_64","linux-aarch_64", "linux-x86_64", "windows-x86_64")
    nettyTcnativeClassifiers.forEach { tcNativeClassifier ->
        runtimeOnly("io.netty:netty-tcnative-boringssl-static") { artifact { classifier = tcNativeClassifier } }
    }

Key points:

  • the classifiers is the set of all deployment and development classifiers;
  • the scope is runtimeOnly as the native libraries only need to be pulled in at runtime;
  • the dependency version is resolved via Netty BOM (in this case, via Spring Boot), preventing version mismatch between native dependencies and their Java peers;

Netty has collaborating components - code in Netty itself and these optional dependencies - making it smart enough to attempt to load the (optional) native library for the current platform. For example, libnetty_tcnative_osx_aarch_64.jnilib is included in the osx-aarch_64 classifier. Note that the library name includes the platform information.

We played with a few options for ACCP:

  1. Create an Uber JAR (combining the JARs for different classifiers that are identical other than their included native library). This had challenges:
  • breaks the JAR signing (only for Oracle JDK, not material for us);
  • collisions in native library names as they don't include platform information, e.g. libamazonCorrettoCryptoProvider.dylib is the same name for x86_64 and aarch64 variants;

That was a non-starter.

  1. Put logic in build.gradle.kts to account for development and deployment requirements:
    // we currently deploy on AMD64 architecture
    val accpDeploymentClassifier = "linux-x86_64"

    val accpClassifier =
        when {
            System.getenv("CI") == "true" -> accpDeploymentClassifier

            // accp does not have a windows artifact; use the deployment classifier so we don't have
            // resolution / compilation issues, but don't initialize in code
            osdetector.os == "windows" -> accpDeploymentClassifier

            // run locally (likely MacOS)
            else -> osdetector.classifier
        }

    implementation(libs.amazonCorrettoCryptoProvider) { artifact { classifier = accpClassifier } }

This works but isn't equivalent to what we had with Netty:

  • its considerably more verbose;
  • it hard-codes the deployment target architecture (no where else do we have that), as only a single ACCP library can be included; this precludes using the same build in different deployment targets;
  • ACCP needs to be a compile-time dependency (due to the intialization steps), however there is no ACCP library for Windows, so we hack around that;
  • it requires the OS Detector plugin (that we otherwise have never needed to use)

Ideally ACCP would support something like:

    // BOM to keep versions aligned
    implementation(platform("software.amazon.cryptools:AmazonCorrettoCryptoProvider-bom:2.4.1"))

    // the Java classes
   implementation("software.amazon.cryptools:AmazonCorrettoCryptoProvider-core")

   // all native dependencies (a JAR that depends on all the individual native jars to pull them all in)
   runtimeOnly("software.amazon.cryptools:AmazonCorrettoCryptoProvider-native-all") 

   // or, for those that wish to selectively pull in platform dependencies
   runtimeOnly("software.amazon.cryptools:AmazonCorrettoCryptoProvider-native")  { artifact { classifier = "linux-x86_64" } }

Aware that ACCP can be deployed out-of-band (into the class path, or installed in the JDK) but that poses additional complexities:

  • its uncommon to drop libs in the class path at deployment time (we have no other apps that do this, and frown on the practice) - why would this lib require that?
  • the challenges in versioning / resolving / managing deployment outside of the regular build process are problematic;

Perhaps similar to #366, with more color.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions