Execute commands with Spring Boot & Kubernetes - java

Environment variables with Spring Boot & Kubernetes
In my OS, the following command retrieves a key managed by K8s:
kubectl exec -it nginx-secret-7665cd8fb8-mj26h cat /mnt/secrets/ScAppCryptKey
As mentioned, the result is something like this:
xPeShVmYq3t6w9z#B#E?H#McQfTjWnZr4u7x%D*F-JaNdRgUkXp2s5v8y#B?E%
Now, I have to find a way to get this result (key) and use it in my Spring Boot Application. I think the most proper way to express my problem is:
During runtime (or when starting my app), I need to execute a command in the OS and get its result.
Is there a way to automatically execute commands in the terminal with Spring? Let me try to explain through code:
// If I had an environment variable, this would be like:
String key = System.getenv("myKey");
// But in my case, I need to execute a command, like this:
String keyFromKubernetes = System.getenv(
"kubectl exec -it nginx-secret-7665cd8fb8-mj26h cat /mnt/secrets/ScAppCryptKey"
);

Related

FSCrawler docker-compose NoSuchElementException

I try to run FSCrawler via docker-compose following the steps described in https://fscrawler.readthedocs.io/en/fscrawler-2.9/installation.html#using-docker-compose.
ELASTIC_VERSION = "7.17.8"
FSCRAWLER_VERSION = "2.9"
PWD = ""
I verified that elasticsearch is running sucessfully.
On running docker-compose up fscrawler, I get the following exception.
You need to use the 2.10-SNAPSHOT which is much more stable although the name does not say that ;)

Calling Local/Server Node JS Application from Spring Boot Java Web API

we have installed a node js utility on a local machine/server.
using npm install -g openapi2Arbitaryservice
I can call this utility and it is working fine. It reads a json and create a service api.
openapi2Arbitaryservice generateApi myProxySwagSep6 -s ./swagger-petstore.json -d ./aug-2021
I want to trigger this when api request comes to the tomcat server with body of JSON. I have a spring-boot application using java 8.
I was trying to use exec method of java to call this locally installed node js application when an api request comes to the server and do the processing
String[] command = { "/bin/bash", "-c", ,"openapi2ArbitaryService", "generateApi", "myProxySwagSep6", "-s",".swagger-petstore.json", "-d", "./aug-2021" };
p = Runtime.getRuntime().exec(command);
But, i get error "Exit Value 127". It seems it's not able to recognise openapi2ArbitaryService
Is this a valid use-case for java calling local/server installed application on user api requests. Should this be decoupled using a queue and then handled separately e.g as a docker task.
Is Golang/python suitable for such use-cases please share some thoughts.
thanks in advance !

How to pass -javagent /path/to/newrelic.jar parameter to the JVM running a HiveMetaStore server

I try to get a Newrelic java agent to run in a docker container to monitor a HiveMetaStore server running in the docker container.
In order to get the Newrelic agent started during the startup of the JVM I have to pass-javaagent /path/to/newrelic.jar flag to the JVM.
I tried:
hive --service metastore -javaagent /path/to/newrelic.jar
This failed with "Unrecognized Option" in the HiveMetaStore server code, where it should not have ended up at all.
The hive script invokes the bin/ext/metastore.sh script which in turn invokes
exec $HADOOP jar $JAR $CLASS "$#"
So I tried to patch this invocation:
exec $HADOOP -javaagent /path/to/newrelic.jar jar $JAR $CLASS "$#"
This failed as well.
Then I took a deeper look at the hadoop script. Finally function hadoop_java_exec in libexec//hadoop_functions.sh invokes:
exec "${JAVA}" "-Dproc_${command}" ${HADOOP_OPTS} "${class}" "$#"
So I patched this code:
exec "${JAVA}" "-javaagent /path/to/newrelic.jar" "-Dproc_${command}" ${HADOOP_OPTS} "${class}" "$#"
This again failed.
Last but not least I recognized that one can pass java properties via HADOOP _OPTS (in libexec/hadoop_functions.sh):
function hadoop_finalize_hadoop_opts
{
hadoop_translate_cygwin_path HADOOP_LOG_DIR
hadoop_add_param HADOOP_OPTS hadoop.log.dir "-Dhadoop.log.dir=${HADOOP_LOG_DIR}"
hadoop_add_param HADOOP_OPTS hadoop.log.file "-Dhadoop.log.file=${HADOOP_LOGFILE}"
…
}
But I could not figure out how to pass -javaagent:/path/to/newrelic.jar using this mechanism.
Is anyone out there who has tried this before and can help with that ?
My apology if this is a stupid question. Thanks upfront, Ute
function hadoop_finalize_hadoop_opts
{
hadoop_translate_cygwin_path HADOOP_LOG_DIR
hadoop_add_param HADOOP_OPTS hadoop.log.dir "-Dhadoop.log.dir=${HADOOP_LOG_DIR}"
hadoop_add_param HADOOP_OPTS hadoop.log.file "-Dhadoop.log.file=${HADOOP_LOGFILE}"
…
hadoop_add _param HADOOP_OPTS java.javaagent -javaagent:${NEWRELIC_AGENT_HOME}\/newrelic.jar
}
Adding the last statement to got the agent started. I see in the container:
/usr/lib/jvm/default-jvm/bin/java -Dproc_jar -Dproc_metastore , … , NullAppender - javaagent:/opt/newrelic-agent-5.10.0/newrelic.jar org.apache.hadoop.util.RunJar /opt/apache-hive-3.1.2-bin/lib/hive-metastore-3.1.2.jar org.apache.hadoop.hive.metastore.HiveMetaStore
I don't understand the "NullAppender" yet but at least the agent seems to be running now.

How can I run Play framework in HTTPS only in the dev mode?

I'd like to run Play Framework over HTTPS only in the development mode and I've done so using the following bit of configuration:
https.port=9443
trustmanager.algorithm=JKS
keystore.file=conf/certificate.jks
keystore.password=password
certificate.password=password
application.mode=dev
%prodenv.application.mode=prod
This works when I run play run but in production we run play run --%prodenv and I want to disable HTTPS as the HTTPS is handled by Nginx. I'm lost with how to do this. I would like to do this via the configuration file and not via additional command-line arguments as it does defy the purpose of having all my application configuration in the application.conf file.
One way to do it is to have two confs file: application.conf and prod.conf
application.conf stays the way it is and prod.conf would look something like
include "application.conf"
https.port = myProdPort
### other params to be overwritten
when launching your application in prod you can do
play run -Dconfig.file=/mypath/prod.conf
sbt run -Dhttps.port=9443 -Dhttp.port=disabled
Rather than have two configuration files, I achieved this by using just one. In order to run the app, I run play run --%dev and this is what the configuration looks like.
%dev.https.port=9443
%dev.trustmanager.algorithm=JKS
%dev.keystore.file=conf/certificate.jks
%dev.keystore.password=password
%dev.certificate.password=password
Similar to the other answer by Johan, I do it the reverse way: my application.conf is for prod and I run a dev.conf just in development:
include "application.conf"
https.port = devPort
And run locally like so:
play run -Dconfig.file=dev.conf
This way you don't have to change any configuration on your prod server.
You could remove the https.port param from your conf file and pass it in via the command line, when you run it in development mode:
play run -Dhttp.port=9443
See: Sprecifying server address and port
Play framework runs using Netty server you can overwrite the server configuration using -D parameters.
In sbt it can be done like:
sbt "project pepe-grillo-server" "run -Dhttps.port=42443 -Dhttp.port=disabled"
If you are using custom ssl engine provider CustomSSLEngineProvider you can use below command to run netty in ssl mode.
./sbt "-Dhttps.port=9443" "-Dplay.server.https.engineProvider=services.https.CustomSSLEngineProvider" "-Dconfig.resource=<config file> run
Once the server is up and running you can curl the endpoint to check cert validity.
curl -v https://127.0.0.1:9443

how to restart tomcat from a running webapp?

I need to restart tomcat service from a webapp running on this tomcat. So I'm trying to execute script that stops tomcat service, and then starts it:
echo "before stop" >> textfile.txt
NET STOP "Tomcat7"
:loop
timeout 3
SC query Tomcat7 | FIND "STATE" | FIND "RUNNING" > NUL
IF ERRORLEVEL 1 (
goto start
) ELSE (
goto loop
)
:start
NET START "Tomcat7"
Java code:
String command = "C:\\Tomcat 7.0\\bin\\restart.bat";
Process p = Runtime.getRuntime().exec(command);
Tomcat is stopped, but not started.
If I run this batch from command line, it works properly.
thank you for your time
This worked:
String fileName = "C:\\Tomcat 7.0\\bin\\restart.bat";
String[] commands = {"cmd", "/c", "start", "\"DummyTitle\"",fileName};
Runtime.getRuntime().exec(commands);
taken from http://www.rgagnon.com/javadetails/java-0014.html
What you are asking is not exactly safe and possible but do take a look at Tomcat manager API that allows you to programmatically manipulate Tomcat deployment and instance:
http://tomcat.apache.org/tomcat-7.0-doc/api/index.html
http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/manager/host/HostManagerServlet.html
Agree with Edmon.
Tomcat is a provider of containers. Each container should act independently of each other, even if they call the services another provides. This should all be done via RMI or alike.
Like Edmon also suggests, you could call using the API, but again... sounds bad. Instead, question why it needs to restart. Then, if there's no work around, use the Tomcat Manager.

Categories