From 8560943c805b933dff35974d3557d6155a6d3d06 Mon Sep 17 00:00:00 2001 From: Casper Thygesen Date: Thu, 1 Oct 2026 12:14:45 +0200 Subject: [PATCH 1/6] Add GitHub Actions workflow for plugin release Signed-off-by: Casper Thygesen --- .dockerignore | 11 ++ .github/workflows/release-plugin-oci.yaml | 121 ++++++++++++++++++++++ Dockerfile | 57 ++++++++++ 3 files changed, 189 insertions(+) create mode 100644 .dockerignore create mode 100644 .github/workflows/release-plugin-oci.yaml create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0333101 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +node_modules +.git +*.md +tests/ +coverage/ +.env +*.log +.github/ +.vscode/ +screenshots/ +img/ \ No newline at end of file diff --git a/.github/workflows/release-plugin-oci.yaml b/.github/workflows/release-plugin-oci.yaml new file mode 100644 index 0000000..0e70ba8 --- /dev/null +++ b/.github/workflows/release-plugin-oci.yaml @@ -0,0 +1,121 @@ +name: Build and publish plugin container image + +on: + # Automatic path: when release-please publishes a vX.Y.Z release, + # build the tagged plugin source and publish its OCI image to GHCR. + release: + types: [published] + # Manual path: retry a failed run (or cut a release without release-please) + # by providing an existing tag such as v0.1.0. + workflow_dispatch: + inputs: + version: + description: "The plugin version (without a v prefix e.g., 0.1.0) - if not provided, will use version from package.json" + required: false + type: string + +permissions: + contents: read + +env: + REGISTRY: ghcr.io + ORG: ${{ github.repository_owner }} + PLUGIN: cnpg-headlamp-plugin + IMAGE_NAME: cnpg-headlamp-plugin +jobs: + build-and-publish: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write # needed for publishing the container image + attestations: write + id-token: write + steps: + - name: Checkout main + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1 + with: + ref: main + + - name: Setup Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 #v7.0.0 + with: + node-version: 24 + cache: npm + + - name: Set up QEMU + uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 #v4.4.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 #v4.4.1 + + - name: Determine version + id: determine_version + run: | + VERSION="${{ github.event.inputs.version }}" + if [ -z "$VERSION" ]; then + echo "Version not provided, extracting from package.json" + VERSION=$(node -p "require('./package.json').version") + echo "Extracted version: $VERSION" + fi + # Remove leading 'v' if present + VERSION="${VERSION#v}" + # Create v-prefixed version for image tags + IMAGE_TAG_VERSION="v${VERSION}" + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "IMAGE_TAG_VERSION=$IMAGE_TAG_VERSION" >> $GITHUB_ENV + echo "FULL_IMAGE_NAME=${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE_NAME }}" >> $GITHUB_ENV + + - name: Log in to the Container registry + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f #v4.6.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Build Docker image + uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc #v7.4.0 + timeout-minutes: 15 + with: + context: . + push: false + load: true + tags: ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG_VERSION }},${{ env.FULL_IMAGE_NAME }}:latest + labels: | + org.opencontainers.image.source=${{ github.event.repository.html_url }} + org.opencontainers.image.licenses=Apache-2.0 + build-args: PLUGIN=${{ env.PLUGIN }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Test + run: | + docker run --rm ${{ env.FULL_IMAGE_NAME }}:latest sh -c "ls /plugins/${{ env.PLUGIN }}" + + - name: Push Docker image + id: push + uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc #v7.4.0 + with: + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG_VERSION }},${{ env.FULL_IMAGE_NAME }}:latest + labels: | + org.opencontainers.image.source=${{ github.event.repository.html_url }} + org.opencontainers.image.licenses=Apache-2.0 + provenance: true + build-args: PLUGIN=${{ env.PLUGIN }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Summary + run: | + echo "## Container Image Published" >> $GITHUB_STEP_SUMMARY + echo "Plugin: ${{ env.PLUGIN }}" >> $GITHUB_STEP_SUMMARY + echo "Version: ${{ env.VERSION }}" >> $GITHUB_STEP_SUMMARY + echo "Image: ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG_VERSION }}" >> $GITHUB_STEP_SUMMARY + + - name: Generate artifact attestation + uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 #v4.2.2 + with: + subject-name: ${{ env.FULL_IMAGE_NAME }} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..edeb9e7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,57 @@ +FROM node:24-alpine@sha256:ebfe2f90462722a7a4de65e91990e97fe0d401c70e0e762c5b53302f905ec1c1 AS builder + +# Set the working directory inside the container +WORKDIR /headlamp-plugins + +# Add a build argument for the desired plugin to be built +ARG PLUGIN + +# Check if the PLUGIN argument is provided +RUN if [ -z "$PLUGIN" ]; then \ + echo "Error: PLUGIN argument is required"; \ + exit 1; \ + fi + +# Remove any existing node_modules and package-lock.json to avoid arch-specific conflicts +COPY package.json package-lock.json /headlamp-plugins/${PLUGIN}/ + +# Install dependencies for the specified plugin +RUN --mount=type=cache,target=/root/.npm \ + echo "Installing deps for plugin $PLUGIN..."; \ + cd /headlamp-plugins/${PLUGIN}; \ + npm ci + +# Create a directory for the plugin build +COPY . /headlamp-plugins/${PLUGIN} + +# Build the specified plugin +RUN echo "Building plugin $PLUGIN..."; \ + cd /headlamp-plugins/${PLUGIN}; \ + npm run build + +# Extract the built plugin to the build directory +RUN mkdir -p /headlamp-plugins/build && \ + echo "Extracting plugin ${PLUGIN}..." && \ + cd "/headlamp-plugins/${PLUGIN}" && \ + npx --no-install headlamp-plugin extract . "/headlamp-plugins/build/${PLUGIN}" + +FROM alpine:3.24.2@sha256:294b683cb724975bec92580e1e685676bd4b50bda910ddb8c51d4cabeaec77e6 AS final + +# Create a non-root user and group +RUN addgroup -S headlamp && adduser -S headlamp -G headlamp + +# Copy the built plugin files from the builder stage to the /plugins directory in the final image +COPY --from=builder /headlamp-plugins/build/ /plugins/ + +# Set appropriate permissions for the plugins directory +RUN chown -R headlamp:headlamp /plugins && \ + chmod -R 755 /plugins + +LABEL org.opencontainers.image.source=https://github.com/cloudnative-pg/cnpg-headlamp-plugin +LABEL org.opencontainers.image.licenses=Apache-2.0 + +# Switch to non-root user +USER headlamp + +# Set the default command to list the installed plugins +CMD ["sh", "-c", "echo Plugins installed at /plugins/:; ls /plugins/"] \ No newline at end of file From e4f6c04a67f2b2296b3ac37c6a1813c98d88b845 Mon Sep 17 00:00:00 2001 From: Casper Thygesen Date: Tue, 13 Oct 2026 08:43:41 +0200 Subject: [PATCH 2/6] chore: reorganize .dockerignore for clarity and consistency Signed-off-by: Casper Thygesen --- .dockerignore | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/.dockerignore b/.dockerignore index 0333101..dd4184d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,11 +1,24 @@ -node_modules +# Repository metadata .git -*.md -tests/ +.github/ +.vscode/ + +# Dependencies and generated output +node_modules/ +build/ +dist/ coverage/ +*.tar.gz +.eslintcache + +# Local-only files .env *.log -.github/ -.vscode/ + +# Tests, documentation, and image assets +*.md +tests/ +docs/ screenshots/ -img/ \ No newline at end of file +img/ +.DS_Store From 823d5f7a642e470f14e4bba7cff782a9fa07932e Mon Sep 17 00:00:00 2001 From: Casper Thygesen Date: Tue, 13 Oct 2026 08:44:12 +0200 Subject: [PATCH 3/6] chore: update Docker metadata handling Signed-off-by: Casper Thygesen --- .github/workflows/release-plugin-oci.yaml | 25 +++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release-plugin-oci.yaml b/.github/workflows/release-plugin-oci.yaml index 0e70ba8..a9e7f54 100644 --- a/.github/workflows/release-plugin-oci.yaml +++ b/.github/workflows/release-plugin-oci.yaml @@ -21,7 +21,7 @@ env: REGISTRY: ghcr.io ORG: ${{ github.repository_owner }} PLUGIN: cnpg-headlamp-plugin - IMAGE_NAME: cnpg-headlamp-plugin + FULL_IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/cnpg-headlamp-plugin jobs: build-and-publish: runs-on: ubuntu-latest @@ -63,7 +63,14 @@ jobs: IMAGE_TAG_VERSION="v${VERSION}" echo "VERSION=$VERSION" >> $GITHUB_ENV echo "IMAGE_TAG_VERSION=$IMAGE_TAG_VERSION" >> $GITHUB_ENV - echo "FULL_IMAGE_NAME=${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE_NAME }}" >> $GITHUB_ENV + + - name: Docker meta + id: meta + uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 #v6.2.0 + with: + images: ${{ env.FULL_IMAGE_NAME }} + tags: | + type=raw,value=${{ env.IMAGE_TAG_VERSION }} - name: Log in to the Container registry uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f #v4.6.0 @@ -78,18 +85,15 @@ jobs: with: context: . push: false + tags: ${{ steps.meta.outputs.tags }} load: true - tags: ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG_VERSION }},${{ env.FULL_IMAGE_NAME }}:latest - labels: | - org.opencontainers.image.source=${{ github.event.repository.html_url }} - org.opencontainers.image.licenses=Apache-2.0 build-args: PLUGIN=${{ env.PLUGIN }} cache-from: type=gha cache-to: type=gha,mode=max - name: Test run: | - docker run --rm ${{ env.FULL_IMAGE_NAME }}:latest sh -c "ls /plugins/${{ env.PLUGIN }}" + docker run --rm ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG_VERSION }} sh -c "ls /plugins/${{ env.PLUGIN }}" - name: Push Docker image id: push @@ -97,10 +101,9 @@ jobs: with: platforms: linux/amd64,linux/arm64 push: true - tags: ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG_VERSION }},${{ env.FULL_IMAGE_NAME }}:latest - labels: | - org.opencontainers.image.source=${{ github.event.repository.html_url }} - org.opencontainers.image.licenses=Apache-2.0 + tags: ${{ steps.meta.outputs.tags }} + annotations: ${{ steps.meta.outputs.annotations }} + labels: ${{ steps.meta.outputs.labels }} provenance: true build-args: PLUGIN=${{ env.PLUGIN }} cache-from: type=gha From e4855150c8f84ffa97ff29e6e0fdb03c16ef7b58 Mon Sep 17 00:00:00 2001 From: Casper Thygesen Date: Tue, 13 Oct 2026 08:44:24 +0200 Subject: [PATCH 4/6] chore: remove unnecessary labels from Dockerfile as its handled by workflow Signed-off-by: Casper Thygesen --- Dockerfile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index edeb9e7..a205a95 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,11 +47,8 @@ COPY --from=builder /headlamp-plugins/build/ /plugins/ RUN chown -R headlamp:headlamp /plugins && \ chmod -R 755 /plugins -LABEL org.opencontainers.image.source=https://github.com/cloudnative-pg/cnpg-headlamp-plugin -LABEL org.opencontainers.image.licenses=Apache-2.0 - # Switch to non-root user USER headlamp # Set the default command to list the installed plugins -CMD ["sh", "-c", "echo Plugins installed at /plugins/:; ls /plugins/"] \ No newline at end of file +CMD ["sh", "-c", "echo Plugins installed at /plugins/:; ls /plugins/"] From 0b40465640035d99c3c424b6457e1e09362b3da2 Mon Sep 17 00:00:00 2001 From: Casper Thygesen Date: Tue, 13 Oct 2026 08:52:37 +0200 Subject: [PATCH 5/6] docs: add installation instructions for in-cluster deployment of the plugin Signed-off-by: Casper Thygesen --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 8fe37d8..2c06ad7 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,24 @@ List and detail views for managing available Postgres operand images. 1. Download the `cnpg-headlamp-plugin-.tar.gz` archive from the [GitHub Releases](https://github.com/cloudnative-pg/cnpg-headlamp-plugin/releases) page 2. Install it following the [Headlamp plugin installation documentation](https://headlamp.dev/docs/latest/development/plugins/) +### In-Clusterr install + +1. Install Headlamp (https://headlamp.dev/docs/latest/installation/in-cluster/) +2. Deploy the container image `ghcr.io/cloudnative-pg/cnpg-headlamp-plugin` as a sidecar container to the headlamp deployment. + +```yaml +initContainers: + - command: + - /bin/sh + - '-c' + - mkdir -p /build/plugins && cp -r /plugins/* /build/plugins/ + image: ghcr.io/cloudnative-pg/cnpg-headlamp-plugin:v0.1.4 + name: cnpg-plugin + volumeMounts: + - mountPath: /build/plugins + name: headlamp-plugins +``` + ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, the live-load From c917f556c8010a9b1c964a27c56a92e6197f500c Mon Sep 17 00:00:00 2001 From: Leonardo Cecchi Date: Wed, 14 Oct 2026 15:24:19 +0200 Subject: [PATCH 6/6] chore: review Signed-off-by: Leonardo Cecchi --- .github/workflows/release-plugin-oci.yaml | 71 +++++++++++++++++------ README.md | 27 ++++----- deploy/headlamp-with-cnpg.yaml | 56 ++++++++++++++++++ 3 files changed, 119 insertions(+), 35 deletions(-) create mode 100644 deploy/headlamp-with-cnpg.yaml diff --git a/.github/workflows/release-plugin-oci.yaml b/.github/workflows/release-plugin-oci.yaml index a9e7f54..08b64e3 100644 --- a/.github/workflows/release-plugin-oci.yaml +++ b/.github/workflows/release-plugin-oci.yaml @@ -9,9 +9,9 @@ on: # by providing an existing tag such as v0.1.0. workflow_dispatch: inputs: - version: - description: "The plugin version (without a v prefix e.g., 0.1.0) - if not provided, will use version from package.json" - required: false + tag: + description: 'Existing release tag to (re)build, e.g. v0.1.0' + required: true type: string permissions: @@ -31,10 +31,10 @@ jobs: attestations: write id-token: write steps: - - name: Checkout main + - name: Checkout release tag uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1 with: - ref: main + ref: ${{ github.event.release.tag_name || github.event.inputs.tag }} - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 #v7.0.0 @@ -48,29 +48,62 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 #v4.4.1 - - name: Determine version - id: determine_version + - name: Resolve version + id: version run: | - VERSION="${{ github.event.inputs.version }}" - if [ -z "$VERSION" ]; then - echo "Version not provided, extracting from package.json" - VERSION=$(node -p "require('./package.json').version") - echo "Extracted version: $VERSION" + if [ "${{ github.event_name }}" = "release" ]; then + TAG="${{ github.event.release.tag_name }}" + else + TAG="${{ github.event.inputs.tag }}" fi - # Remove leading 'v' if present - VERSION="${VERSION#v}" - # Create v-prefixed version for image tags - IMAGE_TAG_VERSION="v${VERSION}" + if [ -z "$TAG" ]; then + echo "Error: no tag resolved (release.tag_name or inputs.tag)" >&2 + exit 1 + fi + if [ "${TAG#v}" = "$TAG" ]; then + echo "Error: tag must be v-prefixed, got '$TAG'" >&2 + exit 1 + fi + # Tags are v-prefixed (v0.1.0); the plugin version is not (0.1.0). + VERSION="${TAG#v}" + echo "tag=$TAG" >> $GITHUB_OUTPUT + echo "version=$VERSION" >> $GITHUB_OUTPUT echo "VERSION=$VERSION" >> $GITHUB_ENV - echo "IMAGE_TAG_VERSION=$IMAGE_TAG_VERSION" >> $GITHUB_ENV + echo "TAG=$TAG" >> $GITHUB_ENV + echo "IMAGE_TAG_VERSION=$TAG" >> $GITHUB_ENV - name: Docker meta id: meta uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 #v6.2.0 + env: + # Attach annotations to both manifests and the multi-arch index + # so they are visible on GHCR, following cloudnative-pg/docker-bake.hcl + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index with: - images: ${{ env.FULL_IMAGE_NAME }} - tags: | + images: ${{ env.FULL_IMAGE_NAME }} + tags: | type=raw,value=${{ env.IMAGE_TAG_VERSION }} + # version, revision, created, source are auto-generated by + # metadata-action. We only pin the stable descriptive fields here, + # mirroring cloudnative-pg/docker-bake.hcl. + labels: | + org.opencontainers.image.title=CloudNativePG Headlamp Plugin + org.opencontainers.image.description=Headlamp plugin for managing CloudNativePG resources - directly from the Headlamp + org.opencontainers.image.vendor=CloudNativePG + org.opencontainers.image.authors=The CloudNativePG Contributors + org.opencontainers.image.licenses=Apache-2.0 + org.opencontainers.image.documentation=https://cloudnative-pg.io/documentation/ + org.opencontainers.image.url=https://github.com/cloudnative-pg/cnpg-headlamp-plugin + # metadata-action does not propagate custom labels to annotations + # automatically, so mirror them explicitly. + annotations: | + org.opencontainers.image.title=CloudNativePG Headlamp Plugin + org.opencontainers.image.description=Headlamp plugin for managing CloudNativePG resources - directly from the Headlamp + org.opencontainers.image.vendor=CloudNativePG + org.opencontainers.image.authors=The CloudNativePG Contributors + org.opencontainers.image.licenses=Apache-2.0 + org.opencontainers.image.documentation=https://cloudnative-pg.io/documentation/ + org.opencontainers.image.url=https://github.com/cloudnative-pg/cnpg-headlamp-plugin - name: Log in to the Container registry uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f #v4.6.0 diff --git a/README.md b/README.md index 2c06ad7..810cd0c 100644 --- a/README.md +++ b/README.md @@ -90,24 +90,19 @@ List and detail views for managing available Postgres operand images. 1. Download the `cnpg-headlamp-plugin-.tar.gz` archive from the [GitHub Releases](https://github.com/cloudnative-pg/cnpg-headlamp-plugin/releases) page 2. Install it following the [Headlamp plugin installation documentation](https://headlamp.dev/docs/latest/development/plugins/) -### In-Clusterr install - -1. Install Headlamp (https://headlamp.dev/docs/latest/installation/in-cluster/) -2. Deploy the container image `ghcr.io/cloudnative-pg/cnpg-headlamp-plugin` as a sidecar container to the headlamp deployment. - -```yaml -initContainers: - - command: - - /bin/sh - - '-c' - - mkdir -p /build/plugins && cp -r /plugins/* /build/plugins/ - image: ghcr.io/cloudnative-pg/cnpg-headlamp-plugin:v0.1.4 - name: cnpg-plugin - volumeMounts: - - mountPath: /build/plugins - name: headlamp-plugins +### In-Cluster install + +Deploy Headlamp together with the plugin using the example manifest in [`deploy/headlamp-with-cnpg.yaml`](deploy/headlamp-with-cnpg.yaml), replacing `vX.Y.Z` with a [released plugin version](https://github.com/cloudnative-pg/cnpg-headlamp-plugin/releases): + +```sh +VERSION=vX.Y.Z # e.g. VERSION=v0.1.4 +curl -s https://raw.githubusercontent.com/cloudnative-pg/cnpg-headlamp-plugin/main/deploy/headlamp-with-cnpg.yaml \ + | sed "s/vX.Y.Z/$VERSION/" \ + | kubectl apply -f - ``` +Note: with `-in-cluster`, Headlamp authenticates with its own ServiceAccount, so grant it the RBAC permissions described in the [Headlamp in-cluster documentation](https://headlamp.dev/docs/latest/installation/in-cluster/) and generate a login token for your user (`kubectl create token `). + ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, the live-load diff --git a/deploy/headlamp-with-cnpg.yaml b/deploy/headlamp-with-cnpg.yaml new file mode 100644 index 0000000..020c42f --- /dev/null +++ b/deploy/headlamp-with-cnpg.yaml @@ -0,0 +1,56 @@ +# Example: run Headlamp in-cluster with the CNPG plugin installed. +# +# Replace vX.Y.Z below with a released plugin version, e.g. v0.1.4: +# https://github.com/cloudnative-pg/cnpg-headlamp-plugin/releases +apiVersion: apps/v1 +kind: Deployment +metadata: + name: headlamp-with-cnpg + labels: + app: headlamp-with-cnpg +spec: + selector: + matchLabels: + app: headlamp-with-cnpg + template: + metadata: + labels: + app: headlamp-with-cnpg + spec: + initContainers: + - name: fetch-plugins + image: ghcr.io/cloudnative-pg/cnpg-headlamp-plugin:vX.Y.Z + # Copy the plugins into the shared volume before Headlamp starts. + command: ["/bin/sh", "-c"] + args: ["cp -r /plugins/* /headlamp/plugins/ && ls -l /headlamp/plugins"] + volumeMounts: + - name: plugins + mountPath: /headlamp/plugins + containers: + - name: headlamp + image: ghcr.io/headlamp-k8s/headlamp:latest + args: + - -plugins-dir=/headlamp/plugins + - -in-cluster + ports: + - containerPort: 4466 + volumeMounts: + - name: plugins + mountPath: /headlamp/plugins + volumes: + - name: plugins + emptyDir: {} +--- +apiVersion: v1 +kind: Service +metadata: + name: headlamp-with-cnpg + labels: + app: headlamp-with-cnpg +spec: + selector: + app: headlamp-with-cnpg + ports: + - name: http + port: 4466 + targetPort: 4466