Skip to content

Commit

Permalink
Add Java e2e tests (#16)
Browse files Browse the repository at this point in the history
* Add Java e2e tests

* Test with a longer sleep time

* Update Java Dockerfile to use a shell script for downloading the agent.

* Revert back to lower sleep time

* Java is slow
  • Loading branch information
jasonjkeller authored Jun 2, 2024
1 parent 23d18bf commit 148ee50
Show file tree
Hide file tree
Showing 11 changed files with 344 additions and 4 deletions.
166 changes: 166 additions & 0 deletions .github/workflows/java.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Copyright 2024 New Relic, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
---
name: Java Agent CI

on:
workflow_dispatch: # run test job only
pull_request: # run check modified files / test jobs
release: # run check modified files / test / publish jobs
types:
- published

# only allow one instance of this workflow to be running per PR or branch, cancels any that are already running
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

env:
K8S_OPERATOR_IMAGE_TAG: edge

permissions:
contents: read

jobs:
check-modified-files:
name: Check whether any Java-related files were modified, skip the test job if not
uses: ./.github/workflows/check-modified-files.yml
secrets: inherit
permissions:
contents: read
with:
agent-language: java

test:
name: Run Java init container tests
runs-on: ubuntu-latest
needs: check-modified-files
# run only if files were modified or the workflow was manually invoked
if: needs.check-modified-files.outputs.files-changed == 'true' || github.event_name == 'workflow_dispatch'

steps:
# For some reason, Harden Runner causes setup-minikube to not work correctly
# - name: Harden Runner
# uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
# with:
# #disable-sudo: true
# egress-policy: audit

- name: Checkout code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1
with:
persist-credentials: false
fetch-depth: 0

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # 3.3.0

- name: Start minikube
uses: medyagh/setup-minikube@317d92317e473a10540357f1f4b2878b80ee7b95 # 0.0.16

- name: Deploy cert-manager to minikube
run: |
helm repo add jetstack https://charts.jetstack.io --force-update
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.14.5 --set installCRDs=true
echo "waiting for cert-manager pods to be ready..."
sleep 5
kubectl wait --for=condition=Ready -n cert-manager --all pods --timeout=60s
- name: Deploy New Relic k8s-agents-operator to minikube
run: |
helm repo add k8s-agents-operator https://newrelic.github.io/k8s-agents-operator
helm upgrade --install k8s-agents-operator k8s-agents-operator/k8s-agents-operator \
--namespace=default \
--set=licenseKey=${{ secrets.NEW_RELIC_LICENSE_KEY }} \
--set=controllerManager.manager.image.tag=${{ env.K8S_OPERATOR_IMAGE_TAG }}
sleep 5
kubectl wait --for=condition=Ready -n default --all pods --timeout=60s
- name: Build init container for e2e test
# When the init container image is built without specifying the agent version via a build arg, the current agent version published to download.newrelic.com will be used.
run: |
minikube image build -t e2e/newrelic-java-init:e2e src/java/
- name: Build test app container
run: |
minikube image build -t e2e/test-app-java:e2e tests/java/
- name: Run e2e-test
uses: newrelic/newrelic-integration-e2e-action@a97ced80a4841c8c6261d1f9dca6706b1d89acb1 # 1.11.0
with:
retry_seconds: 60
retry_attempts: 5
agent_enabled: false
spec_path: tests/java/test-specs.yml
account_id: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
api_key: ${{ secrets.NEW_RELIC_API_KEY }}
license_key: ${{ secrets.NEW_RELIC_LICENSE_KEY }}
# set the region to Staging if using a staging license key. Also set NEW_RELIC_HOST in tests/chart/templates/deployment.yaml
#region: Staging

publish:
runs-on: ubuntu-latest
needs: test
# only publish on a java release
if: (github.event_name == 'release' && endsWith(github.ref, '_java'))

steps:
- name: Harden Runner
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
disable-sudo: true
egress-policy: audit

- name: Extract Agent Version from release tag
id: version
run: |
agent_version=${{ github.ref_name }} # Use tag name
agent_version=${agent_version##v} # Remove v prefix
agent_version=${agent_version%%_java} # Remove language suffix
echo "agent_version=${agent_version}" | tee -a "$GITHUB_OUTPUT"
- name: Checkout code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # 4.1.1
with:
persist-credentials: false
fetch-depth: 0

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # 3.3.0

- name: Generate Docker metadata (tags and labels)
id: meta
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # 5.5.1
with:
images: newrelic/newrelic-java-init
tags: |
type=raw,value=${{ steps.version.outputs.agent_version }}
type=raw,value=latest
- name: Login to Docker Hub Container Registry
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # 3.1.0
with:
username: ${{ github.repository_owner }}
password: ${{ secrets.DOCKER_TOKEN }}

- name: Build and publish Java Agent init container image
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # 5.3.0
with:
push: true
context: src/java/
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@

# VS Code
**/.vscode/

# IntelliJ IDEA
.idea/

*.DS_Store
17 changes: 13 additions & 4 deletions src/java/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
# To build one auto-instrumentation image for Java, please:
# - Download the newrelic `newrelic-agent-$version.jar` to `/newrelic-agent.jar`. This is required as when instrumenting the pod,
# one init container will be created to copy the jar to your app's container.
# - Grant the necessary access to the jar. `chmod -R go+r //newrelic-agent.jar`
# - Download the newrelic java agent jar file to `/newrelic-agent.jar` using the java-agent-download.sh.
# This is required as when instrumenting the pod, one init container will be created to copy the jar to your app's container.
# - Grant the necessary access to the jar. `chmod -R go+r /newrelic-agent.jar`
FROM busybox
ARG version
ADD https://download.newrelic.com/newrelic/java-agent/newrelic-agent/$version/newrelic-agent-$version.jar /newrelic-agent.jar

# Copy shell script to image
COPY java-agent-download.sh /
# Set executable permissions on shell script
RUN chmod +x /java-agent-download.sh
# Execute shell script to download agent, passing the version build arg to it
RUN /java-agent-download.sh $version
# Remove script from image when it's no longer needed
RUN rm /java-agent-download.sh
# Set executable permissions on Java agent jar file
RUN chmod -R go+r /newrelic-agent.jar
22 changes: 22 additions & 0 deletions src/java/java-agent-download.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh
:'Shell script to download the New Relic Java agent.
This script takes an optional agent `version` argument (e.g. java-agent-download.sh 8.12.0).
If no input argument is provided, then the current Java agent version will be downloaded,
otherwise the agent version specified by the input argument will be downloaded.'

# If the input arg is empty...
if [ -z "$1" ]
then
# Download current Java agent version if no argument is provided
wget https://download.newrelic.com/newrelic/java-agent/newrelic-agent/current/newrelic-agent.jar
else
# Download the Java agent version specified by the provided input argument
wget https://download.newrelic.com/newrelic/java-agent/newrelic-agent/$1/newrelic-agent-$1.jar
fi

# If the Java agent jar file exists...
if [ -e newrelic*.jar ]
then
# Rename the Java agent jar file to newrelic-agent.jar
mv newrelic*.jar newrelic-agent.jar
fi
29 changes: 29 additions & 0 deletions tests/java/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# BUILD STAGE
FROM eclipse-temurin:17-jdk-jammy as build

# Install git
RUN apt update
RUN apt install -y git

# Clone and build SpringBoot PetClinic Java service
RUN git clone https://github.com/spring-projects/spring-petclinic
# Checkout a specific commit to pin the PetClinic service to a known working version. Comment this out to get latest version.
RUN cd ./spring-petclinic && git checkout 923e2b7aa331b8194a6579da99fb6388f15d7f3e
# Build SpringBoot PetClinic Java service
RUN cd ./spring-petclinic && ./mvnw -Dmaven.test.skip=true clean package

# PRODUCTION STAGE
FROM eclipse-temurin:17-jre-jammy as production

# Create work directory
WORKDIR /petclinic-app

# Copy PetClinic jar from build stage to work directory
COPY --from=build /spring-petclinic/target/spring-petclinic*.jar .

# SpringBoot listens on port 8080 by default
# To change it set the -Dserver.port=8083 system propery in the following CMD step
# Alternatively, change the SERVER_PORT and port mapping in docker-compose.yml
EXPOSE 8080

CMD java -jar spring-petclinic*.jar
23 changes: 23 additions & 0 deletions tests/java/chart/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
6 changes: 6 additions & 0 deletions tests/java/chart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: test-app-java
description: A Helm chart for Kubernetes
type: application
version: 1.0.0
appVersion: "1.0.0"
53 changes: 53 additions & 0 deletions tests/java/chart/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-app-java
spec:
selector:
matchLabels:
app: test-app-java
replicas: 1
template:
metadata:
labels:
app: test-app-java
annotations:
instrumentation.newrelic.com/inject-java: "true"
spec:
containers:
- name: test-app-java
image: e2e/test-app-java:e2e
imagePullPolicy: Never
ports:
- containerPort: 8080
env:
- name: NEW_RELIC_APP_NAME
value: k8s-e2e-test-app-java
- name: NEW_RELIC_LABELS # labels used by the e2e Github action
value: "testKey:{{ .Values.scenarioTag | default "NOTSET" }}"
- name: NEW_RELIC_SYNC_STARTUP
value: "true"
- name: NEW_RELIC_SEND_DATA_ON_EXIT
value: "true"
- name: NEW_RELIC_SEND_DATA_ON_EXIT_THRESHOLD
value: "0"
# for testing, comment out if not needed
#- name: NEW_RELIC_LOG_LEVEL
# value: finest
# set the host to staging if using a staging license key
#- name: NEW_RELIC_HOST
# value: staging-collector.newrelic.com

---
apiVersion: v1
kind: Service
metadata:
name: test-app-java-service
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
selector:
app: test-app-java
11 changes: 11 additions & 0 deletions tests/java/chart/templates/instrumentation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
apiVersion: newrelic.com/v1alpha1
kind: Instrumentation
metadata:
labels:
app.kubernetes.io/name: instrumentation
app.kubernetes.io/created-by: newrelic-agent-operator
name: newrelic-instrumentation
spec:
java:
image: e2e/newrelic-java-init:e2e
1 change: 1 addition & 0 deletions tests/java/chart/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
scenarioTag: ""
15 changes: 15 additions & 0 deletions tests/java/test-specs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
description: End-to-end tests for java initcontainer
custom_test_key: tags.testKey
scenarios:
- description: This scenario will verify that a transaction is reported by the test app after a curl request
before:
- helm install test-java ./chart/ --set=scenarioTag="${SCENARIO_TAG}" -n default
- sleep 120
- kubectl wait --for=condition=Ready -n default --all pods
- curl --fail-with-body $(minikube service test-app-java-service --url -n default)
tests:
nrqls:
- query: SELECT latest(duration) AS duration FROM Transaction WHERE appName = 'k8s-e2e-test-app-java'
expected_results:
- key: "duration"
lowerBoundedValue: 0.0

0 comments on commit 148ee50

Please sign in to comment.