Skip to content
This repository was archived by the owner on Jan 30, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Binaries for programs and plugins
pull-secret
pull-secret-mvp
/pull-secret
/pull-secret-mvp
*.exe
*.exe~
*.dll
Expand Down
8 changes: 6 additions & 2 deletions charts/pull-secret/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ description: HyperFleet Pull Secret Adapter - Manages pull secrets in GCP Secret
type: application
version: 0.1.0
appVersion: "1.0"
maintainers:
- name: HyperFleet Team
email: hyperfleet-team@redhat.com
keywords:
- hyperfleet
- adapter
- pull-secret
- gcp
- secret-manager
maintainers:
- name: HyperFleet Team
- kubernetes
home: https://github.com/openshift-hyperfleet/adapter-pull-secret
229 changes: 169 additions & 60 deletions charts/pull-secret/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
# Pull Secret Adapter Helm Chart

This Helm chart deploys the HyperFleet Pull Secret Adapter as a Kubernetes Job on GKE.
This Helm chart deploys the HyperFleet Pull Secret Adapter using the Adapter Framework pattern. The adapter listens to PubSub messages and dynamically creates jobs to store pull secrets in GCP Secret Manager.

## Architecture

```
┌──────────────────────────────────────────────────────────────────┐
│ Adapter Framework (Deployment) │
│ - Listens to PubSub messages │
│ - Creates Jobs based on AdapterConfig │
└────────────────────────┬─────────────────────────────────────────┘
▼ (creates dynamically)
┌──────────────────────────────────────────────────────────────────┐
│ Pull Secret Job (per cluster) │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ pull-secret │ │ status-reporter │ │
│ │ (main container) │ │ (sidecar) │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │ │ │
│ └───── shared volume ─────┘ │
└──────────────────────────────────────────────────────────────────┘
```

## Prerequisites

Expand All @@ -16,123 +37,209 @@ This Helm chart deploys the HyperFleet Pull Secret Adapter as a Kubernetes Job o
--project=YOUR_PROJECT_ID
```

3. **Workload Identity configured**
- Service Account: `your-service-account@your-project.iam.gserviceaccount.com`
- Workload Pool: `your-project.svc.id.goog`
3. **GCP Pub/Sub configured**
- Topic for adapter messages
- Subscription for the adapter

4. **Workload Identity configured**
- Using `principalSet://` for Workload Identity Federation
- No ServiceAccount annotation required (modern approach)

## Installation

### Quick Start

Deploy with default values:
Deploy with required Pub/Sub configuration:

```bash
helm install pullsecret-job ./charts/pull-secret \
helm install pull-secret-adapter ./charts/pull-secret \
--namespace hyperfleet-system \
--create-namespace
--create-namespace \
--set broker.googlepubsub.projectId=my-project \
--set broker.googlepubsub.topic=hyperfleet-events \
--set broker.googlepubsub.subscription=pull-secret-adapter-sub \
--set hyperfleetApi.baseUrl=https://api.hyperfleet.example.com
```

### Custom Values

Deploy with custom configuration:

```bash
helm install pullsecret-job ./charts/pull-secret \
helm install pull-secret-adapter ./charts/pull-secret \
--namespace hyperfleet-system \
--create-namespace \
--set env.gcpProjectId=my-project \
--set env.clusterId=my-cluster-123 \
--set env.pullSecretData='{"auths":{...}}' \
--set image.tag=latest
--set broker.googlepubsub.projectId=my-project \
--set broker.googlepubsub.topic=hyperfleet-events \
--set broker.googlepubsub.subscription=pull-secret-adapter-sub \
--set hyperfleetApi.baseUrl=https://api.hyperfleet.example.com \
--set pullSecretAdapter.image.tag=v1.0.0
```

### Using a Values File

Create a custom values file (`my-values.yaml`):

```yaml
env:
gcpProjectId: "my-gcp-project"
clusterId: "my-cluster-123"
secretName: "hyperfleet-my-cluster-123-pull-secret"
pullSecretData: '{"auths":{"registry.example.com":{"auth":"...","email":"user@example.com"}}}'

serviceAccount:
gcpServiceAccount: "my-service-account@my-project.iam.gserviceaccount.com"

image:
tag: "v1.0.0"
broker:
type: "googlepubsub"
googlepubsub:
projectId: "my-gcp-project"
topic: "hyperfleet-events"
subscription: "pull-secret-adapter-sub"

hyperfleetApi:
baseUrl: "https://api.hyperfleet.example.com"
version: "v1"

pullSecretAdapter:
image:
tag: "v1.0.0"
```

Then install:

```bash
helm install pullsecret-job ./charts/pull-secret \
helm install pull-secret-adapter ./charts/pull-secret \
--namespace hyperfleet-system \
--create-namespace \
-f my-values.yaml
```

## Umbrella Chart Integration

This chart supports integration with the `hyperfleet-chart` umbrella chart.

### Adding to hyperfleet-chart

In your umbrella chart's `Chart.yaml`:

```yaml
dependencies:
- name: pull-secret
version: "0.1.0"
repository: "git+https://github.com/openshift-hyperfleet/adapter-pull-secret@charts/pull-secret?ref=main"
condition: pull-secret.enabled
```
Comment on lines +117 to +123
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for helm-git mentions and repository setup documentation
rg -n -C5 'helm-git|git\+https|repository.*git' charts/pull-secret/ --type md

echo "---"
# Also check if there are any prerequisites or setup docs
rg -n -i 'prerequisite|requirement|setup|install' charts/pull-secret/README.md

echo "---"
# Check the full README structure to see all sections
head -100 charts/pull-secret/README.md

Repository: openshift-hyperfleet/adapter-pull-secret

Length of output: 3381


🏁 Script executed:

#!/bin/bash
# Check if this git+ format is used elsewhere in the codebase
git ls-files | xargs rg -l 'git\+https.*\?ref=' 2>/dev/null | head -20

Repository: openshift-hyperfleet/adapter-pull-secret

Length of output: 112


🏁 Script executed:

#!/bin/bash
# Look for any Helm documentation or references to special repository types
find . -name "*.md" -type f | xargs rg -l 'helm-git|git.*repository|OCI.*registry' 2>/dev/null | head -10

Repository: openshift-hyperfleet/adapter-pull-secret

Length of output: 66


Document the helm-git plugin requirement for Umbrella Chart Integration.

The git+ repository format in the Umbrella Chart Integration section (line 96) requires the helm-git plugin to function. Add this to the Prerequisites section:

4. **helm-git plugin installed** (required for umbrella chart integration with git+ repositories)
   ```bash
   helm plugin install https://github.com/aslafy-z/helm-git --version 0.15.1

Alternatively, use a standard Helm repository format (OCI registry or HTTP chart repository URL) instead of the git+ format.

<details>
<summary>🤖 Prompt for AI Agents</summary>

In @charts/pull-secret/README.md around lines 92 - 98, The README's Umbrella
Chart Integration uses a git+ repository URL in the dependencies block
(repository:
"git+https://github.com/openshift-hyperfleet/adapter-pull-secret@charts/pull-secret?ref=main")
which requires the helm-git plugin; update the Prerequisites section to document
that requirement by adding an entry for installing the helm-git plugin (include
the install command and recommended version), or instead change the repository
format to a standard Helm repo (OCI or HTTP chart repo) so the git+ URL is not
necessary; reference the dependencies block and the repository field when making
the change.


</details>

<!-- fingerprinting:phantom:triton:puma -->

<!-- This is an auto-generated comment by CodeRabbit -->


### Global Image Override

When deployed via umbrella chart, you can set a global image registry:

```yaml
global:
image:
registry: "quay.io/my-org" # Overrides all subchart image registries

pull-secret:
enabled: true
broker:
googlepubsub:
projectId: "my-project"
topic: "hyperfleet-events"
subscription: "pull-secret-adapter-sub"
```

## Configuration

The following table lists the configurable parameters:

| Parameter | Description | Default |
|-----------|-------------|---------|
| `namespace` | Kubernetes namespace | `hyperfleet-system` |
| `job.name` | Job name | `pullsecret-job` |
| `job.backoffLimit` | Number of retries on failure | `3` |
| `job.ttlSecondsAfterFinished` | Cleanup delay after completion | `3600` (1 hour) |
| `image.repository` | Container image repository | `quay.io/hyperfleet/pull-secret` |
| `image.tag` | Container image tag | `latest` |
| **Global** | | |
| `global.image.registry` | Global image registry override | `""` |
| `nameOverride` | Override chart name | `""` |
| `fullnameOverride` | Override full release name | `""` |
| `replicaCount` | Number of adapter framework replicas | `1` |
| **Adapter Framework Image** | | |
| `image.registry` | Adapter framework image registry | `registry.ci.openshift.org` |
| `image.repository` | Adapter framework image repository | `ci/hyperfleet-adapter` |
| `image.tag` | Adapter framework image tag | `latest` |
| `image.pullPolicy` | Image pull policy | `Always` |
| `serviceAccount.name` | Kubernetes ServiceAccount name | `pullsecret-adapter` |
| `serviceAccount.gcpServiceAccount` | GCP service account for Workload Identity | `your-service-account@your-project.iam.gserviceaccount.com` |
| `env.gcpProjectId` | GCP project ID | `your-gcp-project` |
| `env.clusterId` | Cluster identifier | `your-cluster-id` |
| `env.secretName` | Secret name in GCP Secret Manager | `hyperfleet-your-cluster-id-pull-secret` |
| `env.pullSecretData` | Pull secret JSON data (required) | `{"auths":{...}}` |
| `resources.requests.cpu` | CPU request | `100m` |
| `resources.requests.memory` | Memory request | `128Mi` |
| `resources.limits.cpu` | CPU limit | `500m` |
| `resources.limits.memory` | Memory limit | `512Mi` |
| `imagePullSecrets` | Image pull secrets | `[]` |
| **ServiceAccount** | | |
| `serviceAccount.create` | Create ServiceAccount | `true` |
| `serviceAccount.name` | ServiceAccount name | `""` (auto-generated) |
| `serviceAccount.annotations` | ServiceAccount annotations | `{}` |
| **RBAC** | | |
| `rbac.create` | Create RBAC resources | `true` |
| **Logging** | | |
| `logging.level` | Log level (debug, info, warn, error) | `info` |
| `logging.format` | Log format (text, json) | `text` |
| `logging.output` | Log output (stdout, stderr) | `stderr` |
| **Broker** | | |
| `broker.type` | Broker type (googlepubsub, rabbitmq) | `googlepubsub` |
| `broker.googlepubsub.projectId` | GCP project ID for Pub/Sub | `""` |
| `broker.googlepubsub.topic` | Pub/Sub topic name | `""` |
| `broker.googlepubsub.subscription` | Pub/Sub subscription name | `""` |
| `broker.googlepubsub.deadLetterTopic` | Dead letter topic (optional) | `""` |
| `broker.subscriber.parallelism` | Message processing parallelism | `1` |
| **HyperFleet API** | | |
| `hyperfleetApi.baseUrl` | HyperFleet API base URL | `""` |
| `hyperfleetApi.version` | HyperFleet API version | `v1` |
| **Pull Secret Adapter** | | |
| `pullSecretAdapter.image.registry` | Job container image registry | `quay.io/openshift-hyperfleet` |
| `pullSecretAdapter.image.repository` | Job container image repository | `pull-secret` |
| `pullSecretAdapter.image.tag` | Job container image tag | `latest` |
| `pullSecretAdapter.statusReporterImage` | Status reporter sidecar image | `registry.ci.openshift.org/ci/status-reporter:latest` |
| `pullSecretAdapter.resultsPath` | Shared result path | `/results/adapter-result.json` |
| `pullSecretAdapter.maxWaitTimeSeconds` | Max job wait time | `300` |
| `pullSecretAdapter.logLevel` | Job container log level | `info` |
| **Scheduling** | | |
| `nodeSelector` | Node selector | `{}` |
| `tolerations` | Tolerations | `[]` |
| `affinity` | Affinity rules | `{}` |
| `env` | Additional environment variables | `[]` |

## How It Works

1. **PubSub Message**: HyperFleet sends a message with cluster info (`clusterId`, `projectId`, `pullSecretData`)
2. **Adapter Framework**: Receives the message and creates a Job based on the AdapterConfig
3. **Pull Secret Job**: Stores the pull secret in GCP Secret Manager
4. **Status Reporter**: Reports job status back to HyperFleet API

## Usage

### Monitoring

Check job status:
Check deployment status:
```bash
helm status pull-secret-adapter -n hyperfleet-system
kubectl get deployment -n hyperfleet-system
kubectl get pods -n hyperfleet-system
```

View adapter logs:
```bash
helm status pullsecret-job -n hyperfleet-system
kubectl get job pullsecret-job -n hyperfleet-system
kubectl logs -f deployment/pull-secret-adapter -n hyperfleet-system
```

View logs:
View job logs (for a specific cluster):
```bash
kubectl logs -f job/pullsecret-job -n hyperfleet-system
kubectl logs -f job/pull-secret-<cluster-id>-<generation> -n <cluster-id>
```

### Upgrading

Upgrade the deployment with new values:
Upgrade the deployment:
```bash
helm upgrade pullsecret-job ./charts/pull-secret \
helm upgrade pull-secret-adapter ./charts/pull-secret \
--namespace hyperfleet-system \
--set image.tag=v1.1.0
--set pullSecretAdapter.image.tag=v1.1.0
```

### Uninstalling

Remove the job:
Remove the adapter:
```bash
helm uninstall pullsecret-job -n hyperfleet-system
helm uninstall pull-secret-adapter -n hyperfleet-system
```

## Dry Run Mode

Test without creating secrets:
Test without deploying:
```bash
helm install pullsecret-job ./charts/pull-secret \
helm install pull-secret-adapter ./charts/pull-secret \
--namespace hyperfleet-system \
--dry-run --debug
```
Expand All @@ -141,26 +248,26 @@ helm install pullsecret-job ./charts/pull-secret \

### View rendered templates
```bash
helm template pullsecret-job ./charts/pull-secret
helm template pull-secret-adapter ./charts/pull-secret
```

### Check deployment issues
```bash
kubectl describe job pullsecret-job -n hyperfleet-system
kubectl describe deployment pull-secret-adapter -n hyperfleet-system
kubectl get events -n hyperfleet-system --sort-by='.lastTimestamp'
```

### Authentication errors

Verify Workload Identity binding:
Verify Workload Identity:
```bash
# Check ServiceAccount
kubectl get sa pullsecret-adapter -n hyperfleet-system -o yaml
kubectl get sa -n hyperfleet-system

# Check GCP IAM binding
gcloud iam service-accounts get-iam-policy \
your-service-account@your-project.iam.gserviceaccount.com \
--project=your-project
# Verify IAM binding (using principalSet)
gcloud projects get-iam-policy YOUR_PROJECT_ID \
--flatten="bindings[].members" \
--filter="bindings.members:principalSet://"
```

## Development
Expand Down Expand Up @@ -191,3 +298,5 @@ helm package ./charts/pull-secret
- [Helm Documentation](https://helm.sh/docs/)
- [GKE Workload Identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
- [Kubernetes Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/job/)
- [HyperFleet Chart](https://github.com/openshift-hyperfleet/hyperfleet-chart)
- [Adapter Framework Pattern](https://github.com/openshift-hyperfleet/adapter-validation-gcp)
Loading