OpenLiberty / ci.maven

Maven plugins for managing Liberty profile servers #devops
Apache License 2.0
130 stars 91 forks source link

Provide ability to generate Liberty config from POM properties without needing a Liberty install #1094

Open scottkurz opened 3 years ago

scottkurz commented 3 years ago

I can write a two-stage Docker build like this, which in stage 1, packages a WAR and generates Liberty config (bootstrap.properties, liberty-plugin-variable-config.xml, etc.) from the POM properties, and then in stage 2 takes the WAR binary and generated config and copies it on top of the Open Liberty base image to produce an app image.

# STAGE 1 - build WAR, gen
FROM adoptopenjdk/maven-openjdk11

RUN mkdir /work
COPY --chown=1001:0 ./src /work/src
COPY --chown=1001:0 ./pom.xml /work/pom.xml

RUN cd /work/ && \
    mvn liberty:create package

# STAGE 2
FROM openliberty/open-liberty:20.0.0.12-full-java11-openj9-ubi

# copy generated config from /work/target/liberty/wlp/usr/servers/defaultServer/

But I have to do a whole Open Liberty install just to cause the config generation function to run.

The config gen can be conveniently customized via profiles and CLI -Dx=y parameterization, but I may not have any need for the install (if I'm not going to run any tests in stage 1).

I could imagine this provided via:

  1. a new goal like: liberty:generate OR
  2. a parameter of the create goal, e.g. mvn -DskipInstall liberty:create
scottkurz commented 3 years ago

Another related idea would be the ability to use copyDependencies to get a dependency in place for a Docker build..but in a case in which you wanted to skip install of target/liberty/wlp/ itself.

E.g.: mvn -DskipInstall liberty:create package to copy deps into place and package a WAR, and you do a Docker build from there, without any need for the rest of target/liberty/wlp/.

pugmas commented 9 months ago

This is exactly what I was looking for.

Currently, we first create an empty directory "target/liberty/wlp/usr/servers/defaultServer" in our build job, so that "liberty:deploy " copies the dependencies for us to ../lib/global" without needing OL in "target/...".

We then copy these artifacts in the Dockerfile and thus separate dependencies from application.

Would there be anything against having "target/liberty/wlp/usr/servers/defaultServer" created by "liberty:deploy" if it does not exist and no user/installDirectory is configured?

scottkurz commented 9 months ago

Would there be anything against having "target/liberty/wlp/usr/servers/defaultServer" created by "liberty:deploy" if it does not exist and no user/installDirectory is configured?

I think one could imagine the liberty:deploy goal allowing this but at the moment it does not, and fails with an error.

This is exactly what I was looking for.

I'm curious if there are any downsides or "pain" you might be experiencing around this lack, or if you are simply surprised to find that nothing like this exists?

E.g. in the example I started with, a two-stage Docker build... the extra install is confined to the first stage, so it's not like it ends up increasing the size of the final image. The download and unzip of the kernel artifact seems pretty small/quick to me.

So to me the only downside was the time spent for the user to learn that they needed to use the "create" goal for this case.

I'm wondering then if you're experiencing the same or you have discovered another negative with your use case.

Appreciate your feedback..thanks !

pugmas commented 9 months ago

Our pipelines simply build the application with "mvn package" in an ibm-semeru-runtimes:open-17-jdk container. Only the requirement to store the growing number of dependencies separately led to the search for a suitable copy solution. I think I remembered "copyDependencies" from an OL blog post...

So in our case, only the complexity of the pom.xml increases slightly in order to create the required directory.

         <plugin>
              <groupId>io.openliberty.tools</groupId>
              <artifactId>liberty-maven-plugin</artifactId>
              <version>3.10</version>
              <executions>
                  <execution>
                      <id>copy-dependencies</id>
                      <phase>package</phase>
                      <goals>
                          <goal>deploy</goal>
                      </goals>
                      <configuration>
                          <copyDependencies>
                              <dependencyGroup>
                                  <location>lib/global/wtfs</location>
                                  <dependency>
                                      <groupId>way.too.fat.sdks</groupId>
                                      <artifactId>replace.me.by.mpRestClient</artifactId>
                                  </dependency>
                              </dependencyGroup>
                              ...
                      </configuration>
                  </execution>
              </executions>
          </plugin>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-antrun-plugin</artifactId>
              <version>3.1.0</version>
              <executions>
                  <execution>
                      <phase>generate-sources</phase>
                      <configuration>
                          <target>
                              <!-- Preparation for "liberty:deploy", which requires at least the "defaultServer" directory -->
                              <mkdir dir="target/liberty/wlp/usr/servers/defaultServer/lib/global"/>
                          </target>
                      </configuration>
                      <goals>
                          <goal>run</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>

I think your idea for "-DskipInstall" would also be a good fit for our purpose :)