mirror of
https://github.com/1Password/onepassword-operator.git
synced 2025-10-22 15:38:06 +00:00
Compare commits
24 Commits
03b093ac17
...
vzt/fix-ok
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d403a29fdc | ||
![]() |
d30ed0b9d7 | ||
![]() |
db2053fde4 | ||
![]() |
316f605680 | ||
![]() |
7135f439a5 | ||
![]() |
625297c1fb | ||
![]() |
e967f7ce1e | ||
![]() |
5199e9f350 | ||
![]() |
878b38deac | ||
![]() |
1a40b4fb95 | ||
![]() |
4b5d3c5f1a | ||
![]() |
8d4908fb72 | ||
![]() |
6cf52a7bfc | ||
![]() |
7ef9ec6de7 | ||
![]() |
3f52bb2840 | ||
![]() |
63e3f29be9 | ||
![]() |
49bc9cb329 | ||
![]() |
de62e07bcf | ||
![]() |
3ebc536dd7 | ||
![]() |
6769e25a98 | ||
![]() |
d8734c9ae3 | ||
![]() |
460742869b | ||
![]() |
35e476230c | ||
![]() |
3a9691576a |
17
.github/pull_request_template.md
vendored
17
.github/pull_request_template.md
vendored
@@ -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. -->
|
|
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -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
52
.github/workflows/e2e-tests.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
name: E2E Tests [reusable]
|
||||||
|
|
||||||
|
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 }}
|
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
@@ -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
25
.github/workflows/ok-to-test.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Write comments "/ok-to-test sha=<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
|
2
.github/workflows/release-pr.yml
vendored
2
.github/workflows/release-pr.yml
vendored
@@ -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
|
||||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -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
|
||||||
|
|
||||||
|
67
.github/workflows/test-e2e-fork.yml
vendored
Normal file
67
.github/workflows/test-e2e-fork.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
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:
|
||||||
|
run-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: 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.run-e2e-tests.result }}
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
script: |
|
||||||
|
const { data: checks } = await github.rest.checks.listForRef({
|
||||||
|
...context.repo,
|
||||||
|
ref: process.env.ref
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
check_run_id: check[0].id,
|
||||||
|
status: 'completed',
|
||||||
|
conclusion: process.env.conclusion
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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;
|
57
.github/workflows/test-e2e.yml
vendored
57
.github/workflows/test-e2e.yml
vendored
@@ -1,48 +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
|
|
||||||
|
|
||||||
# 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: |
|
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
|
run-e2e-tests:
|
||||||
run: make test-e2e
|
needs: check-external-pr
|
||||||
env:
|
if: always() && (needs.check-external-pr.result == 'success' || github.event_name != 'pull_request')
|
||||||
|
uses: ./.github/workflows/e2e-tests.yml
|
||||||
|
secrets:
|
||||||
|
OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }}
|
||||||
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }}
|
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }}
|
||||||
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
|
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
|
||||||
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -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
|
||||||
|
|
||||||
|
@@ -8,9 +8,6 @@ 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
|
||||||
|
|
||||||
|
109
docs/fork-pr-testing.md
Normal file
109
docs/fork-pr-testing.md
Normal 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
|
@@ -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.
|
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. Put `1password-credentials.json` into project root.
|
4. `make test-e2e`
|
||||||
5. `make test-e2e`
|
5. Put `1password-credentials.json` into project root.
|
||||||
|
|
||||||
|
**Run**: `make test-e2e`
|
||||||
|
6
go.mod
6
go.mod
@@ -4,18 +4,15 @@ 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
|
||||||
@@ -106,7 +103,6 @@ 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
|
||||||
|
@@ -1,115 +0,0 @@
|
|||||||
# OnePassword Operator Test Helper
|
|
||||||
|
|
||||||
This is a standalone Go module that provides testing utilities for Kubernetes operators, specifically designed for testing OnePassword operators but can be used for any Kubernetes operator 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 a secret from environment variable
|
|
||||||
secret := kubeClient.Secret("my-secret")
|
|
||||||
secret.CreateFromEnvVar(ctx, "MY_ENV_VAR")
|
|
||||||
|
|
||||||
// Create a secret from file
|
|
||||||
data := []byte("secret content")
|
|
||||||
secret.CreateFromFile(ctx, "filename", data)
|
|
||||||
|
|
||||||
// Check if secret exists
|
|
||||||
secret.CheckIfExists(ctx)
|
|
||||||
|
|
||||||
// Get secret
|
|
||||||
secretObj := secret.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.
|
|
@@ -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
|
|
||||||
)
|
|
@@ -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=
|
|
@@ -11,7 +11,6 @@ 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"
|
||||||
@@ -23,12 +22,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"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -47,7 +46,6 @@ type Config struct {
|
|||||||
type Kube struct {
|
type Kube struct {
|
||||||
Config *Config
|
Config *Config
|
||||||
Client client.Client
|
Client client.Client
|
||||||
Clientset kubernetes.Interface
|
|
||||||
Mapper meta.RESTMapper
|
Mapper meta.RESTMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +73,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(admissionregistrationv1.AddToScheme(scheme))
|
utilruntime.Must(apiv1.AddToScheme(scheme)) // add OnePasswordItem to scheme
|
||||||
|
|
||||||
kubernetesClient, err := client.New(restConfig, client.Options{
|
kubernetesClient, err := client.New(restConfig, client.Options{
|
||||||
Scheme: scheme,
|
Scheme: scheme,
|
||||||
@@ -83,10 +81,6 @@ 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 context’s namespace in kubeconfig
|
// update the current context’s namespace in kubeconfig
|
||||||
pathOpts := clientcmd.NewDefaultPathOptions()
|
pathOpts := clientcmd.NewDefaultPathOptions()
|
||||||
cfg, err := pathOpts.GetStartingConfig()
|
cfg, err := pathOpts.GetStartingConfig()
|
||||||
@@ -105,7 +99,6 @@ func NewKubeClient(config *Config) *Kube {
|
|||||||
return &Kube{
|
return &Kube{
|
||||||
Config: config,
|
Config: config,
|
||||||
Client: kubernetesClient,
|
Client: kubernetesClient,
|
||||||
Clientset: clientset,
|
|
||||||
Mapper: rm,
|
Mapper: rm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,7 +122,6 @@ 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,
|
||||||
clientset: k.Clientset,
|
|
||||||
config: k.Config,
|
config: k.Config,
|
||||||
selector: selector,
|
selector: selector,
|
||||||
}
|
}
|
||||||
@@ -143,16 +135,8 @@ func (k *Kube) Namespace(name string) *Namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Kube) Webhook(name string) *Webhook {
|
// ApplyOnePasswordItem applies a OnePasswordItem manifest.
|
||||||
return &Webhook{
|
func (k *Kube) ApplyOnePasswordItem(ctx context.Context, fileName string) {
|
||||||
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.
|
||||||
|
@@ -2,7 +2,6 @@ package kube
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
//nolint:staticcheck // ST1001
|
//nolint:staticcheck // ST1001
|
||||||
@@ -11,13 +10,11 @@ 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
|
||||||
clientset kubernetes.Interface
|
|
||||||
config *Config
|
config *Config
|
||||||
selector map[string]string
|
selector map[string]string
|
||||||
}
|
}
|
||||||
@@ -48,90 +45,3 @@ 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())
|
|
||||||
|
|
||||||
// Use the first pod found
|
|
||||||
pod := pods.Items[0]
|
|
||||||
podName := pod.Name
|
|
||||||
|
|
||||||
// Verify pod is running before getting logs
|
|
||||||
Expect(pod.Status.Phase).To(Equal(corev1.PodRunning), "pod %s is not running (status: %s)", podName, pod.Status.Phase)
|
|
||||||
|
|
||||||
// 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())
|
|
||||||
|
|
||||||
// Use the first pod found
|
|
||||||
pod := pods.Items[0]
|
|
||||||
|
|
||||||
// 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())
|
|
||||||
}
|
|
||||||
|
@@ -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())
|
|
||||||
}
|
|
@@ -106,7 +106,7 @@ var _ = Describe("Onepassword Operator e2e", Ordered, func() {
|
|||||||
func runCommonTestCases(ctx context.Context) {
|
func runCommonTestCases(ctx context.Context) {
|
||||||
It("Should create kubernetes 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.Apply(ctx, "secret.yaml")
|
kubeClient.ApplyOnePasswordItem(ctx, "secret.yaml")
|
||||||
kubeClient.Secret("login").CheckIfExists(ctx)
|
kubeClient.Secret("login").CheckIfExists(ctx)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ func runCommonTestCases(ctx context.Context) {
|
|||||||
secretName := itemName
|
secretName := itemName
|
||||||
|
|
||||||
By("Creating secret `" + secretName + "` from 1Password item")
|
By("Creating secret `" + secretName + "` from 1Password item")
|
||||||
kubeClient.Apply(ctx, secretName+".yaml")
|
kubeClient.ApplyOnePasswordItem(ctx, secretName+".yaml")
|
||||||
kubeClient.Secret(secretName).CheckIfExists(ctx)
|
kubeClient.Secret(secretName).CheckIfExists(ctx)
|
||||||
|
|
||||||
By("Reading old password")
|
By("Reading old password")
|
||||||
@@ -147,7 +147,7 @@ func runCommonTestCases(ctx context.Context) {
|
|||||||
secretName := itemName
|
secretName := itemName
|
||||||
|
|
||||||
By("Creating secret `" + secretName + "` from 1Password item")
|
By("Creating secret `" + secretName + "` from 1Password item")
|
||||||
kubeClient.Apply(ctx, secretName+".yaml")
|
kubeClient.ApplyOnePasswordItem(ctx, secretName+".yaml")
|
||||||
kubeClient.Secret(secretName).CheckIfExists(ctx)
|
kubeClient.Secret(secretName).CheckIfExists(ctx)
|
||||||
|
|
||||||
By("Reading old password")
|
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
|
// 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)
|
kubeClient.Secret("secret-for-update").CheckIfExists(ctx)
|
||||||
|
|
||||||
// add custom secret to the operator
|
// add custom secret to the operator
|
||||||
|
Reference in New Issue
Block a user