Skip to content
This repository has been archived by the owner on Sep 16, 2023. It is now read-only.

Commit

Permalink
docs(sample): Add sample for Native Image Support (#711)
Browse files Browse the repository at this point in the history
* docs(sample): Add sample for Native Image Support

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* fix setup for standard java mmode

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* use Java 8; clean up integration test

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
  • Loading branch information
mpeddada1 and gcf-owl-bot[bot] authored Mar 2, 2022
1 parent 36899d2 commit 1afd3aa
Show file tree
Hide file tree
Showing 6 changed files with 435 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-secretmanager

| Sample | Source Code | Try it |
| --------------------------- | --------------------------------- | ------ |
| Native Image Secret Manager Sample | [source code](https://github.com/googleapis/java-secretmanager/blob/main/samples/native-image-sample/src/main/java/secretmanager/NativeImageSecretManagerSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-secretmanager&page=editor&open_in_editor=samples/native-image-sample/src/main/java/secretmanager/NativeImageSecretManagerSample.java) |
| Access Secret Version | [source code](https://github.com/googleapis/java-secretmanager/blob/main/samples/snippets/src/main/java/secretmanager/AccessSecretVersion.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-secretmanager&page=editor&open_in_editor=samples/snippets/src/main/java/secretmanager/AccessSecretVersion.java) |
| Add Secret Version | [source code](https://github.com/googleapis/java-secretmanager/blob/main/samples/snippets/src/main/java/secretmanager/AddSecretVersion.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-secretmanager&page=editor&open_in_editor=samples/snippets/src/main/java/secretmanager/AddSecretVersion.java) |
| Create Secret | [source code](https://github.com/googleapis/java-secretmanager/blob/main/samples/snippets/src/main/java/secretmanager/CreateSecret.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-secretmanager&page=editor&open_in_editor=samples/snippets/src/main/java/secretmanager/CreateSecret.java) |
Expand Down
78 changes: 78 additions & 0 deletions samples/native-image-sample/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Secret Manager Sample Application with Native Image

The Secret Manager sample application demonstrates some common operations with [Google Cloud Secret Manager](https://cloud.google.com/secret-manager) and is compatible with Native Image compilation.

This application will create a new secret named `native-secretmanager-test-secret` if it does not already exist.
It will then add a new version of the secret and then attempt to read it.

## Setup Instructions

You will need to follow these prerequisite steps in order to run these samples:

1. If you have not already, [create a Google Cloud Platform Project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project).

2. Install the [Google Cloud SDK](https://cloud.google.com/sdk/) which will allow you to run the sample with your project's credentials.

Once installed, log in with Application Default Credentials using the following command:

```
gcloud auth application-default login
```
**Note:** Authenticating with Application Default Credentials is convenient to use during development, but we recommend [alternate methods of authentication](https://cloud.google.com/docs/authentication/production) during production use.
3. Install the GraalVM compiler.
You can follow the [official installation instructions](https://www.graalvm.org/docs/getting-started/#install-graalvm) from the GraalVM website.
After following the instructions, ensure that you install the Native Image extension installed by running:
```
gu install native-image
```
Once you finish following the instructions, verify that the default version of Java is set to the GraalVM version by running `java -version` in a terminal.
You will see something similar to the below output:
```
$ java -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02)
OpenJDK 64-Bit Server VM GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02, mixed mode, sharing)
```
4. [Enable the Secret Manager APIs](https://console.cloud.google.com/apis/api/secretmanager.googleapis.com).
### Run with Native Image Compilation
Navigate to this directory in a new terminal.
1. Compile the application using the Native Image Compiler. This step may take a few minutes.
```
mvn package -P native -DskipTests
```
2. Run the application:
```
./target/native-image-sample
```
3. The application runs through some basic Secret Manager operations (create, update, read) and then prints some results of the operations.
```
Created secret: projects/xxxxxx/secrets/graal-secretmanager-test-secret
Added Secret Version: projects/xxxxxx/secrets/graal-secretmanager-test-secret/versions/1
Reading secret value: Hello World
(Note: Don't print secret values in prod!)
```
## Sample Integration test with Native Image Support
In order to run the sample integration test as a native image, call the following command:
```
mvn test -Pnative
```
173 changes: 173 additions & 0 deletions samples/native-image-sample/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<?xml version='1.0' encoding='UTF-8'?>
<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.google.cloud</groupId>
<artifactId>native-image-sample</artifactId>
<name>Native Image Sample</name>
<url>https://github.com/googleapis/java-secretmanager</url>

<!--
The parent pom defines common style checks and testing strategies for our samples.
Removing or replacing it should not affect the execution of the samples in anyway.
-->
<parent>
<groupId>com.google.cloud.samples</groupId>
<artifactId>shared-configuration</artifactId>
<version>1.2.0</version>
</parent>

<properties>
<!-- Java 8 because the Kokoro Sample test uses that Java version -->
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>libraries-bom</artifactId>
<version>24.3.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-core</artifactId>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-secretmanager</artifactId>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<version>1.1.3</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<!-- This plugin enables building the application to a JAR *not* using Native Image -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>dependency-jars/</classpathPrefix>
<mainClass>secretmanager.NativeImageSecretManagerSample</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/dependency-jars/
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

<!-- Native Profile-->
<profiles>
<profile>
<id>native</id>

<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>native-image-support</artifactId>
<version>0.12.0</version>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>junit-platform-native</artifactId>
<version>0.9.9</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin
</artifactId> <!-- Must use older version of surefire plugin for native-image testing. -->
<version>2.22.2</version>
<configuration>
<includes>
<include>**/*IT</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.9.9</version>
<extensions>true</extensions>
<configuration>
<mainClass>secretmanager.NativeImageSecretManagerSample</mainClass>
<buildArgs>
<buildArg>--no-fallback</buildArg>
<buildArg>--no-server</buildArg>
</buildArgs>
</configuration>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>build</goal>
<goal>test</goal>
</goals>
<phase>package</phase>
</execution>
<execution>
<id>test-native</id>
<goals>
<goal>test</goal>
</goals>
<phase>test</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package secretmanager;

import com.google.cloud.ServiceOptions;
import com.google.cloud.secretmanager.v1.AccessSecretVersionResponse;
import com.google.cloud.secretmanager.v1.ProjectName;
import com.google.cloud.secretmanager.v1.Replication;
import com.google.cloud.secretmanager.v1.Secret;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient.ListSecretsPagedResponse;
import com.google.cloud.secretmanager.v1.SecretName;
import com.google.cloud.secretmanager.v1.SecretPayload;
import com.google.cloud.secretmanager.v1.SecretVersion;
import com.google.protobuf.ByteString;
import java.io.IOException;

/**
* Sample application demonstrating Native Image compatibility with Google Cloud Secret Manager
* APIs.
*/
public class NativeImageSecretManagerSample {

private static final String NATIVE_TEST_SECRET_ID = "native-secretmanager-test-secret";

/** Runs the Secret Manager sample application. */
public static void main(String[] args) throws IOException {
String projectId = ServiceOptions.getDefaultProjectId();

try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
if (!hasSecret(client, projectId, NATIVE_TEST_SECRET_ID)) {
createSecret(client, projectId, NATIVE_TEST_SECRET_ID);
} else {
System.out.println("Project already has secret: " + NATIVE_TEST_SECRET_ID);
}

SecretVersion version = addSecretVersion(client, projectId, NATIVE_TEST_SECRET_ID);
printSecretVersion(client, version);
}
}

static void createSecret(SecretManagerServiceClient client, String projectId, String secretId) {

Secret secret =
Secret.newBuilder()
.setReplication(
Replication.newBuilder()
.setAutomatic(Replication.Automatic.newBuilder().build())
.build())
.build();
ProjectName projectName = ProjectName.of(projectId);
Secret createdSecret = client.createSecret(projectName, secretId, secret);
System.out.println("Created secret: " + createdSecret.getName());
}

static boolean hasSecret(SecretManagerServiceClient client, String projectId, String secretId) {

ProjectName projectName = ProjectName.of(projectId);
ListSecretsPagedResponse pagedResponse = client.listSecrets(projectName);

for (Secret secret : pagedResponse.iterateAll()) {
String otherSecretId = extractSecretId(secret);
if (secretId.equals(otherSecretId)) {
return true;
}
}

return false;
}

static SecretVersion addSecretVersion(
SecretManagerServiceClient client, String projectId, String secretId) {

SecretName secretName = SecretName.of(projectId, secretId);
SecretPayload payload =
SecretPayload.newBuilder().setData(ByteString.copyFromUtf8("Hello World")).build();

SecretVersion version = client.addSecretVersion(secretName, payload);
System.out.println("Added Secret Version: " + version.getName());
return version;
}

static void printSecretVersion(SecretManagerServiceClient client, SecretVersion version) {
AccessSecretVersionResponse response = client.accessSecretVersion(version.getName());
String payload = response.getPayload().getData().toStringUtf8();
System.out.println("Reading secret value: " + payload);
System.out.println("(Note: Don't print secret values in prod!)");
}

/**
* Returns the secret ID from the fully-qualified secret name which has the format:
* projects/YOUR_PROJECT_ID/secrets/YOUR_SECRET_ID.
*/
private static String extractSecretId(Secret secret) {
String[] secretNameTokens = secret.getName().split("/");
return secretNameTokens[secretNameTokens.length - 1];
}
}
Loading

0 comments on commit 1afd3aa

Please sign in to comment.