fabric8: how does helm goal work? - fabric8

We're using fabric8 maven plugin in order to build and deploy our maven projects into kubernetes.
I don't quite figure out how to use fabric8:helm goal.
I've tried to get some details about what exactly it makes, but I don't quite get it:
$ mvn help:describe -Dgoal=helm -DgroupId=io.fabric8 -DartifactId=fabric8-maven-plugin -Ddetail
And this is the output:
fabric8:helm
Description: Generates a Helm chart for the kubernetes resources
Implementation: io.fabric8.maven.plugin.mojo.build.HelmMojo
Language: java
Bound to phase: pre-integration-test
Available parameters:
helm
(no description available)
kubernetesManifest (Default:
${basedir}/target/classes/META-INF/fabric8/kubernetes.yml)
User property: fabric8.kubernetesManifest
The generated kubernetes YAML file
kubernetesTemplate (Default:
${basedir}/target/classes/META-INF/fabric8/k8s-template.yml)
User property: fabric8.kubernetesTemplate
The generated kubernetes YAML file
skip (Default: false)
User property: fabric8.skip
(no description available)
...
Inside our projects we have out artifacts inside src/main/fabric8. The content of this folder is:
tree src/main/fabric8
src/main/fabric8
├── forum-configmap.yaml
├── forum-deployment.yaml
├── forum-route.yaml
└── forum-service.yaml
These are files only related with kubernetes.
I've not been able to find any snippet over there about:
Which kind of files do I need to add on my project? helm files?
Which is exactly the output of this goal?

Just to play around with this I grabbed a basic spring boot project with Web dependency and a RestController created with the spring initializr. The fabric8 plugin docs say to run the resource goal first so I went to the base directory of my project and ran mvn -B io.fabric8:fabric8-maven-plugin:3.5.41:resource. That generated kubernetes descriptors for my project under /target/classes/META-INF/fabric8/.
So then I ran mvn -B io.fabric8:fabric8-maven-plugin:3.5.41:resource io.fabric8:fabric8-maven-plugin:3.5.41:helm. At first I got an error that:
target/classes/META-INF/fabric8/k8s-template does not exist so cannot make chart <project_name>. Probably you need run 'mvn fabric8:resource' before.
But the descriptors did exist under /target/classes/META-INF/fabric8/kubernetes/ so I just renamed that directory to k8s-template and ran again. Then it created a helm chart for me in the /target/fabric8/helm/kubernetes/ directory.
So I followed the the docs literally and then ran helm install target/fabric8/helm/kubernetes/. That complained there was no Chart.yaml. I realised then that I had followed the doc too literally and needed to run helm install target/fabric8/helm/kubernetes/<project_name>. That did indeed create a helm release and install my project to kubernetes. It didn't start as I hadn't created any docker image. It seems to default to an image name of <groupId>/<artifactId>:<version/snapshot-number>. Presumably that would've been there if I'd also run the 'build' goal and push goals and had a docker registry accessible to my kubernetes.
So in short the helm goal generates a basic helm chart. I believe you'd need to customise this chart manually if you have an app that needs to access shared resources with urls or credentials being injected (e.g. for a database or message broker or authentication system) or if your app exposes multiple ports or if you need initContainers or custom startup parameters. Presumably you are trying to customize these generated resources and are doing so by putting files in your /src/fabric8/. If it's the k8s files that you're trying to feed through then I guess they'd have to go in /src/fabric8/kubernetes/ in order to feed through into the expected /target/ directory and also be named <project-name>-deployment.yml and <project-name>-svc.yml.
I guess the generated chart is at least a starting-point and presumably the experience can be a bit smoother than my experimenting was if you add all the plugin to the pom and do all the setup rather than running individual goals.

Related

Deploying mvn with multiple executibles on Cloud Run

I have a maven project structured:
/root
/CommonProject
/executable1
/executable2
/subroot
/subrootCommon
/...
So far I am trying to just deploy executable1.
I wanted to the project to use Java 19, I am fine with Java 17 if it's easier.
When I activate cloud shell, I am able to:
Change $JAVA_HOME to jdk 17
clone project
maven package it
run it in cloud shell.
However my project has no mapping for "/", just specific endpoints like "/test/hello" and I do not see anything in WebPreview on port 8080.
I have tried different ways to deploy, I am not familiar enough with Docker, so I tried CloudRun with Cloud Build with trigger from Source.
Here lies my current problem - every build has failed so far. It is using jdk 11 which is a problem (or at least one of them).
I have tried also adding cloudbuild.yaml or local Dockerfile just to deploy jar built manually, but I am still failing.
+FROM openjdk:17
+COPY root/target/executable1-1.0-SNAPSHOT-jar-with-dependencies.jar /home/user/var/run/executable1.jar
+CMD ["java", "-jar", "/home/user/var/run/executable1.jar"]
I have done the same steps to deploy, which were shown in how-to-guides or available online labs, so I think the issue is with the fact that maybe buildpacks do not process correctly projects with dependencies?
executable1 and executable2 depend on CommonProject. Do I need to split my big maven project into separate projects, to build each of them individually?
I have tried Dockerfile, cloudbuild.yaml, something like project.toml.
I would like to deploy for now just 1 project, at one point in the future all executable projects from this maven.

java/spring-boot/gradle Wrong Entrypoint in image built with pack and paketobuildpacks/builder:base

I have a really simple java spring-boot gradle application.
When I build an image from source with:
pack build testapp:0.0.1 --builder paketobuildpacks/builder:base
and try to run it with docker I get the following error:
ERROR: failed to launch: determine start command: when there is no default process a command is required.
The generated Entrypoint in this image is "/cnb/lifecycle/launcher".
When I inspect the image with pack inspect-image there are no processes.
I tried this with different java spring-boot gradle applications. When I use the "bootBuildImage" gradle task, it does nearly the same but uses the pre-build .jar-file and the resulting image works. The generated Entrypoint in this image is "/cnb/process/web" and pack inspect-image shows three processes.
Any ideas?
I can't see your build output, but it sounds like you're hitting a known issue. If this is not your problem, please include the full output of running pack build.
Onto the issue. By default, Spring Boot Gradle projects will build both an executable and non-executable JAR. Because this produces two JAR files, it presently confuses the buildpacks.
There are a couple of solutions:
Tell Gradle to not build the non-executable JAR. The buildpack requires the executable JAR. You can do this by adding the following to your build.gradle file:
jar {
enabled = false
}
This is the solution we have used in the Paketo buildpack samples.
If you don't want to make the change suggested in #1, then you can add the following argument to pack build: -e BP_GRADLE_BUILT_ARTIFACT=build/libs/<your-jar>.jar. For ex: -e BP_GRADLE_BUILT_ARTIFACT=build/libs/demo-0.0.1-SNAPSHOT.jar. You can use glob-style pattern matching here, but you need to make sure that what you enter does not match *-plain.jar. That will be the non-executable JAR that gets built by default.
This option just simply tells the Gradle buildpack more specifically what the JAR file to pass along to subsequent buildpacks.
We also have an open issue that should help to mitigate this problem. When the executable-jar buildpack gains support for multiple JARs, it'll be less likely that you'll need to set this. Essentially, this fill will add support so the executable-jar buildpack can inspect and detect an executable JAR, which would allow it to throw out the -plain.jar file since it's not executable.

Dockerfile to create image of spring boot

I want to create Docker image for a spring boot application.It uses gardle as build tool.
In bitbucket repository i could see below files are placed
--> src
--> build.gradle
--> Dockerfile
--> gradlew
--> gradlew.bat
Now Dockerfile has below content
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=target/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
EXPOSE 8080
ENTRYPOINT ["java","-cp","app:app/lib/*","eds.billnq"]
When i try to create image using Dockerfile i get error
target/dependency/BOOT-INF library not found
target/dependency/META-INF library not found
My query is why here there is no gradle build steps in docker file ?
Also where target/dependency/ will be created ?
why here there is no gradle build steps in docker file ?
It looks like the Dockerfile is expecting the application to have already been built (by Gradle) before the Docker image is built, and for the resulting class files and jars to be available in various directories under target/dependency.
The Spring Boot Docker guide referred to by #WonChul Heo in the comments goes into how to build a Docker image using Gradle and specifically with the plugin gradle.plugin.com.palantir.gradle.docker:gradle-docker.
Also where target/dependency/ will be created ?
I'm guessing they should be created when you run your Gradle build, but without knowing more about how the build is configured, it's hard to say for sure.
I suggest you read through the guide again and compare what it recommends to what you have in your codebase, especially the Gradle build definitions.
At the end of the day, if you've pulled code from a private code repo and can't figure out how to make it build, it's probably best to seek out advice from the people who've committed to the codebase than from SO.
When working With Gradle ur jar file is going to be generated inside build/libs/{Your jar}
Can you please change ARG DEPENDENCY=target/dependency to ARG DEPENDENCY=build/libs and try? It will work.

Modify a service inside GitLab CI

I'm attempting to set up GitLab CI and I have some integration tests that run against elasticsearch. I'd like to install elasticsearch using the official docker image, so:
services:
- elasticsearch:2.2.2
But I want the mapper-attachments plugin. I have had no luck adding a command in the before_script section to install the mapper-attachments plugin, because the elasticsearch files don't seem to be in the environment that the before_script section is running inside of. How can I modify the elasticsearch image that has been installed into the runner?
You should create you custom elasticsearch container.
You could adapt the following Dockerfile:
FROM elasticsearch:2.3
MAINTAINER Your Name <you#example.com>
RUN /usr/share/elasticsearch/bin/plugin install analysis-phonetic
You can find this image on Docker Hub.
Here are detailed steps:
Register at https://hub.docker.com and link you Github account with it
Create a new repo at Github, e.g. "elasticsearch-docker"
Create a Dockerfile which inherits FROM elasticsearch and installs your plugins (see this example)
Create an Automated build at Dockerhub form this github repo (in my case: https://hub.docker.com/r/tmaier/elasticsearch/)
Configure the Build Settings at Docker Hub
I added two tags. One "latest" and one matching the elasticsearch release I am using.
I also linked the elasticsearch repository, so that mine gets rebuilt when there is a new elasticsearch release
See that the Container gets built successfully by Docker Hub
Over at Gitlab CI, change the service to point to your new Docker image. In my example, I would use tmaier/elasticsearch:latest
See your integration tests passing

How to specify files to ignore when push to Cloud Foundry using cf-gradle-plugin

I am trying to deploy my static application to cloud foundry using cf-gradle-plugin.
in my gradle file I have defined buildpack:
buildpack = "https://github.com/cloudfoundry/staticfile-buildpack.git#v1.1.0"
and files to deploy:
file = file('.')
I would like to specify which files should be not pushed to the cf. I have tried to do it by specifying .cfignore file in the root directory, but it does not work. Does anybody know how to filter files which should be deployed to CF when using cf-gradle-plugin and staticfile buildpack?
There isn't a way to filter files with the v1 version of the Gradle plugin. As you probably saw from your issue on the project, supporting .cfignore should be supported in v2.
For now, you could use Gradle to package the contents of your project into a zip archive, using the sophisticated filtering rules that Gradle supports, then specify the zip file in the Cloud Foundry Gradle plugin.

Resources