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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions