Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e66450e
try code coverage script
Sep 30, 2025
1810d6f
move upterm job higher
Sep 30, 2025
8719956
move upterm job in always condition
Sep 30, 2025
554a451
remove early upterm job
Sep 30, 2025
94874d8
instead of killing pod scale down deployment
Sep 30, 2025
07857e1
wait for pod killed, not deployment status
Sep 30, 2025
017b64b
provide the COVERAGE_HOST_PATH to the test.sh script
Sep 30, 2025
d2b81f8
TEMP DEBUG
Sep 30, 2025
9080de7
add a try to jq
Sep 30, 2025
486403f
explicit set path
Sep 30, 2025
c304321
retur to using COVERAGE_HOST_PATH; add podSecurityContext
Oct 1, 2025
2366d01
try sending sigquit signal
Oct 1, 2025
334914e
dont kill the agent
Oct 1, 2025
d4b7b1c
add shareProcessNamespace=true to the agent
Oct 1, 2025
e303a34
fixx err no flag
Oct 1, 2025
964f548
remove shareProcessNamespace
Oct 2, 2025
8c1012a
remove revert to original test.sh; create new test_ci.sh; add mounts …
Oct 2, 2025
e6fc461
try back the GKE script
Oct 3, 2025
81ab929
change the make target
Oct 3, 2025
8cbb396
start ci run
Oct 3, 2025
3acfd9f
try func to pull files
Oct 3, 2025
018d7dd
change the port to avoid clash with healthz
Oct 3, 2025
87f4a1f
uncondintional build of coverage server
Oct 3, 2025
76a7b99
jsonify logging
Oct 3, 2025
4d90fa8
remove initial logging
Oct 3, 2025
e38f94c
refactored script ver
Oct 3, 2025
a39f7de
add intermediate buffer
Oct 3, 2025
645ce63
set the covermode to atomic
Oct 3, 2025
49335c6
add intermediate buffer to meta file download
Oct 3, 2025
6572f1e
try an older version of script after resolving -covermode problem
Oct 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ jobs:

- run: make -j test-unit test-helm

- name: Upload test artifacts
uses: actions/upload-artifact@v4
with:
name: unit-artifacts
path: _bin/artifacts

test-e2e:
if: contains(github.event.pull_request.labels.*.name, 'test-e2e')
runs-on: ubuntu-latest
Expand Down Expand Up @@ -136,3 +142,16 @@ jobs:
--project=machineidentitysecurity-jsci-e \
--zone=europe-west1-b \
--quiet

# TODO: REMOVE THIS DEBUGGING!
- name: Setup upterm session
if: always()
uses: owenthereal/action-upterm@v1
with:
limit-access-to-actor: true

- name: Upload test artifacts
uses: actions/upload-artifact@v4
with:
name: e2e-artifacts
path: _bin/artifacts
70 changes: 70 additions & 0 deletions coverage_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package main

import (
"bytes"
"log"
"net/http"
"runtime/coverage"
)

func startCoverageServer() {
adminMux := http.NewServeMux()

adminMux.HandleFunc("/_debug/coverage/download", func(w http.ResponseWriter, r *http.Request) {
var buffer bytes.Buffer

// Attempt to write the coverage counters to the buffer.
if err := coverage.WriteCounters(&buffer); err != nil {
log.Printf("Error writing coverage counters to buffer: %v", err)
// Inform the client that an internal error occurred.
http.Error(w, "Failed to generate coverage report", http.StatusInternalServerError)
return
}

// Check if any data was written to the buffer.
if buffer.Len() == 0 {
log.Println("Coverage data is empty. No counters were written.")
} else {
log.Printf("Successfully wrote %d bytes of coverage data to the buffer.", buffer.Len())
}

// If successful, proceed to write the buffer's content to the actual HTTP response.
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", `attachment; filename="coverage.out"`)

// Write the captured coverage data from the buffer to the response writer.
if _, err := w.Write(buffer.Bytes()); err != nil {
log.Printf("Error writing coverage data from buffer to response: %v", err)
}
})

adminMux.HandleFunc("/_debug/coverage/meta/download", func(w http.ResponseWriter, r *http.Request) {
log.Println("Received request to download coverage metadata...")

var buffer bytes.Buffer
if err := coverage.WriteMeta(&buffer); err != nil {
log.Printf("Error writing coverage meta to buffer: %v", err)
// Inform the client that an internal error occurred.
http.Error(w, "Failed to generate coverage meta", http.StatusInternalServerError)
return
}
// Check if any data was written to the buffer.
if buffer.Len() == 0 {
log.Println("Coverage meta is empty.")
} else {
log.Printf("Successfully wrote %d bytes of coverage meta to the buffer.", buffer.Len())
}

w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", `attachment; filename="coverage.meta"`)
if _, err := w.Write(buffer.Bytes()); err != nil {
log.Printf("Error writing coverage meta from buffer to response: %v", err)
}
})

go func() {
if err := http.ListenAndServe("localhost:8089", adminMux); err != nil {
log.Printf("Admin server failed: %v", err)
}
}()
}
69 changes: 69 additions & 0 deletions hack/e2e/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ if ! gcloud container clusters get-credentials "${CLUSTER_NAME}"; then
fi
kubectl create ns venafi || true

kubectl apply -n venafi -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: coverage-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
EOF

# Pull secret for Venafi OCI registry
# IMPORTANT: we pick the first team as the owning team for the registry and
# workload identity service account as it doesn't matter.
Expand Down Expand Up @@ -127,6 +140,8 @@ venctl components kubernetes apply \
--venafi-kubernetes-agent-custom-chart-repository "oci://${OCI_BASE}/charts"

kubectl apply -n venafi -f venafi-components.yaml
kubectl set env deployments/venafi-kubernetes-agent -n venafi GOCOVERDIR=/coverage
kubectl rollout status deployment/venafi-kubernetes-agent -n venafi --timeout=2m

subject="system:serviceaccount:venafi:venafi-components"
audience="https://${VEN_API_HOST}"
Expand Down Expand Up @@ -233,3 +248,57 @@ getCertificate() {

# Wait 5 minutes for the certificate to appear.
for ((i=0;;i++)); do if getCertificate; then exit 0; fi; sleep 30; done | timeout -v -- 5m cat

export AGENT_POD_NAME=$(kubectl get pods -n venafi -l app.kubernetes.io/name=venafi-kubernetes-agent -o jsonpath="{.items[0].metadata.name}")

echo "Sending SIGQUIT to agent pod '${AGENT_POD_NAME}' to trigger graceful shutdown and flush coverage..."
# Use kubectl debug to attach a busybox container to the running pod.
# --target specifies the container to share the process space with.
# --share-processes allows our new container to see and signal the agent process.
# We then run 'kill -s QUIT 1' to signal PID 1 (the agent) to quit gracefully.
kubectl debug -q -n venafi "${AGENT_POD_NAME}" \
--image=busybox:1.36 \
--target=venafi-kubernetes-agent \
--share-processes \
-- sh -c 'kill -s QUIT 1'

echo "Waiting for agent pod '${AGENT_POD_NAME}' to terminate gracefully..."
# The pod will now terminate because its main process is exiting.
# We wait for Kubernetes to recognize this and delete the pod object.
kubectl wait --for=delete pod/${AGENT_POD_NAME} -n venafi --timeout=90s

echo "Scaling down deployment to prevent pod from restarting..."
# Now that the pod is gone and coverage is flushed, we scale the deployment
# to ensure the ReplicaSet controller doesn't create a new one.
kubectl scale deployment venafi-kubernetes-agent -n venafi --replicas=0
echo "Waiting for agent pod '${AGENT_POD_NAME}' to terminate as a result of the scale-down..."
kubectl wait --for=delete pod/${AGENT_POD_NAME} -n venafi --timeout=90s
echo "Starting helper pod to retrieve coverage files from the PVC..."

kubectl apply -n venafi -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: coverage-helper-pod
spec:
containers:
- name: helper
image: alpine:latest
command: ["sleep", "infinity"]
volumeMounts:
- name: coverage-storage
mountPath: /coverage-data
volumes:
- name: coverage-storage
persistentVolumeClaim:
claimName: coverage-pvc
EOF

echo "Waiting for the helper pod to be ready..."
kubectl wait --for=condition=Ready pod/coverage-helper-pod -n venafi --timeout=2m

echo "Copying coverage files from the helper pod..."
mkdir -p $COVERAGE_HOST_PATH
kubectl cp -n venafi "coverage-helper-pod:/coverage-data/." $COVERAGE_HOST_PATH
echo "Coverage files retrieved. Listing contents:"
ls -la $COVERAGE_HOST_PATH
Loading
Loading