How to add module to Wildfly using CLI - java

I'm trying to create a Wildfly docker image with a postgres datasource.
When I build the dockerfile it always fails with Permission Denied when I try to install the postgres module.
My dockerfile looks look this:
FROM wildflyext/wildfly-camel
RUN /opt/jboss/wildfly/bin/add-user.sh admin admin --silent
ADD postgresql-9.4-1201.jdbc41.jar /tmp/
ADD config.sh /tmp/
ADD batch.cli /tmp/
RUN /tmp/config.sh
Which calls the following:
#!/bin/bash
JBOSS_HOME=/opt/jboss/wildfly
JBOSS_CLI=$JBOSS_HOME/bin/jboss-cli.sh
JBOSS_MODE=${1:-"standalone"}
JBOSS_CONFIG=${2:-"$JBOSS_MODE.xml"}
function wait_for_wildfly() {
until `$JBOSS_CLI -c "ls /deployment" &> /dev/null`; do
sleep 10
done
}
echo "==> Starting WildFly..."
$JBOSS_HOME/bin/$JBOSS_MODE.sh -c $JBOSS_CONFIG > /dev/null &
echo "==> Waiting..."
wait_for_wildfly
echo "==> Executing..."
$JBOSS_CLI -c --file=`dirname "$0"`/batch.cli --connect
echo "==> Shutting down WildFly..."
if [ "$JBOSS_MODE" = "standalone" ]; then
$JBOSS_CLI -c ":shutdown"
else
$JBOSS_CLI -c "/host=*:shutdown"
fi
And
batch
module add --name=org.postgresql --resources=/tmp/postgresql-9.4-1201.jdbc41.jar --dependencies=javax.api,javax.transaction.api
/subsystem=datasources/jdbc-driver=postgresql:add(driver-name=postgresql,driver-module-name=org.postgresql,driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource)
run-batch
The output when building is:
==> Starting WildFly...
==> Waiting...
==> Executing... Failed to locate the file on the filesystem copying /tmp/postgresql-9.4-1201.jdbc41.jar to
/opt/jboss/wildfly/modules/org/postgresql/main/postgresql-9.4-1201.jdbc41.jar:
/tmp/postgresql-9.4-1201.jdbc41.jar (Permission denied)
What permissions are required, and where do I set the permission(s)?
Thanks

It seems the JAR file is not readable by the jboss user (the user comming from parent image). The postgresql-9.4-1201.jdbc41.jar is added under the root user - find details in this GitHub discussion.
You could
either add permissions to JAR file before adding it to the image
or add permissions to JAR file in the image after the adding
or change ownership of the file in the image
The simplest solution could be the first one. The other 2 solutions need also switching user to root (USER root in dockerfile) and then back to jboss.

Here a advice : make a cli file like this :
connect
module add --name=sqlserver.jdbc --resources=#INSTALL_FOLDER#/libext/jtds-1.3.1.jar --dependencies=javax.api,javax.transaction.api
/subsystem=datasources/jdbc-driver=sqlserver:add(driver-module-name=sqlserver.jdbc,driver-name=sqlserver,driver-class-name=#JDBC_DRIVER#)
/subsystem=datasources/data-source=#DATASOURCENAME#:add(jndi-name=java:jboss/#JNDI_NAME#,enabled="true",use-java-context="true",driver-name=sqlserver,connection-url="#JDBC_URL#",user-name=#JDBC_USER#,password=#JDBC_PASSWORD#,validate-on-match=true,background-validation=true)
replace #VAR# by our own value... and It should work!
Be caution than JBOSS/Wildfly 10 think relatively for jar --resources by default but wildfly 8 think absolute path this could make you weird ! ;-)
cheers!

Related

prometheus jmx_exporter in kubernetes

Im using kubenetes and I have a pod contain ignite db I added to the pod another container - sscaling/jmx-prometheus-exporter:latest
I read in git I should run this
To run as a javaagent download the jar and run:
java -javaagent:./jmx_prometheus_javaagent-0.14.0.jar=8080:config.yaml -jar yourJar.jar
but I didnt understand, should I also download the file for the kubenrtes container as well?
can someone assist how can I continue from here
I have the following default configuration:
---
hostPort: localhost:5555
username:
password:
rules:
- pattern: ".*"

'no identity found' when using gradle to exec codesign

I am trying to sign my Java/JavaFX application using codesign with gradle. My gradle code is as following:
exec {
val codeSignArgs = listOf("-s", "'${macSigningKeyDeveloperIdApp}'", "--timestamp", "--options", "runtime", "--entitlements", "../../../entitlements.plist", "--deep", "-f", "--verbose", "UTMCoordinateConverter.app")
logger.quiet("code sign args: $codeSignArgs")
workingDir = macRel
isIgnoreExitValue = true
executable = codeSignTool.absolutePath
args(codeSignArgs)
}
Where codeSignTool is /usr/bin/codesign and macRel is the directory where the app file is, and macSigningKeyDeveloperIdApp is my signing developer id.
Gradle gives me the following output:
> Task :codeSign
Inside codeSign
code sign args: [-s, 'Developer ID Application: Victor Ewert (XXXXXXXXXX)', --timestamp, --options, runtime, --entitlements, ../../../entitlements.plist, --deep, -f, --verbose, UTMCoordinateConverter.app]
BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed
'Developer ID Application: Victor Ewert (XXXXXXXXXX)': no identity found
2:38:26 p.m.: Task execution finished 'codeSign'.
The strange thing is, I can run the (equivalent) command fine, from the command line using:
/usr/bin/codesign -s 'Developer ID Application: Victor Ewert (XXXXXXXXX)' --timestamp --options runtime --entitlements ../../../entitlements.plist --deep -f --verbose UTMCoordinateConverter.app
run from the location of the app file.
I have double and triple checked my Developer ID, and it looks fine (checked using security find-identity -p codesigning -v login.keychain. I have also made sure my login keychain is unlocked. I don't think it is a problem with my Developer ID.
I'm guessing it has something to do with how gradle is executing the command, but I can't figure it out.

Not able to set environment variables inside a docker container when building image using gradle task

I have written a gradle task buildDocker in my build.gradle file as follows:
task buildDocker(type: Docker, dependsOn: copyJar) {
push = false
baseImage "openjdk:8u151"
println System.getenv('AWS_ACCESS_KEY_ID')
println System.getenv('AWS_SECRET_ACCESS_KEY')
setEnvironment('AWS_ACCESS_KEY_ID',System.getenv('AWS_ACCESS_KEY_ID'))
setEnvironment('AWS_SECRET_ACCESS_KEY',System.getenv('AWS_SECRET_ACCESS_KEY'))
runCommand("mkdir myProject")
addFile("myProject-0.0.jar","myProject/")
workingDir("/myProject")
runCommand("unzip -q myProject-0.0.jar")
exposePort(8888)
entryPoint(["java","-XX:+UnlockExperimentalVMOptions","-
XX:+UseCGroupMemoryLimitForHeap","-XX:MaxRAMFraction=1","-XshowSettings:vm","-cp",
"/myProject-config:.","org.springframework.boot.loader.JarLauncher"])
}
When I build the image by running the task I am able to see the println outputs in the terminal. But when I run the image, I keep getting the following exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'simpleMessageListenerContainer' defined in class path resource [org/springframework/cloud/aws/messaging/config/annotation/SqsConfiguration.class]: Invocation of init method failed; nested exception is com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain: [com.amazonaws.auth.profile.ProfileCredentialsProvider#46244e65: profile file cannot be null]
Caused by: com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain: [com.amazonaws.auth.profile.ProfileCredentialsProvider#46244e65: profile file cannot be null]
I have also tried setting the environment variables directly in the run statement by using the -e parameters in the run command and by mounting my ~/.aws/credentials file to the docker container , but with those also, I get the same exception.
EDIT1: here's the docker run command using the -e flags :
docker run -e AWS_ACCESS_KEY_ID=XXXX -e AWS_SECRET_ACCESS_KEY=XXXX --link mysql --name myapp <imageName>
Also, put the credentials as key value pairs in a file-env.list and tried this:
docker run --env-file env.list -v --link mysql --name myapp <imagename>
Environment variables that are defined in scripts that run when building an image, are not kept when creating a container based on that image.
You need to explicitly set environment variables using ENV directive in your Dockerfile, or set them when running the container using the -e flag, for example.
Please see this article for more information.
Finally got it working with mounting my credentials file to the docker container:
docker run -p 8888:8888 -v ~/.aws:/root/.aws --link mysql --name myapp <imageName>
the credentials are created and stored in the .aws folder. The mistake I was doing earlier, with mounting was a stupid one, probably because of fatigue, I kept mounting it on the /home directory in the container but home folder (~) in the container is /root instead, so once I changed that , there weren't any issues.Though I still don't understand why the -e flags are not working, as according to this - https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html the amazon java sdk will try to load the credentials from the env variables first and then from the java system properties and then from the default credential profiles file.

How can I deploy cloudfoundry-uaa as a docker image based on tomcat?

We were using the cf-uaa's gradle tasks to create a docker image but those have been removed in the latest version. I've loaded the war in a recent version, but the service does not seem to be starting correctly.
I've been building the war from the v74 tag, adding it to tomcat:8.5.45-jdk12-openjdk-oracle or tomcat:9.0.24-jdk12-openjdk-oracle, and setting the various env vars that we were passing in to the previous image. I'm not seeing any log entries after the initial tomcat output stating that my war has been deployed and the server startup time.
The Dockerfile is basically just an adaptation of what was being passed in the previous image:
FROM tomcat:8.5.45-jdk12-openjdk-oracle
#FROM tomcat:9.0.24-jdk12-openjdk-oracle
ENV LOGIN_CONFIG_URL WEB-INF/classes/required_configuration.yml
ENV UAA_CONFIG_PATH /uaa
RUN bash -c "rm -r /usr/local/tomcat/webapps/ROOT"
RUN bash -c "rm -r /usr/local/tomcat/webapps/host-manager"
RUN bash -c "rm -r /usr/local/tomcat/webapps/manager"
RUN bash -c "rm -r /usr/local/tomcat/webapps/examples"
RUN bash -c "rm -r /usr/local/tomcat/webapps/docs"
ADD *.war /usr/local/tomcat/webapps/uaa.war
RUN bash -c "echo $LOGIN_CONFIG_URL"
EXPOSE 8080
I would expect to see the service responding to my requests, or some errors in the log indicating that the war failed to deploy. I am not currently getting any log output generated from the application code. When I send a request to the service, the response is a 500 with the an error header from the service.
X-Cf-Uaa-Error:Server failed to start. Possible configuration error.
update: I've located the uaa logs within .../tomcat/logs/uaa.log I'm not seeing anything indicating that the service failed to deploy, but I am also not seeing anything to indicate that it is picking up the env vars I have set in the container. I recreated the service using the war from the original setup which started successfully using the uaa.yml which I mounted as a volume. Comparing the logs, the original setup's first log entry is YamlProcessor which does not show up in the v75 logs at all. In fact, no debug entries show up at all, which suggests to me that my LOG_LEVEL env var is not propagating either.
Update 2: We reverted the image base to FROM tomcat:8.5-jre8 and started seeing flyway errors in the uaa.log. Our previous datasource url format was url: jdbc:postgresql://${POSTGRES_NAME}:5432/${DB}?currentSchema=uaa which caused a flyway exception. After removing the schema reference, it created the tables in the public schema. By creating the uaa schema manually before starting the service, it was able to run with the original format. The flyway version has updated, so perhaps there something new that needs to be set.
The application seems to be running, but when I try to get a token at /uaa/oauth/token I get a 500 with this error in the logs: Caused by: java.lang.NoSuchMethodError: java.nio.CharBuffer.limit(I)Ljava/nio/CharBuffer;
Since Jan 2021, UAA server docker images is now be available on cloudfoundry/uaa dockerhub repository.
docker pull cloudfoundry/uaa:75.0.0
See its Dockerfile for more details.
Can you try following ?
https://github.com/hortonworks/docker-cloudbreak-uaa
This works very well.

Gracefully Shutdown Spring Boot Application from Shell Script

I have a spring boot application which I run using an executable jar file. Currently to stop the service we are just killing the process. I saw that we can use the following methods to shutdown the application gracefully.
ApplicationContext ctx = SpringApplication.run(Application.class, args);
and then somewhere in the code I can call ctx.close() Or we can use the following static method.
SpringApplication.exit(ApplicationContext, ExitCodeGenerator)
It works for us currently, but we are actually calling this ctx.close() method inside a controller as follows.
#RequestMapping("/shutdownSpringBoot")
public void shutdownApplication() {
MyApplication.ctx.close(); // I'm saving the context returned by spring boot in a static variable inside my main class
}
When we hit this controller method via http the application is gracefully shutdown. But we dont want to do it this way. Is it possible to write a shell / batch script to trigger the java class inside which I can call the ctx.close() method ? We are looking for a shutdown script like the one we get from a standalone tomcat container (shutdown.bat / shutdown.sh), so that we can give our application as a jar file to our customers and they can start or stop the application by executing those scripts. (Which they are used to).
Thanks,
Sanjay
I think you can simply detect that you are running your jar as a command line utility by inspecting command line parameters and instead of loading whole Spring context and booting up the web application, you just HTTP access the local shutdownSpringBoot URL using built-in Java HTTP client.
You can create a shell script and directly shutdown the springboot application. Just make sure you register shutdown hook to your spring boot application. In the shutdown hook, you can close the context. You can check my answer here
I use PID file writer to write file and store Jar and Pid in folder with same name as of application name and shell scripts also have same name with start and stop in the end.
Main Class
#SpringBootApplication
public class MyApplication {
public static final void main(String[] args) {
SpringApplicationBuilder app = new SpringApplicationBuilder(MyApplication.class);
app.build().addListeners(new ApplicationPidFileWriter());
app.run();
}
}
YML FILE
spring.pid.fail-on-write-error: true
spring.pid.file: /server-path-with-folder-as-app-name-for-ID/appName/appName.pid
Here is the start script(start-appname.sh):
shellScriptFileName=$(basename -- "$0")
shellScriptFileNameWithoutExt="${shellScriptFileName%.*}"
appName=${shellScriptFileNameWithoutExt:6}
PROCESS=$1
PIDS=`ps aux |grep [j]ava.*$appName.*jar | awk {'print $2'}`
if [ -z "$PIDS" ]; then
echo "No instances of $appName is running..." 1>&2
else
for PID in $PIDS; do
echo "Waiting for the process($PID) to finish on it's own for 3 mins..."
sleep 3m
echo "FATAL:Killing $appName with PID:$PID."
kill -9 $PID
done
fi
# Preparing the java home path for execution
JAVA_EXEC='/usr/bin/java'
# Java Executable - Jar Path Obtained from latest file in directory
JAVA_APP=$(ls -t /server-path-with-folder-as-app-name/$appName/$appName*.jar | head -n1)
# JVM Parameters and Spring boot initialization parameters
JVM_PARAM="-Xms512m -Xmx1024m -Dspring.profiles.active=sit -Dcom.webmethods.jms.clientIDSharing=true"
# To execute the application.
FINAL_EXEC="$JAVA_EXEC $JVM_PARAM -jar $JAVA_APP"
# Making executable command using tilde symbol and running completely detached from terminal
`nohup $FINAL_EXEC </dev/null >/dev/null 2>&1 &`
echo "$appName has been started successfully."
Here is the stop script(stop-appname.sh):
shellScriptFileName=$(basename -- "$0")
shellScriptFileNameWithoutExt="${shellScriptFileName%.*}"
appName=${shellScriptFileNameWithoutExt:5}
# Script to stop the application
PID_PATH="server-path-with-folder-as-app-name-for-PID/$appName/$appName.pid"
if [ ! -f "$PID_PATH" ]; then
echo "Process Id FilePath($PID_PATH) Not found"
else
pid=`cat $PID_PATH`
if [ ! -e /proc/$pid -a /proc/$pid/exe ]; then
echo "$appName was not running.";
else
kill $pid;
echo "Gracefully stopping $appName with PID:$pid..."
fi
fi

Categories