Inject application.properties value in GitLab CICD - java

Currently my tech stack is Java, Spring Boot.
I am using application-dev.properties to keep the AWS access key and secret key.
In application-dev.properties to inject the keys I have:
#This property provide access key details
com.abc.sqs.accesskey = AWS_ACCESS_KEY
#This property provide secret key details
com.abc.sqs.secretkey = AWS_SECRET_KEY
Now from GitLab CICD .gitlab-ci.yml file while I am trying to smoke test of the application .jar I have something like this (stage is smoke test) -
smoke test:
stage: smoke-test
image: openjdk:12-alpine
before_script:
- apk add --update curl && rm -rf /var/cache/apk/*
script:
- ls -la ./app-service/target/
- sed -i "s/AWS_ACCESS_KEY/$AWS_ACCESS_KEY_ID/" ./app-service/src/main/resources/application-dev.properties
- sed -i "s/AWS_SECRET_KEY/$AWS_SECRET_ACCESS_KEY/" ./app-service/src/main/resources/application-dev.properties
- java -jar -Dspring.profiles.active=dev ./app-service/target/app-service.jar &
- sleep 30
- curl http://localhost:5000/actuator/health | grep "UP"
- curl -i -X POST http://localhost:5000/actuator/shutdown
Here I am bringing $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY from GitLab CICD environment variables and trying to replace AWS_ACCESS_KEY and AWS_SECRET_KEY of properties file. But this way I am not able to inject during start of the server.
While trying to test the jar getting following exception:
Caused by: com.amazonaws.services.sqs.model.AmazonSQSException: The
security token included in the request is invalid. (Service:
AmazonSQS; Status Code: 403; Error Code: InvalidClientTokenId;
Please need your suggestion.
Advance thanks.

If you want to override properties in a properties file, instead of using sed, you can simply declare an environment variable or a JVM variable with a similar name. It will have the priority over properties declare in file.
For instance:
com.abc.sqs.accesskey = AWS_ACCESS_KEY
Can become with a JVM variable:
java -jar -Dspring.profiles.active=dev -Dcom.abc.sqs.accesskey=$AWS_ACCESS_KEY_ID ./app-service/target/app-service.jar
This will override the value of the properties file, and this will be available on application startup.

Related

What causes this dependabot issue?

I am following this : https://bobbybouwmann.nl/blog/dependabot-on-gitlab, to attempt to get Dependabot working with gitlab. I get the following error?
Using docker image sha256:bc6c0ffef6650bcfbb0afd5a07b813b5ccf1d00ecddccadb85123c6ee57a7995 for docker with digest docker#sha256:63107bd6ce718f130bb2668704239467b74f034c446f9e9c4ae1ffa5ddf4e3dd ...
$ docker build -t "dependabot/dependabot-script" -f Dockerfile .
error during connect: Post "http://docker:2375/v1.24/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&rm=1&shmsize=0&t=dependabot%2Fdependabot-script&target=&ulimits=null&version=1": dial tcp: lookup docker on 172.31.0.2:53: no such host
So I checked, and the specified docker image does not exist: https://hub.docker.com/u/dependabot
but, if I use a different, publicly available image, I get this:
Executing "step_script" stage of the job script
00:03
Using docker image sha256:ed97757f85d791b7e0a967622f0d671b810d1ad45aef30d5314dcaef94e7c457 for sethjones/dependabot-script with digest sethjones/dependabot-script#sha256:209a0952bfeb845f67f2eeb9a647c25e058bbae1b9b0e343d7891884840f17e0 ...
/usr/local/lib/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require': cannot load such file -- dependabot/file_fetchers (LoadError)
from /usr/local/lib/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
from ./generic-update-script.rb:4:in `<main>'
Cleaning up file based variables
00:01
ERROR: Job failed: exit code 1
I'd recommend that you check out the Dependabot GitLab repository. They provide a CI/CD template that is kept up-to-date, so instead of having to write your own jobs you can include their template using:
include:
- project: 'dependabot-gitlab/dependabot-standalone'
file: '.gitlab-ci.yml'
They also provide instructions on their page for how to configure it to automatically create MRs.

How do I get Java testcontainers to work in Docker Multistage builds?

I have a problem similar to Run (Docker) Test Container in gitlab with Maven. The difference is that rather than my script running mvn directly it runs a docker multistage build that runs the test inside of the docker image. Unfortunately this doesn't appear to work for the PostgreSQL Test Container.
Dockerfile
#############
### build ###
#############
# base image
FROM maven:3-jdk-11 as build
# set working directory
WORKDIR /app
# add app
COPY . .
RUN export MAVEN_OPTS="-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true" && export MAVEN_CLI_OPTS="-B -U --batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
RUN mvn $MAVEN_CLI_OPTS clean install
############
### prod ###
############
# Yea this isn't right, but it crashes before it gets to this point. This is for example purposes only.
FROM openjdk:15-jdk-alpine
COPY --from=build /app/reproducer-testcontainer/target/reproducer-testcontainer.jar /reproducer-testcontainer.jar
CMD java -jar reproducer-testcontainer.jar
When I run mvn clean install it works properly and runs my test using the PostgreSQL Test Container. However, when I run docker build . it fails at the mvn clean install step with the below stack trace.
Stack trace:
13:05:01.250 [main] ERROR org.testcontainers.dockerclient.EnvironmentAndSystemPropertyClientProviderStrategy - ping failed with configuration Environment variables, system properties and defaults. Resolved:
dockerHost=unix:///var/run/docker.sock
apiVersion='{UNKNOWN_VERSION}'
registryUrl='https://index.docker.io/v1/'
registryUsername='root'
registryPassword='null'
registryEmail='null'
dockerConfig='DefaultDockerClientConfig[dockerHost=unix:///var/run/docker.sock,registryUsername=root,registryPassword=<null>,registryEmail=<null>,registryUrl=https://index.docker.io/v1/,dockerConfigPath=/root/.docker,sslConfig=<null>,apiVersion={UNKNOWN_VERSION},dockerConfig=<null>]'
due to org.rnorth.ducttape.TimeoutException: Timeout waiting for result with exception
org.rnorth.ducttape.TimeoutException: Timeout waiting for result with exception
at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:51)
<snip>
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: java.io.IOException: com.sun.jna.LastErrorException: [2] No such file or directory
at org.testcontainers.shaded.org.scalasbt.ipcsocket.UnixDomainSocket.<init>(UnixDomainSocket.java:62)
<snip>
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: com.sun.jna.LastErrorException: [2] No such file or directory
at org.testcontainers.shaded.org.scalasbt.ipcsocket.UnixDomainSocketLibrary.connect(Native Method)
at org.testcontainers.shaded.org.scalasbt.ipcsocket.UnixDomainSocket.<init>(UnixDomainSocket.java:57)
... 35 common frames omitted
In my CI pipeline I'd like to only run docker build . and not worry about having another stage that does the mvn clean install.
How do I fix the configuration to get the java PostgreSQL Testcontainers to work inside of a Docker build so that I can use it in a multi-stage build?
Full Code example: https://gitlab.com/raymondcg/reproducer-testcontainer
Not really Testcontainers related.
Testcontainers requires a valid Docker daemon. When you build images, there is no daemon mounted into the image build context.
You can easily verify that by doing:
RUN curl --unix-socket /var/run/docker.sock http:/_/_ping
Make this command return "OK" (no need to run the Testcontainers code), and your tests will pass as well.
You can overwrite testcontainers default docker host by adding:
ENV DOCKER_HOST=tcp://host.docker.internal:2375
to your build stage.

How to externally provide mysql host to spring boot while executing JAR

I have a java Spring boot project which uses a MySQL database. I have the following application.properties file to specify the MySQL url, user and password:
spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}
spring.datasource.username=${MYSQL_USER}
spring.datasource.password=${MYSQL_PASSWORD}
Using this property file, I can run the application from Eclipse if I edit the run configurations and set the values of DB_HOST, DB_PORT, DB_NAME, MYSQL_USER and MYSQL_PASSWORD in the Environment tab and run it.. everything works fine.
But now I want to run it on the server, by generating a JAR and passing these values from command line to the Jar during run time. So, I created a Jar file like this:
/gradlew clean build bootJar -DDB_HOST=mock -DDB_PORT=mock -DDB_NAME=mock \
-Dmysql_user=mock \
-Dmysql_password=mock
this successfully generates the executable Jar file.. then I try to run the generated jar file like this:
java -jar build/libs/MyApplication.jar -Ddb_host=localhost \
-Ddb_port=3306 \
-Ddb_name=my_db \
-Dmysql_user=root \
-Dmysql_password=root
but it gives the following error:
...
Failed to parse the host:port pair '${DB_HOST}:${DB_PORT}'
...
java.lang.NumberFormatException: For input string: "${DB_PORT}"
...
Which means that it is not actually replacing the values during runtime.
How do I fix this?
Edit: I also tried to open up the jar using archive utility and saw the application.properties file.. it contains the following line:
spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}
which means that these values should have been updated during runtime. but it isn't
I was eventually able to get this to work by adding a DatasourceConfig class and setting the values programatically.
I removed all the spring.datasource.* values from my application.property file and then created a new class:
#Configuration
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class DatasourceConfig {
#Bean
#Primary
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(System.getProperty("MYSQL_URL"));
dataSource.setUsername(System.getProperty("MYSQL_USER"));
dataSource.setPassword(System.getProperty("MYSQL_PASSWORD"));
return dataSource;
}
}
This allows you to configure the datasource, username and password externally as VM arguments at runtime.
The values MYSQL_URL,MYSQL_USER,MYSQL_PASSWORD are passed onto the gradle command while building like this:
./gradlew clean build bootJar -DMYSQL_URL=mock -DMYSQL_USER=mock -DMYSQL_PASSWORD=mock
, and similarly to the java command while running the jar like this:
java -jar build/libs/MyApplication.jar -DMYSQL_URL=jdbc:mysql://localhost:3306/my_db -DMYSQL_USER=root -DMYSQL_PASSWORD=root
You just need to expose those Fields as Environment Variables before running the jar.
For Linux:
$ export DB_HOST=localhost
$ export DB_PORT=3306
$ export DB_NAME=my_db
$ export MYSQL_USER=root
$ export MYSQL_PASSWORD=root
$ java -jar build/libs/MyApplication.jar

Java/jmeter http request fails but curl works

I am trying a very basic http request with jmeter, but it seems to always get the error below. I have tried a simple get against google which is fine but the internal servers are not :
java.net.NoRouteToHostException: No route to host (Host unreachable)
I can curl the same url successfully with a 200 response, so not sure if its jmeter or java? The only thing that is unique is that our internal servers are resolving with ipv6, but I would not think that would be the problem?
Try adding the next line to system.properties file (lives in "bin" folder of your JMeter installation)
java.net.preferIPv6Addresses=true
Or pass the aforementioned property via -D command-line argument like:
jmeter -Djava.net.preferIPv6Addresses=true -n -t test.jmx -l result.jtl
References:
Java: Networking Properties
Configuring JMeter
Apache JMeter Properties Customization Guide
Overriding Properties Via The Command Line

What is "$ play test" dropdown in circleCI?

Im trying to upload my project to circleci but from some reason it fails in a dropdown called "$ play test", I have no idea what is it, and I dont have tests in my project at all.
this is the section im talking about:
and im getting error there, this is the error:
I deleted "- sbt test" from my circle.yml so its not that, and I saw another folder of test in play so I thought maybe its that, but its empty, so I created a file in it and put nothing in it and still getting the same error...its driving me crazy ://///
please helpppppp
if you need this is my circle.yml:
machine:
services:
- docker
java:
version: oraclejdk8
environment:
SBT_VERSION: 0.13.9
SBT_OPTS: "-Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M"
dependencies:
cache_directories:
- "~/.sbt"
- "~/.ivy2"
- "~/.m2"
- "~/docker"
pre:
- wget --output-document=$HOME/bin/sbt-launch.jar https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/"$SBT_VERSION"/sbt-launch.jar
- echo "java $SBT_OPTS -jar \`dirname \$0\`/sbt-launch.jar \"\$#\"" > $HOME/bin/sbt
- chmod u+x $HOME/bin/sbt
- sbt sbt-version
override:
- sbt clean update
post:
- find . -type f -regex ".*/target/test-reports/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/ \;
general:
artifacts:
- "target/universal/*.tgz"
deployment:
feature:
branch: /.*/
commands:
- docker login -e admin#something.com -u ${ART_USER} -p ${ART_KEY} docker-local.artifactoryonline.com
- sbt -DBUILD_NUMBER="${CIRCLE_BUILD_NUM}" docker:publish
CircleCI has a feature called Inference that looks at what language your project is in as well as directories found, file extensions, etc to guess what dependencies and test you have.
If you look to the right of where you saw "play test" you'll see that it says "inference" which means this test was a result of Interference and not circle.yml. Inference made an assumption you needed the Play test framework (https://www.playframework.com/) and thus ran a default check, play test (the $ is part of the prompt).
If this is not what you want, which looks to be the case, you'll need to override the test command to instead run whatever test you want. This would be something like:
test:
override:
- echo "This is my test"
- ./my-custom-command
More information: https://circleci.com/docs/configuration/#test

Categories

Resources