This example will demonstrate how to pair Helidon with OCI DevOps pipeline to build a quick start Helidon MP application and deploy to either an OCI Instance, an OKE Cluster or both.
- Create an OCI DevOps project that will build and deploy a Helidon MP application example.
- Create an Instance Group or OKE Cluster deployment targets.
- Use Terraform to create automation of OCI resources provisioning that will be needed to build the DevOps environment.
- Provide a quick tutorial on how to add OCI Object Storage integration into a Helidon application.
- Use OCI cloud-shell to run this example through.
- An OCI tenancy that can provision a Compute Node and work with the DevOps Service such as a paid service. This will also work on the free trial of the OCI Free Tier.
- If you are already a super-user with administrator rights that has access to all resources in the tenancy, skip to the next section. Otherwise, continue to the next step.
- Create a new group and add your user as a member of that group.
- Create a new policy and provide that group a cloud-shell access:
Allow group '<my_cloud_shell_access_group>' to use cloud-shell in tenancy
- Verify that it works by opening the OCI Code Editor from the OCI Console.
- Start the OCI Code Editor if it is not yet open.
- Open a new terminal from the Code Editor. On the terminal, make sure you are in the home directory
cd ~
- Use git to clone the main repository. This will create
oci-devops-helidon-example
directory in the home directory.git clone https://github.com/klustria/oci-devops-helidon-example.git
The goal of this task is to prepare the environment for the DevOps setup by creating a Compartment, Dynamic Groups, User Group and Polices. This section requires a user with administrator privilege. If you don't have it, make sure to request another user with such privilege to run this for you.
-
Open the newly cloned repository directory
oci-devops-helidon-example
from the code editor. -
From the root directory of the repository, open
terraform.tfvars
and set the values of the following variables:tenancy_ocid
- This can be retrieved by opening theProfile
menu and clickTenancy: <your_tenancy_name>
. The tenancy OCID is shown underTenancy Information
. ClickShow
to display the entire ID or clickCopy
to copy it to your clipboard.region
- From OCI Console's home screen, open theRegion
menu, and then clickManage Regions
. Locate the Home Region and copy the Region identifier.user_ocid
- This can be retrieved by opening theProfile
menu and clicking onMy Profile
. UnderUser information
, clickShow
to display the entire ID or clickCopy
to copy it to your clipboard.
Note: Ensure that
region
reflects your home region as this exercise will not work in other regions. If DevOps resources provisioning, that will be performed in the next section, will be done on the same home region, then use theregion
parameter for this purpose. However, if the intention is to target DevOps provisioning on a different non-home region, then for this step, set the value of thehome_region
parameter instead. -
Go to the
init
directory.cd init
-
Use Terraform to execute the scripts to provision the compartment, dynamic groups and polices.
terraform init terraform plan terraform apply -auto-approve
-
Open
oci-devops-helidon-example
project from Code Editor. -
From the root directory of the project, open
terraform.tfvars
and fill up the values of the following variables:tenancy_ocid
- If already set from the previous exercise, leave as is. Otherwise, this can be retrieved by opening theProfile
menu and clickTenancy: <your_tenancy_name>
. The tenancy OCID is shown underTenancy Information
. ClickShow
to display the entire ID or clickCopy
to copy it to your clipboard.region
- If already set from the previous exercise, leave as is. Otherwise, from OCI Console's home screen, open theRegion
menu, and then clickManage Regions
. Locate the Home Region and copy the Region identifier.compartment_ocid
- This can be automatically populated by running the toolupdate_compartment.sh
or otherwise, value can be retrieved from the previous exercise's terraform output.utils/update_compartment.sh
deployment_target
- Choose the deployment target destination. Allowed values are the following (not case sensitive):- INSTANCE - Deploys to a provisioned instance
- OKE - Deploys to a provisioned OKE Cluster
- ALL - Deploys to both OKE and INSTANCE. This is the default value.
-
Open a new terminal and go to
main
directory,cd main
-
Use Terraform to execute the scripts to provision all the DevOps resources.
terraform init terraform plan terraform apply -auto-approve
This will provision the following resources:
- OCI DevOps Service
OCI DevOps Project
that will contain all the DevOps components needed for this project.OCI Code Repository
that will host the Application source code project.DevOps Build Pipeline
for theINSTANCE
if configured, with the following stages:- Manage Build - Executes steps to download JDK20, maven and building the Helidon application.
- Deliver Artifacts - Uploads the built Helidon app and the Deployment spec to the Artifact Repository.
- Trigger Deployment - Triggers the Instance's Deployment Pipeline.
DevOps Deployment Pipeline
for theINSTANCE
if configured, that will perform the following on the target environment:- Download JDK20
- Install OCI CLI and use it to download the Application Deliverable
- Run the Application
DevOps Build Pipeline
forOKE
if configured, with the following stages:- Manage Build - Executes a Dockerfile to build the application as a Docker image.
- Deliver Artifacts - Uploads image to the Container Registry and the Deployment spec to the Artifact Repository
- Trigger Deployment - Triggers the OKE's Deployment Pipeline.
DevOps Deployment Pipeline
forOKE
if configured, that will perform the following on the target environment:- Create a Kubernetes service with LoadBalancer type.
- Create a Kubernetes deployment using the built docker image
DevOps Trigger
for theINSTANCE
andOKE
, whichever is configured, that will invoke the pipeline lifecycle from start to finish when a push event occurs on theOCI Code Repository
.
- OCI Artifact Registry
OCI Artifact Repository
that will host the built Helidon App Binaries and Deployment Manifest as versioned artifacts.OCI Container Registry
that will host the built Helidon App as a versioned Docker image.
- OCI Platform
INSTANCE
if configured.OCI Compute Instance
that opens port 8080 from the firewall. This is where the application will be eventually deployed.OCI Virtual Cloud Network (VCN)
withSecurity List
containing an Ingress that opens port 8080. Port 8080 is where the Helidon application will be accessed from. TheOCI VCN
will be used by theOCI Compute Instance
for its network needs.
OKE
if configured.OKE Cluster
that will host the application as a Kubernetes deployment.OKE Node Pool
with 1 worker node.OCI Virtual Cloud Network (VCN)
withSubnets
andSecurity Lists
for the Kubernetes API endpoint, Worker Node, and LoadBalancer.
- OCI DevOps Service
-
Diagram below depicts how the DevOps setup will work:
-
Generate an auth token that will be used to access the DevOps code repository. From the OCI Console's home screen, open the Profile menu and click
My Profile
. UnderResources
, click onAuth tokens
, followed by clickingGenerate token
and fill in theDescription
. A new window will open with a notice toCopy the generated token as it will not be shown again
. Do so and ensure to keep it in a safe place for future usage. -
Go to the home directory
cd ~
-
Download Helidon cli.
curl -L -O https://helidon.io/cli/latest/linux/helidon chmod +x ./helidon
-
Execute the cli to generate a Helidon Microprofile application project.
./helidon init
-
When it prompts for
Helidon version
, enter4.0.0-ALPHA6
Helidon version (default: 3.2.2): 4.0.0-ALPHA6
-
When prompted to
Select a Flavor
, chooseHelidon MP
| Helidon Flavor Select a Flavor (1) se | Helidon SE (2) mp | Helidon MP (3) nima | Helidon Níma Enter selection (default: 1): 2
-
When prompted to
Select an Application Type
, chooseOCI
Select an Application Type (1) quickstart | Quickstart (2) database | Database (3) custom | Custom (4) oci | OCI Enter selection (default: 1): 4
-
When prompted for
Project groupId
,Project artifactId
andProject version
, just accept the default values. -
When prompted for
Java package name
, usedemo.mp.oci
Java package name (default: me.first_last.mp.oci): demo.mp.oci
-
Once completed, this will generate an
oci-mp
project. Openoci-mp
from Code Editor followed by starting a new terminal. -
The terminal should already be in the
oci-mp
directory, but if it is not, go inside that directory.cd ~/oci-mp
-
Copy the build and deployment pipeline specs from the
oci-devops-helidon-example
repository.cp ~/oci-devops-helidon-example/pipeline_specs/* .
-
Add .gitignore so files and directories that are not needed to be part of the repository will be ignored by git.
cp ~/oci-devops-helidon-example/.gitignore .
-
Copy the
Dockerfile
and replace the existing. This will be used to create the application as a Docker image if the deployment target is OKE, otherwise this step can be skipped. This step will also not be needed in a future version of the Helidon archetype as it will generate the proper Dockerfile.cp ~/oci-devops-helidon-example/main/Dockerfile .
-
Initialize the oci-mp project directory to become a git repository.
git init
-
Set the branch to
main
to match the corresponding remote branch.git checkout -b main
-
Set the remote repository. Use the OCI Code Repository's https url displayed from the last terraform output or use the
get.sh
tool fromoci-devops-helidon-example
to retrieve that value.git remote add origin $(~/oci-devops-helidon-example/main/get.sh code_repo_https_url) git remote -v
-
Configure git to use credential helper store so that oci repository's username and password will be entered only once on git commands that require them. Also, set user.name and user.email which is required by git commit.
git config credential.helper store git config --global user.email "my.name@example.com" git config --global user.name "FIRST_NAME LAST_NAME"
-
Synchronize the oci repository's git log with the local repository by using git pull.
git pull origin main
-
This will prompt for username and password. Use
<tenancy name>/<username>
for the username and oci user auth token that was generated at the very start of this section for the password.Username for 'https://devops.scmservice.us-ashburn-1.oci.oraclecloud.com': tenancy_name/my.name@example.com Password for 'https://tenancyname/my.name@example.com@devops.scmservice.us-ashburn-1.oci.oraclecloud.com':
-
Run the utility script from the main repository (
oci-devops-helidon-example
) to update the Config parameters:~/oci-devops-helidon-example/utils/update_config_values.sh
Invoking this script will perform the following:
- Updates in
~/oci-mp/server/src/main/resources/application.yaml
config file to set up a Helidon feature that sends Helidon generated metrics to the OCI monitoring service.- compartmentId - Compartment ocid that is used for this demo
- namespace - This can be any string but for this demo, this will be set to
helidon_metrics
.
- Updates in
~/oci-mp/server/src/main/resources/META-INF/microprofile-config.properties
config file to set up configuration parameters used by the Helidon app code to perform integration with OCI Logging and Metrics service.- oci.monitoring.compartmentId - Compartment ocid that is used for this demo
- oci.monitoring.namespace - This can be any string but for this demo, this will be set to
helidon_application
. - oci.logging.id - Application log id that was provisioned by the terraform scripts.
- Update in
~/oci-mp/server/src/main/resources/META-INF/microprofile-config.properties
config file to set upoci.bucket.name
property to contain the Object Storage bucket name that was provisioned by the terraform scripts that will be used in a later exercise to demonstrate Object Storage support from a Helidon application.
Note: Make sure to validate that
application.yaml
andmicroprofile-config.properties
has been updated by opening them from Code Editor and checking that the mentioned config parameters had been properly populated. - Updates in
-
Stage all the files for git commit
git add . git status
-
Perform the first commit
git commit -m "Helidon oci-mp first commit"
-
Push the changes to the remote repository
git push -u origin main
-
This will trigger the DevOps to start the pipeline.
- From the OCI Console, go to
Developer Services
->Projects (under DevOps)
. - Choose the
Compartment
value that has the format ofdevops-compartment-helidon-demo-<4 char random value>
. - Click on the project that is displayed with the name format of
devops-project-helidon-demo-<4 char random value>
. - Scroll down to the
Latest Build History
and wait until the Status of the runs turn toSucceeded
. You can also click on the specific runs to observe the progress of the build pipelines. - Scroll down to the
Latest deployments
and wait until the Status of the runs turn toSucceeded
. You can also click on the specific runs to observe the progress of the build pipelines.
- From the OCI Console, go to
- Go back to an open terminal from the Code Editor or open a new one.
- If a compute instance was configured as the deployment target, i.e.
deployment_target
is set toINSTANCE
orALL
, access the application by using curl to do a GET & PUT http requests.- Set the endpoint using the instance's public ip:
export ENDPOINT_IP=$(~/oci-devops-helidon-example/main/get.sh public_ip) echo "Instance public ip is $ENDPOINT_IP"
- Test Hello world request:
results to:
curl http://$ENDPOINT_IP:8080/greet
{"message":"Hello World!","date":[2023,5,10]}
- Test Hello to a name, i.e. to
Joe
:results to:curl http://$ENDPOINT_IP:8080/greet/Joe
{"message":"Hello Joe!","date":[2023,5,10]}
- Replace Hello with another greeting word, i.e.
Hola
:results to:curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Hola"}' http://$ENDPOINT_IP:8080/greet/greeting curl http://$ENDPOINT_IP:8080/greet
{"message":"Hola World!","date":[2023,5,10]}
- Set the endpoint using the instance's public ip:
- If OKE was configured as the deployment target, i.e.
deployment_target
is set toOKE
orALL
, access the application by using curl to do GET & PUT rest requests.- Set the endpoint using the LoadBalancer's external IP:
export ENDPOINT_IP=$(kubectl --kubeconfig=$HOME/oci-devops-helidon-example/main/generated/kubeconfig get services oci-mp-server -o jsonpath='{.status.loadBalancer.ingress[].ip}') echo "Kubernetes LoadBalancer ip is $ENDPOINT_IP"
- Test hello world request:
results to:
curl http://$ENDPOINT_IP:8080/greet
{"message":"Hello World!","date":[2023,5,10]}
- Test Hello to a name, i.e. to
Joe
:results to:curl http://$ENDPOINT_IP:8080/greet/Joe
{"message":"Hello Joe!","date":[2023,5,10]}
- Replace Hello with another greeting word, i.e.
Hola
:results to:curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Hola"}' http://$ENDPOINT_IP:8080/greet/greeting curl http://$ENDPOINT_IP:8080/greet
{"message":"Hola World!","date":[2023,5,10]}
- Set the endpoint using the LoadBalancer's external IP:
- Validate that the Helidon Metrics are pushed to the OCI Monitoring Service using the OCI metric integration that was added in the Helidon application:
- From the OCI Console, go to
Observability & Management
->Metrics Explorer (under Monitoring)
. - On
Query 1
, choose theCompartment
value with the format ofdevops-compartment-helidon-demo-<4 char random value>
. - Select
helidon_metrics
underMetric namespace
. - Select
requests.count_counter
underMetric Name
. - Above the empty graph, you can choose values for
Start time/End Time
or choose the time duration underQuick Selects
. - Click
Update Chart
at the bottom ofQuery 1
to show all the metric data for therequest count
. You can also toggle to enableShow Data Table
on the right upper portion of the graph to show the list of data for the chosen metric. - You can also explore other Metrics by going back to step 4 and choosing a new value.
- From the OCI Console, go to
- Validate OCI Logging SDK integration that was added in the Helidon application. This will push log messages to the OCI Logging Service:
- From the OCI Console, go to
Observability & Management
->Logs (under Logging)
. - Change
Compartment
with a value that has the format ofdevops-compartment-helidon-demo-<4 char random value>
. - Under
Filters
, changeLog Group
toapp-log-group-helidon-demo
. - Choose and click on
app-log-helidon-demo
from the Logs table. - Choose
Filter by time
value within the scope of your last request. For example, you can chooseToday
to see all request that was made today. - The
Explore Log
display should output some graphs of the logging activity and below it will also show a list of the logs that has been captured.
- From the OCI Console, go to
- The Helidon oci-mp application adds Health Check feature to validate
liveness
and/orreadiness
. You can checkGreetLivenessCheck
andGreetReadinessCheck
class files respectively in the project to see how they are done. This will particularly be useful when running the app as a microservice on an orchestrator environment like Kubernetes to determine if the microservice needs to be restarted if it is not healthy. Specific to this lab, thereadiness
check is leveraged in theDevOps deployment pipeline spec
after the app is started to determine if the Helidon application started successfully. Check out code in deployment_spec.yaml to see it in action, particulary in the line that calls a rest request that has a path of/health/ready
.- If a compute instance was configured as the deployment target, i.e.
deployment_target
is set toINSTANCE
orALL
:- Set the endpoint using the instance's public ip:
export ENDPOINT_IP=$(~/oci-devops-helidon-example/main/get.sh public_ip) echo "Instance public ip is $ENDPOINT_IP"
- Liveness Check
results to:
curl http://$ENDPOINT_IP:8080/health/live
{"status":"UP","checks":[{"name":"CustomLivenessCheck","status":"UP","data":{"time":1684391639448}}]}
- Readiness Check
results to:
curl http://$ENDPOINT_IP:8080/health/ready
{"status":"UP","checks":[{"name":"CustomReadinessCheck","status":"UP","data":{"time":1684391438298}}]}
- Set the endpoint using the instance's public ip:
- If OKE was configured as the deployment target, i.e.
deployment_target
is set toOKE
orALL
:- Set the endpoint using the LoadBalancer's external IP:
export ENDPOINT_IP=$(kubectl --kubeconfig=$HOME/oci-devops-helidon-example/main/generated/kubeconfig get services oci-mp-server -o jsonpath='{.status.loadBalancer.ingress[].ip}') echo "Kubernetes LoadBalancer ip is $ENDPOINT_IP"
- Liveness Check
results to:
curl http://$ENDPOINT_IP:8080/health/live
{"status":"UP","checks":[{"name":"CustomLivenessCheck","status":"UP","data":{"time":1684391639448}}]}
- Readiness Check
results to:
curl http://$ENDPOINT_IP:8080/health/ready
{"status":"UP","checks":[{"name":"CustomReadinessCheck","status":"UP","data":{"time":1684391438298}}]}
- Set the endpoint using the LoadBalancer's external IP:
- If a compute instance was configured as the deployment target, i.e.
The objective of this exercise is to demonstrate how to add Object Storage access from the Helidon code. This is done by replacing a variable which is used to store the greeting word with an object that will now become the new greeting word container and is stored and retrieved from an Object Storage bucket. Since the object is persisted, the last greeting word value will survive application restarts. Without this change and with greeting word in memory via the variable, the greeting word will reset to default value when the application is restarted.
- Make sure that Code Editor is open with
oci-mp
local directory as the active workspace - Open
pom.xml
under theserver
directory and add the Object Storage OCI SDK dependency inside thedependencies
clause.<dependency> <groupId>com.oracle.oci.sdk</groupId> <artifactId>oci-java-sdk-objectstorage</artifactId> </dependency>
- Perform the following updates to
oci-mp/server/src/main/java/demo/mp/oci/server/GreetingProvider.java
.- Replace the existing GreetingProvider constructor method with the code that will have the following characteristics:
- From the constructor's argument section, add
ObjectStorage objectStorageClient
parameter. Since this is part of @Injected annotation, the parameter will automatically be processed and set by Helidon to contain the client which can be used to communicate with the Object Storage service without having to add several lines of OCI SDK code for that purpose. - From the same constructor's argument section, add ConfigProperty which will extract value from an
oci.bucket.name
property in the configuration. This has earlier been populated inmicroprofile-config.properties
during the initial application setup when a utility script calledupdate_config_values.sh
was executed from theoci-devops-helidon-example
repository directory. - Using getNamespace() Object Storage SDK method, \retrieve the Object Storage's namespace as it will be used later to retrieve or store an object:
public GreetingProvider(@ConfigProperty(name = "app.greeting") String message, ObjectStorage objectStorageClient, @ConfigProperty(name = "oci.bucket.name") String bucketName) { try { this.bucketName = bucketName; GetNamespaceResponse namespaceResponse = objectStorageClient.getNamespace(GetNamespaceRequest.builder().build()); this.objectStorageClient = objectStorageClient; this.namespaceName = namespaceResponse.getValue(); LOGGER.info("Object storage namespace: " + namespaceName); setMessage(message); } catch (Exception e) { LOGGER.warning("Error invoking getNamespace from Object Storage: " + e); } }
- From the constructor's argument section, add
- Right below the GreetingProvider class, remove the variable declaration:
and replace it with local global variables like below:
private final AtomicReference<String> message = new AtomicReference<>();
private static final Logger LOGGER = Logger.getLogger(GreetingProvider.class.getName()); private ObjectStorage objectStorageClient; private String namespaceName; private String bucketName; private final String objectName = "hello.txt";
LOGGER
will be used for logging whileobjectStorageClient
,namespaceName
,bucketName
andobjectName
will be used on Object Storage SDK calls. - Replace the content of
getMessage()
with:This will usetry { GetObjectResponse getResponse = objectStorageClient.getObject( GetObjectRequest.builder() .namespaceName(namespaceName) .bucketName(bucketName) .objectName(objectName) .build()); return new String(getResponse.getInputStream().readAllBytes()); } catch (Exception e) { LOGGER.warning("Error invoking getObject from Object Storage: " + e); return "Hello-Error"; }
getObject()
SDK method to retrieve the greeting word from thehello.txt
object fetched from the bucket. - Replace the content of
void setMessage(String message)
method with:This will usetry { byte[] contents = message.getBytes(); PutObjectRequest putObjectRequest = PutObjectRequest.builder() .namespaceName(namespaceName) .bucketName(bucketName) .objectName(objectName) .putObjectBody(new ByteArrayInputStream(message.getBytes())) .contentLength(Long.valueOf(contents.length)) .build(); objectStorageClient.putObject(putObjectRequest); } catch (Exception e) { LOGGER.warning("Error invoking putObject from Object Storage: " + e); }
putObject()
SDK method to store thehello.txt
object containing the greeting word into the bucket. - Remove the import:
and replace with the these new imports to support all the new code that has been added:
import java.util.concurrent.atomic.AtomicReference;
import java.io.ByteArrayInputStream; import java.util.logging.Logger; import com.oracle.bmc.objectstorage.ObjectStorage; import com.oracle.bmc.objectstorage.requests.GetNamespaceRequest; import com.oracle.bmc.objectstorage.requests.GetObjectRequest; import com.oracle.bmc.objectstorage.requests.PutObjectRequest; import com.oracle.bmc.objectstorage.responses.GetNamespaceResponse; import com.oracle.bmc.objectstorage.responses.GetObjectResponse;
~/oci-devops-helidon-example/source/GreetingProvider.java
. You can use that to compare the changes you've gone through. Alternatively, you can also just copy that file over the existing file. For example, you can do this from the root ofoci-mp
directory:cp ~/oci-devops-helidon-example/source/GreetingProvider.java server/src/main/java/demo/mp/oci/server/
- Replace the existing GreetingProvider constructor method with the code that will have the following characteristics:
- Commit and push the changes:
git add . git status git commit -m "Add support Object Storage integration" git push
- Wait until the DevOps lifecycle is completed by monitoring the build and deployment pipeline logs.
- If a compute instance was configured as the deployment target, i.e.
deployment_target
is set toINSTANCE
orALL
, test it by using curl and check that a newhello.txt
object has been added in the bucket. Validate that the size of the object is the same as the size of the greeting word. For example, if the greeting word isHello
, then the size should be 5. If the greeting word isHola
, then the size should be 4.- Set up the deployment node public ip as an environment variable:
export ENDPOINT_IP=$(~/oci-devops-helidon-example/main/get.sh public_ip) echo "Instance public ip is $ENDPOINT_IP"
- Call default Hello world request:
results to:
curl http://$ENDPOINT_IP:8080/greet
{"message":"Hello World!","date":[2023,5,10]}
- From the OCI Console, go to
Storage
->Buckets (under Object Storage & Archive Storage)
, set the Compartment value todevops-compartment-helidon-demo-<4 char random value>
followed by clicking on the bucket that appears, i.e.app-bucket-helidon-demo-<4 char random value>
. Check that the bucket now contains an objecthello.txt
and has a size of 5 bytes because the greeting word isHello
. You can also download the object and verify that the content is indeedHello
. - Replace
Hello
greeting word withHola
:results to:curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Hola"}' http://$ENDPOINT_IP:8080/greet/greeting curl http://$ENDPOINT_IP:8080/greet
{"message":"Hola World!","date":[2023,5,10]}
- Check that the bucket's
hello.txt
object now has a size of 4 bytes because the greeting word is replaced withHola
. You can also download the object and verify that the content is changed toHola
. - Restart the application using
restart.sh
tool to demonstrate that the value of the greeting word will survive as it is persisted in the Object Storage.Respond~/oci-devops-helidon-example/utils/restart.sh
yes
when askedif you want to continue...
, which will then show an output like below:Created private.key and can be used to ssh to the deployment instance by running this command: "ssh -i private.key opc@xxx.xxx.xx.xxxx" FIPS mode initialized FIPS mode initialized The authenticity of host 'x.x.x.x (x.x.x.x)' can't be established. ECDSA key fingerprint is SHA256:sha256dataxxxxxxxxxxx. ECDSA key fingerprint is SHA1:sha1dataxxxxxxxxxxx. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'x.x.x.x' (ECDSA) to the list of known hosts. Stopping oci-mp-server.jar with pid 13032 Starting oci-mp-server.jar from helidon-app.service Stopping oci-mp-server.jar with pid 999990 Starting oci-mp-server.jar Helidon app is now running with pid 999991! Cleaning up ssh private.key
- Call default Hello world request and observe that the greeting word is still
Hola
.results to:curl http://$ENDPOINT_IP:8080/greet
{"message":"Hola World!","date":[2023,5,10]}
- Set up the deployment node public ip as an environment variable:
- If OKE was configured as the deployment target, i.e.
deployment_target
is set toOKE
orALL
, test it by using curl and check that a newhello.txt
object has been added in the bucket. Validate that the size of the object is the same as the size of the greeting word. For example, if the greeting word isHello
, then the size should be 5. If the greeting word isHola
, then the size should be 4.- Set the endpoint using the LoadBalancer's external IP:
export ENDPOINT_IP=$(kubectl --kubeconfig=$HOME/oci-devops-helidon-example/main/generated/kubeconfig get services oci-mp-server -o jsonpath='{.status.loadBalancer.ingress[].ip}') echo "Kubernetes LoadBalancer ip is $ENDPOINT_IP"
- Call default Hello world request:
If testing against instance deployment was completed from the previous step, this will result to:
curl http://$ENDPOINT_IP:8080/greet
If this is the first time this will be run, this will result to:{"message":"Hola World!","date":[2023,5,10]}
{"message":"Hello World!","date":[2023,5,10]}
- From the OCI Console, go to
Storage
->Buckets (under Object Storage & Archive Storage)
, set the Compartment value todevops-compartment-helidon-demo-<4 char random value>
followed by clicking on the bucket that appears, i.e.app-bucket-helidon-demo-<4 char random value>
. Check that the bucket contains an objecthello.txt
and has a size of 4 bytes if the greeting word isHola
and 5 bytes if it isHello
. You can also download the object and verify that the content is correct. - Replace greeting word with
Bonjour
:results to:curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Bonjour"}' http://$ENDPOINT_IP:8080/greet/greeting curl http://$ENDPOINT_IP:8080/greet
{"message":"Bonjour World!","date":[2023,5,10]}
- Check that the bucket's
hello.txt
object now has a size of 7 bytes because the greeting word is replaced withBonjour
. You can also download the object and verify that the content is now changed toBonjour
. - Restart the application by restarting the Kubernetes deployment. This is to demonstrate that the value of the greeting word will survive as it is persisted in the Object Storage.
which will show an output like below if restart succeeds:
kubectl --kubeconfig=${HOME}/oci-devops-helidon-example/main/generated/kubeconfig rollout restart deployment oci-mp-server
deployment.apps/oci-mp-server restarted
- Call default Hello world request and observe that the greeting word is still
Bonjour
.results to:curl http://$ENDPOINT_IP:8080/greet
{"message":"Bonjour World!","date":[2023,5,10]}
- Set the endpoint using the LoadBalancer's external IP:
When the environment is no longer needed, all the OCI resources can be cleaned up by following these steps:
- Go back to Code Editor and reopen
oci-devops-helidon-example
project, followed by opening a terminal. - Cleaning up all resources used for the DevOps demo.
- From the terminal, change directory to main to destroy all the resources created for DevOps.
cd main
- Run the destroy script. This will remove all artifacts stored in the artifact repository, remove kubernetes service (which will also remove the provisioned LoadBalancer) and deployment from OKE, if they exist, and finally will destroy all the OCI resources created by the terraform script.
destroy.sh
- From the terminal, change directory to main to destroy all the resources created for DevOps.
- Cleaning up the created compartment, dynamic-groups, groups and policies.
- From the same terminal, change directory to init.
cd ../init
- Run the destroy command from terraform.
terraform destroy -auto-approve
- From the same terminal, change directory to init.