Compare commits

..

30 Commits

Author SHA1 Message Date
Volodymyr Zotov
5ccb0d88bb Merge pull request #224 from 1Password/vzt/test-contributions-workflow
Add workflow to test contributors' PRs
2025-10-02 08:16:43 -05:00
Volodymyr Zotov
3f52bb2840 Add new line at the end of the file 2025-10-02 08:09:04 -05:00
Volodymyr Zotov
7650aef60a Merge pull request #225 from 1Password/vzt/testhelper-module
Introduce testhelper module
2025-10-02 08:07:26 -05:00
Volodymyr Zotov
63e3f29be9 Refactor e2e test workflows 2025-09-30 21:44:16 -05:00
Volodymyr Zotov
49bc9cb329 Use workflow anchors 2025-09-30 21:37:11 -05:00
Volodymyr Zotov
a5e4a352e9 Update readme 2025-09-30 16:59:30 -05:00
Volodymyr Zotov
edde903759 Do not use first pod, but look for matching pod in array 2025-09-30 16:56:10 -05:00
Volodymyr Zotov
03b093ac17 Add webhooks to schema 2025-09-17 11:21:21 -05:00
Volodymyr Zotov
79ee171b7f Add functions to testhelper package 2025-09-17 11:08:11 -05:00
Volodymyr Zotov
c9a8cc6fb8 Add go.sum 2025-09-17 10:52:12 -05:00
Volodymyr Zotov
a390354100 Make testhelper as a standalone module to install as dependency into kubernetes-secrets-injector 2025-09-17 10:45:50 -05:00
Volodymyr Zotov
de62e07bcf Bump action versions in other workflows 2025-09-11 12:20:40 -05:00
Volodymyr Zotov
3ebc536dd7 Add empty line at the end of the file 2025-09-11 11:50:02 -05:00
Volodymyr Zotov
6769e25a98 Do not run e2e tests when making a change on documentation or not realted to the operator files 2025-09-11 11:49:09 -05:00
Volodymyr Zotov
d8734c9ae3 Run e2e tests when pusing to main and bump actions to the latest 2025-09-11 11:16:47 -05:00
Volodymyr Zotov
460742869b Add workflow to run e2e tests on contributor's branch 2025-09-11 11:14:10 -05:00
Volodymyr Zotov
35e476230c Add ok-to-test workflow 2025-09-11 10:52:53 -05:00
Volodymyr Zotov
0f56cab693 Merge pull request #220 from 1Password/vzt/pr-template
Add pull request template
2025-09-09 14:16:03 -05:00
Volodymyr Zotov
a1ab24f244 Add 'Resolves' section 2025-09-09 14:08:15 -05:00
Volodymyr Zotov
13e4b16846 Merge pull request #219 from 1Password/vzt/test-improvements
Add e2e tests
2025-09-09 13:59:59 -05:00
Volodymyr Zotov
3a9691576a Add ok to test workflow 2025-09-05 13:45:29 -05:00
Volodymyr Zotov
94602ddd72 Fix lint errors 2025-09-05 11:34:18 -05:00
Volodymyr Zotov
292c6f0e93 Update testing doc to mention integration and unit tests under single command 2025-09-05 11:24:02 -05:00
Volodymyr Zotov
0f1293ca95 Update testing doc to merge integration and unit tests under single command 2025-09-05 11:20:08 -05:00
Volodymyr Zotov
706ebdd8b8 Copy manager.yaml from test/e2e when starting e2e tests 2025-09-05 10:40:46 -05:00
Volodymyr Zotov
bd963bcd1d Revert config/manager.yaml 2025-09-05 10:40:45 -05:00
Volodymyr Zotov
bf6cac81cb Add capabilities for ["CHOWN", "FOWNER"] to make it more striker 2025-09-04 11:17:38 -05:00
Volodymyr Zotov
9c4849ec2e Ignore these files across entire project 2025-09-04 10:43:55 -05:00
Volodymyr Zotov
c2788770fd Add comment about installing 1p cli in test workflow 2025-09-04 10:41:25 -05:00
Volodymyr Zotov
128954cd80 Add pull request template 2025-08-26 17:05:52 -05:00
25 changed files with 864 additions and 95 deletions

17
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,17 @@
### ✨ 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

@@ -11,10 +11,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Clone the code - name: Clone the code
uses: actions/checkout@v4 uses: actions/checkout@v5
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v5 uses: actions/setup-go@v6
with: with:
go-version-file: go.mod go-version-file: go.mod

52
.github/workflows/e2e-tests.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: E2E Tests
on:
workflow_call:
secrets:
OP_CONNECT_CREDENTIALS:
description: '1Password Connect credentials'
required: true
OP_CONNECT_TOKEN:
description: '1Password Connect token'
required: true
OP_SERVICE_ACCOUNT_TOKEN:
description: '1Password service account token'
required: true
jobs:
e2e-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Install dependencies
run: go mod tidy
- name: Create kind cluster
uses: helm/kind-action@v1
with:
cluster_name: onepassword-operator-test-e2e
# install cli to interact with item in 1Password to update/read using `testhelper/op` package
- name: Install 1Password CLI
uses: 1password/install-cli-action@v2
with:
version: 2.32.0
- name: Create '1password-credentials.json' file
env:
OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }}
run: |
echo "$OP_CONNECT_CREDENTIALS" > 1password-credentials.json
- name: Run E2E tests
run: make test-e2e
env:
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }}
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}

View File

@@ -11,10 +11,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Clone the code - name: Clone the code
uses: actions/checkout@v4 uses: actions/checkout@v5
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v5 uses: actions/setup-go@v6
with: with:
go-version-file: go.mod go-version-file: go.mod

25
.github/workflows/ok-to-test.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
# Write comments "/ok-to-test <hash>" on a pull request. This will emit a repository_dispatch event.
name: Ok To Test
on:
issue_comment:
types: [created]
jobs:
ok-to-test:
runs-on: ubuntu-latest
permissions:
pull-requests: write # For adding reactions to the pull request comments
contents: write # For executing the repository_dispatch event
# Only run for PRs, not issue comments
if: ${{ github.event.issue.pull_request }}
steps:
- name: Slash Command Dispatch
uses: volodymyrZotov/slash-command-dispatch@7c1b623a2b0eba93f684c34f689a441f0be84cf1 # TODO: use peter-evans/slash-command-dispatch when fix for team permissions is released https://github.com/peter-evans/slash-command-dispatch/pull/424
with:
token: ${{ secrets.GITHUB_TOKEN }}
reaction-token: ${{ secrets.GITHUB_TOKEN }}
issue-type: pull-request
commands: ok-to-test
# The repository permission level required by the user to dispatch commands. Only allows 1Password collaborators to run this.
permission: write

View File

@@ -43,7 +43,7 @@ jobs:
name: Create Release Pull Request name: Create Release Pull Request
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v5
- name: Parse release version - name: Parse release version
id: get_version id: get_version

View File

@@ -12,7 +12,7 @@ jobs:
DOCKER_CLI_EXPERIMENTAL: "enabled" DOCKER_CLI_EXPERIMENTAL: "enabled"
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v5
with: with:
fetch-depth: 0 fetch-depth: 0

56
.github/workflows/test-e2e-fork.yml vendored Normal file
View File

@@ -0,0 +1,56 @@
name: E2E tests [fork]
on:
repository_dispatch:
types: [ ok-to-test-command ]
permissions:
contents: read
checks: write
concurrency:
group: e2e-fork-${{ github.event.client_payload.pull_request.number || github.run_id }}
cancel-in-progress: true # cancel previous job runs for the same branch
jobs:
e2e-tests:
uses: ./.github/workflows/e2e-tests.yml
if: |
github.event_name == 'repository_dispatch' &&
github.event.client_payload.slash_command.args.named.sha != '' &&
contains(
github.event.client_payload.pull_request.head.sha,
github.event.client_payload.slash_command.args.named.sha
)
secrets:
OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }}
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }}
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
update-check-status:
needs: 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 }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { data: checks } = await github.rest.checks.listForRef({
...context.repo,
ref: process.env.ref
});
const check = checks.check_runs.filter(c => c.name === 'e2e-test');
const { data: result } = await github.rest.checks.update({
...context.repo,
check_run_id: check[0].id,
status: 'completed',
conclusion: process.env.conclusion
});
return result;

View File

@@ -1,47 +1,43 @@
name: Test E2E name: E2E Tests
on: on:
pull_request: pull_request:
types: [opened, synchronize, reopened] types: [opened, synchronize, reopened]
branches: ['**'] # run for PRs targeting any branch (main and others) branches: ['**'] # run for PRs targeting any branch (main and others)
paths-ignore: &ignore_paths
- 'docs/**'
- '*.md'
- '.golangci.yml'
- '.gitignore'
- '.dockerignore'
- 'LICENSE'
push:
branches: [main]
paths-ignore: *ignore_paths
concurrency: concurrency:
group: e2e-${{ github.event.pull_request.head.ref }} group: e2e-${{ github.event.pull_request.head.ref }}
cancel-in-progress: true # cancel previous job runs for the same branch cancel-in-progress: true # cancel previous job runs for the same branch
jobs: jobs:
e2e-test: check-external-pr:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps: steps:
- name: Checkout code - name: Check if PR is from external contributor
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Install dependencies
run: go mod tidy
- name: Create kind cluster
uses: helm/kind-action@v1
with:
cluster_name: onepassword-operator-test-e2e
- name: Install 1Password CLI
uses: 1password/install-cli-action@v2
with:
version: 2.32.0
- name: Create '1password-credentials.json' file
env:
OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }}
run: | run: |
echo "$OP_CONNECT_CREDENTIALS" > 1password-credentials.json if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then
echo "❌ External PR detected. This workflow requires approval from a maintainer."
echo "Please ask a maintainer to run '/ok-to-test' command to trigger the fork workflow."
exit 1
fi
echo "✅ Internal PR detected. Proceeding with tests."
- name: Run E2E tests e2e-test:
run: make test-e2e needs: check-external-pr
env: if: always() && (needs.check-external-pr.result == 'success' || github.event_name != 'pull_request')
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }} uses: ./.github/workflows/e2e-tests.yml
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} secrets:
OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }}
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }}
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}

View File

@@ -11,10 +11,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Clone the code - name: Clone the code
uses: actions/checkout@v4 uses: actions/checkout@v5
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v5 uses: actions/setup-go@v6
with: with:
go-version-file: go.mod go-version-file: go.mod

4
.gitignore vendored
View File

@@ -26,5 +26,5 @@ go.work
*.swo *.swo
*~ *~
1password-credentials.json **/1password-credentials.json
op-session **/op-session

View File

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

View File

@@ -39,6 +39,7 @@ spec:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
capabilities: capabilities:
drop: [ "ALL" ] drop: [ "ALL" ]
add: ["CHOWN", "FOWNER"]
containers: containers:
- name: connect-api - name: connect-api
image: 1password/connect-api:latest image: 1password/connect-api:latest

View File

@@ -74,7 +74,6 @@ spec:
- --leader-elect - --leader-elect
- --health-probe-bind-address=:8081 - --health-probe-bind-address=:8081
image: 1password/onepassword-operator:latest image: 1password/onepassword-operator:latest
imagePullPolicy: Never
name: manager name: manager
env: env:
- name: OPERATOR_NAME - name: OPERATOR_NAME
@@ -97,7 +96,7 @@ spec:
name: onepassword-token name: onepassword-token
key: token key: token
- name: MANAGE_CONNECT - name: MANAGE_CONNECT
value: "true" value: "false"
# Uncomment the following lines to enable service account token and comment out the OP_CONNECT_TOKEN, OP_CONNECT_HOST and MANAGE_CONNECT env vars. # Uncomment the following lines to enable service account token and comment out the OP_CONNECT_TOKEN, OP_CONNECT_HOST and MANAGE_CONNECT env vars.
# - name: OP_SERVICE_ACCOUNT_TOKEN # - name: OP_SERVICE_ACCOUNT_TOKEN
# valueFrom: # valueFrom:

View File

@@ -1,27 +1,20 @@
# Testing # Testing
## Unit tests ## Unit & Integration tests
**When**: Pure Go logic, no Kubernetes apiserver or network. **When**: Unit (pure Go) and integration (controller-runtime envtest).
**Where**: `internal/...`, `pkg/...` **Where**: `internal/...`, `pkg/...`
**Add files in**: `*_test.go` next to the code. **Add files in**: `*_test.go` next to the code.
**Run**: `make test`
## Integration tests (envtest)
**When**: Controller/reconciler behavior against a mocked kubernetes cluster.
**Where**: `internal/controller/...`
**Framework**: controller-runtimes `envtest`.
**Run**: `make test` **Run**: `make test`
## E2E tests (kind) ## E2E tests (kind)
**When**: Full cluster behavior (CRDs, operator image, Connect/SA flows). **When**: Full cluster behavior (CRDs, operator image, Connect/SA flows).
**Where**: `test/e2e/...` **Where**: `test/e2e/...`
**Add files in**: `*_test.go` next to the code.
**Framework**: Ginkgo + `pkg/testhelper`. **Framework**: Ginkgo + `pkg/testhelper`.
**Local prep**: **Local prep**:
1. [Install `kind`](https://kind.sigs.k8s.io/docs/user/quick-start/#installing-with-a-package-manager) to spin up local Kubernetes cluster. 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>` 2. `export OP_CONNECT_TOKEN=<token>`
3. `export OP_SERVICE_ACCOUNT_TOKEN=<token>` 3. `export OP_SERVICE_ACCOUNT_TOKEN=<token>`
4. `make test-e2e` 4. Put `1password-credentials.json` into project root.
5. Put `1password-credentials.json` into project root. 5. `make test-e2e`
**Run**: `make test-e2e`

6
go.mod
View File

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

115
pkg/testhelper/README.md Normal file
View File

@@ -0,0 +1,115 @@
# 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.

59
pkg/testhelper/go.mod Normal file
View File

@@ -0,0 +1,59 @@
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
)

156
pkg/testhelper/go.sum Normal file
View File

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

View File

@@ -2,6 +2,7 @@ package kube
import ( import (
"context" "context"
"io"
"time" "time"
//nolint:staticcheck // ST1001 //nolint:staticcheck // ST1001
@@ -10,13 +11,15 @@ import (
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
) )
type Pod struct { type Pod struct {
client client.Client client client.Client
config *Config clientset kubernetes.Interface
selector map[string]string config *Config
selector map[string]string
} }
func (p *Pod) WaitingForRunningPod(ctx context.Context) { func (p *Pod) WaitingForRunningPod(ctx context.Context) {
@@ -45,3 +48,101 @@ func (p *Pod) WaitingForRunningPod(ctx context.Context) {
g.Expect(foundRunning).To(BeTrue(), "pod not Running yet") g.Expect(foundRunning).To(BeTrue(), "pod not Running yet")
}, p.config.TestConfig.Timeout, p.config.TestConfig.Interval).Should(Succeed()) }, 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

@@ -0,0 +1,33 @@
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

@@ -1,7 +1,9 @@
package system package system
import ( import (
"errors"
"fmt" "fmt"
"io"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@@ -51,3 +53,42 @@ func GetProjectRoot() (string, error) {
dir = parent dir = parent
} }
} }
func ReplaceFile(src, dst string) error {
rootDir, err := GetProjectRoot()
if err != nil {
return err
}
// Open the source file
sourceFile, err := os.Open(filepath.Join(rootDir, src))
if err != nil {
return err
}
defer func(sourceFile *os.File) {
cerr := sourceFile.Close()
if err != nil {
err = errors.Join(err, cerr)
}
}(sourceFile)
// Create (or overwrite) the destination file
destFile, err := os.Create(filepath.Join(rootDir, dst))
if err != nil {
return err
}
defer func(destFile *os.File) {
cerr := destFile.Close()
if err != nil {
err = errors.Join(err, cerr)
}
}(destFile)
// Copy contents
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
// Ensure data is written to disk
return destFile.Sync()
}

View File

@@ -60,39 +60,42 @@ var _ = Describe("Onepassword Operator e2e", Ordered, func() {
kubeClient.Secret("onepassword-service-account-token").CreateFromEnvVar(ctx, "OP_SERVICE_ACCOUNT_TOKEN") kubeClient.Secret("onepassword-service-account-token").CreateFromEnvVar(ctx, "OP_SERVICE_ACCOUNT_TOKEN")
kubeClient.Secret("onepassword-service-account-token").CheckIfExists(ctx) kubeClient.Secret("onepassword-service-account-token").CheckIfExists(ctx)
By("Replace manager.yaml")
err = system.ReplaceFile("test/e2e/manifests/manager.yaml", "config/manager/manager.yaml")
Expect(err).NotTo(HaveOccurred())
_, err = system.Run("make", "deploy") _, err = system.Run("make", "deploy")
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
kubeClient.Pod(map[string]string{"name": "onepassword-connect-operator"}).WaitingForRunningPod(ctx) kubeClient.Pod(map[string]string{"name": "onepassword-connect-operator"}).WaitingForRunningPod(ctx)
}) })
Context("Use the operator with Connect", func() { Context("Use the operator with Service Account", func() {
BeforeAll(func() {
kubeClient.Pod(map[string]string{"app": "onepassword-connect"}).WaitingForRunningPod(ctx)
})
runCommonTestCases(ctx) runCommonTestCases(ctx)
}) })
Context("Use the operator with Service Account", func() { Context("Use the operator with Connect", func() {
BeforeAll(func() { BeforeAll(func() {
kubeClient.Deployment("onepassword-connect-operator").PatchEnvVars(ctx, []corev1.EnvVar{ kubeClient.Deployment("onepassword-connect-operator").PatchEnvVars(ctx, []corev1.EnvVar{
{Name: "MANAGE_CONNECT", Value: "false"}, {Name: "MANAGE_CONNECT", Value: "true"},
{Name: "OP_CONNECT_HOST", Value: "http://onepassword-connect:8080"},
{ {
Name: "OP_SERVICE_ACCOUNT_TOKEN", Name: "OP_CONNECT_TOKEN",
ValueFrom: &corev1.EnvVarSource{ ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{ SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{ LocalObjectReference: corev1.LocalObjectReference{
Name: "onepassword-service-account-token", Name: "onepassword-token",
}, },
Key: "token", Key: "token",
}, },
}, },
}, },
}, []string{"OP_CONNECT_HOST", "OP_CONNECT_TOKEN"}) }, []string{"OP_SERVICE_ACCOUNT_TOKEN"})
kubeClient.Secret("login").Delete(ctx) // remove secret crated in previous test kubeClient.Secret("login").Delete(ctx) // remove secret crated in previous test
kubeClient.Secret("secret-ignored").Delete(ctx) // remove secret crated in previous test kubeClient.Secret("secret-ignored").Delete(ctx) // remove secret crated in previous test
kubeClient.Secret("secret-for-update").Delete(ctx) // remove secret crated in previous test kubeClient.Secret("secret-for-update").Delete(ctx) // remove secret crated in previous test
kubeClient.Pod(map[string]string{"app": "onepassword-connect"}).WaitingForRunningPod(ctx)
}) })
runCommonTestCases(ctx) runCommonTestCases(ctx)
@@ -101,18 +104,18 @@ var _ = Describe("Onepassword Operator e2e", Ordered, func() {
// runCommonTestCases contains test cases that are common to both Connect and Service Account authentication methods. // runCommonTestCases contains test cases that are common to both Connect and Service Account authentication methods.
func runCommonTestCases(ctx context.Context) { func runCommonTestCases(ctx context.Context) {
It("Should create secret from manifest file", func() { It("Should create kubernetes secret from manifest file", func() {
By("Creating secret `login` from 1Password item") By("Creating secret `login` from 1Password item")
kubeClient.ApplyOnePasswordItem(ctx, "secret.yaml") kubeClient.Apply(ctx, "secret.yaml")
kubeClient.Secret("login").CheckIfExists(ctx) kubeClient.Secret("login").CheckIfExists(ctx)
}) })
It("Secret is updated after POOLING_INTERVAL", func() { It("Kubernetes secret is updated after POOLING_INTERVAL, when updating item in 1Password", func() {
itemName := "secret-for-update" itemName := "secret-for-update"
secretName := itemName secretName := itemName
By("Creating secret `" + secretName + "` from 1Password item") By("Creating secret `" + secretName + "` from 1Password item")
kubeClient.ApplyOnePasswordItem(ctx, secretName+".yaml") kubeClient.Apply(ctx, secretName+".yaml")
kubeClient.Secret(secretName).CheckIfExists(ctx) kubeClient.Secret(secretName).CheckIfExists(ctx)
By("Reading old password") By("Reading old password")
@@ -139,12 +142,12 @@ func runCommonTestCases(ctx context.Context) {
}, defaults.E2ETimeout, defaults.E2EInterval).Should(Succeed()) }, defaults.E2ETimeout, defaults.E2EInterval).Should(Succeed())
}) })
It("1Password item with `ignore-secret` doesn't pull updates to kubernetes secret", func() { It("1Password item with `ignore-secret` tag doesn't pull updates to kubernetes secret", func() {
itemName := "secret-ignored" itemName := "secret-ignored"
secretName := itemName secretName := itemName
By("Creating secret `" + secretName + "` from 1Password item") By("Creating secret `" + secretName + "` from 1Password item")
kubeClient.ApplyOnePasswordItem(ctx, secretName+".yaml") kubeClient.Apply(ctx, secretName+".yaml")
kubeClient.Secret(secretName).CheckIfExists(ctx) kubeClient.Secret(secretName).CheckIfExists(ctx)
By("Reading old password") By("Reading old password")
@@ -202,7 +205,7 @@ func runCommonTestCases(ctx context.Context) {
}) })
// Ensure the secret exists (created in earlier test), but apply again safely just in case // Ensure the secret exists (created in earlier test), but apply again safely just in case
kubeClient.ApplyOnePasswordItem(ctx, "secret-for-update.yaml") kubeClient.Apply(ctx, "secret-for-update.yaml")
kubeClient.Secret("secret-for-update").CheckIfExists(ctx) kubeClient.Secret("secret-for-update").CheckIfExists(ctx)
// add custom secret to the operator // add custom secret to the operator

View File

@@ -0,0 +1,99 @@
# This manager file is used for e2e tests.
# It will be copied to `config/manager` and be used when deploying the operator in e2e tests
# The purpose of it is to increase e2e tests speed and do not introduce additional changes in original `manager.yaml`
apiVersion: v1
kind: Namespace
metadata:
labels:
control-plane: onepassword-connect-operator
app.kubernetes.io/name: namespace
app.kubernetes.io/instance: system
app.kubernetes.io/component: manager
app.kubernetes.io/created-by: onepassword-connect-operator
app.kubernetes.io/part-of: onepassword-connect-operator
app.kubernetes.io/managed-by: kustomize
name: system
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: onepassword-connect-operator
namespace: system
labels:
control-plane: controller-manager
app.kubernetes.io/name: deployment
app.kubernetes.io/instance: controller-manager
app.kubernetes.io/component: manager
app.kubernetes.io/created-by: onepassword-connect-operator
app.kubernetes.io/part-of: onepassword-connect-operator
app.kubernetes.io/managed-by: kustomize
spec:
selector:
matchLabels:
name: onepassword-connect-operator
control-plane: onepassword-connect-operator
replicas: 1
template:
metadata:
annotations:
kubectl.kubernetes.io/default-container: manager
labels:
name: onepassword-connect-operator
control-plane: onepassword-connect-operator
spec:
securityContext:
runAsNonRoot: true
containers:
- command:
- /manager
args:
- --leader-elect
- --health-probe-bind-address=:8081
image: 1password/onepassword-operator:latest
imagePullPolicy: Never
name: manager
env:
- name: OPERATOR_NAME
value: "onepassword-connect-operator"
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: WATCH_NAMESPACE
value: "default"
- name: POLLING_INTERVAL
value: "10"
- name: AUTO_RESTART
value: "false"
- name: OP_SERVICE_ACCOUNT_TOKEN
valueFrom:
secretKeyRef:
name: onepassword-service-account-token
key: token
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
serviceAccountName: onepassword-connect-operator
terminationGracePeriodSeconds: 10