Skip to content

Commit b1b0429

Browse files
authored
psilberk/adb wallet (oracle-samples#179)
* Sample to be used with the Wallet downloaded with the Kubernetes Operator (or a new one stored as a Kubernetes Secret) Signed-off-by: psilberk <psilberkasten@gmail.com> * changing secret name * adding UPL license Co-authored-by: psilberk <pablo.silberkasten@oracle.com>
1 parent 0238d0e commit b1b0429

File tree

5 files changed

+378
-0
lines changed

5 files changed

+378
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Java Sample Using an Oracle Wallet as a Kubernetes Secret
2+
3+
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).
4+
5+
An example is also provided to use a wallet downloaded from the Cloud Console.
6+
7+
This microservice can also be used to validate connectivity with the database by looking at its log or issuing http requests.
8+
9+
## Configuration
10+
11+
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.
12+
13+
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.
14+
15+
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:
16+
17+
```sh
18+
kubectl create secret generic instance-wallet --from-file=<path-to-wallets-unzipped-folder>
19+
```
20+
The Java microservice retrieves username, password and url also from a secret. To create it you can use the following script as an example:
21+
22+
```sh
23+
kubectl create secret generic user-jdbc \
24+
--from-literal=user='<username>' \
25+
--from-literal=password='<password>' \
26+
--from-literal=url='jdbc:oracle:thin:@<alias-in-tnsnames.ora>'
27+
```
28+
## Install, build and deploy
29+
30+
It is as simple as to build the maven project, create the docker image and deploy the Pod:
31+
32+
```sh
33+
mvn clean install
34+
docker build -t adb-health-check target
35+
kubectl apply -f target/app.yaml
36+
```
37+
38+
## Usage
39+
40+
After successsful installation you can validate first connectivity through the Pod's log:
41+
42+
```sh
43+
kubectl logs pods/adb-health-check
44+
'Database version: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production'
45+
'Version 19.13.0.1.0'
46+
'Retrieveing connections: true'
47+
```
48+
49+
And you can use the Pod's http listener to validate connectivity (for local tests you can just port forward a local port):
50+
51+
```sh
52+
kubectl port-forward adb-health-check 8080:8080 &
53+
curl -X GET http://localhost:8080
54+
'{"database-version": "19.0", "database-sysdate": "2021-10-06 15:38:43"}'
55+
```
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<groupId>adb-health-check</groupId>
6+
<artifactId>adb-health-check</artifactId>
7+
<version>0.0.1-SNAPSHOT</version>
8+
<name>demok8s</name>
9+
10+
<properties>
11+
<package>adb-health-check</package>
12+
<mainClass>com.oracle.healthcheck.Client</mainClass>
13+
<maven.compiler.source>11</maven.compiler.source>
14+
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
15+
<libs.classpath.prefix>libs</libs.classpath.prefix>
16+
<copied.libs.dir>${project.build.directory}/${libs.classpath.prefix}</copied.libs.dir>
17+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
19+
<argLine>-Dfile.encoding=UTF-8</argLine>
20+
<checkstyle.config.location>etc/checkstyle.xml</checkstyle.config.location>
21+
</properties>
22+
23+
24+
<build>
25+
<finalName>${project.artifactId}</finalName>
26+
<pluginManagement>
27+
<plugins>
28+
<plugin>
29+
<groupId>org.apache.maven.plugins</groupId>
30+
<artifactId>maven-compiler-plugin</artifactId>
31+
<version>3.8.1</version>
32+
</plugin>
33+
<plugin>
34+
<groupId>org.apache.maven.plugins</groupId>
35+
<artifactId>maven-surefire-plugin</artifactId>
36+
<version>2.19.1</version>
37+
<dependencies>
38+
<dependency>
39+
<groupId>org.junit.platform</groupId>
40+
<artifactId>junit-platform-surefire-provider</artifactId>
41+
<version>1.1.0</version>
42+
</dependency>
43+
</dependencies>
44+
</plugin>
45+
<plugin>
46+
<groupId>org.apache.maven.plugins</groupId>
47+
<artifactId>maven-dependency-plugin</artifactId>
48+
<version>3.1.1</version>
49+
</plugin>
50+
<plugin>
51+
<groupId>org.apache.maven.plugins</groupId>
52+
<artifactId>maven-resources-plugin</artifactId>
53+
<version>3.1.0</version>
54+
</plugin>
55+
<plugin>
56+
<groupId>org.apache.maven.plugins</groupId>
57+
<artifactId>maven-jar-plugin</artifactId>
58+
<version>3.1.2</version>
59+
<configuration>
60+
<archive>
61+
<manifest>
62+
<addClasspath>true</addClasspath>
63+
<classpathPrefix>${libs.classpath.prefix}</classpathPrefix>
64+
<mainClass>${mainClass}</mainClass>
65+
</manifest>
66+
</archive>
67+
</configuration>
68+
</plugin>
69+
</plugins>
70+
</pluginManagement>
71+
72+
<plugins>
73+
<plugin>
74+
<groupId>org.apache.maven.plugins</groupId>
75+
<artifactId>maven-dependency-plugin</artifactId>
76+
<executions>
77+
<execution>
78+
<id>copy-dependencies</id>
79+
<phase>prepare-package</phase>
80+
<goals>
81+
<goal>copy-dependencies</goal>
82+
</goals>
83+
<configuration>
84+
<outputDirectory>${copied.libs.dir}</outputDirectory>
85+
<overWriteReleases>false</overWriteReleases>
86+
<overWriteSnapshots>false</overWriteSnapshots>
87+
<overWriteIfNewer>true</overWriteIfNewer>
88+
<overWriteIfNewer>true</overWriteIfNewer>
89+
<includeScope>runtime</includeScope>
90+
<excludeScope>test</excludeScope>
91+
</configuration>
92+
</execution>
93+
</executions>
94+
</plugin>
95+
<plugin>
96+
<groupId>org.apache.maven.plugins</groupId>
97+
<artifactId>maven-resources-plugin</artifactId>
98+
<executions>
99+
<execution>
100+
<id>copy-dockerfile</id>
101+
<phase>process-resources</phase>
102+
<goals>
103+
<goal>copy-resources</goal>
104+
</goals>
105+
<configuration>
106+
<outputDirectory>${project.build.directory}</outputDirectory>
107+
<resources>
108+
<resource>
109+
<directory>src/main/docker</directory>
110+
<filtering>true</filtering>
111+
<includes>
112+
<include>Dockerfile</include>
113+
</includes>
114+
</resource>
115+
<resource>
116+
<filtering>true</filtering>
117+
<directory>src/main/k8s</directory>
118+
<includes>
119+
<include>app.yaml</include>
120+
</includes>
121+
</resource>
122+
</resources>
123+
</configuration>
124+
</execution>
125+
</executions>
126+
</plugin>
127+
</plugins>
128+
</build>
129+
130+
<dependencies>
131+
<dependency>
132+
<groupId>com.oracle.database.jdbc</groupId>
133+
<artifactId>ojdbc11</artifactId>
134+
<version>21.3.0.0</version>
135+
</dependency>
136+
<dependency>
137+
<groupId>com.oracle.database.jdbc</groupId>
138+
<artifactId>ucp</artifactId>
139+
<version>21.3.0.0</version>
140+
</dependency>
141+
<dependency>
142+
<groupId>com.oracle.database.ha</groupId>
143+
<artifactId>ons</artifactId>
144+
<version>21.3.0.0</version>
145+
</dependency>
146+
<dependency>
147+
<groupId>com.oracle.database.security</groupId>
148+
<artifactId>oraclepki</artifactId>
149+
<version>21.3.0.0</version>
150+
</dependency>
151+
<dependency>
152+
<groupId>com.oracle.database.security</groupId>
153+
<artifactId>osdt_core</artifactId>
154+
<version>21.3.0.0</version>
155+
</dependency>
156+
<dependency>
157+
<groupId>com.oracle.database.security</groupId>
158+
<artifactId>osdt_cert</artifactId>
159+
<version>21.3.0.0</version>
160+
</dependency>
161+
</dependencies>
162+
</project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
FROM openjdk:11
2+
3+
RUN mkdir /app
4+
COPY libs /app/libs
5+
COPY ${project.artifactId}.jar /app
6+
7+
# The driver will look for the wallet in folder /app/wallet
8+
# This value must match the one in the mountPath of the container
9+
# Reference in src/main/k8s/app.yaml
10+
11+
CMD ["java", \
12+
"-Doracle.net.tns_admin=/app/wallet", \
13+
"-Doracle.net.wallet_location=/app/wallet", \
14+
"-Doracle.jdbc.fanEnabled=false", \
15+
"-jar", \
16+
"/app/${project.artifactId}.jar"]
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
** Copyright (c) 2021 Oracle and/or its affiliates.
3+
**
4+
** The Universal Permissive License (UPL), Version 1.0
5+
**
6+
** Subject to the condition set forth below, permission is hereby granted to any
7+
** person obtaining a copy of this software, associated documentation and/or data
8+
** (collectively the "Software"), free of charge and under any and all copyright
9+
** rights in the Software, and any and all patent rights owned or freely
10+
** licensable by each licensor hereunder covering either (i) the unmodified
11+
** Software as contributed to or provided by such licensor, or (ii) the Larger
12+
** Works (as defined below), to deal in both
13+
**
14+
** (a) the Software, and
15+
** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
** one is included with the Software (each a "Larger Work" to which the Software
17+
** is contributed by such licensors),
18+
**
19+
** without restriction, including without limitation the rights to copy, create
20+
** derivative works of, display, perform, and distribute the Software and make,
21+
** use, sell, offer for sale, import, export, have made, and have sold the
22+
** Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
** either these or other terms.
24+
**
25+
** This license is subject to the following condition:
26+
** The above copyright notice and either this complete permission notice or at
27+
** a minimum a reference to the UPL must be included in all copies or
28+
** substantial portions of the Software.
29+
**
30+
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
** SOFTWARE.
37+
*/
38+
39+
package com.oracle.healthcheck;
40+
41+
import java.io.IOException;
42+
import java.io.OutputStream;
43+
import java.net.InetSocketAddress;
44+
import java.sql.ResultSet;
45+
import java.sql.SQLException;
46+
import java.sql.Statement;
47+
48+
import javax.net.ssl.HttpsURLConnection;
49+
50+
import com.sun.net.httpserver.HttpServer;
51+
52+
import oracle.jdbc.internal.OracleConnection;
53+
import oracle.jdbc.pool.OracleDataSource;
54+
55+
public class Client {
56+
57+
public static void main(String[] args)
58+
throws SQLException, IOException {
59+
60+
// Retrieve user credentials from environment variables.
61+
// They are set in the Pod from a Secret in src/main/k8s/app.yaml
62+
OracleDataSource ds = new OracleDataSource();
63+
ds.setURL(System.getenv("url"));
64+
ds.setUser(System.getenv("user"));
65+
ds.setPassword(System.getenv("password"));
66+
67+
// Validate and log connection
68+
OracleConnection connection = (OracleConnection) ds.getConnection();
69+
System.out.println("Retrieving connections: " + connection.isValid(0));
70+
System.out
71+
.println("Database version: "
72+
+ connection.getMetaData().getDatabaseMajorVersion() + "."
73+
+ connection.getMetaData().getDatabaseMinorVersion());
74+
75+
// Start an HttpServer listening on port 8080 to send database status.
76+
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
77+
server.createContext("/", (httpExchange) -> {
78+
79+
try (OracleConnection conn = (OracleConnection) ds.getConnection();
80+
Statement stmt = conn.createStatement()) {
81+
82+
// Database message: version and sysdate
83+
ResultSet rs = stmt.executeQuery("select SYSDATE from dual");
84+
rs.next();
85+
86+
String message = "{\"database-version\": \""
87+
+ conn.getMetaData().getDatabaseMajorVersion() + "."
88+
+ conn.getMetaData().getDatabaseMinorVersion()
89+
+ "\", \"database-sysdate\": \"" + rs.getString(1) + "\"}";
90+
System.out.println(message);
91+
92+
// Send message, status and flush
93+
httpExchange
94+
.sendResponseHeaders(HttpsURLConnection.HTTP_OK, message.length());
95+
OutputStream os = httpExchange.getResponseBody();
96+
os.write(message.getBytes());
97+
os.close();
98+
99+
} catch (SQLException e) {
100+
e.printStackTrace();
101+
}
102+
});
103+
104+
server.setExecutor(null);
105+
server.start();
106+
}
107+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
kind: Pod
2+
apiVersion: v1
3+
metadata:
4+
name: adb-health-check
5+
spec:
6+
volumes:
7+
- name: wallet
8+
secret:
9+
# Either the secret name of the downloaded wallet with the kubernetes operator
10+
# TODO add link to operator
11+
# Or the secret name holding the wallet created ad-hoc:
12+
# kubectl create secret generic instance-wallet --from-file=<path to wallet dir>
13+
secretName: instance-wallet
14+
containers:
15+
- name: adb-health-check
16+
image: adb-health-check
17+
imagePullPolicy: IfNotPresent
18+
volumeMounts:
19+
- name: wallet
20+
# mountPath must coincide with the one selected for oracle.net.wallet_location
21+
mountPath: "/app/wallet"
22+
readOnly: true
23+
env:
24+
- name: user
25+
valueFrom:
26+
secretKeyRef:
27+
name: user-jdbc
28+
key: user
29+
- name: password
30+
valueFrom:
31+
secretKeyRef:
32+
name: user-jdbc
33+
key: password
34+
- name: url
35+
valueFrom:
36+
secretKeyRef:
37+
name: user-jdbc
38+
key: url

0 commit comments

Comments
 (0)