Compare commits

..

14 Commits

Author SHA1 Message Date
Volodymyr Zotov
d403a29fdc Update documentation 2025-10-02 15:34:51 -05:00
Volodymyr Zotov
d30ed0b9d7 Name the jobs 'run-e2e-tests' 2025-10-02 15:31:23 -05:00
Volodymyr Zotov
db2053fde4 Update status for e2e-test check as well 2025-10-02 15:28:48 -05:00
Volodymyr Zotov
316f605680 Update docs 2025-10-02 13:18:05 -05:00
Volodymyr Zotov
7135f439a5 Update check-external-pr check when e2e test success 2025-10-02 13:14:04 -05:00
Volodymyr Zotov
625297c1fb Add doc explaining how to test forked PR 2025-10-02 12:41:01 -05:00
Volodymyr Zotov
e967f7ce1e Revert job name 2025-10-02 12:40:35 -05:00
Volodymyr Zotov
5199e9f350 Revert "Update status check to 'success' only if e2e tests are passed"
This reverts commit 878b38deac.
2025-10-02 12:37:04 -05:00
Volodymyr Zotov
878b38deac Update status check to 'success' only if e2e tests are passed 2025-10-02 12:36:27 -05:00
Volodymyr Zotov
1a40b4fb95 Pass jobm name as env 2025-10-02 12:35:06 -05:00
Volodymyr Zotov
4b5d3c5f1a Use propper job name e2e-tests 2025-10-02 12:34:10 -05:00
Volodymyr Zotov
8d4908fb72 Updated comment to mention sha= portion to dispatch the event 2025-10-02 11:50:15 -05:00
Volodymyr Zotov
6cf52a7bfc Use process.env.job instead of hardcoding job name 2025-10-02 11:29:31 -05:00
Volodymyr Zotov
7ef9ec6de7 Update e2e job names to avoid confustion and fix updating check status 2025-10-02 08:35:37 -05:00
16 changed files with 153 additions and 535 deletions

View File

@@ -1,17 +0,0 @@
### ✨ Summary
<!-- What does this change do? -->
<!-- What issue does it resolve? -->
### 🔗 Resolves:
### ✅ Checklist
- [ ] 🖊️ Commits are signed
- [ ] 🧪 Tests added/updated: _(See the [Testing Guide](docs/testing.md) for when to use each type and how to run them)_
- [ ] 🔹 Unit
- [ ] 🔸 Integration
- [ ] 🌐 E2E (Connect)
- [ ] 🔑 E2E (Service Account)
- [ ] 📚 Docs updated (if behavior changed)
### 🕵️ Review Notes & ⚠️ Risks
<!-- Notes for reviewers, flags, feature gates, rollout considerations, etc. -->

View File

@@ -1,4 +1,4 @@
name: E2E Tests
name: E2E Tests [reusable]
on:
workflow_call:

View File

@@ -1,4 +1,4 @@
# Write comments "/ok-to-test <hash>" on a pull request. This will emit a repository_dispatch event.
# Write comments "/ok-to-test sha=<hash>" on a pull request. This will emit a repository_dispatch event.
name: Ok To Test
on:

View File

@@ -13,7 +13,7 @@ concurrency:
cancel-in-progress: true # cancel previous job runs for the same branch
jobs:
e2e-tests:
run-e2e-tests:
uses: ./.github/workflows/e2e-tests.yml
if: |
github.event_name == 'repository_dispatch' &&
@@ -28,14 +28,14 @@ jobs:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
update-check-status:
needs: e2e-tests
needs: run-e2e-tests
runs-on: ubuntu-latest
if: always() && github.event_name == 'repository_dispatch'
steps:
- uses: actions/github-script@v6
env:
ref: ${{ github.event.client_payload.pull_request.head.sha }}
conclusion: ${{ needs.e2e-tests.result }}
conclusion: ${{ needs.run-e2e-tests.result }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
@@ -44,7 +44,8 @@ jobs:
ref: process.env.ref
});
const check = checks.check_runs.filter(c => c.name === 'e2e-test');
// update the 'check-external-pr' check run
const check = checks.check_runs.filter(c => c.name === 'check-external-pr');
const { data: result } = await github.rest.checks.update({
...context.repo,
@@ -53,4 +54,14 @@ jobs:
conclusion: process.env.conclusion
});
return result;
// update the 'run-e2e-tests' check run from 'test-e2e.yml' workflow
const check = checks.check_runs.filter(c => c.name === 'run-e2e-tests');
const { data: result } = await github.rest.checks.update({
...context.repo,
check_run_id: check[0].id,
status: 'completed',
conclusion: process.env.conclusion
});
return null;

View File

@@ -33,7 +33,7 @@ jobs:
fi
echo "✅ Internal PR detected. Proceeding with tests."
e2e-test:
run-e2e-tests:
needs: check-external-pr
if: always() && (needs.check-external-pr.result == 'success' || github.event_name != 'pull_request')
uses: ./.github/workflows/e2e-tests.yml

View File

@@ -8,9 +8,6 @@ WORKDIR /workspace
COPY go.mod go.mod
COPY go.sum go.sum
# Copy the testhelper module (needed for replace directive)
COPY pkg/testhelper/ pkg/testhelper/
# Download dependencies
RUN go mod download

109
docs/fork-pr-testing.md Normal file
View File

@@ -0,0 +1,109 @@
# Fork PR Testing Guide
This document explains how to test external pull requests using the dispatch action workflow system.
## Overview
The testing system consists of three main workflows:
1. **E2E Tests** (`test-e2e.yml`) - Runs automatically for internal PRs, requires approval for external PRs
2. **Ok To Test** (`ok-to-test.yml`) - Processes slash commands to trigger fork testing
3. **E2E tests [fork]** (`test-e2e-fork.yml`) - Triggered manually via slash commands for external PRs
## How It Works
### 1. Initial PR State
When a PR is created or updated:
- The `test-e2e.yml` workflow automatically runs
- For **external PRs**: The `check-external-pr` job detects it's from a fork and **fails intentionally**
- For **internal PRs**: The workflow proceeds normally with e2e tests
- External PRs show ❌ for the check-external-pr job with a message asking for maintainer approval
### 2. Manual Approval Required
**Important**: External PRs require manual approval before workflows can run.
**Steps for maintainers:**
1. Go to the PR page
2. Click **"Approve workflow to run"** button
3. The workflow will then execute
**Note**: The `test-e2e.yml` workflow will still fail for external PRs even after approval, as it's designed to prevent automatic execution. Need to use the slash command instead.
### 3. Testing External PRs
Once the initial checks have run (and failed), maintainers can test the PR using slash commands:
#### Step-by-Step Process:
1. **Navigate to the PR**
- Go to the pull request you want to test
2. **Add a comment with slash command**
```
/ok-to-test sha=<commit-sha>
```
Replace `<commit-sha>` with the actual commit SHA from the PR.
**Note**: Use the short SHA.
3. **Dispatch Action Triggers**
- The `ok-to-test.yml` workflow processes the slash command
- It triggers a `repository_dispatch` event with type `ok-to-test-command`
- The `test-e2e-fork.yml` workflow starts
4. **Workflow Execution**
The fork workflow runs two jobs:
**a) `run-e2e-tests` job** (conditional)
- Only runs if:
- Event is `repository_dispatch`
- SHA parameter is not empty
- PR head SHA contains the provided SHA
- Calls the reusable `run-e2e-tests.yml` workflow
- Runs the actual E2E tests if conditions are met
**b) `update-check-status` job** (conditional)
- Runs after `e2e-tests` completes
- Updates the existing check for job named "run-e2e-tests" from 'test-e2e.yml' workflow
- Sets the conclusion based on `run-e2e-tests` result:
- ✅ **Success** if tests pass
- ❌ **Failure** if tests fail
## Troubleshooting
### Workflow Not Running
- **Check**: Ensure you've approved the workflow to run
- **Action**: Click "Approve workflow to run" in the PR checks tab
### SHA Not Found
- **Check**: Verify the SHA exists in the PR commits
- **Action**: Use `git log --oneline` to find valid commit SHAs
### Dispatch Not Triggering
- **Check**: Ensure the slash command format is correct
- **Action**: Use exact format: `/ok-to-test sha=<sha>`
### Check Runs Not Updating
- **Note**: The fork workflow updates the existing "E2E Tests [reusable]" check run
- **Behavior**: The same check run is updated with new results rather than creating a new one
## Security Notes
- Only users with **write** permissions can trigger dispatch commands
- The fork workflow runs in the main repository context, allowing it to update check runs
- Manual approval is required for external PR workflows
- External PRs are automatically detected and prevented from running tests automatically
## Workflow Files
- **`.github/workflows/ok-to-test.yml`** - Ok To Test - Slash command processor
- **`.github/workflows/test-e2e.yml`** - E2E Tests - Initial PR checks
- **`.github/workflows/test-e2e-fork.yml`** - E2E tests [fork] - Dispatch action handler
- **`.github/workflows/e2e-tests.yml`** - E2E Tests [reusable] - Reusable workflow for actual testing
## Testing Checklist
- [ ] PR created with failing check-external-pr check (for external PRs)
- [ ] Workflow approved to run (if required)
- [ ] Slash command posted with valid SHA
- [ ] Dispatch action triggered successfully
- [ ] `check-external-pr` check run updated with correct conclusion

View File

@@ -16,5 +16,7 @@
1. [Install `kind`](https://kind.sigs.k8s.io/docs/user/quick-start/#installing-with-a-package-manager) to spin up local Kubernetes cluster.
2. `export OP_CONNECT_TOKEN=<token>`
3. `export OP_SERVICE_ACCOUNT_TOKEN=<token>`
4. Put `1password-credentials.json` into project root.
5. `make test-e2e`
4. `make test-e2e`
5. Put `1password-credentials.json` into project root.
**Run**: `make test-e2e`

6
go.mod
View File

@@ -4,18 +4,15 @@ go 1.24.0
toolchain go1.24.5
// In main go.mod, add this replace directive:
replace github.com/1Password/onepassword-operator/pkg/testhelper => ./pkg/testhelper
require (
github.com/1Password/connect-sdk-go v1.5.3
github.com/1Password/onepassword-operator/pkg/testhelper v0.0.0-00010101000000-000000000000
github.com/1password/onepassword-sdk-go v0.3.1
github.com/go-logr/logr v1.4.2
github.com/onsi/ginkgo/v2 v2.22.0
github.com/onsi/gomega v1.36.1
github.com/stretchr/testify v1.10.0
k8s.io/api v0.33.0
k8s.io/apiextensions-apiserver v0.33.0
k8s.io/apimachinery v0.33.0
k8s.io/client-go v0.33.0
k8s.io/kubectl v0.29.0
@@ -106,7 +103,6 @@ require (
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.33.0 // indirect
k8s.io/apiserver v0.33.0 // indirect
k8s.io/component-base v0.33.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect

View File

@@ -1,115 +0,0 @@
# OnePassword Operator Test Helper
This is a standalone Go module that provides testing utilities for Kubernetes operators and webhooks. It's specifically designed for testing 1Password Kubernetes operator and secrets injector, but it can be used for any Kubernetes operator or webhook testing.
## Installation
To use this module in your project, add it as a dependency:
```bash
go get github.com/1Password/onepassword-operator/pkg/testhelper@<commit-hash>
```
### Basic Setup
```go
import (
"github.com/1Password/onepassword-operator/pkg/testhelper/kube"
"github.com/1Password/onepassword-operator/pkg/testhelper/defaults"
)
// Create a kube client for testing
kubeClient := kube.NewKubeClient(&kube.Config{
Namespace: "default",
ManifestsDir: "manifests",
TestConfig: &kube.TestConfig{
Timeout: defaults.E2ETimeout,
Interval: defaults.E2EInterval,
},
CRDs: []string{
"path/to/your/crd.yaml",
},
})
```
### Working with Secrets
```go
// Create k8s secret from environment variable
k8sSecret := kubeClient.Secret("my-secret")
k8sSecret.CreateFromEnvVar(ctx, "MY_ENV_VAR")
// Create a secret from file
data := []byte("secret content")
k8sSecret.CreateFromFile(ctx, "filename", data)
// Check if secret exists
k8sSecret.CheckIfExists(ctx)
// Get secret
secretObj := k8sSecret.Get(ctx)
```
### Working with Deployments
```go
deployment := kubeClient.Deployment("my-deployment")
// Read environment variable from deployment
envVar := deployment.ReadEnvVar(ctx, "MY_ENV_VAR")
// Patch environment variables
deployment.PatchEnvVars(ctx,
[]corev1.EnvVar{
{Name: "NEW_VAR", Value: "new_value"},
},
[]string{"OLD_VAR"}, // variables to remove
)
// Wait for deployment rollout
deployment.WaitDeploymentRolledOut(ctx)
```
### Working with Pods
```go
pod := kubeClient.Pod(map[string]string{"app": "my-app"})
pod.WaitingForRunningPod(ctx)
```
### Working with Namespaces
```go
namespace := kubeClient.Namespace("my-namespace")
namespace.LabelNamespace(ctx, map[string]string{
"environment": "test",
})
```
### System Utilities
```go
import "github.com/1Password/onepassword-operator/pkg/testhelper/system"
// Run shell commands
output, err := system.Run("kubectl", "get", "pods")
// Get project root directory
rootDir, err := system.GetProjectRoot()
// Replace files
err := system.ReplaceFile("source.yaml", "dest.yaml")
```
### Kind Integration
```go
import "github.com/1Password/onepassword-operator/pkg/testhelper/kind"
// Load Docker image to Kind cluster
kind.LoadImageToKind("my-image:latest")
```
## License
MIT License - see the main project LICENSE file for details.

View File

@@ -1,59 +0,0 @@
module github.com/1Password/onepassword-operator/pkg/testhelper
go 1.24.0
toolchain go1.24.5
require (
github.com/onsi/ginkgo/v2 v2.22.0
github.com/onsi/gomega v1.36.1
k8s.io/api v0.33.0
k8s.io/apiextensions-apiserver v0.33.0
k8s.io/apimachinery v0.33.0
k8s.io/client-go v0.33.0
sigs.k8s.io/controller-runtime v0.21.0
)
require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.12.0 // indirect
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/x448/float16 v0.8.4 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.26.0 // indirect
golang.org/x/time v0.9.0 // indirect
golang.org/x/tools v0.33.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

View File

@@ -1,156 +0,0 @@
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk=
github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
k8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs=
k8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc=
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=
k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@@ -11,7 +11,6 @@ import (
. "github.com/onsi/ginkgo/v2"
//nolint:staticcheck // ST1001
. "github.com/onsi/gomega"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
@@ -23,12 +22,12 @@ import (
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
apiv1 "github.com/1Password/onepassword-operator/api/v1"
"github.com/1Password/onepassword-operator/pkg/testhelper/defaults"
)
@@ -45,10 +44,9 @@ type Config struct {
}
type Kube struct {
Config *Config
Client client.Client
Clientset kubernetes.Interface
Mapper meta.RESTMapper
Config *Config
Client client.Client
Mapper meta.RESTMapper
}
func NewKubeClient(config *Config) *Kube {
@@ -75,7 +73,7 @@ func NewKubeClient(config *Config) *Kube {
scheme := runtime.NewScheme()
utilruntime.Must(corev1.AddToScheme(scheme))
utilruntime.Must(appsv1.AddToScheme(scheme))
utilruntime.Must(admissionregistrationv1.AddToScheme(scheme))
utilruntime.Must(apiv1.AddToScheme(scheme)) // add OnePasswordItem to scheme
kubernetesClient, err := client.New(restConfig, client.Options{
Scheme: scheme,
@@ -83,10 +81,6 @@ func NewKubeClient(config *Config) *Kube {
})
Expect(err).NotTo(HaveOccurred())
// Create Kubernetes clientset for logs and other operations
clientset, err := kubernetes.NewForConfig(restConfig)
Expect(err).NotTo(HaveOccurred())
// update the current contexts namespace in kubeconfig
pathOpts := clientcmd.NewDefaultPathOptions()
cfg, err := pathOpts.GetStartingConfig()
@@ -103,10 +97,9 @@ func NewKubeClient(config *Config) *Kube {
Expect(err).NotTo(HaveOccurred())
return &Kube{
Config: config,
Client: kubernetesClient,
Clientset: clientset,
Mapper: rm,
Config: config,
Client: kubernetesClient,
Mapper: rm,
}
}
@@ -128,10 +121,9 @@ func (k *Kube) Deployment(name string) *Deployment {
func (k *Kube) Pod(selector map[string]string) *Pod {
return &Pod{
client: k.Client,
clientset: k.Clientset,
config: k.Config,
selector: selector,
client: k.Client,
config: k.Config,
selector: selector,
}
}
@@ -143,16 +135,8 @@ func (k *Kube) Namespace(name string) *Namespace {
}
}
func (k *Kube) Webhook(name string) *Webhook {
return &Webhook{
client: k.Client,
config: k.Config,
name: name,
}
}
// Apply applies a Kubernetes manifest file using server-side apply.
func (k *Kube) Apply(ctx context.Context, fileName string) {
// ApplyOnePasswordItem applies a OnePasswordItem manifest.
func (k *Kube) ApplyOnePasswordItem(ctx context.Context, fileName string) {
By("Applying " + fileName)
// Derive a short-lived context so this API call won't hang indefinitely.

View File

@@ -2,7 +2,6 @@ package kube
import (
"context"
"io"
"time"
//nolint:staticcheck // ST1001
@@ -11,15 +10,13 @@ import (
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client"
)
type Pod struct {
client client.Client
clientset kubernetes.Interface
config *Config
selector map[string]string
client client.Client
config *Config
selector map[string]string
}
func (p *Pod) WaitingForRunningPod(ctx context.Context) {
@@ -48,101 +45,3 @@ func (p *Pod) WaitingForRunningPod(ctx context.Context) {
g.Expect(foundRunning).To(BeTrue(), "pod not Running yet")
}, p.config.TestConfig.Timeout, p.config.TestConfig.Interval).Should(Succeed())
}
func (p *Pod) GetPodLogs(ctx context.Context) string {
// First find the pod by label selector
var pods corev1.PodList
listOpts := []client.ListOption{
client.InNamespace(p.config.Namespace),
client.MatchingLabels(p.selector),
}
err := p.client.List(ctx, &pods, listOpts...)
Expect(err).NotTo(HaveOccurred())
Expect(pods.Items).NotTo(BeEmpty(), "no pods found with selector %q", labels.Set(p.selector).String())
// Find a running pod to get logs from
var pod *corev1.Pod
for i := range pods.Items {
if pods.Items[i].Status.Phase == corev1.PodRunning {
pod = &pods.Items[i]
break
}
}
Expect(pod).NotTo(BeNil(), "no running pod found with selector %q", labels.Set(p.selector).String())
podName := pod.Name
// Get logs using the Kubernetes clientset
req := p.clientset.CoreV1().Pods(p.config.Namespace).GetLogs(podName, &corev1.PodLogOptions{})
stream, err := req.Stream(context.TODO())
Expect(err).NotTo(HaveOccurred(), "failed to stream logs for pod %s", podName)
defer stream.Close()
// Read all logs from the stream
logs, err := io.ReadAll(stream)
Expect(err).NotTo(HaveOccurred(), "failed to read logs for pod %s", podName)
return string(logs)
}
func (p *Pod) VerifyWebhookInjection(ctx context.Context) {
By("Verifying webhook injection for pod with selector " + labels.Set(p.selector).String())
Eventually(func(g Gomega) {
// short per-attempt timeout to avoid hanging calls while Eventually polls
attemptCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
// First find the pod by label selector
var pods corev1.PodList
listOpts := []client.ListOption{
client.InNamespace(p.config.Namespace),
client.MatchingLabels(p.selector),
}
g.Expect(p.client.List(attemptCtx, &pods, listOpts...)).To(Succeed())
g.Expect(pods.Items).NotTo(BeEmpty(), "no pods found with selector %q", labels.Set(p.selector).String())
// Find a running pod to verify webhook injection
var pod *corev1.Pod
for i := range pods.Items {
if pods.Items[i].Status.Phase == corev1.PodRunning {
pod = &pods.Items[i]
break
}
}
g.Expect(pod).NotTo(BeNil(), "no running pod found with selector %q", labels.Set(p.selector).String())
// Check injection status annotation
g.Expect(pod.Annotations).To(HaveKey("operator.1password.io/status"))
g.Expect(pod.Annotations["operator.1password.io/status"]).To(Equal("injected"))
// Check command was modified to use op run
if len(pod.Spec.Containers) > 0 {
container := pod.Spec.Containers[0]
g.Expect(container.Command).To(HaveLen(4))
g.Expect(container.Command[0]).To(Equal("/op/bin/op"))
g.Expect(container.Command[1]).To(Equal("run"))
g.Expect(container.Command[2]).To(Equal("--"))
}
// Check init container was added
g.Expect(pod.Spec.InitContainers).To(HaveLen(1))
g.Expect(pod.Spec.InitContainers[0].Name).To(Equal("copy-op-bin"))
// Check volume mount was added
g.Expect(pod.Spec.Containers[0].VolumeMounts).To(ContainElement(HaveField("Name", "op-bin")))
}, p.config.TestConfig.Timeout, p.config.TestConfig.Interval).Should(Succeed())
}
func (p *Pod) VerifySecretsInjected(ctx context.Context) {
By("Verifying secrets are injected and concealed in pod with selector " + labels.Set(p.selector).String())
Eventually(func(g Gomega) {
// short per-attempt timeout to avoid hanging calls while Eventually polls
attemptCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
logs := p.GetPodLogs(attemptCtx)
// Check that secrets are concealed in the application logs
g.Expect(logs).To(ContainSubstring("SECRET: '<concealed by 1Password>'"))
}, p.config.TestConfig.Timeout, p.config.TestConfig.Interval).Should(Succeed())
}

View File

@@ -1,33 +0,0 @@
package kube
import (
"context"
"time"
//nolint:staticcheck // ST1001
. "github.com/onsi/ginkgo/v2"
//nolint:staticcheck // ST1001
. "github.com/onsi/gomega"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
type Webhook struct {
client client.Client
config *Config
name string
}
func (w *Webhook) WaitForWebhookToBeRegistered(ctx context.Context) {
By("Waiting for webhook " + w.name + " to be registered")
Eventually(func(g Gomega) {
// short per-attempt timeout to avoid hanging calls while Eventually polls
attemptCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
webhookConfig := &admissionregistrationv1.MutatingWebhookConfiguration{}
err := w.client.Get(attemptCtx, client.ObjectKey{Name: w.name}, webhookConfig)
g.Expect(err).ToNot(HaveOccurred())
}, w.config.TestConfig.Timeout, w.config.TestConfig.Interval).Should(Succeed())
}

View File

@@ -106,7 +106,7 @@ var _ = Describe("Onepassword Operator e2e", Ordered, func() {
func runCommonTestCases(ctx context.Context) {
It("Should create kubernetes secret from manifest file", func() {
By("Creating secret `login` from 1Password item")
kubeClient.Apply(ctx, "secret.yaml")
kubeClient.ApplyOnePasswordItem(ctx, "secret.yaml")
kubeClient.Secret("login").CheckIfExists(ctx)
})
@@ -115,7 +115,7 @@ func runCommonTestCases(ctx context.Context) {
secretName := itemName
By("Creating secret `" + secretName + "` from 1Password item")
kubeClient.Apply(ctx, secretName+".yaml")
kubeClient.ApplyOnePasswordItem(ctx, secretName+".yaml")
kubeClient.Secret(secretName).CheckIfExists(ctx)
By("Reading old password")
@@ -147,7 +147,7 @@ func runCommonTestCases(ctx context.Context) {
secretName := itemName
By("Creating secret `" + secretName + "` from 1Password item")
kubeClient.Apply(ctx, secretName+".yaml")
kubeClient.ApplyOnePasswordItem(ctx, secretName+".yaml")
kubeClient.Secret(secretName).CheckIfExists(ctx)
By("Reading old password")
@@ -205,7 +205,7 @@ func runCommonTestCases(ctx context.Context) {
})
// Ensure the secret exists (created in earlier test), but apply again safely just in case
kubeClient.Apply(ctx, "secret-for-update.yaml")
kubeClient.ApplyOnePasswordItem(ctx, "secret-for-update.yaml")
kubeClient.Secret("secret-for-update").CheckIfExists(ctx)
// add custom secret to the operator