Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions java/autonomousdb-wallet-secret-sample/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Java Sample Using an Oracle Wallet as a Kubernetes Secret

In this minimalistic Java sample we show you how to use a wallet downloaded by the [Oracle Database Operator for Kubernetes](https://github.com/oracle/oracle-database-operator).

An example is also provided to use a wallet downloaded from the Cloud Console.

This microservice can also be used to validate connectivity with the database by looking at its log or issuing http requests.

## Configuration

To configure the database wallet you only need to update [src/main/k8s/app.yaml](src/main/k8s/app.yaml) to use the same secret name that you used to download the wallet with the Operator.

The key part to understand its simplicity is that the deployment file uses the same mount path that the container configures in the oracle.net.wallet_location VM parameter [src/main/docker/Dockerfile](src/main/docker/Dockerfile). You don't need to change this file if you are going to use the example's mount path.

If you want to configure a previously downloaded wallet you can just create the secret (and use the same secret name for the Pod's spec) pointing to the directory where you unzipped the wallet:

```sh
kubectl create secret generic instance-wallet --from-file=<path-to-wallets-unzipped-folder>
```
The Java microservice retrieves username, password and url also from a secret. To create it you can use the following script as an example:

```sh
kubectl create secret generic user-jdbc \
--from-literal=user='<username>' \
--from-literal=password='<password>' \
--from-literal=url='jdbc:oracle:thin:@<alias-in-tnsnames.ora>'
```
## Install, build and deploy

It is as simple as to build the maven project, create the docker image and deploy the Pod:

```sh
mvn clean install
docker build -t adb-health-check target
kubectl apply -f target/app.yaml
```

## Usage

After successsful installation you can validate first connectivity through the Pod's log:

```sh
kubectl logs pods/adb-health-check
'Database version: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production'
'Version 19.13.0.1.0'
'Retrieveing connections: true'
```

And you can use the Pod's http listener to validate connectivity (for local tests you can just port forward a local port):

```sh
kubectl port-forward adb-health-check 8080:8080 &
curl -X GET http://localhost:8080
'{"database-version": "19.0", "database-sysdate": "2021-10-06 15:38:43"}'
```
162 changes: 162 additions & 0 deletions java/autonomousdb-wallet-secret-sample/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>adb-health-check</groupId>
<artifactId>adb-health-check</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demok8s</name>

<properties>
<package>adb-health-check</package>
<mainClass>com.oracle.healthcheck.Client</mainClass>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
<libs.classpath.prefix>libs</libs.classpath.prefix>
<copied.libs.dir>${project.build.directory}/${libs.classpath.prefix}</copied.libs.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<argLine>-Dfile.encoding=UTF-8</argLine>
<checkstyle.config.location>etc/checkstyle.xml</checkstyle.config.location>
</properties>


<build>
<finalName>${project.artifactId}</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>${libs.classpath.prefix}</classpathPrefix>
<mainClass>${mainClass}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${copied.libs.dir}</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<overWriteIfNewer>true</overWriteIfNewer>
<includeScope>runtime</includeScope>
<excludeScope>test</excludeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-dockerfile</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<resources>
<resource>
<directory>src/main/docker</directory>
<filtering>true</filtering>
<includes>
<include>Dockerfile</include>
</includes>
</resource>
<resource>
<filtering>true</filtering>
<directory>src/main/k8s</directory>
<includes>
<include>app.yaml</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
<version>21.3.0.0</version>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ucp</artifactId>
<version>21.3.0.0</version>
</dependency>
<dependency>
<groupId>com.oracle.database.ha</groupId>
<artifactId>ons</artifactId>
<version>21.3.0.0</version>
</dependency>
<dependency>
<groupId>com.oracle.database.security</groupId>
<artifactId>oraclepki</artifactId>
<version>21.3.0.0</version>
</dependency>
<dependency>
<groupId>com.oracle.database.security</groupId>
<artifactId>osdt_core</artifactId>
<version>21.3.0.0</version>
</dependency>
<dependency>
<groupId>com.oracle.database.security</groupId>
<artifactId>osdt_cert</artifactId>
<version>21.3.0.0</version>
</dependency>
</dependencies>
</project>
16 changes: 16 additions & 0 deletions java/autonomousdb-wallet-secret-sample/src/main/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM openjdk:11

RUN mkdir /app
COPY libs /app/libs
COPY ${project.artifactId}.jar /app

# The driver will look for the wallet in folder /app/wallet
# This value must match the one in the mountPath of the container
# Reference in src/main/k8s/app.yaml

CMD ["java", \
"-Doracle.net.tns_admin=/app/wallet", \
"-Doracle.net.wallet_location=/app/wallet", \
"-Doracle.jdbc.fanEnabled=false", \
"-jar", \
"/app/${project.artifactId}.jar"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.oracle.healthcheck;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.net.ssl.HttpsURLConnection;

import com.sun.net.httpserver.HttpServer;

import oracle.jdbc.internal.OracleConnection;
import oracle.jdbc.pool.OracleDataSource;

public class Client {

public static void main(String[] args)
throws SQLException, IOException {

// Retrieve user credentials from environment variables.
// They are set in the Pod from a Secret in src/main/k8s/app.yaml
OracleDataSource ds = new OracleDataSource();
ds.setURL(System.getenv("url"));
ds.setUser(System.getenv("user"));
ds.setPassword(System.getenv("password"));

// Validate and log connection
OracleConnection connection = (OracleConnection) ds.getConnection();
System.out.println("Retrieving connections: " + connection.isValid(0));
System.out
.println("Database version: "
+ connection.getMetaData().getDatabaseMajorVersion() + "."
+ connection.getMetaData().getDatabaseMinorVersion());

// Start an HttpServer listening on port 8080 to send database status.
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/", (httpExchange) -> {

try (OracleConnection conn = (OracleConnection) ds.getConnection();
Statement stmt = conn.createStatement()) {

// Database message: version and sysdate
ResultSet rs = stmt.executeQuery("select SYSDATE from dual");
rs.next();

String message = "{\"database-version\": \""
+ conn.getMetaData().getDatabaseMajorVersion() + "."
+ conn.getMetaData().getDatabaseMinorVersion()
+ "\", \"database-sysdate\": \"" + rs.getString(1) + "\"}";
System.out.println(message);

// Send message, status and flush
httpExchange
.sendResponseHeaders(HttpsURLConnection.HTTP_OK, message.length());
OutputStream os = httpExchange.getResponseBody();
os.write(message.getBytes());
os.close();

} catch (SQLException e) {
e.printStackTrace();
}
});

server.setExecutor(null);
server.start();
}
}
38 changes: 38 additions & 0 deletions java/autonomousdb-wallet-secret-sample/src/main/k8s/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
kind: Pod
apiVersion: v1
metadata:
name: adb-health-check
spec:
volumes:
- name: wallet
secret:
# Either the secret name of the downloaded wallet with the kubernetes operator
# TODO add link to operator
# Or the secret name holding the wallet created ad-hoc:
# kubectl create secret generic instance-wallet --from-file=<path to wallet dir>
secretName: instance-wallet
containers:
- name: adb-health-check
image: adb-health-check
imagePullPolicy: IfNotPresent
volumeMounts:
- name: wallet
# mountPath must coincide with the one selected for oracle.net.wallet_location
mountPath: "/app/wallet"
readOnly: true
env:
- name: user
valueFrom:
secretKeyRef:
name: user-jdbc
key: user
- name: password
valueFrom:
secretKeyRef:
name: user-jdbc
key: password
- name: url
valueFrom:
secretKeyRef:
name: user-jdbc
key: url