Compare commits
No commits in common. "master" and "v0.8.1" have entirely different histories.
|
|
@ -14,8 +14,8 @@
|
||||||
"minikube": "none"
|
"minikube": "none"
|
||||||
},
|
},
|
||||||
"ghcr.io/devcontainers/features/go:1": {
|
"ghcr.io/devcontainers/features/go:1": {
|
||||||
"version": "1.22",
|
"version": "1.15",
|
||||||
"golangciLintVersion": "1.58.2"
|
"golangciLintVersion": "1.26.0"
|
||||||
},
|
},
|
||||||
"ghcr.io/mpriscella/features/kind:1": {
|
"ghcr.io/mpriscella/features/kind:1": {
|
||||||
"version": "latest"
|
"version": "latest"
|
||||||
|
|
|
||||||
|
|
@ -15,3 +15,20 @@ review them:
|
||||||
- [ ] Commit messages follow [commit message best practices](https://github.com/jenkinsci/kubernetes-operator/blob/master/CONTRIBUTING.md#commit-messages)
|
- [ ] Commit messages follow [commit message best practices](https://github.com/jenkinsci/kubernetes-operator/blob/master/CONTRIBUTING.md#commit-messages)
|
||||||
|
|
||||||
_See [the contribution guide](https://github.com/jenkinsci/kubernetes-operator/blob/master/CONTRIBUTING.md) for more details._
|
_See [the contribution guide](https://github.com/jenkinsci/kubernetes-operator/blob/master/CONTRIBUTING.md) for more details._
|
||||||
|
|
||||||
|
|
||||||
|
## Reviewer Notes
|
||||||
|
|
||||||
|
If API changes are included, additive changes must be approved by at least two [OWNERS](https://github.com/jenkinsci/kubernetes-operator/blob/master/OWNERS) and backwards incompatible changes must be approved by [more than 50% of the OWNERS](https://github.com/jenkinsci/kubernetes-operator/blob/master/OWNERS).
|
||||||
|
|
||||||
|
# Release Notes
|
||||||
|
|
||||||
|
```
|
||||||
|
Describe any user facing changes here, or delete this block.
|
||||||
|
|
||||||
|
Examples of user facing changes:
|
||||||
|
- API changes
|
||||||
|
- Bug fixes
|
||||||
|
- Any changes in behavior
|
||||||
|
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
name: CI Lint
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, ready_for_review, reopened]
|
||||||
|
jobs:
|
||||||
|
codespell:
|
||||||
|
name: Codespell
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Codespell
|
||||||
|
uses: codespell-project/actions-codespell@v2
|
||||||
|
with:
|
||||||
|
check_filenames: true
|
||||||
|
ignore_words_list: aks,ags,startin,NotIn
|
||||||
|
skip: "*.js,package-lock.json,*.lock,*/Font-Awesome/*,*.toml,*.svg,*assets/vendor/bootstrap*,cert-manager.crds.yaml,*/docs/*"
|
||||||
|
pre-commit:
|
||||||
|
name: PreCommit
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/setup-python@v5.1.0
|
||||||
|
- uses: DeterminateSystems/nix-installer-action@v12
|
||||||
|
with:
|
||||||
|
diagnostic-endpoint: ""
|
||||||
|
- uses: DeterminateSystems/magic-nix-cache-action@v7
|
||||||
|
with:
|
||||||
|
diagnostic-endpoint: ""
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- id: files
|
||||||
|
uses: tj-actions/changed-files@v44
|
||||||
|
- name: nix checks
|
||||||
|
run: nix flake check
|
||||||
|
- name: nix pre-commit
|
||||||
|
run: nix develop . --command pre-commit run --files ${{ steps.files.outputs.all_changed_files }} --show-diff-on-failure
|
||||||
|
|
@ -33,11 +33,14 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name == 'pull_request' || (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
|
if: github.event_name == 'pull_request' || (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
|
||||||
steps:
|
steps:
|
||||||
- uses: DeterminateSystems/nix-installer-action@e50d5f73bfe71c2dd0aa4218de8f4afa59f8f81d # v16
|
- uses: DeterminateSystems/nix-installer-action@v12
|
||||||
|
with:
|
||||||
|
diagnostic-endpoint: ""
|
||||||
|
- uses: DeterminateSystems/magic-nix-cache-action@v7
|
||||||
with:
|
with:
|
||||||
diagnostic-endpoint: ""
|
diagnostic-endpoint: ""
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Check for changes
|
- name: Check for changes
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -51,7 +54,7 @@ jobs:
|
||||||
| sed -e 's/\(.*\)/"\1"/' | xargs sed -i "/date:/c\date: $(date +'%Y-%m-%d')"
|
| sed -e 's/\(.*\)/"\1"/' | xargs sed -i "/date:/c\date: $(date +'%Y-%m-%d')"
|
||||||
|
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v6
|
uses: peter-evans/create-pull-request@v6
|
||||||
if: env.IS_CHANGED == 'true' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
|
if: env.IS_CHANGED == 'true' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
|
||||||
with:
|
with:
|
||||||
commit-message: Auto-updated docs
|
commit-message: Auto-updated docs
|
||||||
|
|
@ -65,11 +68,14 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name == 'pull_request' || (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
|
if: github.event_name == 'pull_request' || (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
|
||||||
steps:
|
steps:
|
||||||
- uses: DeterminateSystems/nix-installer-action@e50d5f73bfe71c2dd0aa4218de8f4afa59f8f81d # v16
|
- uses: DeterminateSystems/nix-installer-action@v12
|
||||||
|
with:
|
||||||
|
diagnostic-endpoint: ""
|
||||||
|
- uses: DeterminateSystems/magic-nix-cache-action@v7
|
||||||
with:
|
with:
|
||||||
diagnostic-endpoint: ""
|
diagnostic-endpoint: ""
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
- name: nix checks
|
- name: nix checks
|
||||||
run: nix flake check
|
run: nix flake check
|
||||||
- name: nix build
|
- name: nix build
|
||||||
|
|
@ -79,9 +85,9 @@ jobs:
|
||||||
run: nix build .#website
|
run: nix build .#website
|
||||||
- name: Setup Pages
|
- name: Setup Pages
|
||||||
id: pages
|
id: pages
|
||||||
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
|
uses: actions/configure-pages@v5
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
|
uses: actions/upload-pages-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: ./result
|
path: ./result
|
||||||
|
|
||||||
|
|
@ -96,4 +102,4 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
id: deployment
|
id: deployment
|
||||||
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
|
uses: actions/deploy-pages@v4
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up env vars
|
- name: Set up env vars
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -51,7 +51,7 @@ jobs:
|
||||||
cp chart/jenkins-operator/crds/jenkins-crd.yaml deploy/crds/jenkins.io_jenkins_crd.yaml
|
cp chart/jenkins-operator/crds/jenkins-crd.yaml deploy/crds/jenkins.io_jenkins_crd.yaml
|
||||||
|
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v6
|
uses: peter-evans/create-pull-request@v6
|
||||||
with:
|
with:
|
||||||
commit-message: Auto-updated Kubernetes Manifests
|
commit-message: Auto-updated Kubernetes Manifests
|
||||||
branch: manifest-deploy-update
|
branch: manifest-deploy-update
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ jobs:
|
||||||
stale:
|
stale:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
|
- uses: actions/stale@v9
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
operations-per-run: 200
|
operations-per-run: 200
|
||||||
|
|
|
||||||
|
|
@ -19,18 +19,15 @@ on:
|
||||||
- 'backup/**'
|
- 'backup/**'
|
||||||
- '*.md'
|
- '*.md'
|
||||||
|
|
||||||
|
#TODO: create a matrix per earch bats file
|
||||||
jobs:
|
jobs:
|
||||||
run-tests:
|
run-tests:
|
||||||
if: github.event.pull_request.draft == false
|
if: github.event.pull_request.draft == false
|
||||||
name: BATS test ${{ matrix.test-file }}
|
name: BATS Run tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
test-file: ["1-deploy", "2-deploy-with-more-options", "3-deploy-with-webhook"]
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up env vars
|
- name: Set up env vars
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -41,7 +38,7 @@ jobs:
|
||||||
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Prepare go environment
|
- name: Prepare go environment
|
||||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
|
||||||
|
|
@ -49,7 +46,7 @@ jobs:
|
||||||
run: make go-dependencies
|
run: make go-dependencies
|
||||||
|
|
||||||
- name: Setup Bats and libs
|
- name: Setup Bats and libs
|
||||||
uses: bats-core/bats-action@e412797c46257a2dbf3775f6f6010b33ee6cb99f # 3.0.1
|
uses: bats-core/bats-action@2.0.0
|
||||||
with:
|
with:
|
||||||
support-path: "${{ github.workspace }}/.bats/bats-support"
|
support-path: "${{ github.workspace }}/.bats/bats-support"
|
||||||
assert-path: "${{ github.workspace }}/.bats/bats-assert"
|
assert-path: "${{ github.workspace }}/.bats/bats-assert"
|
||||||
|
|
@ -57,11 +54,11 @@ jobs:
|
||||||
file-path: "${{ github.workspace }}/.bats/bats-file"
|
file-path: "${{ github.workspace }}/.bats/bats-file"
|
||||||
|
|
||||||
- name: Kind setup
|
- name: Kind setup
|
||||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
uses: helm/kind-action@v1.10.0
|
||||||
with:
|
with:
|
||||||
cluster_name: ${{env.KIND_CLUSTER_NAME}}
|
cluster_name: ${{env.KIND_CLUSTER_NAME}}
|
||||||
|
|
||||||
- name: Jenkins Operator - bats tests
|
- name: Jenkins Operator - bats tests
|
||||||
env:
|
env:
|
||||||
BATS_LIB_PATH: "${{ github.workspace }}/.bats"
|
BATS_LIB_PATH: "${{ github.workspace }}/.bats"
|
||||||
run: BATS_TEST_PATH=${{matrix.test-file}}.bats make bats-tests
|
run: make bats-tests
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
matrix: ${{ steps.matrix.outputs.matrix }}
|
matrix: ${{ steps.matrix.outputs.matrix }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v4
|
||||||
- id: matrix
|
- id: matrix
|
||||||
run: |
|
run: |
|
||||||
script=$(./test/make_matrix_ginkgo.sh e2e)
|
script=$(./test/make_matrix_ginkgo.sh e2e)
|
||||||
|
|
@ -37,7 +37,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [create-e2e-list]
|
needs: [create-e2e-list]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up env vars
|
- name: Set up env vars
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -46,7 +46,7 @@ jobs:
|
||||||
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Prepare go environment
|
- name: Prepare go environment
|
||||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ jobs:
|
||||||
matrix: ${{ fromJSON(needs.create-e2e-list.outputs.matrix) }}
|
matrix: ${{ fromJSON(needs.create-e2e-list.outputs.matrix) }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up env vars
|
- name: Set up env vars
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -76,7 +76,7 @@ jobs:
|
||||||
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Prepare go environment
|
- name: Prepare go environment
|
||||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
|
||||||
|
|
@ -84,7 +84,7 @@ jobs:
|
||||||
run: make go-dependencies
|
run: make go-dependencies
|
||||||
|
|
||||||
- name: Kind setup
|
- name: Kind setup
|
||||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
uses: helm/kind-action@v1.10.0
|
||||||
with:
|
with:
|
||||||
cluster_name: ${{env.KIND_CLUSTER_NAME}}
|
cluster_name: ${{env.KIND_CLUSTER_NAME}}
|
||||||
config: kind-cluster.yaml
|
config: kind-cluster.yaml
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
matrix: ${{ steps.matrix.outputs.matrix }}
|
matrix: ${{ steps.matrix.outputs.matrix }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v4
|
||||||
- id: matrix
|
- id: matrix
|
||||||
run: |
|
run: |
|
||||||
script=$(./test/make_matrix_ginkgo.sh helm)
|
script=$(./test/make_matrix_ginkgo.sh helm)
|
||||||
|
|
@ -37,7 +37,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [create-helm-list]
|
needs: [create-helm-list]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up env vars
|
- name: Set up env vars
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -46,7 +46,7 @@ jobs:
|
||||||
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Prepare go environment
|
- name: Prepare go environment
|
||||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ jobs:
|
||||||
matrix: ${{ fromJSON(needs.create-helm-list.outputs.matrix) }}
|
matrix: ${{ fromJSON(needs.create-helm-list.outputs.matrix) }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up env vars
|
- name: Set up env vars
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -77,7 +77,7 @@ jobs:
|
||||||
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Prepare go environment
|
- name: Prepare go environment
|
||||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ jobs:
|
||||||
run: make go-dependencies
|
run: make go-dependencies
|
||||||
|
|
||||||
- name: Kind setup
|
- name: Kind setup
|
||||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
uses: helm/kind-action@v1.10.0
|
||||||
with:
|
with:
|
||||||
cluster_name: ${{env.KIND_CLUSTER_NAME}}
|
cluster_name: ${{env.KIND_CLUSTER_NAME}}
|
||||||
config: kind-cluster.yaml
|
config: kind-cluster.yaml
|
||||||
|
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
name: auto-update-jenkins-lts
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 7 * * 0'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-and-update-jenkins-lts:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Check out code
|
|
||||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
|
||||||
|
|
||||||
- name: Set up env vars
|
|
||||||
run: |
|
|
||||||
echo "GO111MODULE=on" >> $GITHUB_ENV
|
|
||||||
echo "GO_VERSION=v$(sed -n 's/GO_VERSION=//p' config.base.env | tr -d '\n' | tr -d '"')" >> $GITHUB_ENV
|
|
||||||
echo "KIND_CLUSTER_NAME=$(sed -n 's/KIND_CLUSTER_NAME=//p' config.base.env | tr -d '\n' | tr -d '"')" >> $GITHUB_ENV
|
|
||||||
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Check if update needed
|
|
||||||
id: check
|
|
||||||
run: |
|
|
||||||
CURRENT=$(sed -n 's/LATEST_LTS_VERSION=//p' config.base.env | tr -d '\n' | tr -d '"')
|
|
||||||
LATEST=$(curl -s https://www.jenkins.io/changelog-stable/ | grep -oP 'changelog/\K\d+\.\d+\.\d+' | head -1)
|
|
||||||
|
|
||||||
echo "current=$CURRENT" >> $GITHUB_OUTPUT
|
|
||||||
echo "latest=$LATEST" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
if [ "$CURRENT" != "$LATEST" ]; then
|
|
||||||
echo "needs_update=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "needs_update=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Prepare go environment
|
|
||||||
if: steps.check.outputs.needs_update == 'true'
|
|
||||||
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
|
|
||||||
- name: Ensure Golang runtime dependencies
|
|
||||||
if: steps.check.outputs.needs_update == 'true'
|
|
||||||
run: make go-dependencies
|
|
||||||
|
|
||||||
- name: Update Jenkins lts version
|
|
||||||
if: steps.check.outputs.needs_update == 'true'
|
|
||||||
run: make update-jenkins-lts
|
|
||||||
|
|
||||||
- name: Update Jenkins base plugins
|
|
||||||
if: steps.check.outputs.needs_update == 'true'
|
|
||||||
run: make update-plugins
|
|
||||||
|
|
||||||
- name: Run verify
|
|
||||||
if: steps.check.outputs.needs_update == 'true'
|
|
||||||
run: make verify
|
|
||||||
|
|
||||||
- name: Create Pull Request
|
|
||||||
if: steps.check.outputs.needs_update == 'true'
|
|
||||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
commit-message: "chore: update Jenkins lts version to ${{ steps.check.outputs.latest }}"
|
|
||||||
title: "chore: update Jenkins lts version to ${{ steps.check.outputs.latest }}"
|
|
||||||
body: "auto-update Jenkins lts version from ${{ steps.check.outputs.current }} to ${{ steps.check.outputs.latest }}"
|
|
||||||
branch: auto-update-jenkins-lts-${{ steps.check.outputs.latest }}
|
|
||||||
delete-branch: true
|
|
||||||
|
|
@ -20,7 +20,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Check envs
|
- name: Check envs
|
||||||
run: make -C backup/pvc check-env
|
run: make -C backup/pvc check-env
|
||||||
|
|
@ -46,7 +46,7 @@ jobs:
|
||||||
|
|
||||||
- name: Login to Quay.io
|
- name: Login to Quay.io
|
||||||
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request'
|
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request'
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: quay.io
|
registry: quay.io
|
||||||
username: ${{ secrets.QUAYIO_USERNAME }}
|
username: ${{ secrets.QUAYIO_USERNAME }}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Deploy Helm chart
|
- name: Deploy Helm chart
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -31,7 +31,7 @@ jobs:
|
||||||
|
|
||||||
# Creates pull request with new chart version
|
# Creates pull request with new chart version
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v6
|
uses: peter-evans/create-pull-request@v6
|
||||||
with:
|
with:
|
||||||
commit-message: Release Helm chart ${{ github.event.inputs.chartVersion }}
|
commit-message: Release Helm chart ${{ github.event.inputs.chartVersion }}
|
||||||
branch: helm-chart-release-${{ github.event.inputs.chartVersion }}
|
branch: helm-chart-release-${{ github.event.inputs.chartVersion }}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Prep - check out code
|
- name: Prep - check out code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Prep - Set up env vars
|
- name: Prep - Set up env vars
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -26,7 +26,7 @@ jobs:
|
||||||
|
|
||||||
- name: Prep - setup Bats and bats libs
|
- name: Prep - setup Bats and bats libs
|
||||||
if: ${{ github.event.inputs.skipTests != 'true' }}
|
if: ${{ github.event.inputs.skipTests != 'true' }}
|
||||||
uses: bats-core/bats-action@472edde1138d59aca53ff162fb8d996666d21e4a # 2.0.0
|
uses: bats-core/bats-action@2.0.0
|
||||||
with:
|
with:
|
||||||
support-path: "${{ github.workspace }}/.bats/bats-support"
|
support-path: "${{ github.workspace }}/.bats/bats-support"
|
||||||
assert-path: "${{ github.workspace }}/.bats/bats-assert"
|
assert-path: "${{ github.workspace }}/.bats/bats-assert"
|
||||||
|
|
@ -34,7 +34,7 @@ jobs:
|
||||||
file-path: "${{ github.workspace }}/.bats/bats-file"
|
file-path: "${{ github.workspace }}/.bats/bats-file"
|
||||||
|
|
||||||
- name: Prep - go environment
|
- name: Prep - go environment
|
||||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ jobs:
|
||||||
|
|
||||||
- name: Prep - Kind setup
|
- name: Prep - Kind setup
|
||||||
if: ${{ github.event.inputs.skipTests != 'true' }}
|
if: ${{ github.event.inputs.skipTests != 'true' }}
|
||||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
uses: helm/kind-action@v1.10.0
|
||||||
with:
|
with:
|
||||||
cluster_name: ${{env.KIND_CLUSTER_NAME}}
|
cluster_name: ${{env.KIND_CLUSTER_NAME}}
|
||||||
config: kind-cluster.yaml
|
config: kind-cluster.yaml
|
||||||
|
|
@ -77,7 +77,7 @@ jobs:
|
||||||
run: make bats-tests
|
run: make bats-tests
|
||||||
|
|
||||||
- name: Post - Login to Quay.io
|
- name: Post - Login to Quay.io
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: quay.io
|
registry: quay.io
|
||||||
username: ${{ secrets.QUAYIO_USERNAME }}
|
username: ${{ secrets.QUAYIO_USERNAME }}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ jobs:
|
||||||
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Prepare go environment
|
- name: Prepare go environment
|
||||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
|
||||||
|
|
@ -40,12 +40,12 @@ jobs:
|
||||||
echo "VERSION=$(cat VERSION.txt)" >> $GITHUB_ENV
|
echo "VERSION=$(cat VERSION.txt)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ env.VERSION }}
|
tag_name: ${{ env.VERSION }}
|
||||||
|
|
||||||
- name: Login to Quay.io
|
- name: Login to Quay.io
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: quay.io
|
registry: quay.io
|
||||||
username: ${{ secrets.QUAYIO_USERNAME }}
|
username: ${{ secrets.QUAYIO_USERNAME }}
|
||||||
|
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../" && pwd)"
|
|
||||||
|
|
||||||
PLUGINS=(
|
|
||||||
"configuration-as-code"
|
|
||||||
"git"
|
|
||||||
"job-dsl"
|
|
||||||
"kubernetes"
|
|
||||||
"kubernetes-credentials-provider"
|
|
||||||
"workflow-aggregator"
|
|
||||||
)
|
|
||||||
|
|
||||||
version_compare() {
|
|
||||||
local ver1="$1"
|
|
||||||
local ver2="$2"
|
|
||||||
|
|
||||||
ver1=$(echo "$ver1" | sed 's/\([0-9.]*\).*/\1/')
|
|
||||||
ver2=$(echo "$ver2" | sed 's/\([0-9.]*\).*/\1/')
|
|
||||||
|
|
||||||
if [ "$ver1" = "$ver2" ]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local sorted=$(printf '%s\n%s' "$ver1" "$ver2" | sort -V)
|
|
||||||
local first=$(echo "$sorted" | head -n1)
|
|
||||||
|
|
||||||
if [ "$first" = "$ver1" ]; then
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
return 2
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch_update_center_data() {
|
|
||||||
local jenkins_version="$1"
|
|
||||||
local url="https://updates.jenkins.io/update-center.actual.json?version=${jenkins_version}"
|
|
||||||
local data=$(curl -s -L -f "$url")
|
|
||||||
|
|
||||||
if ! echo "$data" | jq . > /dev/null 2>&1; then
|
|
||||||
echo "error something happened" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$data"
|
|
||||||
}
|
|
||||||
|
|
||||||
find_compatible_version() {
|
|
||||||
local plugin_id="$1"
|
|
||||||
local jenkins_version="$2"
|
|
||||||
local update_data="$3"
|
|
||||||
local plugin_data=$(echo "$update_data" | jq ".plugins[\"$plugin_id\"]")
|
|
||||||
local plugin_version=$(echo "$plugin_data" | jq -r '.version')
|
|
||||||
local compatible_since=$(echo "$plugin_data" | jq -r '.compatibleSinceVersion // empty')
|
|
||||||
|
|
||||||
if [ -n "$compatible_since" ]; then
|
|
||||||
version_compare "$jenkins_version" "$compatible_since"
|
|
||||||
local result=$?
|
|
||||||
if [ $result -eq 1 ]; then
|
|
||||||
echo "Error: Plugin '$plugin_id' requires Jenkins $compatible_since or newer" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$plugin_version"
|
|
||||||
}
|
|
||||||
|
|
||||||
update_go_file() {
|
|
||||||
local file_path="$1"
|
|
||||||
local plugin_id="$2"
|
|
||||||
local new_version="$3"
|
|
||||||
local dry_run="$4"
|
|
||||||
|
|
||||||
local var_name=""
|
|
||||||
case "$plugin_id" in
|
|
||||||
"configuration-as-code") var_name="configurationAsCodePlugin" ;;
|
|
||||||
"git") var_name="gitPlugin" ;;
|
|
||||||
"job-dsl") var_name="jobDslPlugin" ;;
|
|
||||||
"kubernetes") var_name="kubernetesPlugin" ;;
|
|
||||||
"kubernetes-credentials-provider") var_name="kubernetesCredentialsProviderPlugin" ;;
|
|
||||||
"workflow-aggregator") var_name="workflowAggregatorPlugin" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
local relative_path=$(realpath --relative-to="$PROJECT_ROOT" "$file_path")
|
|
||||||
local new_line=" ${var_name} = \"${plugin_id}:${new_version}\""
|
|
||||||
|
|
||||||
if [ "$dry_run" = "true" ]; then
|
|
||||||
echo "$relative_path: $plugin_id:$new_version"
|
|
||||||
else
|
|
||||||
sed -i "s|^[[:space:]]*${var_name}[[:space:]]*=.*|${new_line}|" "$file_path"
|
|
||||||
echo "$relative_path: $var_name -> $plugin_id:$new_version"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
if [ $# -lt 1 ]; then
|
|
||||||
echo "usage: $0 <jenkins-version> [--dry-run]" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local jenkins_version="$1"
|
|
||||||
local dry_run="false"
|
|
||||||
|
|
||||||
if [ $# -gt 1 ] && [ "$2" = "--dry-run" ]; then
|
|
||||||
dry_run="true"
|
|
||||||
fi
|
|
||||||
|
|
||||||
local update_data
|
|
||||||
if ! update_data=$(fetch_update_center_data "$jenkins_version"); then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
for plugin_id in "${PLUGINS[@]}"; do
|
|
||||||
local compatible_version
|
|
||||||
if compatible_version=$(find_compatible_version "$plugin_id" "$jenkins_version" "$update_data"); then
|
|
||||||
#printf "%-35s %-30s\n" "$plugin_id" "$compatible_version"
|
|
||||||
update_go_file "$PROJECT_ROOT/pkg/plugins/base_plugins.go" "$plugin_id" "$compatible_version" "$dry_run"
|
|
||||||
update_go_file "$PROJECT_ROOT/test/e2e/configuration_test.go" "$plugin_id" "$compatible_version" "$dry_run"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
|
|
@ -1,41 +1,30 @@
|
||||||
run:
|
run:
|
||||||
deadline: 5m
|
deadline: 10m
|
||||||
allow-parallel-runners: true
|
|
||||||
skip-files:
|
skip-files:
|
||||||
- api/v1alpha2/zz_generated.deepcopy.go
|
- api/v1alpha2/zz_generated.deepcopy.go
|
||||||
issues:
|
linters-settings:
|
||||||
exclude-use-default: false
|
errcheck:
|
||||||
exclude-rules:
|
check-blank: false
|
||||||
- path: "internal/*"
|
ignore: fmt:.*,io/ioutil:^Read.*,Write
|
||||||
linters:
|
|
||||||
- dupl
|
|
||||||
- path: (.+)_test.go
|
|
||||||
linters:
|
|
||||||
- dupl
|
|
||||||
linters:
|
linters:
|
||||||
disable-all: true
|
enable-all: true
|
||||||
enable:
|
disable:
|
||||||
- dupl
|
- funlen
|
||||||
- errcheck
|
- gocognit
|
||||||
- exportloopref
|
- godox
|
||||||
- goconst
|
- gomnd
|
||||||
|
- gochecknoglobals
|
||||||
|
- gochecknoinits
|
||||||
|
- lll
|
||||||
|
- prealloc
|
||||||
|
- wsl
|
||||||
- gocyclo
|
- gocyclo
|
||||||
- gofmt
|
- scopelint
|
||||||
- goimports
|
- dupl
|
||||||
- gosimple
|
- gosec
|
||||||
- govet
|
- maligned
|
||||||
- ineffassign
|
- testpackage
|
||||||
- loggercheck
|
- goerr113
|
||||||
- misspell
|
|
||||||
- nakedret
|
- nakedret
|
||||||
- staticcheck
|
- nestif
|
||||||
- typecheck
|
- godot
|
||||||
- unconvert
|
|
||||||
- unparam
|
|
||||||
- unused
|
|
||||||
output:
|
|
||||||
sort-results: true
|
|
||||||
sort-order:
|
|
||||||
- file
|
|
||||||
- severity
|
|
||||||
- linter
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,21 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/sirosen/check-jsonschema
|
- repo: https://github.com/sirosen/check-jsonschema
|
||||||
rev: a167de9d5f4e87e1cdb16cb560aa704b79b6f655 # frozen: 0.32.1
|
rev: 0.28.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-github-workflows
|
- id: check-github-workflows
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b # frozen: v5.0.0
|
rev: v4.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: detect-private-key
|
- id: detect-private-key
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- repo: https://github.com/gruntwork-io/pre-commit
|
- repo: https://github.com/gruntwork-io/pre-commit
|
||||||
rev: "d9196b3a0a6fbc530f2bacea36c11a3b0214ff13" # frozen: v0.1.28
|
rev: "v0.1.19"
|
||||||
hooks:
|
hooks:
|
||||||
- id: helmlint
|
- id: helmlint
|
||||||
- repo: https://github.com/norwoodj/helm-docs
|
- repo: https://github.com/norwoodj/helm-docs
|
||||||
rev: "37d3055fece566105cf8cff7c17b7b2355a01677" # frozen: v1.14.2
|
rev: "v1.11.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: helm-docs
|
- id: helm-docs
|
||||||
args:
|
args:
|
||||||
- --chart-search-root=chart/jenkins-operator
|
- --chart-search-root=chart/jenkins-operator
|
||||||
- repo: https://github.com/brokenpip3/pre-commit-hooks
|
|
||||||
rev: dd7b3821637ba3c3a8628ad487fd84edec8006f2 # frozen: 0.0.1
|
|
||||||
hooks:
|
|
||||||
- id: github-actions-hash
|
|
||||||
files: ^.github/workflows/.*\.(yml|yaml)$ # limit only to github workflows
|
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
* @brokenpip3
|
|
||||||
|
|
@ -16,14 +16,14 @@ RUN go mod download
|
||||||
|
|
||||||
# Copy the go source
|
# Copy the go source
|
||||||
COPY api/ api/
|
COPY api/ api/
|
||||||
COPY internal/controller/ internal/controller/
|
COPY controllers/ controllers/
|
||||||
COPY internal/ internal/
|
COPY internal/ internal/
|
||||||
COPY pkg/ pkg/
|
COPY pkg/ pkg/
|
||||||
COPY version/ version/
|
COPY version/ version/
|
||||||
COPY cmd/main.go cmd/main.go
|
COPY main.go main.go
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go
|
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags "-w $CTIMEVAR" -o manager main.go
|
||||||
|
|
||||||
# Use distroless as minimal base image to package the manager binary
|
# Use distroless as minimal base image to package the manager binary
|
||||||
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
||||||
|
|
|
||||||
191
Makefile
191
Makefile
|
|
@ -70,20 +70,16 @@ HAS_GOLINT := $(shell which $(PROJECT_DIR)/bin/golangci-lint)
|
||||||
lint: ## Verifies `golint` passes
|
lint: ## Verifies `golint` passes
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
ifndef HAS_GOLINT
|
ifndef HAS_GOLINT
|
||||||
GOBIN=$(PROJECT_DIR)/bin go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.0
|
$(call go-get-tool,$(PROJECT_DIR)/bin/golangci-lint,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.26.0)
|
||||||
endif
|
endif
|
||||||
@bin/golangci-lint run
|
@bin/golangci-lint run
|
||||||
|
|
||||||
.PHONY: lint-fix
|
|
||||||
lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes
|
|
||||||
@bin/golangci-lint run --fix
|
|
||||||
|
|
||||||
.PHONY: goimports
|
.PHONY: goimports
|
||||||
HAS_GOIMPORTS := $(shell which $(PROJECT_DIR)/bin/goimports)
|
HAS_GOIMPORTS := $(shell which $(PROJECT_DIR)/bin/goimports)
|
||||||
goimports: ## Verifies `goimports` passes
|
goimports: ## Verifies `goimports` passes
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
ifndef HAS_GOIMPORTS
|
ifndef HAS_GOIMPORTS
|
||||||
$(call GOBIN=$(PROJECT_DIR)/bin go install golang.org/x/tools/cmd/goimports@v0.1.0)
|
$(call go-get-tool,$(PROJECT_DIR)/bin/goimports,golang.org/x/tools/cmd/goimports@v0.1.0)
|
||||||
endif
|
endif
|
||||||
@bin/goimports -l -e $(shell find . -type f -name '*.go' -not -path "./vendor/*")
|
@bin/goimports -l -e $(shell find . -type f -name '*.go' -not -path "./vendor/*")
|
||||||
|
|
||||||
|
|
@ -93,17 +89,11 @@ test: ## Runs the go tests
|
||||||
@RUNNING_TESTS=1 go test -tags "$(BUILDTAGS) cgo" $(PACKAGES_FOR_UNIT_TESTS)
|
@RUNNING_TESTS=1 go test -tags "$(BUILDTAGS) cgo" $(PACKAGES_FOR_UNIT_TESTS)
|
||||||
|
|
||||||
.PHONY: e2e
|
.PHONY: e2e
|
||||||
e2e: deepcopy-gen manifests backup-kind-load jenkins-kind-load ## Runs e2e tests, you can use EXTRA_ARGS
|
e2e: deepcopy-gen manifests backup-kind-load ## Runs e2e tests, you can use EXTRA_ARGS
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
RUNNING_TESTS=1 go test -parallel=1 "./test/e2e/" -ginkgo.v -tags "$(BUILDTAGS) cgo" -v -timeout 60m -run "$(E2E_TEST_SELECTOR)" \
|
RUNNING_TESTS=1 go test -parallel=1 "./test/e2e/" -ginkgo.v -tags "$(BUILDTAGS) cgo" -v -timeout 60m -run "$(E2E_TEST_SELECTOR)" \
|
||||||
-jenkins-api-hostname=$(JENKINS_API_HOSTNAME) -jenkins-api-port=$(JENKINS_API_PORT) -jenkins-api-use-nodeport=$(JENKINS_API_USE_NODEPORT) $(E2E_TEST_ARGS)
|
-jenkins-api-hostname=$(JENKINS_API_HOSTNAME) -jenkins-api-port=$(JENKINS_API_PORT) -jenkins-api-use-nodeport=$(JENKINS_API_USE_NODEPORT) $(E2E_TEST_ARGS)
|
||||||
|
|
||||||
.PHONY: jenkins-kind-load
|
|
||||||
jenkins-kind-load: ## Load the jenkins lts version in kind to speed up tests
|
|
||||||
@echo "+ $@"
|
|
||||||
docker pull jenkins/jenkins:$(LATEST_LTS_VERSION)
|
|
||||||
kind load docker-image jenkins/jenkins:$(LATEST_LTS_VERSION) --name $(KIND_CLUSTER_NAME)
|
|
||||||
|
|
||||||
## Backup Section
|
## Backup Section
|
||||||
|
|
||||||
.PHONY: backup-kind-load
|
.PHONY: backup-kind-load
|
||||||
|
|
@ -118,11 +108,11 @@ HAS_HELM := $(shell command -v helm 2> /dev/null)
|
||||||
helm: ## Download helm if it's not present, otherwise symlink
|
helm: ## Download helm if it's not present, otherwise symlink
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
ifeq ($(strip $(HAS_HELM)),)
|
ifeq ($(strip $(HAS_HELM)),)
|
||||||
mkdir -p $(PROJECT_DIR)/bin
|
mkdir -p $(PROJECT_DIR)/bin
|
||||||
curl -Lo $(PROJECT_DIR)/bin/helm.tar.gz https://get.helm.sh/helm-v$(HELM_VERSION)-$(PLATFORM)-amd64.tar.gz && tar xzfv $(PROJECT_DIR)/bin/helm.tar.gz -C $(PROJECT_DIR)/bin
|
curl -Lo $(PROJECT_DIR)/bin/helm.tar.gz https://get.helm.sh/helm-v$(HELM_VERSION)-$(PLATFORM)-amd64.tar.gz && tar xzfv $(PROJECT_DIR)/bin/helm.tar.gz -C $(PROJECT_DIR)/bin
|
||||||
mv $(PROJECT_DIR)/bin/$(PLATFORM)-amd64/helm $(PROJECT_DIR)/bin/helm
|
mv $(PROJECT_DIR)/bin/$(PLATFORM)-amd64/helm $(PROJECT_DIR)/bin/helm
|
||||||
rm -rf $(PROJECT_DIR)/bin/$(PLATFORM)-amd64
|
rm -rf $(PROJECT_DIR)/bin/$(PLATFORM)-amd64
|
||||||
rm -rf $(PROJECT_DIR)/bin/helm.tar.gz
|
rm -rf $(PROJECT_DIR)/bin/helm.tar.gz
|
||||||
else
|
else
|
||||||
mkdir -p $(PROJECT_DIR)/bin
|
mkdir -p $(PROJECT_DIR)/bin
|
||||||
test -L $(PROJECT_DIR)/bin/helm || ln -sf $(shell command -v helm) $(PROJECT_DIR)/bin/helm
|
test -L $(PROJECT_DIR)/bin/helm || ln -sf $(shell command -v helm) $(PROJECT_DIR)/bin/helm
|
||||||
|
|
@ -144,7 +134,7 @@ helm-release-latest: helm
|
||||||
.PHONY: helm-e2e
|
.PHONY: helm-e2e
|
||||||
IMAGE_NAME := quay.io/$(QUAY_ORGANIZATION)/$(QUAY_REGISTRY):$(GITCOMMIT)-amd64
|
IMAGE_NAME := quay.io/$(QUAY_ORGANIZATION)/$(QUAY_REGISTRY):$(GITCOMMIT)-amd64
|
||||||
|
|
||||||
helm-e2e: helm container-runtime-build-amd64 backup-kind-load ## Runs helm e2e tests, you can use EXTRA_ARGS
|
helm-e2e: helm container-runtime-build-amd64 ## Runs helm e2e tests, you can use EXTRA_ARGS
|
||||||
kind load docker-image ${IMAGE_NAME} --name $(KIND_CLUSTER_NAME)
|
kind load docker-image ${IMAGE_NAME} --name $(KIND_CLUSTER_NAME)
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
RUNNING_TESTS=1 go test -parallel=1 "./test/helm/" -ginkgo.v -tags "$(BUILDTAGS) cgo" -v -timeout 60m -run "$(E2E_TEST_SELECTOR)" -image-name=$(IMAGE_NAME) $(E2E_TEST_ARGS)
|
RUNNING_TESTS=1 go test -parallel=1 "./test/helm/" -ginkgo.v -tags "$(BUILDTAGS) cgo" -v -timeout 60m -run "$(E2E_TEST_SELECTOR)" -image-name=$(IMAGE_NAME) $(E2E_TEST_ARGS)
|
||||||
|
|
@ -162,7 +152,7 @@ staticcheck: ## Verifies `staticcheck` passes
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
ifndef HAS_STATICCHECK
|
ifndef HAS_STATICCHECK
|
||||||
$(eval TMP_DIR := $(shell mktemp -d))
|
$(eval TMP_DIR := $(shell mktemp -d))
|
||||||
wget -O $(TMP_DIR)/staticcheck_$(PLATFORM)_amd64.tar.gz https://github.com/dominikh/go-tools/releases/download/2023.1.7/staticcheck_$(PLATFORM)_amd64.tar.gz
|
wget -O $(TMP_DIR)/staticcheck_$(PLATFORM)_amd64.tar.gz https://github.com/dominikh/go-tools/releases/download/2020.1.3/staticcheck_$(PLATFORM)_amd64.tar.gz
|
||||||
tar zxvf $(TMP_DIR)/staticcheck_$(PLATFORM)_amd64.tar.gz -C $(TMP_DIR)
|
tar zxvf $(TMP_DIR)/staticcheck_$(PLATFORM)_amd64.tar.gz -C $(TMP_DIR)
|
||||||
mkdir -p $(PROJECT_DIR)/bin
|
mkdir -p $(PROJECT_DIR)/bin
|
||||||
mv $(TMP_DIR)/staticcheck/staticcheck $(PROJECT_DIR)/bin
|
mv $(TMP_DIR)/staticcheck/staticcheck $(PROJECT_DIR)/bin
|
||||||
|
|
@ -174,8 +164,7 @@ endif
|
||||||
cover: ## Runs go test with coverage
|
cover: ## Runs go test with coverage
|
||||||
@echo "" > coverage.txt
|
@echo "" > coverage.txt
|
||||||
@for d in $(PACKAGES); do \
|
@for d in $(PACKAGES); do \
|
||||||
ENVTEST_K8S_VERSION = 1.26
|
IMG_RUNNING_TESTS=1 go test -race -coverprofile=profile.out -covermode=atomic "$$d"; \
|
||||||
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" IMG_RUNNING_TESTS=1 go test -race -coverprofile=profile.out -covermode=atomic "$$d"; \
|
|
||||||
if [ -f profile.out ]; then \
|
if [ -f profile.out ]; then \
|
||||||
cat profile.out >> coverage.txt; \
|
cat profile.out >> coverage.txt; \
|
||||||
rm profile.out; \
|
rm profile.out; \
|
||||||
|
|
@ -191,36 +180,6 @@ install: ## Installs the executable
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
go install -tags "$(BUILDTAGS)" ${GO_LDFLAGS} $(BUILD_PATH)
|
go install -tags "$(BUILDTAGS)" ${GO_LDFLAGS} $(BUILD_PATH)
|
||||||
|
|
||||||
.PHONY: update-plugins
|
|
||||||
update-plugins: ## Update jenkins base plugins
|
|
||||||
@echo "+ $@"
|
|
||||||
@JENKINS_VERSION=$$(sed -n 's/LATEST_LTS_VERSION=//p' config.base.env | tr -d '\n' | tr -d '"'); \
|
|
||||||
echo "updating plugins for Jenkins $$JENKINS_VERSION"; \
|
|
||||||
./.github/workflows/update-plugins.sh "$$JENKINS_VERSION"
|
|
||||||
|
|
||||||
.PHONY: update-plugins-dry-run
|
|
||||||
update-plugins-dry-run: ## Update jenkins base plugin -- dry run
|
|
||||||
@echo "+ $@"
|
|
||||||
@JENKINS_VERSION=$$(sed -n 's/LATEST_LTS_VERSION=//p' config.base.env | tr -d '\n' | tr -d '"'); \
|
|
||||||
echo "checking plugins for Jenkins $$JENKINS_VERSION -- dry run"; \
|
|
||||||
./.github/workflows/update-plugins.sh "$$JENKINS_VERSION" --dry-run
|
|
||||||
|
|
||||||
.PHONY: update-jenkins-lts
|
|
||||||
update-jenkins-lts: ## Fetch latest Jenkins lts version and update if necessary
|
|
||||||
@echo "+ $@"
|
|
||||||
@LATEST_VERSION=$$(curl -s https://www.jenkins.io/changelog-stable/ | grep -oP 'changelog/\K\d+\.\d+\.\d+' | head -1); \
|
|
||||||
CURRENT_VERSION=$$(sed -n 's/LATEST_LTS_VERSION=//p' config.base.env | tr -d '\n' | tr -d '"'); \
|
|
||||||
echo "current version: $$CURRENT_VERSION"; \
|
|
||||||
echo "latest version: $$LATEST_VERSION"; \
|
|
||||||
if [ "$$CURRENT_VERSION" != "$$LATEST_VERSION" ]; then \
|
|
||||||
echo "updating Jenkins lts version from $$CURRENT_VERSION to $$LATEST_VERSION"; \
|
|
||||||
sed -i "s/LATEST_LTS_VERSION=\".*\"/LATEST_LTS_VERSION=\"$$LATEST_VERSION\"/" config.base.env; \
|
|
||||||
$(MAKE) update-lts-version LATEST_LTS_VERSION=$$LATEST_VERSION; \
|
|
||||||
echo "updated Jenkins LTS version to $$LATEST_VERSION"; \
|
|
||||||
else \
|
|
||||||
echo "up to date"; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
.PHONY: update-lts-version
|
.PHONY: update-lts-version
|
||||||
update-lts-version: ## Update the latest lts version
|
update-lts-version: ## Update the latest lts version
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
|
|
@ -368,7 +327,7 @@ container-runtime-release: container-runtime-release-version container-runtime-r
|
||||||
# so that the user can send e.g. ^C through.
|
# so that the user can send e.g. ^C through.
|
||||||
INTERACTIVE := $(shell [ -t 0 ] && echo 1 || echo 0)
|
INTERACTIVE := $(shell [ -t 0 ] && echo 1 || echo 0)
|
||||||
ifeq ($(INTERACTIVE), 1)
|
ifeq ($(INTERACTIVE), 1)
|
||||||
DOCKER_FLAGS += -t
|
DOCKER_FLAGS += -t
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: container-runtime-run
|
.PHONY: container-runtime-run
|
||||||
|
|
@ -418,22 +377,18 @@ kind-clean: ## Delete kind cluster
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
kind delete cluster --name $(KIND_CLUSTER_NAME)
|
kind delete cluster --name $(KIND_CLUSTER_NAME)
|
||||||
|
|
||||||
.PHONY: kind-revamp
|
.PHONY: bats-tests
|
||||||
kind-revamp: kind-clean kind-setup ## Delete and recreate kind cluster
|
|
||||||
@echo "+ $@"
|
|
||||||
|
|
||||||
.PHONY: bats-tests ## Run bats tests
|
|
||||||
IMAGE_NAME := quay.io/$(QUAY_ORGANIZATION)/$(QUAY_REGISTRY):$(GITCOMMIT)-amd64
|
IMAGE_NAME := quay.io/$(QUAY_ORGANIZATION)/$(QUAY_REGISTRY):$(GITCOMMIT)-amd64
|
||||||
BUILD_PRESENT := $(shell docker images |grep -q ${IMAGE_NAME})
|
BUILD_PRESENT := $(shell docker images |grep -q ${IMAGE_NAME})
|
||||||
ifndef BUILD_PRESENT
|
ifndef BUILD_PRESENT
|
||||||
bats-tests: backup-kind-load container-runtime-build-amd64 ## Run bats tests
|
bats-tests: backup-kind-load container-runtime-build-amd64 ## Run bats tests
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
kind load docker-image ${IMAGE_NAME} --name $(KIND_CLUSTER_NAME)
|
kind load docker-image ${IMAGE_NAME} --name $(KIND_CLUSTER_NAME)
|
||||||
OPERATOR_IMAGE="${IMAGE_NAME}" TERM=xterm bats -T -p test/bats$(if $(BATS_TEST_PATH),/${BATS_TEST_PATH})
|
OPERATOR_IMAGE="${IMAGE_NAME}" TERM=xterm bats -T -p test/bats
|
||||||
else
|
else
|
||||||
bats-tests: backup-kind-load
|
bats-tests: backup-kind-load
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
OPERATOR_IMAGE="${IMAGE_NAME}" TERM=xterm bats -T -p test/bats$(if $(BATS_TEST_PATH),/${BATS_TEST_PATH})
|
OPERATOR_IMAGE="${IMAGE_NAME}" TERM=xterm bats -T -p test/bats
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: crc-start
|
.PHONY: crc-start
|
||||||
|
|
@ -497,7 +452,7 @@ ifneq ($(GITUNTRACKEDCHANGES),)
|
||||||
endif
|
endif
|
||||||
ifneq ($(GITIGNOREDBUTTRACKEDCHANGES),)
|
ifneq ($(GITIGNOREDBUTTRACKEDCHANGES),)
|
||||||
@echo "Ignored but tracked files:"
|
@echo "Ignored but tracked files:"
|
||||||
@git ls-files -i -o --exclude-standard
|
@git ls-files -i -c --exclude-standard
|
||||||
@echo
|
@echo
|
||||||
endif
|
endif
|
||||||
@echo "Dependencies:"
|
@echo "Dependencies:"
|
||||||
|
|
@ -509,7 +464,6 @@ endif
|
||||||
HUGO_PATH = $(shell pwd)/bin/hugo
|
HUGO_PATH = $(shell pwd)/bin/hugo
|
||||||
HUGO_VERSION = v0.99.1
|
HUGO_VERSION = v0.99.1
|
||||||
HAS_HUGO := $(shell $(HUGO_PATH)/hugo version 2>&- | grep $(HUGO_VERSION))
|
HAS_HUGO := $(shell $(HUGO_PATH)/hugo version 2>&- | grep $(HUGO_VERSION))
|
||||||
.PHONY: hugo
|
|
||||||
hugo:
|
hugo:
|
||||||
ifeq ($(HAS_HUGO), )
|
ifeq ($(HAS_HUGO), )
|
||||||
@echo "Installing Hugo $(HUGO_VERSION)"
|
@echo "Installing Hugo $(HUGO_VERSION)"
|
||||||
|
|
@ -532,77 +486,59 @@ run-docs: hugo
|
||||||
|
|
||||||
##################### FROM OPERATOR SDK ########################
|
##################### FROM OPERATOR SDK ########################
|
||||||
# Install CRDs into a cluster
|
# Install CRDs into a cluster
|
||||||
.PHONY: install-crds
|
|
||||||
install-crds: manifests kustomize
|
install-crds: manifests kustomize
|
||||||
$(KUSTOMIZE) build config/crd | kubectl apply -f -
|
$(KUSTOMIZE) build config/crd | kubectl apply -f -
|
||||||
|
|
||||||
# Uninstall CRDs from a cluster
|
# Uninstall CRDs from a cluster
|
||||||
ifndef ignore-not-found
|
|
||||||
ignore-not-found = false
|
|
||||||
endif
|
|
||||||
.PHONY: uninstall-crds
|
|
||||||
uninstall-crds: manifests kustomize
|
uninstall-crds: manifests kustomize
|
||||||
$(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f -
|
$(KUSTOMIZE) build config/crd | kubectl delete -f -
|
||||||
|
|
||||||
# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
|
# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
|
||||||
.PHONY: deploy
|
|
||||||
deploy: manifests kustomize
|
deploy: manifests kustomize
|
||||||
cd config/manager && $(KUSTOMIZE) edit set image controller=quay.io/$(QUAY_ORGANIZATION)/$(QUAY_REGISTRY):$(GITCOMMIT)
|
cd config/manager && $(KUSTOMIZE) edit set image controller=quay.io/$(QUAY_ORGANIZATION)/$(QUAY_REGISTRY):$(GITCOMMIT)
|
||||||
$(KUSTOMIZE) build config/default | kubectl apply -f -
|
$(KUSTOMIZE) build config/default | kubectl apply -f -
|
||||||
|
|
||||||
# UnDeploy controller from the configured Kubernetes cluster in ~/.kube/config
|
# UnDeploy controller from the configured Kubernetes cluster in ~/.kube/config
|
||||||
.PHONY: undeploy
|
|
||||||
undeploy:
|
undeploy:
|
||||||
$(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f -
|
$(KUSTOMIZE) build config/default | kubectl delete -f -
|
||||||
|
|
||||||
# Generate manifests e.g. CRD, RBAC etc.
|
# Generate manifests e.g. CRD, RBAC etc.
|
||||||
.PHONY: manifests
|
|
||||||
manifests: controller-gen
|
manifests: controller-gen
|
||||||
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
|
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
|
||||||
|
|
||||||
# Generate code
|
# Generate code
|
||||||
.PHONY: generate
|
|
||||||
generate: controller-gen
|
generate: controller-gen
|
||||||
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
|
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
|
||||||
|
|
||||||
##@ Build Dependencies
|
# Download controller-gen locally if necessary
|
||||||
|
CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
|
||||||
|
controller-gen:
|
||||||
|
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.4.1)
|
||||||
|
|
||||||
## Location to install dependencies to
|
# Download kustomize locally if necessary
|
||||||
LOCALBIN ?= $(shell pwd)/bin
|
KUSTOMIZE = $(shell pwd)/bin/kustomize
|
||||||
$(LOCALBIN):
|
kustomize:
|
||||||
mkdir -p $(LOCALBIN)
|
$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v3.8.7)
|
||||||
|
|
||||||
## Tool Binaries
|
# go-get-tool will 'go get' any package $2 and install it to $1.
|
||||||
KUSTOMIZE ?= $(LOCALBIN)/kustomize
|
define go-get-tool
|
||||||
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
|
@[ -f $(1) ] || { \
|
||||||
ENVTEST ?= $(LOCALBIN)/setup-envtest
|
set -e ;\
|
||||||
|
TMP_DIR=$$(mktemp -d) ;\
|
||||||
## Tool Versions
|
cd $$TMP_DIR ;\
|
||||||
KUSTOMIZE_VERSION ?= v5.3.0
|
go mod init tmp ;\
|
||||||
CONTROLLER_TOOLS_VERSION ?= v0.14.0
|
echo "Downloading $(2)" ;\
|
||||||
|
GOBIN=$(PROJECT_DIR)/bin go get $(2) ;\
|
||||||
KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"
|
rm -rf $$TMP_DIR ;\
|
||||||
.PHONY: kustomize
|
}
|
||||||
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
|
endef
|
||||||
$(KUSTOMIZE): $(LOCALBIN)
|
|
||||||
test -s $(LOCALBIN)/kustomize || { curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); }
|
|
||||||
|
|
||||||
.PHONY: controller-gen
|
|
||||||
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
|
|
||||||
$(CONTROLLER_GEN): $(LOCALBIN)
|
|
||||||
test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
|
|
||||||
|
|
||||||
.PHONY: envtest
|
|
||||||
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
|
|
||||||
$(ENVTEST): $(LOCALBIN)
|
|
||||||
test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@release-0.17
|
|
||||||
|
|
||||||
.PHONY: operator-sdk
|
.PHONY: operator-sdk
|
||||||
HAS_OPERATOR_SDK := $(shell which $(PROJECT_DIR)/bin/operator-sdk)
|
HAS_OPERATOR_SDK := $(shell which $(PROJECT_DIR)/bin/operator-sdk)
|
||||||
operator-sdk: # Download operator-sdk locally if necessary
|
operator-sdk: # Download operator-sdk locally if necessary
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
ifndef HAS_OPERATOR_SDK
|
ifndef HAS_OPERATOR_SDK
|
||||||
wget -O $(PROJECT_DIR)/bin/operator-sdk https://github.com/operator-framework/operator-sdk/releases/download/v${OPERATOR_SDK_VERSION}/operator-sdk_$(PLATFORM)_amd64
|
wget -O $(PROJECT_DIR)/bin/operator-sdk https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/operator-sdk_$(PLATFORM)_amd64
|
||||||
chmod +x $(PROJECT_DIR)/bin/operator-sdk
|
chmod +x $(PROJECT_DIR)/bin/operator-sdk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
@ -611,7 +547,7 @@ endif
|
||||||
bundle: manifests operator-sdk kustomize
|
bundle: manifests operator-sdk kustomize
|
||||||
bin/operator-sdk generate kustomize manifests -q
|
bin/operator-sdk generate kustomize manifests -q
|
||||||
cd config/manager && $(KUSTOMIZE) edit set image controller=quay.io/$(QUAY_ORGANIZATION)/$(QUAY_REGISTRY):$(VERSION_TAG)
|
cd config/manager && $(KUSTOMIZE) edit set image controller=quay.io/$(QUAY_ORGANIZATION)/$(QUAY_REGISTRY):$(VERSION_TAG)
|
||||||
$(KUSTOMIZE) build config/manifests | bin/operator-sdk generate bundle $(BUNDLE_GEN_FLAGS)
|
$(KUSTOMIZE) build config/manifests | bin/operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
|
||||||
bin/operator-sdk bundle validate ./bundle
|
bin/operator-sdk bundle validate ./bundle
|
||||||
|
|
||||||
# Build the bundle image.
|
# Build the bundle image.
|
||||||
|
|
@ -620,7 +556,6 @@ bundle-build:
|
||||||
docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) .
|
docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) .
|
||||||
|
|
||||||
# Download kubebuilder
|
# Download kubebuilder
|
||||||
.PHONY: kubebuilder
|
|
||||||
kubebuilder:
|
kubebuilder:
|
||||||
mkdir -p ${ENVTEST_ASSETS_DIR}
|
mkdir -p ${ENVTEST_ASSETS_DIR}
|
||||||
test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.7.0/hack/setup-envtest.sh
|
test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.7.0/hack/setup-envtest.sh
|
||||||
|
|
@ -634,50 +569,6 @@ uninstall-cert-manager: kind-setup
|
||||||
kubectl delete -f https://github.com/jetstack/cert-manager/releases/download/v1.5.1/cert-manager.yaml
|
kubectl delete -f https://github.com/jetstack/cert-manager/releases/download/v1.5.1/cert-manager.yaml
|
||||||
|
|
||||||
# Deploy the operator locally along with webhook using helm charts
|
# Deploy the operator locally along with webhook using helm charts
|
||||||
.PHONY: deploy-webhook
|
|
||||||
deploy-webhook: container-runtime-build-amd64
|
deploy-webhook: container-runtime-build-amd64
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
bin/helm upgrade jenkins chart/jenkins-operator --install --set-string operator.image=${IMAGE_NAME} --set webhook.enabled=true --set jenkins.enabled=false
|
bin/helm upgrade jenkins chart/jenkins-operator --install --set-string operator.image=${IMAGE_NAME} --set webhook.enabled=true --set jenkins.enabled=false
|
||||||
|
|
||||||
# https://sdk.operatorframework.io/docs/upgrading-sdk-version/v1.6.1/#gov2-gov3-ansiblev1-helmv1-add-opm-and-catalog-build-makefile-targets
|
|
||||||
.PHONY: opm
|
|
||||||
OPM = ./bin/opm
|
|
||||||
opm:
|
|
||||||
ifeq (,$(wildcard $(OPM)))
|
|
||||||
ifeq (,$(shell which opm 2>/dev/null))
|
|
||||||
@{ \
|
|
||||||
set -e ;\
|
|
||||||
mkdir -p $(dir $(OPM)) ;\
|
|
||||||
curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$${OS}-$${ARCH}-opm ;\
|
|
||||||
chmod +x $(OPM) ;\
|
|
||||||
}
|
|
||||||
else
|
|
||||||
OPM = $(shell which opm)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
BUNDLE_IMGS ?= $(BUNDLE_IMG)
|
|
||||||
CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) ifneq ($(origin CATALOG_BASE_IMG), undefined) FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) endif
|
|
||||||
.PHONY: catalog-build
|
|
||||||
catalog-build: opm
|
|
||||||
$(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)
|
|
||||||
|
|
||||||
.PHONY: catalog-push
|
|
||||||
catalog-push: ## Push the catalog image.
|
|
||||||
$(MAKE) docker-push IMG=$(CATALOG_IMG)
|
|
||||||
|
|
||||||
# PLATFORMS defines the target platforms for the manager image be build to provide support to multiple
|
|
||||||
# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:
|
|
||||||
# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/
|
|
||||||
# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/
|
|
||||||
# - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=<myregistry/image:<tag>> than the export will fail)
|
|
||||||
# To properly provided solutions that supports more than one platform you should use this option.
|
|
||||||
PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
|
|
||||||
.PHONY: docker-buildx
|
|
||||||
docker-buildx: test ## Build and push docker image for the manager for cross-platform support
|
|
||||||
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
|
|
||||||
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
|
|
||||||
- docker buildx create --name project-v3-builder
|
|
||||||
docker buildx use project-v3-builder
|
|
||||||
- docker buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross
|
|
||||||
- docker buildx rm project-v3-builder
|
|
||||||
rm Dockerfile.cross
|
|
||||||
|
|
|
||||||
15
PROJECT
15
PROJECT
|
|
@ -1,21 +1,14 @@
|
||||||
domain: jenkins.io
|
domain: jenkins.io
|
||||||
layout: go.kubebuilder.io/v4
|
layout: go.kubebuilder.io/v3
|
||||||
projectName: jenkins-operator
|
projectName: jenkins-operator
|
||||||
repo: github.com/jenkinsci/kubernetes-operator
|
repo: github.com/jenkinsci/kubernetes-operator
|
||||||
resources:
|
resources:
|
||||||
- api:
|
- crdVersion: v1
|
||||||
crdVersion: v1
|
|
||||||
namespaced: true
|
|
||||||
# TODO(user): Uncomment the below line if this resource implements a controller, else delete it.
|
|
||||||
# controller: true
|
|
||||||
domain: jenkins.io
|
|
||||||
group: jenkins.io
|
group: jenkins.io
|
||||||
kind: Jenkins
|
kind: Jenkins
|
||||||
path: github.com/jenkinsci/kubernetes-operator/api/v1alpha2
|
|
||||||
version: v1alpha2
|
version: v1alpha2
|
||||||
webhooks:
|
webhookVersion: v1
|
||||||
webhookVersion: v1
|
version: 3-alpha
|
||||||
version: "3"
|
|
||||||
plugins:
|
plugins:
|
||||||
manifests.sdk.operatorframework.io/v2: {}
|
manifests.sdk.operatorframework.io/v2: {}
|
||||||
scorecard.sdk.operatorframework.io/v2: {}
|
scorecard.sdk.operatorframework.io/v2: {}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
v0.9.0-beta1
|
v0.8.1
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ type JenkinsSpec struct {
|
||||||
Master JenkinsMaster `json:"master"`
|
Master JenkinsMaster `json:"master"`
|
||||||
|
|
||||||
// SeedJobs defines list of Jenkins Seed Job configurations
|
// SeedJobs defines list of Jenkins Seed Job configurations
|
||||||
// More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuring-seed-jobs-and-pipelines/
|
// More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuration#configure-seed-jobs-and-pipelines
|
||||||
// +optional
|
// +optional
|
||||||
SeedJobs []SeedJob `json:"seedJobs,omitempty"`
|
SeedJobs []SeedJob `json:"seedJobs,omitempty"`
|
||||||
|
|
||||||
|
|
@ -46,12 +46,12 @@ type JenkinsSpec struct {
|
||||||
SlaveService Service `json:"slaveService,omitempty"`
|
SlaveService Service `json:"slaveService,omitempty"`
|
||||||
|
|
||||||
// Backup defines configuration of Jenkins backup
|
// Backup defines configuration of Jenkins backup
|
||||||
// More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuring-backup-and-restore/
|
// More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configure-backup-and-restore/
|
||||||
// +optional
|
// +optional
|
||||||
Backup Backup `json:"backup,omitempty"`
|
Backup Backup `json:"backup,omitempty"`
|
||||||
|
|
||||||
// Backup defines configuration of Jenkins backup restore
|
// Backup defines configuration of Jenkins backup restore
|
||||||
// More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuring-backup-and-restore/
|
// More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configure-backup-and-restore/
|
||||||
// +optional
|
// +optional
|
||||||
Restore Restore `json:"restore,omitempty"`
|
Restore Restore `json:"restore,omitempty"`
|
||||||
|
|
||||||
|
|
@ -311,7 +311,6 @@ type JenkinsMaster struct {
|
||||||
// periodSeconds: 10
|
// periodSeconds: 10
|
||||||
// successThreshold: 1
|
// successThreshold: 1
|
||||||
// timeoutSeconds: 5
|
// timeoutSeconds: 5
|
||||||
// lifecycle: {}
|
|
||||||
// name: jenkins-master
|
// name: jenkins-master
|
||||||
// readinessProbe:
|
// readinessProbe:
|
||||||
// failureThreshold: 3
|
// failureThreshold: 3
|
||||||
|
|
@ -377,12 +376,6 @@ type JenkinsMaster struct {
|
||||||
// +optional
|
// +optional
|
||||||
LatestPlugins *bool `json:"latestPlugins,omitempty"`
|
LatestPlugins *bool `json:"latestPlugins,omitempty"`
|
||||||
|
|
||||||
// Allow to skip installation of both BasePlugins and Plugins.
|
|
||||||
// Requires using a custom image which includes the BasePlugins.
|
|
||||||
// Defaults to false.
|
|
||||||
// +optional
|
|
||||||
SkipPlugins *bool `json:"skipPlugins,omitempty"`
|
|
||||||
|
|
||||||
// DisableCSRFProtection allows you to toggle CSRF Protection on Jenkins
|
// DisableCSRFProtection allows you to toggle CSRF Protection on Jenkins
|
||||||
DisableCSRFProtection bool `json:"disableCSRFProtection"`
|
DisableCSRFProtection bool `json:"disableCSRFProtection"`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -33,7 +34,6 @@ import (
|
||||||
ctrl "sigs.k8s.io/controller-runtime"
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -44,11 +44,11 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Hosturl = "https://ci.jenkins.io/job/Infra/job/plugin-site-api/job/generate-data/lastSuccessfulBuild/artifact/plugins.json.gzip"
|
Hosturl = "https://ci.jenkins.io/job/Infra/job/plugin-site-api/job/generate-data/lastSuccessfulBuild/artifact/plugins.json.gzip"
|
||||||
PluginDataFileCompressedPath = "/tmp/plugins.json.gzip"
|
CompressedFilePath = "/tmp/plugins.json.gzip"
|
||||||
PluginDataFile = "/tmp/plugins.json"
|
PluginDataFile = "/tmp/plugins.json"
|
||||||
shortenedCheckingPeriod = 1 * time.Hour
|
shortenedCheckingPeriod = 1 * time.Hour
|
||||||
defaultCheckingPeriod = 12 * time.Minute
|
defaultCheckingPeriod = 12 * time.Minute
|
||||||
)
|
)
|
||||||
|
|
||||||
func (in *Jenkins) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
func (in *Jenkins) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||||
|
|
@ -58,31 +58,30 @@ func (in *Jenkins) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
|
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
|
||||||
// +kubebuilder:webhook:path=/validate-jenkins-io-jenkins-io-v1alpha2-jenkins,mutating=false,failurePolicy=fail,sideEffects=None,groups=jenkins.io.jenkins.io,resources=jenkins,verbs=create;update,versions=v1alpha2,name=vjenkins.kb.io,admissionReviewVersions={v1}
|
// +kubebuilder:webhook:path=/validate-jenkins-io-jenkins-io-v1alpha2-jenkins,mutating=false,failurePolicy=fail,sideEffects=None,groups=jenkins.io.jenkins.io,resources=jenkins,verbs=create;update,versions=v1alpha2,name=vjenkins.kb.io,admissionReviewVersions={v1,v1beta1}
|
||||||
|
|
||||||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
|
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
|
||||||
func (in *Jenkins) ValidateCreate() (admission.Warnings, error) {
|
func (in *Jenkins) ValidateCreate() error {
|
||||||
if in.Spec.ValidateSecurityWarnings {
|
if in.Spec.ValidateSecurityWarnings {
|
||||||
jenkinslog.Info("validate create", "name", in.Name)
|
jenkinslog.Info("validate create", "name", in.Name)
|
||||||
err := Validate(*in)
|
return Validate(*in)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
|
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
|
||||||
func (in *Jenkins) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
|
func (in *Jenkins) ValidateUpdate(old runtime.Object) error {
|
||||||
if in.Spec.ValidateSecurityWarnings {
|
if in.Spec.ValidateSecurityWarnings {
|
||||||
jenkinslog.Info("validate update", "name", in.Name)
|
jenkinslog.Info("validate update", "name", in.Name)
|
||||||
return nil, Validate(*in)
|
return Validate(*in)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *Jenkins) ValidateDelete() (admission.Warnings, error) {
|
func (in *Jenkins) ValidateDelete() error {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type SecurityValidator struct {
|
type SecurityValidator struct {
|
||||||
|
|
@ -264,17 +263,11 @@ func (in *SecurityValidator) fetchPluginData() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *SecurityValidator) download() error {
|
func (in *SecurityValidator) download() error {
|
||||||
pluginDataFileCompressed, err := os.Create(PluginDataFileCompressedPath)
|
out, err := os.Create(CompressedFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer out.Close()
|
||||||
// ensure pluginDataFileCompressed is closed
|
|
||||||
defer func() {
|
|
||||||
if err := pluginDataFileCompressed.Close(); err != nil {
|
|
||||||
jenkinslog.V(log.VDebug).Info("Failed to close SecurityValidator.download io", "error", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodGet, Hosturl, nil)
|
req, err := http.NewRequest(http.MethodGet, Hosturl, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -291,45 +284,30 @@ func (in *SecurityValidator) download() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer httpResponseCloser(response)
|
defer response.Body.Close()
|
||||||
|
|
||||||
_, err = io.Copy(pluginDataFileCompressed, response.Body)
|
|
||||||
|
|
||||||
|
_, err = io.Copy(out, response.Body)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *SecurityValidator) extract() error {
|
func (in *SecurityValidator) extract() error {
|
||||||
reader, err := os.Open(PluginDataFileCompressedPath)
|
reader, err := os.Open(CompressedFilePath)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer reader.Close()
|
||||||
if err := reader.Close(); err != nil {
|
|
||||||
log.Log.Error(err, "failed to close SecurityValidator.extract.reader ")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
archive, err := gzip.NewReader(reader)
|
archive, err := gzip.NewReader(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer archive.Close()
|
||||||
if err := archive.Close(); err != nil {
|
|
||||||
log.Log.Error(err, "failed to close SecurityValidator.extract.archive ")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
writer, err := os.Create(PluginDataFile)
|
writer, err := os.Create(PluginDataFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer writer.Close()
|
||||||
defer func() {
|
|
||||||
if err := writer.Close(); err != nil {
|
|
||||||
log.Log.Error(err, "failed to close SecurityValidator.extract.writer")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
_, err = io.Copy(writer, archive)
|
_, err = io.Copy(writer, archive)
|
||||||
return err
|
return err
|
||||||
|
|
@ -341,12 +319,8 @@ func (in *SecurityValidator) cache() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer jsonFile.Close()
|
||||||
if err := jsonFile.Close(); err != nil {
|
byteValue, err := ioutil.ReadAll(jsonFile)
|
||||||
log.Log.Error(err, "failed to close SecurityValidator.cache.jsonFile")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
byteValue, err := io.ReadAll(jsonFile)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -372,9 +346,3 @@ func compareVersions(firstVersion string, lastVersion string, pluginVersion stri
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func httpResponseCloser(response *http.Response) {
|
|
||||||
if err := response.Body.Close(); err != nil {
|
|
||||||
log.Log.Error(err, "failed to close http response body")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ func TestValidate(t *testing.T) {
|
||||||
t.Run("Validating when plugins data file is not fetched", func(t *testing.T) {
|
t.Run("Validating when plugins data file is not fetched", func(t *testing.T) {
|
||||||
userplugins := []Plugin{{Name: "script-security", Version: "1.77"}, {Name: "git-client", Version: "3.9"}, {Name: "git", Version: "4.8.1"}, {Name: "plain-credentials", Version: "1.7"}}
|
userplugins := []Plugin{{Name: "script-security", Version: "1.77"}, {Name: "git-client", Version: "3.9"}, {Name: "git", Version: "4.8.1"}, {Name: "plain-credentials", Version: "1.7"}}
|
||||||
jenkinscr := *createJenkinsCR(userplugins, true)
|
jenkinscr := *createJenkinsCR(userplugins, true)
|
||||||
_, got := jenkinscr.ValidateCreate()
|
got := jenkinscr.ValidateCreate()
|
||||||
assert.Equal(t, got, errors.New("plugins data has not been fetched"))
|
assert.Equal(t, got, errors.New("plugins data has not been fetched"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@ func TestValidate(t *testing.T) {
|
||||||
{Name: "plain-credentials"}}}
|
{Name: "plain-credentials"}}}
|
||||||
userplugins := []Plugin{{Name: "script-security", Version: "1.77"}, {Name: "git-client", Version: "3.9"}, {Name: "git", Version: "4.8.1"}, {Name: "plain-credentials", Version: "1.7"}}
|
userplugins := []Plugin{{Name: "script-security", Version: "1.77"}, {Name: "git-client", Version: "3.9"}, {Name: "git", Version: "4.8.1"}, {Name: "plain-credentials", Version: "1.7"}}
|
||||||
jenkinscr := *createJenkinsCR(userplugins, true)
|
jenkinscr := *createJenkinsCR(userplugins, true)
|
||||||
_, got := jenkinscr.ValidateCreate()
|
got := jenkinscr.ValidateCreate()
|
||||||
assert.Nil(t, got)
|
assert.Nil(t, got)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -113,7 +113,7 @@ func TestValidate(t *testing.T) {
|
||||||
}}
|
}}
|
||||||
userplugins := []Plugin{{Name: "google-login", Version: "1.2"}, {Name: "mailer", Version: "1.1"}, {Name: "git", Version: "4.8.1"}, {Name: "command-launcher", Version: "1.6"}, {Name: "workflow-cps", Version: "2.59"}}
|
userplugins := []Plugin{{Name: "google-login", Version: "1.2"}, {Name: "mailer", Version: "1.1"}, {Name: "git", Version: "4.8.1"}, {Name: "command-launcher", Version: "1.6"}, {Name: "workflow-cps", Version: "2.59"}}
|
||||||
jenkinscr := *createJenkinsCR(userplugins, true)
|
jenkinscr := *createJenkinsCR(userplugins, true)
|
||||||
_, got := jenkinscr.ValidateCreate()
|
got := jenkinscr.ValidateCreate()
|
||||||
assert.Equal(t, got, errors.New("security vulnerabilities detected in the following user-defined plugins: \nworkflow-cps:2.59\ngoogle-login:1.2\nmailer:1.1"))
|
assert.Equal(t, got, errors.New("security vulnerabilities detected in the following user-defined plugins: \nworkflow-cps:2.59\ngoogle-login:1.2\nmailer:1.1"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -136,19 +136,19 @@ func TestValidate(t *testing.T) {
|
||||||
|
|
||||||
userplugins = []Plugin{{Name: "handy-uri-templates-2-api", Version: "2.1.8-1.0"}, {Name: "resource-disposer", Version: "0.8"}, {Name: "jjwt-api", Version: "0.11.2-9.c8b45b8bb173"}, {Name: "blueocean-github-pipeline", Version: "1.2.0-beta-3"}, {Name: "ghprb", Version: "1.39"}}
|
userplugins = []Plugin{{Name: "handy-uri-templates-2-api", Version: "2.1.8-1.0"}, {Name: "resource-disposer", Version: "0.8"}, {Name: "jjwt-api", Version: "0.11.2-9.c8b45b8bb173"}, {Name: "blueocean-github-pipeline", Version: "1.2.0-beta-3"}, {Name: "ghprb", Version: "1.39"}}
|
||||||
newjenkinscr := *createJenkinsCR(userplugins, true)
|
newjenkinscr := *createJenkinsCR(userplugins, true)
|
||||||
_, got := newjenkinscr.ValidateUpdate(&oldjenkinscr)
|
got := newjenkinscr.ValidateUpdate(&oldjenkinscr)
|
||||||
assert.Equal(t, got, errors.New("security vulnerabilities detected in the following user-defined plugins: \nhandy-uri-templates-2-api:2.1.8-1.0\nresource-disposer:0.8\nblueocean-github-pipeline:1.2.0-beta-3\nghprb:1.39"))
|
assert.Equal(t, got, errors.New("security vulnerabilities detected in the following user-defined plugins: \nhandy-uri-templates-2-api:2.1.8-1.0\nresource-disposer:0.8\nblueocean-github-pipeline:1.2.0-beta-3\nghprb:1.39"))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Validation is turned off", func(t *testing.T) {
|
t.Run("Validation is turned off", func(t *testing.T) {
|
||||||
userplugins := []Plugin{{Name: "google-login", Version: "1.2"}, {Name: "mailer", Version: "1.1"}, {Name: "git", Version: "4.8.1"}, {Name: "command-launcher", Version: "1.6"}, {Name: "workflow-cps", Version: "2.59"}}
|
userplugins := []Plugin{{Name: "google-login", Version: "1.2"}, {Name: "mailer", Version: "1.1"}, {Name: "git", Version: "4.8.1"}, {Name: "command-launcher", Version: "1.6"}, {Name: "workflow-cps", Version: "2.59"}}
|
||||||
jenkinscr := *createJenkinsCR(userplugins, false)
|
jenkinscr := *createJenkinsCR(userplugins, false)
|
||||||
_, got := jenkinscr.ValidateCreate()
|
got := jenkinscr.ValidateCreate()
|
||||||
assert.Nil(t, got)
|
assert.Nil(t, got)
|
||||||
|
|
||||||
userplugins = []Plugin{{Name: "google-login", Version: "1.2"}, {Name: "mailer", Version: "1.1"}, {Name: "git", Version: "4.8.1"}, {Name: "command-launcher", Version: "1.6"}, {Name: "workflow-cps", Version: "2.59"}}
|
userplugins = []Plugin{{Name: "google-login", Version: "1.2"}, {Name: "mailer", Version: "1.1"}, {Name: "git", Version: "4.8.1"}, {Name: "command-launcher", Version: "1.6"}, {Name: "workflow-cps", Version: "2.59"}}
|
||||||
newjenkinscr := *createJenkinsCR(userplugins, false)
|
newjenkinscr := *createJenkinsCR(userplugins, false)
|
||||||
_, got = newjenkinscr.ValidateUpdate(&jenkinscr)
|
got = newjenkinscr.ValidateUpdate(&jenkinscr)
|
||||||
assert.Nil(t, got)
|
assert.Nil(t, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
//go:build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2021.
|
Copyright 2021.
|
||||||
|
|
@ -361,11 +361,6 @@ func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) {
|
||||||
*out = new(bool)
|
*out = new(bool)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
if in.SkipPlugins != nil {
|
|
||||||
in, out := &in.SkipPlugins, &out.SkipPlugins
|
|
||||||
*out = new(bool)
|
|
||||||
**out = **in
|
|
||||||
}
|
|
||||||
if in.HostAliases != nil {
|
if in.HostAliases != nil {
|
||||||
in, out := &in.HostAliases, &out.HostAliases
|
in, out := &in.HostAliases, &out.HostAliases
|
||||||
*out = make([]corev1.HostAlias, len(*in))
|
*out = make([]corev1.HostAlias, len(*in))
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ RUN apt update \
|
||||||
"$USER"
|
"$USER"
|
||||||
|
|
||||||
COPY bin/*.sh /home/user/bin/
|
COPY bin/*.sh /home/user/bin/
|
||||||
RUN chmod -R a+rx /home/user
|
RUN chmod +x /home/user/bin/*.sh
|
||||||
WORKDIR /home/user/bin
|
WORKDIR /home/user/bin
|
||||||
USER user
|
USER user
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
v0.4.3
|
v0.4.0
|
||||||
|
|
|
||||||
|
|
@ -51,10 +51,6 @@ if [[ "$ret" -eq 0 ]]; then
|
||||||
_log "INFO" "[backup] backup ${BACKUP_NUMBER} was completed without warnings"
|
_log "INFO" "[backup] backup ${BACKUP_NUMBER} was completed without warnings"
|
||||||
elif [[ "$ret" -eq 1 ]]; then
|
elif [[ "$ret" -eq 1 ]]; then
|
||||||
_log "INFO" "[backup] backup ${BACKUP_NUMBER} was completed with some warnings"
|
_log "INFO" "[backup] backup ${BACKUP_NUMBER} was completed with some warnings"
|
||||||
else
|
|
||||||
_log "ERROR" "[backup] backup ${BACKUP_NUMBER} failed with error code: $ret"
|
|
||||||
_clean
|
|
||||||
exit "$ret"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mv "${BACKUP_TMP_DIR}/${BACKUP_NUMBER}.tar.zstd" "${BACKUP_DIR}/${BACKUP_NUMBER}.tar.zstd"
|
mv "${BACKUP_TMP_DIR}/${BACKUP_NUMBER}.tar.zstd" "${BACKUP_DIR}/${BACKUP_NUMBER}.tar.zstd"
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ is_backup_not_exist() {
|
||||||
|
|
||||||
# Check if we have any backup
|
# Check if we have any backup
|
||||||
if is_backup_not_exist "${BACKUP_DIR}"; then
|
if is_backup_not_exist "${BACKUP_DIR}"; then
|
||||||
_log "No backups exist in ${BACKUP_DIR}"
|
|
||||||
echo "-1"
|
echo "-1"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
@ -33,7 +32,6 @@ fi
|
||||||
latest=$(find "${BACKUP_DIR}"/*.tar.* -maxdepth 0 -exec basename {} \; | sort -g | tail -n 1)
|
latest=$(find "${BACKUP_DIR}"/*.tar.* -maxdepth 0 -exec basename {} \; | sort -g | tail -n 1)
|
||||||
|
|
||||||
if [[ "${latest}" == "" ]]; then
|
if [[ "${latest}" == "" ]]; then
|
||||||
_log "Could not get the latest backup."
|
|
||||||
echo "-1"
|
echo "-1"
|
||||||
else
|
else
|
||||||
echo "${latest%%.*}"
|
echo "${latest%%.*}"
|
||||||
|
|
|
||||||
|
|
@ -39,17 +39,7 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tar $OPTS -C "${JENKINS_HOME}" -xf "${BACKUP_DIR}/${BACKUP_NUMBER}.${EXT}" || ret=$?
|
tar $OPTS -C "${JENKINS_HOME}" -xf "${BACKUP_DIR}/${BACKUP_NUMBER}.${EXT}"
|
||||||
|
|
||||||
if [[ "$ret" -eq 0 ]]; then
|
|
||||||
_log "INFO" "[restore] restore ${BACKUP_NUMBER} was completed without warnings"
|
|
||||||
elif [[ "$ret" -eq 1 ]]; then
|
|
||||||
_log "INFO" "[restore] restore ${BACKUP_NUMBER} was completed with some warnings"
|
|
||||||
else
|
|
||||||
_log "ERROR" "[restore] restore ${BACKUP_NUMBER} failed with error code: $ret"
|
|
||||||
exit "$ret"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
_log "INFO" "[restore] deleting lock file ${TRAP_FILE}"
|
_log "INFO" "[restore] deleting lock file ${TRAP_FILE}"
|
||||||
test -f "${TRAP_FILE}" && rm -f "${TRAP_FILE}"
|
test -f "${TRAP_FILE}" && rm -f "${TRAP_FILE}"
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,6 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
entries:
|
entries:
|
||||||
jenkins-operator:
|
jenkins-operator:
|
||||||
- apiVersion: v2
|
|
||||||
appVersion: 0.9.0-beta1
|
|
||||||
created: "2025-04-06T21:25:18.36969916Z"
|
|
||||||
dependencies:
|
|
||||||
- condition: cert-manager.enabled
|
|
||||||
name: cert-manager
|
|
||||||
repository: https://charts.jetstack.io
|
|
||||||
version: 1.14.2
|
|
||||||
- condition: cert-manager.enabled
|
|
||||||
name: cert-manager-crds
|
|
||||||
repository: ""
|
|
||||||
version: 1.14.2
|
|
||||||
description: Kubernetes native operator which fully manages Jenkins on Kubernetes
|
|
||||||
digest: 78b0756202efbf6a05d5016a4358053a07c89c0f4a3f3f1fb447eaf7323df078
|
|
||||||
icon: https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/assets/jenkins-operator-icon.png
|
|
||||||
name: jenkins-operator
|
|
||||||
urls:
|
|
||||||
- https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart/jenkins-operator/jenkins-operator-0.9.0-beta1.tgz
|
|
||||||
version: 0.9.0-beta1
|
|
||||||
- apiVersion: v2
|
- apiVersion: v2
|
||||||
appVersion: 0.8.1
|
appVersion: 0.8.1
|
||||||
created: "2024-07-05T15:26:01.708923805Z"
|
created: "2024-07-05T15:26:01.708923805Z"
|
||||||
|
|
@ -416,4 +397,4 @@ entries:
|
||||||
urls:
|
urls:
|
||||||
- https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart/jenkins-operator/jenkins-operator-0.0.1.tgz
|
- https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart/jenkins-operator/jenkins-operator-0.0.1.tgz
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
generated: "2025-04-06T21:25:18.363088324Z"
|
generated: "2024-07-05T15:26:01.702900485Z"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
appVersion: "0.9.0-beta1"
|
appVersion: "0.8.1"
|
||||||
description: Kubernetes native operator which fully manages Jenkins on Kubernetes
|
description: Kubernetes native operator which fully manages Jenkins on Kubernetes
|
||||||
name: jenkins-operator
|
name: jenkins-operator
|
||||||
version: 0.9.0-beta1
|
version: 0.8.1
|
||||||
icon: https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/assets/jenkins-operator-icon.png
|
icon: https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/assets/jenkins-operator-icon.png
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: cert-manager
|
- name: cert-manager
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# jenkins-operator
|
# jenkins-operator
|
||||||
|
|
||||||
 
|
 
|
||||||
|
|
||||||
Kubernetes native operator which fully manages Jenkins on Kubernetes
|
Kubernetes native operator which fully manages Jenkins on Kubernetes
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ Kubernetes native operator which fully manages Jenkins on Kubernetes
|
||||||
| jenkins.backup.env[2].name | string | `"BACKUP_COUNT"` | |
|
| jenkins.backup.env[2].name | string | `"BACKUP_COUNT"` | |
|
||||||
| jenkins.backup.env[2].value | string | `"3"` | |
|
| jenkins.backup.env[2].value | string | `"3"` | |
|
||||||
| jenkins.backup.getLatestAction[0] | string | `"/home/user/bin/get-latest.sh"` | |
|
| jenkins.backup.getLatestAction[0] | string | `"/home/user/bin/get-latest.sh"` | |
|
||||||
| jenkins.backup.image | string | `"quay.io/jenkins-kubernetes-operator/backup-pvc:v0.4.3"` | |
|
| jenkins.backup.image | string | `"quay.io/jenkins-kubernetes-operator/backup-pvc:v0.4.1"` | |
|
||||||
| jenkins.backup.interval | int | `30` | |
|
| jenkins.backup.interval | int | `30` | |
|
||||||
| jenkins.backup.makeBackupBeforePodDeletion | bool | `true` | |
|
| jenkins.backup.makeBackupBeforePodDeletion | bool | `true` | |
|
||||||
| jenkins.backup.pvc.className | string | `""` | |
|
| jenkins.backup.pvc.className | string | `""` | |
|
||||||
|
|
@ -54,12 +54,11 @@ Kubernetes native operator which fully manages Jenkins on Kubernetes
|
||||||
| jenkins.enabled | bool | `true` | |
|
| jenkins.enabled | bool | `true` | |
|
||||||
| jenkins.env | list | `[]` | |
|
| jenkins.env | list | `[]` | |
|
||||||
| jenkins.hostAliases | object | `{}` | |
|
| jenkins.hostAliases | object | `{}` | |
|
||||||
| jenkins.image | string | `"jenkins/jenkins:2.492.3-lts"` | |
|
| jenkins.image | string | `"jenkins/jenkins:2.452.2-lts"` | |
|
||||||
| jenkins.imagePullPolicy | string | `"Always"` | |
|
| jenkins.imagePullPolicy | string | `"Always"` | |
|
||||||
| jenkins.imagePullSecrets | list | `[]` | |
|
| jenkins.imagePullSecrets | list | `[]` | |
|
||||||
| jenkins.labels | object | `{}` | |
|
| jenkins.labels | object | `{}` | |
|
||||||
| jenkins.latestPlugins | bool | `true` | |
|
| jenkins.latestPlugins | bool | `true` | |
|
||||||
| jenkins.lifecycle | object | `{}` | |
|
|
||||||
| jenkins.livenessProbe.failureThreshold | int | `20` | |
|
| jenkins.livenessProbe.failureThreshold | int | `20` | |
|
||||||
| jenkins.livenessProbe.httpGet.path | string | `"/login"` | |
|
| jenkins.livenessProbe.httpGet.path | string | `"/login"` | |
|
||||||
| jenkins.livenessProbe.httpGet.port | string | `"http"` | |
|
| jenkins.livenessProbe.httpGet.port | string | `"http"` | |
|
||||||
|
|
@ -91,7 +90,6 @@ Kubernetes native operator which fully manages Jenkins on Kubernetes
|
||||||
| jenkins.seedJobAgentImage | string | `""` | |
|
| jenkins.seedJobAgentImage | string | `""` | |
|
||||||
| jenkins.seedJobs | list | `[]` | |
|
| jenkins.seedJobs | list | `[]` | |
|
||||||
| jenkins.serviceAccount.annotations | object | `{}` | |
|
| jenkins.serviceAccount.annotations | object | `{}` | |
|
||||||
| jenkins.skipPlugins | bool | `false` | |
|
|
||||||
| jenkins.terminationGracePeriodSeconds | int | `30` | |
|
| jenkins.terminationGracePeriodSeconds | int | `30` | |
|
||||||
| jenkins.tolerations | list | `[]` | |
|
| jenkins.tolerations | list | `[]` | |
|
||||||
| jenkins.validateSecurityWarnings | bool | `false` | |
|
| jenkins.validateSecurityWarnings | bool | `false` | |
|
||||||
|
|
@ -100,7 +98,7 @@ Kubernetes native operator which fully manages Jenkins on Kubernetes
|
||||||
| jenkins.volumes[0].persistentVolumeClaim.claimName | string | `"jenkins-backup"` | |
|
| jenkins.volumes[0].persistentVolumeClaim.claimName | string | `"jenkins-backup"` | |
|
||||||
| operator.affinity | object | `{}` | |
|
| operator.affinity | object | `{}` | |
|
||||||
| operator.fullnameOverride | string | `""` | |
|
| operator.fullnameOverride | string | `""` | |
|
||||||
| operator.image | string | `"quay.io/jenkins-kubernetes-operator/operator:v0.9.0-beta1"` | |
|
| operator.image | string | `"quay.io/jenkins-kubernetes-operator/operator:v0.8.1"` | |
|
||||||
| operator.imagePullPolicy | string | `"IfNotPresent"` | |
|
| operator.imagePullPolicy | string | `"IfNotPresent"` | |
|
||||||
| operator.imagePullSecrets | list | `[]` | |
|
| operator.imagePullSecrets | list | `[]` | |
|
||||||
| operator.nameOverride | string | `""` | |
|
| operator.nameOverride | string | `""` | |
|
||||||
|
|
@ -114,4 +112,4 @@ Kubernetes native operator which fully manages Jenkins on Kubernetes
|
||||||
| webhook.enabled | bool | `false` | |
|
| webhook.enabled | bool | `false` | |
|
||||||
|
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)
|
Autogenerated from chart metadata using [helm-docs v1.11.2](https://github.com/norwoodj/helm-docs/releases/v1.11.2)
|
||||||
|
|
|
||||||
|
|
@ -1330,11 +1330,6 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
skipPlugins:
|
|
||||||
description: 'Allow to skip installation of both BasePlugins and
|
|
||||||
Plugins. Requires using a custom image which includes the
|
|
||||||
BasePlugins. Defaults to false.'
|
|
||||||
type: boolean
|
|
||||||
terminationGracePeriodSeconds:
|
terminationGracePeriodSeconds:
|
||||||
description: 'Optional duration in seconds the pod needs to terminate gracefully.'
|
description: 'Optional duration in seconds the pod needs to terminate gracefully.'
|
||||||
type: integer
|
type: integer
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -115,7 +115,6 @@ spec:
|
||||||
{{- with .Values.jenkins.hostAliases }}
|
{{- with .Values.jenkins.hostAliases }}
|
||||||
hostAliases: {{ toYaml . | nindent 4 }}
|
hostAliases: {{ toYaml . | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
skipPlugins: {{ .Values.jenkins.skipPlugins }}
|
|
||||||
{{- if .Values.jenkins.terminationGracePeriodSeconds }}
|
{{- if .Values.jenkins.terminationGracePeriodSeconds }}
|
||||||
terminationGracePeriodSeconds: {{ .Values.jenkins.terminationGracePeriodSeconds }}
|
terminationGracePeriodSeconds: {{ .Values.jenkins.terminationGracePeriodSeconds }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
@ -135,9 +134,6 @@ spec:
|
||||||
{{- with .Values.jenkins.env }}
|
{{- with .Values.jenkins.env }}
|
||||||
env: {{- toYaml . | nindent 8 }}
|
env: {{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- with .Values.jenkins.lifecycle}}
|
|
||||||
lifecycle: {{ toYaml . | nindent 10 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.jenkins.volumeMounts }}
|
{{- with .Values.jenkins.volumeMounts }}
|
||||||
volumeMounts: {{- toYaml . | nindent 8 }}
|
volumeMounts: {{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ jenkins:
|
||||||
# image is the name (and tag) of the Jenkins instance
|
# image is the name (and tag) of the Jenkins instance
|
||||||
# Default: jenkins/jenkins:lts
|
# Default: jenkins/jenkins:lts
|
||||||
# It's recommended to use LTS (tag: "lts") version
|
# It's recommended to use LTS (tag: "lts") version
|
||||||
image: jenkins/jenkins:2.528.1-lts
|
image: jenkins/jenkins:2.452.2-lts
|
||||||
|
|
||||||
# env contains jenkins container environment variables
|
# env contains jenkins container environment variables
|
||||||
env: []
|
env: []
|
||||||
|
|
@ -44,9 +44,6 @@ jenkins:
|
||||||
# imagePullPolicy defines policy for pulling images
|
# imagePullPolicy defines policy for pulling images
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
|
|
||||||
# lifecycle is used if you want to specify lifecycle hooks for the master container
|
|
||||||
lifecycle: {}
|
|
||||||
|
|
||||||
# priorityClassName indicates the importance of a Pod relative to other Pods
|
# priorityClassName indicates the importance of a Pod relative to other Pods
|
||||||
# See: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
|
# See: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
|
||||||
priorityClassName: ""
|
priorityClassName: ""
|
||||||
|
|
@ -145,11 +142,6 @@ jenkins:
|
||||||
# SeedJobAgentImage defines the image that will be used by the seed job agent. If not defined jenkins/inbound-agent:3248.v65ecb_254c298-6 will be used.
|
# SeedJobAgentImage defines the image that will be used by the seed job agent. If not defined jenkins/inbound-agent:3248.v65ecb_254c298-6 will be used.
|
||||||
seedJobAgentImage: ""
|
seedJobAgentImage: ""
|
||||||
|
|
||||||
# skipPlugins allows to skip installation of both BasePlugins and Plugins.
|
|
||||||
# Requires using a custom image which includes the BasePlugins.
|
|
||||||
# Defaults to false.
|
|
||||||
skipPlugins: false
|
|
||||||
|
|
||||||
# Resource limit/request for Jenkins
|
# Resource limit/request for Jenkins
|
||||||
# See https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ for details
|
# See https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ for details
|
||||||
resources:
|
resources:
|
||||||
|
|
@ -222,7 +214,7 @@ jenkins:
|
||||||
|
|
||||||
# image used by backup feature
|
# image used by backup feature
|
||||||
# By default using prebuilt backup PVC image
|
# By default using prebuilt backup PVC image
|
||||||
image: quay.io/jenkins-kubernetes-operator/backup-pvc:v0.4.3
|
image: quay.io/jenkins-kubernetes-operator/backup-pvc:v0.4.1
|
||||||
|
|
||||||
# containerName is backup container name
|
# containerName is backup container name
|
||||||
containerName: backup
|
containerName: backup
|
||||||
|
|
@ -320,7 +312,7 @@ operator:
|
||||||
replicaCount: 1
|
replicaCount: 1
|
||||||
|
|
||||||
# image is the name (and tag) of the Jenkins Operator image
|
# image is the name (and tag) of the Jenkins Operator image
|
||||||
image: quay.io/jenkins-kubernetes-operator/operator:v0.9.0-beta1
|
image: quay.io/jenkins-kubernetes-operator/operator:v0.8.1
|
||||||
|
|
||||||
# imagePullPolicy defines policy for pulling images
|
# imagePullPolicy defines policy for pulling images
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@ API_VERSION_NEXT="v1alpha3"
|
||||||
API_VERSION="v1alpha2"
|
API_VERSION="v1alpha2"
|
||||||
CLUSTER_DOMAIN="cluster.local"
|
CLUSTER_DOMAIN="cluster.local"
|
||||||
GEN_CRD_API="gen-crd-api-reference-docs"
|
GEN_CRD_API="gen-crd-api-reference-docs"
|
||||||
GO_VERSION="1.22"
|
GO_VERSION="1.15.6"
|
||||||
HELM_VERSION="3.12.3"
|
HELM_VERSION="3.12.3"
|
||||||
IMAGE_PULL_MODE="local"
|
IMAGE_PULL_MODE="local"
|
||||||
KIND_CLUSTER_NAME="jenkins"
|
KIND_CLUSTER_NAME="jenkins"
|
||||||
LATEST_LTS_VERSION="2.528.1"
|
LATEST_LTS_VERSION="2.452.2"
|
||||||
NAME="kubernetes-operator"
|
NAME="kubernetes-operator"
|
||||||
NAMESPACE="default"
|
NAMESPACE="default"
|
||||||
OPERATOR_SDK_VERSION="1.35.0"
|
OPERATOR_SDK_VERSION="1.3.0"
|
||||||
PKG="github.com/jenkinsci/kubernetes-operator"
|
PKG="github.com/jenkinsci/kubernetes-operator"
|
||||||
QUAY_ORGANIZATION="jenkins-kubernetes-operator"
|
QUAY_ORGANIZATION="jenkins-kubernetes-operator"
|
||||||
QUAY_REGISTRY="operator"
|
QUAY_REGISTRY="operator"
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -28,9 +28,7 @@ patchesStrategicMerge:
|
||||||
# Protect the /metrics endpoint by putting it behind auth.
|
# Protect the /metrics endpoint by putting it behind auth.
|
||||||
# If you want your controller-manager to expose the /metrics
|
# If you want your controller-manager to expose the /metrics
|
||||||
# endpoint w/o any authn/z, please comment the following line.
|
# endpoint w/o any authn/z, please comment the following line.
|
||||||
# Mount the controller config file for loading manager configurations
|
- manager_auth_proxy_patch.yaml
|
||||||
# through a ComponentConfig type
|
|
||||||
- manager_config_patch.yaml
|
|
||||||
|
|
||||||
# Mount the controller config file for loading manager configurations
|
# Mount the controller config file for loading manager configurations
|
||||||
# through a ComponentConfig type
|
# through a ComponentConfig type
|
||||||
|
|
|
||||||
|
|
@ -10,23 +10,15 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: kube-rbac-proxy
|
- name: kube-rbac-proxy
|
||||||
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.1
|
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0
|
||||||
args:
|
args:
|
||||||
- "--secure-listen-address=0.0.0.0:8443"
|
- "--secure-listen-address=0.0.0.0:8443"
|
||||||
- "--upstream=http://127.0.0.1:8080/"
|
- "--upstream=http://127.0.0.1:8080/"
|
||||||
- "--logtostderr=true"
|
- "--logtostderr=true"
|
||||||
- "--v=0"
|
- "--v=10"
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8443
|
- containerPort: 8443
|
||||||
protocol: TCP
|
|
||||||
name: https
|
name: https
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: 500m
|
|
||||||
memory: 128Mi
|
|
||||||
requests:
|
|
||||||
cpu: 5m
|
|
||||||
memory: 64Mi
|
|
||||||
- name: manager
|
- name: manager
|
||||||
args:
|
args:
|
||||||
- "--health-probe-bind-address=:8081"
|
- "--health-probe-bind-address=:8081"
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,6 @@ spec:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
control-plane: controller-manager
|
control-plane: controller-manager
|
||||||
annotations:
|
|
||||||
kubectl.kubernetes.io/default-container: manager
|
|
||||||
spec:
|
spec:
|
||||||
serviceAccountName: jenkins-operator
|
serviceAccountName: jenkins-operator
|
||||||
securityContext:
|
securityContext:
|
||||||
|
|
@ -25,7 +23,7 @@ spec:
|
||||||
- /manager
|
- /manager
|
||||||
args:
|
args:
|
||||||
- --leader-elect
|
- --leader-elect
|
||||||
image: quay.io/jenkins-kubernetes-operator/operator:v0.8.0
|
image: virtuslab/jenkins-operator:v0.7.1
|
||||||
name: jenkins-operator
|
name: jenkins-operator
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
securityContext:
|
securityContext:
|
||||||
|
|
@ -44,8 +42,8 @@ spec:
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpu: 200m
|
cpu: 100m
|
||||||
memory: 100Mi
|
memory: 30Mi
|
||||||
requests:
|
requests:
|
||||||
cpu: 100m
|
cpu: 100m
|
||||||
memory: 20Mi
|
memory: 20Mi
|
||||||
|
|
@ -54,5 +52,4 @@ spec:
|
||||||
valueFrom:
|
valueFrom:
|
||||||
fieldRef:
|
fieldRef:
|
||||||
fieldPath: metadata.namespace
|
fieldPath: metadata.namespace
|
||||||
serviceAccountName: controller-manager
|
|
||||||
terminationGracePeriodSeconds: 10
|
terminationGracePeriodSeconds: 10
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
# Prometheus Monitor Service (Metrics)
|
# Prometheus Monitor Service (Metrics)
|
||||||
apiVersion: monitoring.coreos.com/v1
|
apiVersion: monitoring.coreos.com/v1
|
||||||
kind: ServiceMonitor
|
kind: ServiceMonitor
|
||||||
|
|
@ -10,10 +11,6 @@ spec:
|
||||||
endpoints:
|
endpoints:
|
||||||
- path: /metrics
|
- path: /metrics
|
||||||
port: https
|
port: https
|
||||||
scheme: https
|
|
||||||
bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
|
|
||||||
tlsConfig:
|
|
||||||
insecureSkipVerify: true
|
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
control-plane: controller-manager
|
control-plane: controller-manager
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,5 @@ roleRef:
|
||||||
name: proxy-role
|
name: proxy-role
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: controller-manager
|
name: default
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ spec:
|
||||||
ports:
|
ports:
|
||||||
- name: https
|
- name: https
|
||||||
port: 8443
|
port: 8443
|
||||||
protocol: TCP
|
|
||||||
targetPort: https
|
targetPort: https
|
||||||
selector:
|
selector:
|
||||||
control-plane: controller-manager
|
control-plane: controller-manager
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,3 @@ resources:
|
||||||
- auth_proxy_role.yaml
|
- auth_proxy_role.yaml
|
||||||
- auth_proxy_role_binding.yaml
|
- auth_proxy_role_binding.yaml
|
||||||
- auth_proxy_client_clusterrole.yaml
|
- auth_proxy_client_clusterrole.yaml
|
||||||
- service_account.yaml
|
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,9 @@ metadata:
|
||||||
rules:
|
rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- ""
|
- ""
|
||||||
resources:
|
|
||||||
- configmaps
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- create
|
|
||||||
- update
|
|
||||||
- patch
|
|
||||||
- delete
|
|
||||||
- apiGroups:
|
|
||||||
- coordination.k8s.io
|
- coordination.k8s.io
|
||||||
resources:
|
resources:
|
||||||
|
- configmaps
|
||||||
- leases
|
- leases
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
name: manager-role
|
name: manager-role
|
||||||
rules:
|
rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: controller-manager
|
|
||||||
namespace: system
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: admissionregistration.k8s.io/v1
|
apiVersion: admissionregistration.k8s.io/v1
|
||||||
kind: ValidatingWebhookConfiguration
|
kind: ValidatingWebhookConfiguration
|
||||||
metadata:
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
name: validating-webhook-configuration
|
name: validating-webhook-configuration
|
||||||
webhooks:
|
webhooks:
|
||||||
- admissionReviewVersions:
|
- admissionReviewVersions:
|
||||||
- v1
|
- v1
|
||||||
|
- v1beta1
|
||||||
clientConfig:
|
clientConfig:
|
||||||
service:
|
service:
|
||||||
name: webhook-service
|
name: webhook-service
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ metadata:
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 443
|
- port: 443
|
||||||
protocol: TCP
|
|
||||||
targetPort: 9443
|
targetPort: 9443
|
||||||
selector:
|
selector:
|
||||||
control-plane: controller-manager
|
control-plane: controller-manager
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
|
@ -20,15 +19,15 @@ import (
|
||||||
// enqueueRequestForJenkins enqueues a Request for Secrets and ConfigMaps created by jenkins-operator.
|
// enqueueRequestForJenkins enqueues a Request for Secrets and ConfigMaps created by jenkins-operator.
|
||||||
type enqueueRequestForJenkins struct{}
|
type enqueueRequestForJenkins struct{}
|
||||||
|
|
||||||
func (e *enqueueRequestForJenkins) Create(ctx context.Context, evt event.CreateEvent, q workqueue.RateLimitingInterface) {
|
func (e *enqueueRequestForJenkins) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) {
|
||||||
if req := e.getOwnerReconcileRequests(ctx, evt.Object); req != nil {
|
if req := e.getOwnerReconcileRequests(evt.Object); req != nil {
|
||||||
q.Add(*req)
|
q.Add(*req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *enqueueRequestForJenkins) Update(ctx context.Context, evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
func (e *enqueueRequestForJenkins) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
||||||
req1 := e.getOwnerReconcileRequests(ctx, evt.ObjectOld)
|
req1 := e.getOwnerReconcileRequests(evt.ObjectOld)
|
||||||
req2 := e.getOwnerReconcileRequests(ctx, evt.ObjectNew)
|
req2 := e.getOwnerReconcileRequests(evt.ObjectNew)
|
||||||
|
|
||||||
if req1 != nil || req2 != nil {
|
if req1 != nil || req2 != nil {
|
||||||
jenkinsName := "unknown"
|
jenkinsName := "unknown"
|
||||||
|
|
@ -52,19 +51,19 @@ func (e *enqueueRequestForJenkins) Update(ctx context.Context, evt event.UpdateE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *enqueueRequestForJenkins) Delete(ctx context.Context, evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
func (e *enqueueRequestForJenkins) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
||||||
if req := e.getOwnerReconcileRequests(ctx, evt.Object); req != nil {
|
if req := e.getOwnerReconcileRequests(evt.Object); req != nil {
|
||||||
q.Add(*req)
|
q.Add(*req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *enqueueRequestForJenkins) Generic(ctx context.Context, evt event.GenericEvent, q workqueue.RateLimitingInterface) {
|
func (e *enqueueRequestForJenkins) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) {
|
||||||
if req := e.getOwnerReconcileRequests(ctx, evt.Object); req != nil {
|
if req := e.getOwnerReconcileRequests(evt.Object); req != nil {
|
||||||
q.Add(*req)
|
q.Add(*req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *enqueueRequestForJenkins) getOwnerReconcileRequests(_ context.Context, object metav1.Object) *reconcile.Request {
|
func (e *enqueueRequestForJenkins) getOwnerReconcileRequests(object metav1.Object) *reconcile.Request {
|
||||||
if object.GetLabels()[constants.LabelAppKey] == constants.LabelAppValue &&
|
if object.GetLabels()[constants.LabelAppKey] == constants.LabelAppValue &&
|
||||||
object.GetLabels()[constants.LabelWatchKey] == constants.LabelWatchValue &&
|
object.GetLabels()[constants.LabelWatchKey] == constants.LabelWatchValue &&
|
||||||
len(object.GetLabels()[constants.LabelJenkinsCRKey]) > 0 {
|
len(object.GetLabels()[constants.LabelJenkinsCRKey]) > 0 {
|
||||||
|
|
@ -80,24 +79,24 @@ type jenkinsDecorator struct {
|
||||||
handler handler.EventHandler
|
handler handler.EventHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *jenkinsDecorator) Create(ctx context.Context, evt event.CreateEvent, q workqueue.RateLimitingInterface) {
|
func (e *jenkinsDecorator) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) {
|
||||||
log.Log.WithValues("cr", evt.Object.GetName()).Info(fmt.Sprintf("%T/%s was created", evt.Object, evt.Object.GetName()))
|
log.Log.WithValues("cr", evt.Object.GetName()).Info(fmt.Sprintf("%T/%s was created", evt.Object, evt.Object.GetName()))
|
||||||
e.handler.Create(ctx, evt, q)
|
e.handler.Create(evt, q)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *jenkinsDecorator) Update(ctx context.Context, evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
func (e *jenkinsDecorator) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
||||||
if !reflect.DeepEqual(evt.ObjectOld.(*v1alpha2.Jenkins).Spec, evt.ObjectNew.(*v1alpha2.Jenkins).Spec) {
|
if !reflect.DeepEqual(evt.ObjectOld.(*v1alpha2.Jenkins).Spec, evt.ObjectNew.(*v1alpha2.Jenkins).Spec) {
|
||||||
log.Log.WithValues("cr", evt.ObjectNew.GetName()).Info(
|
log.Log.WithValues("cr", evt.ObjectNew.GetName()).Info(
|
||||||
fmt.Sprintf("%T/%s has been updated", evt.ObjectNew, evt.ObjectNew.GetName()))
|
fmt.Sprintf("%T/%s has been updated", evt.ObjectNew, evt.ObjectNew.GetName()))
|
||||||
}
|
}
|
||||||
e.handler.Update(ctx, evt, q)
|
e.handler.Update(evt, q)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *jenkinsDecorator) Delete(ctx context.Context, evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
func (e *jenkinsDecorator) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
||||||
log.Log.WithValues("cr", evt.Object.GetName()).Info(fmt.Sprintf("%T/%s was deleted", evt.Object, evt.Object.GetName()))
|
log.Log.WithValues("cr", evt.Object.GetName()).Info(fmt.Sprintf("%T/%s was deleted", evt.Object, evt.Object.GetName()))
|
||||||
e.handler.Delete(ctx, evt, q)
|
e.handler.Delete(evt, q)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *jenkinsDecorator) Generic(ctx context.Context, evt event.GenericEvent, q workqueue.RateLimitingInterface) {
|
func (e *jenkinsDecorator) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) {
|
||||||
e.handler.Generic(ctx, evt, q)
|
e.handler.Generic(evt, q)
|
||||||
}
|
}
|
||||||
|
|
@ -46,6 +46,7 @@ import (
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
type reconcileError struct {
|
type reconcileError struct {
|
||||||
|
|
@ -78,22 +79,9 @@ type JenkinsReconciler struct {
|
||||||
// SetupWithManager sets up the controller with the Manager.
|
// SetupWithManager sets up the controller with the Manager.
|
||||||
func (r *JenkinsReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
func (r *JenkinsReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
jenkinsHandler := &enqueueRequestForJenkins{}
|
jenkinsHandler := &enqueueRequestForJenkins{}
|
||||||
configMapResource := &corev1.Secret{
|
configMapResource := &source.Kind{Type: &corev1.ConfigMap{TypeMeta: metav1.TypeMeta{APIVersion: APIVersion, Kind: ConfigMapKind}}}
|
||||||
TypeMeta: metav1.TypeMeta{
|
secretResource := &source.Kind{Type: &corev1.Secret{TypeMeta: metav1.TypeMeta{APIVersion: APIVersion, Kind: SecretKind}}}
|
||||||
APIVersion: APIVersion,
|
decorator := jenkinsDecorator{handler: &handler.EnqueueRequestForObject{}}
|
||||||
Kind: SecretKind,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
secretResource := &corev1.Secret{
|
|
||||||
TypeMeta: metav1.TypeMeta{
|
|
||||||
APIVersion: APIVersion,
|
|
||||||
Kind: SecretKind,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
decorator := jenkinsDecorator{
|
|
||||||
handler: &handler.EnqueueRequestForObject{},
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctrl.NewControllerManagedBy(mgr).
|
return ctrl.NewControllerManagedBy(mgr).
|
||||||
For(&v1alpha2.Jenkins{}).
|
For(&v1alpha2.Jenkins{}).
|
||||||
Owns(&corev1.Pod{}).
|
Owns(&corev1.Pod{}).
|
||||||
|
|
@ -101,7 +89,7 @@ func (r *JenkinsReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
Owns(&corev1.ConfigMap{}).
|
Owns(&corev1.ConfigMap{}).
|
||||||
Watches(secretResource, jenkinsHandler).
|
Watches(secretResource, jenkinsHandler).
|
||||||
Watches(configMapResource, jenkinsHandler).
|
Watches(configMapResource, jenkinsHandler).
|
||||||
Watches(&v1alpha2.Jenkins{}, &decorator).
|
Watches(&source.Kind{Type: &v1alpha2.Jenkins{}}, &decorator).
|
||||||
Complete(r)
|
Complete(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,7 +193,7 @@ func (r *JenkinsReconciler) Reconcile(_ context.Context, request ctrl.Request) (
|
||||||
return reconcile.Result{Requeue: true}, nil
|
return reconcile.Result{Requeue: true}, nil
|
||||||
}
|
}
|
||||||
if result.Requeue && result.RequeueAfter == 0 {
|
if result.Requeue && result.RequeueAfter == 0 {
|
||||||
result.RequeueAfter = time.Duration(rand.Intn(10)) * time.Second
|
result.RequeueAfter = time.Duration(rand.Intn(10)) * time.Millisecond
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
@ -390,11 +378,6 @@ func (r *JenkinsReconciler) setDefaults(jenkins *v1alpha2.Jenkins) (requeue bool
|
||||||
changed = true
|
changed = true
|
||||||
jenkinsContainer.LivenessProbe = resources.NewProbe(containerProbeURI, containerProbePortName, corev1.URISchemeHTTP, 80, 5, 12)
|
jenkinsContainer.LivenessProbe = resources.NewProbe(containerProbeURI, containerProbePortName, corev1.URISchemeHTTP, 80, 5, 12)
|
||||||
}
|
}
|
||||||
if jenkinsContainer.Lifecycle == nil {
|
|
||||||
logger.Info("Setting default Jenkins lifecycle")
|
|
||||||
changed = true
|
|
||||||
jenkinsContainer.Lifecycle = &corev1.Lifecycle{}
|
|
||||||
}
|
|
||||||
if len(jenkinsContainer.Command) == 0 {
|
if len(jenkinsContainer.Command) == 0 {
|
||||||
logger.Info("Setting default Jenkins container command")
|
logger.Info("Setting default Jenkins container command")
|
||||||
changed = true
|
changed = true
|
||||||
|
|
@ -232,8 +232,8 @@ metadata:
|
||||||
name: jenkins-operator
|
name: jenkins-operator
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: jenkins-operator
|
app.kubernetes.io/name: jenkins-operator
|
||||||
helm.sh/chart: jenkins-operator-0.9.0-beta1
|
helm.sh/chart: jenkins-operator-0.8.1
|
||||||
app.kubernetes.io/version: "0.9.0-beta1"
|
app.kubernetes.io/version: "0.8.1"
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
|
|
@ -247,7 +247,7 @@ spec:
|
||||||
serviceAccountName: jenkins-operator
|
serviceAccountName: jenkins-operator
|
||||||
containers:
|
containers:
|
||||||
- name: jenkins-operator
|
- name: jenkins-operator
|
||||||
image: quay.io/jenkins-kubernetes-operator/operator:v0.9.0-beta1
|
image: quay.io/jenkins-kubernetes-operator/operator:v0.8.1
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
|
|
|
||||||
|
|
@ -1330,11 +1330,6 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
skipPlugins:
|
|
||||||
description: 'Allow to skip installation of both BasePlugins and
|
|
||||||
Plugins. Requires using a custom image which includes the
|
|
||||||
BasePlugins. Defaults to false.'
|
|
||||||
type: boolean
|
|
||||||
terminationGracePeriodSeconds:
|
terminationGracePeriodSeconds:
|
||||||
description: 'Optional duration in seconds the pod needs to terminate gracefully.'
|
description: 'Optional duration in seconds the pod needs to terminate gracefully.'
|
||||||
type: integer
|
type: integer
|
||||||
|
|
|
||||||
73
flake.lock
73
flake.lock
|
|
@ -5,11 +5,11 @@
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1731533236,
|
"lastModified": 1705309234,
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -18,21 +18,53 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"go_15": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1610974077,
|
||||||
|
"narHash": "sha256-kfU2R7Q6eMU34VooazWvCqxOKwQOApCYh9TH79oZ8VA=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "4eccd6f731627ba5ad9915bcf600c9329a34ca78",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "4eccd6f731627ba5ad9915bcf600c9329a34ca78",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"golangci": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1593485095,
|
||||||
|
"narHash": "sha256-cgfJfZKqPgqQ1fdFWdpNnDEO2HmIVIDCvBTGke2LpnI=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "e912fb83d2155a393e7146da98cda0e455a80fb6",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "e912fb83d2155a393e7146da98cda0e455a80fb6",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"gomod2nix": {
|
"gomod2nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": [
|
"flake-utils": [
|
||||||
"flake-utils"
|
"flake-utils"
|
||||||
],
|
],
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs-rolling"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1742209644,
|
"lastModified": 1705314449,
|
||||||
"narHash": "sha256-jMy1XqXqD0/tJprEbUmKilTkvbDY/C0ZGSsJJH4TNCE=",
|
"narHash": "sha256-yfQQ67dLejP0FLK76LKHbkzcQqNIrux6MFe32MMFGNQ=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "gomod2nix",
|
"repo": "gomod2nix",
|
||||||
"rev": "8f3534eb8f6c5c3fce799376dc3b91bae6b11884",
|
"rev": "30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -59,27 +91,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1743231893,
|
"lastModified": 1707451808,
|
||||||
"narHash": "sha256-tpJsHMUPEhEnzySoQxx7+kA+KUtgWqvlcUBqROYNNt0=",
|
"narHash": "sha256-UwDBUNHNRsYKFJzyTMVMTF5qS4xeJlWoeyJf+6vvamU=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "c570c1f5304493cafe133b8d843c7c1c4a10d3a6",
|
"rev": "442d407992384ed9c0e6d352de75b69079904e4e",
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nixos",
|
|
||||||
"ref": "nixos-24.11",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-rolling": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1743259260,
|
|
||||||
"narHash": "sha256-ArWLUgRm1tKHiqlhnymyVqi5kLNCK5ghvm06mfCl4QY=",
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "eb0e0f21f15c559d2ac7633dc81d079d1caf5f5f",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -92,10 +108,11 @@
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
|
"go_15": "go_15",
|
||||||
|
"golangci": "golangci",
|
||||||
"gomod2nix": "gomod2nix",
|
"gomod2nix": "gomod2nix",
|
||||||
"hugo_099": "hugo_099",
|
"hugo_099": "hugo_099",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs"
|
||||||
"nixpkgs-rolling": "nixpkgs-rolling"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
|
|
|
||||||
55
flake.nix
55
flake.nix
|
|
@ -2,64 +2,55 @@
|
||||||
description = "Jenkins Kubernetes Operator";
|
description = "Jenkins Kubernetes Operator";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-24.11";
|
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||||
nixpkgs-rolling.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
go_15.url = "github:nixos/nixpkgs/4eccd6f731627ba5ad9915bcf600c9329a34ca78";
|
||||||
|
golangci.url = "github:nixos/nixpkgs/e912fb83d2155a393e7146da98cda0e455a80fb6";
|
||||||
hugo_099.url = "github:nixos/nixpkgs/d6df226c53d46821bd4773bd7ec3375f30238edb";
|
hugo_099.url = "github:nixos/nixpkgs/d6df226c53d46821bd4773bd7ec3375f30238edb";
|
||||||
gomod2nix = {
|
gomod2nix = {
|
||||||
url = "github:nix-community/gomod2nix";
|
url = "github:nix-community/gomod2nix";
|
||||||
inputs.nixpkgs.follows = "nixpkgs-rolling";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
inputs.flake-utils.follows = "flake-utils";
|
inputs.flake-utils.follows = "flake-utils";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs =
|
outputs = { self, nixpkgs, flake-utils, go_15, golangci, gomod2nix, hugo_099, ... }:
|
||||||
{
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
gomod2nix,
|
|
||||||
...
|
|
||||||
}@inputs:
|
|
||||||
inputs.flake-utils.lib.eachDefaultSystem (
|
|
||||||
system:
|
|
||||||
let
|
let
|
||||||
pkgs = inputs.nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
rolling = inputs.nixpkgs-rolling.legacyPackages.${system};
|
go_15_pkgs = go_15.legacyPackages.${system};
|
||||||
hugo_099_pkgs = inputs.hugo_099.legacyPackages.${system};
|
golangci_pkgs = golangci.legacyPackages.${system};
|
||||||
|
hugo_099_pkgs = hugo_099.legacyPackages.${system};
|
||||||
operatorVersion = builtins.readFile ./VERSION.txt;
|
operatorVersion = builtins.readFile ./VERSION.txt;
|
||||||
sdkVersion = ((builtins.fromTOML (builtins.readFile ./config.base.env)).OPERATOR_SDK_VERSION);
|
sdkVersion = ((builtins.fromTOML (builtins.readFile ./config.base.env)).OPERATOR_SDK_VERSION);
|
||||||
jenkinsLtsVersion = ((builtins.fromTOML (builtins.readFile ./config.base.env)).LATEST_LTS_VERSION);
|
jenkinsLtsVersion = ((builtins.fromTOML (builtins.readFile ./config.base.env)).LATEST_LTS_VERSION);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# Nix fmt
|
# Nix fmt
|
||||||
formatter = pkgs.nixpkgs-fmt;
|
formatter = nixpkgs.legacyPackages.${system}.nixpkgs-fmt;
|
||||||
|
|
||||||
# shell in nix develop
|
# shell in nix develop
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = nixpkgs.legacyPackages.${system}.mkShell {
|
||||||
packages = [
|
packages = [
|
||||||
pkgs.gnumake
|
pkgs.gnumake
|
||||||
pkgs.wget
|
pkgs.wget
|
||||||
pkgs.helm-docs
|
pkgs.helm-docs
|
||||||
pkgs.pre-commit
|
pkgs.pre-commit
|
||||||
pkgs.kind
|
|
||||||
pkgs.golangci-lint
|
|
||||||
pkgs.go_1_22
|
|
||||||
rolling.operator-sdk # 1.39.2
|
|
||||||
|
|
||||||
(pkgs.bats.withLibraries (p: [
|
|
||||||
p.bats-support
|
|
||||||
p.bats-assert
|
|
||||||
p.bats-file
|
|
||||||
p.bats-detik
|
|
||||||
]))
|
|
||||||
|
|
||||||
(pkgs.writeShellApplication {
|
(pkgs.writeShellApplication {
|
||||||
name = "make_matrix";
|
name = "make_matrix";
|
||||||
runtimeInputs = with pkgs; [
|
runtimeInputs = with pkgs; [ bash gnugrep gawk ];
|
||||||
bash
|
|
||||||
gnugrep
|
|
||||||
gawk
|
|
||||||
];
|
|
||||||
text = builtins.readFile ./test/make_matrix_ginkgo.sh;
|
text = builtins.readFile ./test/make_matrix_ginkgo.sh;
|
||||||
})
|
})
|
||||||
|
go_15_pkgs.go
|
||||||
|
golangci_pkgs.golangci-lint
|
||||||
|
|
||||||
|
pkgs.kind
|
||||||
|
(pkgs.bats.withLibraries (p: [
|
||||||
|
p.bats-support
|
||||||
|
p.bats-assert
|
||||||
|
p.bats-file
|
||||||
|
p.bats-detik
|
||||||
|
]))
|
||||||
];
|
];
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
echo Operator Version ${operatorVersion}
|
echo Operator Version ${operatorVersion}
|
||||||
|
|
|
||||||
117
go.mod
117
go.mod
|
|
@ -1,106 +1,31 @@
|
||||||
module github.com/jenkinsci/kubernetes-operator
|
module github.com/jenkinsci/kubernetes-operator
|
||||||
|
|
||||||
go 1.22.12
|
go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bndr/gojenkins v1.1.0
|
github.com/bndr/gojenkins v1.0.1
|
||||||
github.com/distribution/reference v0.6.0
|
github.com/docker/distribution v2.7.1+incompatible
|
||||||
github.com/go-logr/logr v1.4.2
|
github.com/emersion/go-smtp v0.11.2
|
||||||
github.com/go-logr/zapr v1.3.0
|
github.com/go-logr/logr v0.3.0
|
||||||
github.com/golang/mock v1.6.0
|
github.com/go-logr/zapr v0.2.0
|
||||||
|
github.com/golang/mock v1.4.1
|
||||||
github.com/mailgun/mailgun-go/v3 v3.6.4
|
github.com/mailgun/mailgun-go/v3 v3.6.4
|
||||||
github.com/onsi/ginkgo v1.14.1
|
github.com/onsi/ginkgo v1.14.1
|
||||||
github.com/onsi/gomega v1.33.1
|
github.com/onsi/gomega v1.10.2
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/openshift/api v3.9.0+incompatible
|
github.com/openshift/api v3.9.0+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.6.1
|
||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.15.0
|
||||||
golang.org/x/crypto v0.31.0
|
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
|
||||||
golang.org/x/mod v0.19.0
|
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
|
||||||
k8s.io/api v0.30.3
|
|
||||||
k8s.io/apimachinery v0.30.3
|
|
||||||
k8s.io/cli-runtime v0.30.3
|
|
||||||
k8s.io/client-go v0.30.3
|
|
||||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
|
|
||||||
sigs.k8s.io/controller-runtime v0.18.4
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
|
||||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
|
||||||
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
|
|
||||||
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
|
|
||||||
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
|
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
|
||||||
github.com/go-chi/chi v4.1.2+incompatible // indirect
|
|
||||||
github.com/go-errors/errors v1.5.1 // 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/gogo/protobuf v1.3.2 // indirect
|
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
|
||||||
github.com/google/btree v1.1.2 // indirect
|
|
||||||
github.com/google/gnostic-models v0.6.8 // indirect
|
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
|
||||||
github.com/google/pprof v0.0.0-20240721033354-7089f98c1d14 // indirect
|
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
|
||||||
github.com/gorilla/websocket v1.5.3 // indirect
|
|
||||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
|
||||||
github.com/imdario/mergo v0.3.16 // indirect
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
|
||||||
github.com/moby/spdystream v0.4.0 // indirect
|
|
||||||
github.com/moby/term v0.5.0 // indirect
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
|
||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
|
||||||
github.com/nxadm/tail v1.4.11 // indirect
|
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
|
||||||
github.com/prometheus/client_golang v1.19.1 // indirect
|
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
|
||||||
github.com/prometheus/common v0.55.0 // indirect
|
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
|
||||||
github.com/spf13/cobra v1.8.1 // indirect
|
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
|
||||||
github.com/xlab/treeprint v1.2.0 // indirect
|
|
||||||
go.starlark.net v0.0.0-20240705175910-70002002b310 // indirect
|
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
|
||||||
golang.org/x/net v0.27.0 // indirect
|
|
||||||
golang.org/x/oauth2 v0.21.0 // indirect
|
|
||||||
golang.org/x/sync v0.10.0 // indirect
|
|
||||||
golang.org/x/sys v0.28.0 // indirect
|
|
||||||
golang.org/x/term v0.27.0 // indirect
|
|
||||||
golang.org/x/text v0.21.0 // indirect
|
|
||||||
golang.org/x/time v0.5.0 // indirect
|
|
||||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
|
||||||
google.golang.org/protobuf v1.34.2 // indirect
|
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
k8s.io/api v0.20.2
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
k8s.io/apimachinery v0.20.2
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
k8s.io/cli-runtime v0.20.2
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
k8s.io/client-go v0.20.2
|
||||||
k8s.io/apiextensions-apiserver v0.30.3 // indirect
|
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
|
||||||
k8s.io/klog/v2 v2.130.1 // indirect
|
sigs.k8s.io/controller-runtime v0.7.0
|
||||||
k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect
|
golang.org/x/mod v0.4.2
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
|
||||||
sigs.k8s.io/kustomize/api v0.17.3 // indirect
|
|
||||||
sigs.k8s.io/kustomize/kyaml v0.17.2 // indirect
|
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
|
||||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
apiVersion: kind.x-k8s.io/v1alpha4
|
apiVersion: kind.x-k8s.io/v1alpha4
|
||||||
kind: Cluster
|
kind: Cluster
|
||||||
networking:
|
|
||||||
dnsSearch: []
|
|
||||||
nodes:
|
nodes:
|
||||||
- role: control-plane
|
- role: control-plane
|
||||||
extraPortMappings:
|
extraPortMappings:
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import (
|
||||||
r "runtime"
|
r "runtime"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
controllers "github.com/jenkinsci/kubernetes-operator/internal/controller"
|
"github.com/jenkinsci/kubernetes-operator/controllers"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/client"
|
"github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
|
|
@ -40,10 +40,7 @@ import (
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/cache"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client/config"
|
"sigs.k8s.io/controller-runtime/pkg/client/config"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/metrics/server"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
|
||||||
|
|
||||||
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
|
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
|
||||||
// to ensure that exec-entrypoint and run can make use of them.
|
// to ensure that exec-entrypoint and run can make use of them.
|
||||||
|
|
@ -129,23 +126,14 @@ func main() {
|
||||||
fatal(errors.Wrap(err, "failed to get config"), *debug)
|
fatal(errors.Wrap(err, "failed to get config"), *debug)
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheNamespace := map[string]cache.Config{}
|
|
||||||
cacheNamespace[namespace] = cache.Config{}
|
|
||||||
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||||
// MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
|
Scheme: scheme,
|
||||||
Metrics: server.Options{
|
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
|
||||||
BindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
|
Port: 9443,
|
||||||
},
|
|
||||||
Scheme: scheme,
|
|
||||||
// Port: 9443,
|
|
||||||
WebhookServer: webhook.NewServer(webhook.Options{
|
|
||||||
Port: 9443,
|
|
||||||
}),
|
|
||||||
HealthProbeBindAddress: probeAddr,
|
HealthProbeBindAddress: probeAddr,
|
||||||
LeaderElection: enableLeaderElection,
|
LeaderElection: enableLeaderElection,
|
||||||
LeaderElectionID: "c674355f.jenkins.io",
|
LeaderElectionID: "c674355f.jenkins.io",
|
||||||
// Namespace: namespace,
|
Namespace: namespace,
|
||||||
Cache: cache.Options{DefaultNamespaces: cacheNamespace},
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal(errors.Wrap(err, "unable to start manager"), *debug)
|
fatal(errors.Wrap(err, "unable to start manager"), *debug)
|
||||||
|
|
@ -11,8 +11,6 @@
|
||||||
)
|
)
|
||||||
, mkGoEnv ? pkgs.mkGoEnv
|
, mkGoEnv ? pkgs.mkGoEnv
|
||||||
, gomod2nix ? pkgs.gomod2nix
|
, gomod2nix ? pkgs.gomod2nix
|
||||||
, go22 ? pkgs.go_1_22
|
|
||||||
, golangci-lint ? pkgs.golangci-lint
|
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
@ -20,8 +18,6 @@ let
|
||||||
in
|
in
|
||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
packages = [
|
packages = [
|
||||||
go22
|
|
||||||
golangci-lint
|
|
||||||
goEnv
|
goEnv
|
||||||
gomod2nix
|
gomod2nix
|
||||||
];
|
];
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -3,7 +3,7 @@
|
||||||
let
|
let
|
||||||
buildPackages = [
|
buildPackages = [
|
||||||
hugo_099_pkgs.hugo #hugo pre-v100
|
hugo_099_pkgs.hugo #hugo pre-v100
|
||||||
pkgs.nodejs_22 #Node 1.22
|
pkgs.nodejs_21 #Node 1.21
|
||||||
pkgs.nodePackages.autoprefixer
|
pkgs.nodePackages.autoprefixer
|
||||||
pkgs.nodePackages.postcss
|
pkgs.nodePackages.postcss
|
||||||
pkgs.nodePackages.postcss-cli
|
pkgs.nodePackages.postcss-cli
|
||||||
|
|
@ -14,9 +14,9 @@ pkgs.buildNpmPackage {
|
||||||
name = "jenkins-kubernetes-operator-website";
|
name = "jenkins-kubernetes-operator-website";
|
||||||
src = ../website;
|
src = ../website;
|
||||||
version = "0.0.2";
|
version = "0.0.2";
|
||||||
npmDepsHash = "sha256-OSUhPFmrwhSVYzxPW7AocSngdIak4bxKSwobF8UfB0g=";
|
npmDepsHash = "sha256-VrHuyqTPUzVJSjah+BWfg7R9yiarJQ2MDvEdqkOWddM=";
|
||||||
nativeBuildInputs = buildPackages;
|
nativeBuildInputs = buildPackages;
|
||||||
buildPhase = "${pkgs.nodejs_22}/bin/npm run build";
|
buildPhase = "${pkgs.nodejs_21}/bin/npm run build";
|
||||||
installPhase = "cp -r public $out";
|
installPhase = "cp -r public $out";
|
||||||
BASE_URL = "${baseUrl}";
|
BASE_URL = "${baseUrl}";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
let
|
let
|
||||||
devShellPackages = [
|
devShellPackages = [
|
||||||
hugo_099_pkgs.hugo #hugo pre-v100
|
hugo_099_pkgs.hugo #hugo pre-v100
|
||||||
pkgs.nodejs_22 #Node 1.22
|
pkgs.nodejs_21 #Node 1.21
|
||||||
pkgs.helm-docs
|
pkgs.helm-docs
|
||||||
];
|
];
|
||||||
baseUrl = ((builtins.fromTOML (builtins.readFile ../website/config.toml)).baseURL);
|
baseUrl = ((builtins.fromTOML (builtins.readFile ../website/config.toml)).baseURL);
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,8 @@ package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/cookiejar"
|
"net/http/cookiejar"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -21,41 +20,41 @@ var (
|
||||||
// Jenkins defines Jenkins API.
|
// Jenkins defines Jenkins API.
|
||||||
type Jenkins interface {
|
type Jenkins interface {
|
||||||
GenerateToken(userName, tokenName string) (*UserToken, error)
|
GenerateToken(userName, tokenName string) (*UserToken, error)
|
||||||
Info(ctx context.Context) (*gojenkins.ExecutorResponse, error)
|
Info() (*gojenkins.ExecutorResponse, error)
|
||||||
SafeRestart(ctx context.Context) error
|
SafeRestart() error
|
||||||
CreateNode(ctx context.Context, name string, numExecutors int, description string, remoteFS string, label string, options ...interface{}) (*gojenkins.Node, error)
|
CreateNode(name string, numExecutors int, description string, remoteFS string, label string, options ...interface{}) (*gojenkins.Node, error)
|
||||||
DeleteNode(ctx context.Context, name string) (bool, error)
|
DeleteNode(name string) (bool, error)
|
||||||
CreateFolder(ctx context.Context, name string, parents ...string) (*gojenkins.Folder, error)
|
CreateFolder(name string, parents ...string) (*gojenkins.Folder, error)
|
||||||
CreateJobInFolder(ctx context.Context, config string, jobName string, parentIDs ...string) (*gojenkins.Job, error)
|
CreateJobInFolder(config string, jobName string, parentIDs ...string) (*gojenkins.Job, error)
|
||||||
CreateJob(ctx context.Context, config string, options ...interface{}) (*gojenkins.Job, error)
|
CreateJob(config string, options ...interface{}) (*gojenkins.Job, error)
|
||||||
CreateOrUpdateJob(config, jobName string) (*gojenkins.Job, bool, error)
|
CreateOrUpdateJob(config, jobName string) (*gojenkins.Job, bool, error)
|
||||||
RenameJob(ctx context.Context, job string, name string) *gojenkins.Job
|
RenameJob(job string, name string) *gojenkins.Job
|
||||||
CopyJob(ctx context.Context, copyFrom string, newName string) (*gojenkins.Job, error)
|
CopyJob(copyFrom string, newName string) (*gojenkins.Job, error)
|
||||||
CreateView(ctx context.Context, name string, viewType string) (*gojenkins.View, error)
|
DeleteJob(name string) (bool, error)
|
||||||
DeleteJob(ctx context.Context, name string) (bool, error)
|
BuildJob(name string, options ...interface{}) (int64, error)
|
||||||
BuildJob(ctx context.Context, name string, options map[string]string) (int64, error)
|
GetNode(name string) (*gojenkins.Node, error)
|
||||||
GetNode(ctx context.Context, name string) (*gojenkins.Node, error)
|
GetLabel(name string) (*gojenkins.Label, error)
|
||||||
GetLabel(ctx context.Context, name string) (*gojenkins.Label, error)
|
|
||||||
GetBuild(jobName string, number int64) (*gojenkins.Build, error)
|
GetBuild(jobName string, number int64) (*gojenkins.Build, error)
|
||||||
GetJob(ctx context.Context, id string, parentIDs ...string) (*gojenkins.Job, error)
|
GetJob(id string, parentIDs ...string) (*gojenkins.Job, error)
|
||||||
GetSubJob(ctx context.Context, parentID string, childID string) (*gojenkins.Job, error)
|
GetSubJob(parentID string, childID string) (*gojenkins.Job, error)
|
||||||
GetFolder(ctx context.Context, id string, parents ...string) (*gojenkins.Folder, error)
|
GetFolder(id string, parents ...string) (*gojenkins.Folder, error)
|
||||||
GetAllNodes(ctx context.Context) ([]*gojenkins.Node, error)
|
GetAllNodes() ([]*gojenkins.Node, error)
|
||||||
GetAllBuildIds(ctx context.Context, job string) ([]gojenkins.JobBuild, error)
|
GetAllBuildIds(job string) ([]gojenkins.JobBuild, error)
|
||||||
GetAllJobNames(context.Context) ([]gojenkins.InnerJob, error)
|
GetAllJobNames() ([]gojenkins.InnerJob, error)
|
||||||
GetAllJobs(context.Context) ([]*gojenkins.Job, error)
|
GetAllJobs() ([]*gojenkins.Job, error)
|
||||||
GetQueue(context.Context) (*gojenkins.Queue, error)
|
GetQueue() (*gojenkins.Queue, error)
|
||||||
GetQueueUrl() string
|
GetQueueUrl() string
|
||||||
GetQueueItem(ctx context.Context, id int64) (*gojenkins.Task, error)
|
GetQueueItem(id int64) (*gojenkins.Task, error)
|
||||||
GetArtifactData(ctx context.Context, id string) (*gojenkins.FingerPrintResponse, error)
|
GetArtifactData(id string) (*gojenkins.FingerPrintResponse, error)
|
||||||
GetPlugins(depth int) (*gojenkins.Plugins, error)
|
GetPlugins(depth int) (*gojenkins.Plugins, error)
|
||||||
UninstallPlugin(ctx context.Context, name string) error
|
UninstallPlugin(name string) error
|
||||||
HasPlugin(ctx context.Context, name string) (*gojenkins.Plugin, error)
|
HasPlugin(name string) (*gojenkins.Plugin, error)
|
||||||
InstallPlugin(ctx context.Context, name string, version string) error
|
InstallPlugin(name string, version string) error
|
||||||
ValidateFingerPrint(ctx context.Context, id string) (bool, error)
|
ValidateFingerPrint(id string) (bool, error)
|
||||||
GetView(ctx context.Context, name string) (*gojenkins.View, error)
|
GetView(name string) (*gojenkins.View, error)
|
||||||
GetAllViews(context.Context) ([]*gojenkins.View, error)
|
GetAllViews() ([]*gojenkins.View, error)
|
||||||
Poll(ctx context.Context) (int, error)
|
CreateView(name string, viewType string) (*gojenkins.View, error)
|
||||||
|
Poll() (int, error)
|
||||||
ExecuteScript(groovyScript string) (logs string, err error)
|
ExecuteScript(groovyScript string) (logs string, err error)
|
||||||
GetNodeSecret(name string) (string, error)
|
GetNodeSecret(name string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
@ -91,15 +90,16 @@ func (t *setBearerToken) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||||
// CreateOrUpdateJob creates or updates a job from config.
|
// CreateOrUpdateJob creates or updates a job from config.
|
||||||
func (jenkins *jenkins) CreateOrUpdateJob(config, jobName string) (job *gojenkins.Job, created bool, err error) {
|
func (jenkins *jenkins) CreateOrUpdateJob(config, jobName string) (job *gojenkins.Job, created bool, err error) {
|
||||||
// create or update
|
// create or update
|
||||||
job, err = jenkins.GetJob(context.TODO(), jobName)
|
job, err = jenkins.GetJob(jobName)
|
||||||
if isNotFoundError(err) {
|
if isNotFoundError(err) {
|
||||||
job, err = jenkins.CreateJob(context.TODO(), config, jobName)
|
job, err = jenkins.CreateJob(config, jobName)
|
||||||
|
created = true
|
||||||
return job, true, errors.WithStack(err)
|
return job, true, errors.WithStack(err)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return job, false, errors.WithStack(err)
|
return job, false, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = job.UpdateConfig(context.TODO(), config)
|
err = job.UpdateConfig(config)
|
||||||
return job, false, errors.WithStack(err)
|
return job, false, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,10 +144,9 @@ func NewBearerTokenAuthorization(url, token string) (Jenkins, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newClient(url, userName, passwordOrToken string) (Jenkins, error) {
|
func newClient(url, userName, passwordOrToken string) (Jenkins, error) {
|
||||||
// if strings.HasSuffix(url, "/") {
|
if strings.HasSuffix(url, "/") {
|
||||||
// url = url[:len(url)-1]
|
url = url[:len(url)-1]
|
||||||
url = strings.TrimSuffix(url, "/")
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
jenkinsClient := &jenkins{}
|
jenkinsClient := &jenkins{}
|
||||||
jenkinsClient.Server = url
|
jenkinsClient.Server = url
|
||||||
|
|
@ -175,11 +174,11 @@ func newClient(url, userName, passwordOrToken string) (Jenkins, error) {
|
||||||
Client: httpClient,
|
Client: httpClient,
|
||||||
BasicAuth: basicAuth,
|
BasicAuth: basicAuth,
|
||||||
}
|
}
|
||||||
if _, err := jenkinsClient.Init(context.TODO()); err != nil {
|
if _, err := jenkinsClient.Init(); err != nil {
|
||||||
return nil, errors.Wrap(err, "couldn't init Jenkins API client")
|
return nil, errors.Wrap(err, "couldn't init Jenkins API client")
|
||||||
}
|
}
|
||||||
|
|
||||||
status, err := jenkinsClient.Poll(context.TODO())
|
status, err := jenkinsClient.Poll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "couldn't poll data from Jenkins API")
|
return nil, errors.Wrap(err, "couldn't poll data from Jenkins API")
|
||||||
}
|
}
|
||||||
|
|
@ -214,13 +213,9 @@ func (jenkins *jenkins) GetNodeSecret(name string) (string, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer resp.Body.Close()
|
||||||
if cerr := resp.Body.Close(); cerr != nil && err == nil {
|
|
||||||
err = cerr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -236,7 +231,7 @@ func (jenkins *jenkins) GetNodeSecret(name string) (string, error) {
|
||||||
// You can supply depth parameter, to limit how much data is returned.
|
// You can supply depth parameter, to limit how much data is returned.
|
||||||
func (jenkins *jenkins) GetPlugins(depth int) (*gojenkins.Plugins, error) {
|
func (jenkins *jenkins) GetPlugins(depth int) (*gojenkins.Plugins, error) {
|
||||||
p := gojenkins.Plugins{Jenkins: &jenkins.Jenkins, Raw: new(gojenkins.PluginResponse), Base: "/pluginManager", Depth: depth}
|
p := gojenkins.Plugins{Jenkins: &jenkins.Jenkins, Raw: new(gojenkins.PluginResponse), Base: "/pluginManager", Depth: depth}
|
||||||
statusCode, err := p.Poll(context.TODO())
|
statusCode, err := p.Poll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/bndr/gojenkins"
|
"github.com/bndr/gojenkins"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (jenkins *jenkins) GetBuild(jobName string, number int64) (*gojenkins.Build, error) {
|
func (jenkins *jenkins) GetBuild(jobName string, number int64) (*gojenkins.Build, error) {
|
||||||
job, err := jenkins.GetJob(context.TODO(), jobName)
|
job, err := jenkins.GetJob(jobName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +21,7 @@ func (jenkins *jenkins) GetBuild(jobName string, number int64) (*gojenkins.Build
|
||||||
job.Raw.URL = jobURL.RequestURI()
|
job.Raw.URL = jobURL.RequestURI()
|
||||||
// workaround end
|
// workaround end
|
||||||
|
|
||||||
build, err := job.GetBuild(context.TODO(), number)
|
build, err := job.GetBuild(number)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -2,7 +2,6 @@ package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
@ -10,7 +9,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bndr/gojenkins"
|
"github.com/bndr/gojenkins"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -40,19 +38,18 @@ func (jenkins *jenkins) executeScript(script string, verifier string) (string, e
|
||||||
data.Set("script", fullScript)
|
data.Set("script", fullScript)
|
||||||
|
|
||||||
ar := gojenkins.NewAPIRequest("POST", "/scriptText", bytes.NewBufferString(data.Encode()))
|
ar := gojenkins.NewAPIRequest("POST", "/scriptText", bytes.NewBufferString(data.Encode()))
|
||||||
if err := jenkins.Requester.SetCrumb(context.TODO(), ar); err != nil {
|
if err := jenkins.Requester.SetCrumb(ar); err != nil {
|
||||||
return output, err
|
return output, err
|
||||||
}
|
}
|
||||||
ar.SetHeader("Content-Type", "application/x-www-form-urlencoded")
|
ar.SetHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||||
ar.Suffix = ""
|
ar.Suffix = ""
|
||||||
|
|
||||||
r, err := jenkins.Requester.Do(context.TODO(), ar, &output, nil)
|
r, err := jenkins.Requester.Do(ar, &output, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrapf(err, "couldn't execute groovy script, logs '%s'", output)
|
return "", errors.Wrapf(err, "couldn't execute groovy script, logs '%s'", output)
|
||||||
}
|
}
|
||||||
if err := r.Body.Close(); err != nil {
|
defer r.Body.Close()
|
||||||
log.Log.Error(err, "failed to close jenkins.executeScript.Requester")
|
|
||||||
}
|
|
||||||
if r.StatusCode != http.StatusOK {
|
if r.StatusCode != http.StatusOK {
|
||||||
return output, errors.Errorf("invalid status code '%d', logs '%s'", r.StatusCode, output)
|
return output, errors.Errorf("invalid status code '%d', logs '%s'", r.StatusCode, output)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ func Test_ExecuteScript(t *testing.T) {
|
||||||
Client: client,
|
Client: client,
|
||||||
BasicAuth: &gojenkins.BasicAuth{Username: "unused", Password: "unused"},
|
BasicAuth: &gojenkins.BasicAuth{Username: "unused", Password: "unused"},
|
||||||
}
|
}
|
||||||
|
|
||||||
logs, err := jenkinsClient.executeScript(script, verifier)
|
logs, err := jenkinsClient.executeScript(script, verifier)
|
||||||
assert.NoError(t, err, logs)
|
assert.NoError(t, err, logs)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -36,18 +34,12 @@ func (jenkins *jenkins) GenerateToken(userName, tokenName string) (*UserToken, e
|
||||||
base: fmt.Sprintf("/user/%s/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken", userName)}
|
base: fmt.Sprintf("/user/%s/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken", userName)}
|
||||||
endpoint := token.base
|
endpoint := token.base
|
||||||
data := map[string]string{"newTokenName": tokenName}
|
data := map[string]string{"newTokenName": tokenName}
|
||||||
r, err := jenkins.Requester.Post(context.TODO(), endpoint, nil, token.raw, data)
|
r, err := jenkins.Requester.Post(endpoint, nil, token.raw, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "couldn't generate API token")
|
return nil, errors.Wrap(err, "couldn't generate API token")
|
||||||
}
|
}
|
||||||
defer func() {
|
defer r.Body.Close()
|
||||||
if err := r.Body.Close(); err != nil {
|
|
||||||
log.Log.Error(err, "failed to close http response body")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if err := r.Body.Close(); err != nil {
|
|
||||||
log.Log.Error(err, "failed to close jenkins.GenerateToken.Requester")
|
|
||||||
}
|
|
||||||
if r.StatusCode == http.StatusOK {
|
if r.StatusCode == http.StatusOK {
|
||||||
if token.raw.Status == "ok" {
|
if token.raw.Status == "ok" {
|
||||||
return token, nil
|
return token, nil
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error
|
||||||
|
|
||||||
backupNumberString := strings.TrimSuffix(backupNumberRaw.String(), "\n")
|
backupNumberString := strings.TrimSuffix(backupNumberRaw.String(), "\n")
|
||||||
if backupNumberString == noBackup {
|
if backupNumberString == noBackup {
|
||||||
bar.logger.V(log.VDebug).Info("Skipping restore backup, get latest action returned -1 (no backups found)")
|
bar.logger.V(log.VDebug).Info("Skipping restore backup, get latest action returned -1")
|
||||||
jenkins.Status.LastBackup = 0
|
jenkins.Status.LastBackup = 0
|
||||||
jenkins.Status.PendingBackup = 1
|
jenkins.Status.PendingBackup = 1
|
||||||
return bar.Client.Status().Update(context.TODO(), jenkins)
|
return bar.Client.Status().Update(context.TODO(), jenkins)
|
||||||
|
|
@ -209,7 +209,7 @@ func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error
|
||||||
func (bar *BackupAndRestore) Backup(setBackupDoneBeforePodDeletion bool) error {
|
func (bar *BackupAndRestore) Backup(setBackupDoneBeforePodDeletion bool) error {
|
||||||
jenkins := bar.Configuration.Jenkins
|
jenkins := bar.Configuration.Jenkins
|
||||||
if len(jenkins.Spec.Backup.ContainerName) == 0 || jenkins.Spec.Backup.Action.Exec == nil {
|
if len(jenkins.Spec.Backup.ContainerName) == 0 || jenkins.Spec.Backup.Action.Exec == nil {
|
||||||
bar.logger.V(log.VDebug).Info("Skipping backup, backup creation not configured")
|
bar.logger.V(log.VDebug).Info("Skipping restore backup, backup restore not configured")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if jenkins.Status.PendingBackup == jenkins.Status.LastBackup {
|
if jenkins.Status.PendingBackup == jenkins.Status.LastBackup {
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *JenkinsBaseConfigurationReconciler) verifyPlugins(jenkinsClient jenkinsclient.Jenkins) (bool, error) {
|
func (r *JenkinsBaseConfigurationReconciler) verifyPlugins(jenkinsClient jenkinsclient.Jenkins) (bool, error) {
|
||||||
if r.Configuration.Jenkins.Spec.Master.SkipPlugins != nil && *r.Configuration.Jenkins.Spec.Master.SkipPlugins {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
allPluginsInJenkins, err := jenkinsClient.GetPlugins(fetchAllPlugins)
|
allPluginsInJenkins, err := jenkinsClient.GetPlugins(fetchAllPlugins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, stackerr.WithStack(err)
|
return false, stackerr.WithStack(err)
|
||||||
|
|
|
||||||
|
|
@ -445,6 +445,7 @@ func Test_compareEnv(t *testing.T) {
|
||||||
var actual []corev1.EnvVar
|
var actual []corev1.EnvVar
|
||||||
|
|
||||||
got := compareEnv(expected, actual)
|
got := compareEnv(expected, actual)
|
||||||
|
|
||||||
assert.True(t, got)
|
assert.True(t, got)
|
||||||
})
|
})
|
||||||
t.Run("same", func(t *testing.T) {
|
t.Run("same", func(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -121,9 +121,6 @@ func (r *JenkinsBaseConfigurationReconciler) Reconcile() (reconcile.Result, jenk
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err = r.ensureBaseConfiguration(jenkinsClient)
|
result, err = r.ensureBaseConfiguration(jenkinsClient)
|
||||||
if err != nil {
|
|
||||||
return reconcile.Result{}, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, jenkinsClient, err
|
return result, jenkinsClient, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,13 @@ def jenkins = Jenkins.instance
|
||||||
|
|
||||||
println("Disabling insecure Jenkins features...")
|
println("Disabling insecure Jenkins features...")
|
||||||
|
|
||||||
|
println("Disabling insecure protocols...")
|
||||||
|
println("Old protocols: [" + jenkins.getAgentProtocols().join(", ") + "]")
|
||||||
|
HashSet<String> newProtocols = new HashSet<>(jenkins.getAgentProtocols())
|
||||||
|
newProtocols.removeAll(Arrays.asList("JNLP3-connect", "JNLP2-connect", "JNLP-connect", "CLI-connect"))
|
||||||
|
println("New protocols: [" + newProtocols.join(", ") + "]")
|
||||||
|
jenkins.setAgentProtocols(newProtocols)
|
||||||
|
|
||||||
println("Disabling CLI access of /cli URL...")
|
println("Disabling CLI access of /cli URL...")
|
||||||
def remove = { list ->
|
def remove = { list ->
|
||||||
list.each { item ->
|
list.each { item ->
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/utils/ptr"
|
"k8s.io/utils/pointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewJenkinsMasterPod builds Jenkins Master Kubernetes Pod resource.
|
// NewJenkinsMasterPod builds Jenkins Master Kubernetes Pod resource.
|
||||||
|
|
@ -24,7 +24,7 @@ func NewJenkinsDeployment(objectMeta metav1.ObjectMeta, jenkins *v1alpha2.Jenkin
|
||||||
Labels: objectMeta.Labels,
|
Labels: objectMeta.Labels,
|
||||||
},
|
},
|
||||||
Spec: appsv1.DeploymentSpec{
|
Spec: appsv1.DeploymentSpec{
|
||||||
Replicas: ptr.To(int32(1)),
|
Replicas: pointer.Int32Ptr(1),
|
||||||
Strategy: appsv1.DeploymentStrategy{Type: appsv1.RollingUpdateDeploymentStrategyType},
|
Strategy: appsv1.DeploymentStrategy{Type: appsv1.RollingUpdateDeploymentStrategyType},
|
||||||
Template: corev1.PodTemplateSpec{
|
Template: corev1.PodTemplateSpec{
|
||||||
ObjectMeta: objectMeta,
|
ObjectMeta: objectMeta,
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,6 @@ func NewJenkinsMasterContainer(jenkins *v1alpha2.Jenkins) corev1.Container {
|
||||||
Image: jenkinsContainer.Image,
|
Image: jenkinsContainer.Image,
|
||||||
ImagePullPolicy: jenkinsContainer.ImagePullPolicy,
|
ImagePullPolicy: jenkinsContainer.ImagePullPolicy,
|
||||||
Command: jenkinsContainer.Command,
|
Command: jenkinsContainer.Command,
|
||||||
Lifecycle: jenkinsContainer.Lifecycle,
|
|
||||||
LivenessProbe: jenkinsContainer.LivenessProbe,
|
LivenessProbe: jenkinsContainer.LivenessProbe,
|
||||||
ReadinessProbe: jenkinsContainer.ReadinessProbe,
|
ReadinessProbe: jenkinsContainer.ReadinessProbe,
|
||||||
Ports: []corev1.ContainerPort{
|
Ports: []corev1.ContainerPort{
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
func NewProbe(uri string, port string, scheme corev1.URIScheme, initialDelaySeconds, timeoutSeconds, failureThreshold int32) *corev1.Probe {
|
func NewProbe(uri string, port string, scheme corev1.URIScheme, initialDelaySeconds, timeoutSeconds, failureThreshold int32) *corev1.Probe {
|
||||||
return &corev1.Probe{
|
return &corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: uri,
|
Path: uri,
|
||||||
Port: intstr.FromString(port),
|
Port: intstr.FromString(port),
|
||||||
|
|
|
||||||
|
|
@ -16,5 +16,5 @@ func randomString(n int) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rand.New(rand.NewSource(time.Now().UnixNano()))
|
rand.Seed(time.Now().UnixNano())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ var jenkins = v1alpha2.Jenkins{
|
||||||
{
|
{
|
||||||
Env: []corev1.EnvVar{},
|
Env: []corev1.EnvVar{},
|
||||||
ReadinessProbe: &corev1.Probe{
|
ReadinessProbe: &corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{},
|
HTTPGet: &corev1.HTTPGetAction{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
LivenessProbe: &corev1.Probe{
|
LivenessProbe: &corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{},
|
HTTPGet: &corev1.HTTPGetAction{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -118,7 +118,7 @@ func TestSetLivenessAndReadinessPath(t *testing.T) {
|
||||||
|
|
||||||
jenkins.Spec.Master.Containers[0].ReadinessProbe =
|
jenkins.Spec.Master.Containers[0].ReadinessProbe =
|
||||||
&corev1.Probe{
|
&corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/login",
|
Path: "/login",
|
||||||
},
|
},
|
||||||
|
|
@ -127,7 +127,7 @@ func TestSetLivenessAndReadinessPath(t *testing.T) {
|
||||||
|
|
||||||
jenkins.Spec.Master.Containers[0].LivenessProbe =
|
jenkins.Spec.Master.Containers[0].LivenessProbe =
|
||||||
&corev1.Probe{
|
&corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/login",
|
Path: "/login",
|
||||||
},
|
},
|
||||||
|
|
@ -148,7 +148,7 @@ func TestSetLivenessAndReadinessPath(t *testing.T) {
|
||||||
|
|
||||||
jenkins.Spec.Master.Containers[0].ReadinessProbe =
|
jenkins.Spec.Master.Containers[0].ReadinessProbe =
|
||||||
&corev1.Probe{
|
&corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/login",
|
Path: "/login",
|
||||||
},
|
},
|
||||||
|
|
@ -157,7 +157,7 @@ func TestSetLivenessAndReadinessPath(t *testing.T) {
|
||||||
|
|
||||||
jenkins.Spec.Master.Containers[0].LivenessProbe =
|
jenkins.Spec.Master.Containers[0].LivenessProbe =
|
||||||
&corev1.Probe{
|
&corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/login",
|
Path: "/login",
|
||||||
},
|
},
|
||||||
|
|
@ -178,7 +178,7 @@ func TestSetLivenessAndReadinessPath(t *testing.T) {
|
||||||
|
|
||||||
jenkins.Spec.Master.Containers[0].ReadinessProbe =
|
jenkins.Spec.Master.Containers[0].ReadinessProbe =
|
||||||
&corev1.Probe{
|
&corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/jenkins/login",
|
Path: "/jenkins/login",
|
||||||
},
|
},
|
||||||
|
|
@ -187,7 +187,7 @@ func TestSetLivenessAndReadinessPath(t *testing.T) {
|
||||||
|
|
||||||
jenkins.Spec.Master.Containers[0].LivenessProbe =
|
jenkins.Spec.Master.Containers[0].LivenessProbe =
|
||||||
&corev1.Probe{
|
&corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/jenkins/login",
|
Path: "/jenkins/login",
|
||||||
},
|
},
|
||||||
|
|
@ -205,7 +205,7 @@ func TestSetLivenessAndReadinessPath(t *testing.T) {
|
||||||
|
|
||||||
jenkins.Spec.Master.Containers[0].ReadinessProbe =
|
jenkins.Spec.Master.Containers[0].ReadinessProbe =
|
||||||
&corev1.Probe{
|
&corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/jenkins/login",
|
Path: "/jenkins/login",
|
||||||
},
|
},
|
||||||
|
|
@ -214,7 +214,7 @@ func TestSetLivenessAndReadinessPath(t *testing.T) {
|
||||||
|
|
||||||
jenkins.Spec.Master.Containers[0].LivenessProbe =
|
jenkins.Spec.Master.Containers[0].LivenessProbe =
|
||||||
&corev1.Probe{
|
&corev1.Probe{
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/jenkins/login",
|
Path: "/jenkins/login",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
|
|
@ -15,8 +14,6 @@ import (
|
||||||
|
|
||||||
const installPluginsCommand = "jenkins-plugin-cli"
|
const installPluginsCommand = "jenkins-plugin-cli"
|
||||||
|
|
||||||
var requiredBasePlugins = []string{"configuration-as-code", "git", "job-dsl", "kubernetes", "kubernetes-credentials-provider", "workflow-aggregator"}
|
|
||||||
|
|
||||||
var initBashTemplate = template.Must(template.New(InitScriptName).Parse(`#!/usr/bin/env bash
|
var initBashTemplate = template.Must(template.New(InitScriptName).Parse(`#!/usr/bin/env bash
|
||||||
set -e
|
set -e
|
||||||
set -x
|
set -x
|
||||||
|
|
@ -39,7 +36,6 @@ mkdir -p {{ .JenkinsHomePath }}/scripts
|
||||||
cp {{ .JenkinsScriptsVolumePath }}/*.sh {{ .JenkinsHomePath }}/scripts
|
cp {{ .JenkinsScriptsVolumePath }}/*.sh {{ .JenkinsHomePath }}/scripts
|
||||||
chmod +x {{ .JenkinsHomePath }}/scripts/*.sh
|
chmod +x {{ .JenkinsHomePath }}/scripts/*.sh
|
||||||
|
|
||||||
{{if not .SkipPlugins }}
|
|
||||||
{{- $jenkinsHomePath := .JenkinsHomePath }}
|
{{- $jenkinsHomePath := .JenkinsHomePath }}
|
||||||
{{- $installPluginsCommand := .InstallPluginsCommand }}
|
{{- $installPluginsCommand := .InstallPluginsCommand }}
|
||||||
|
|
||||||
|
|
@ -62,19 +58,6 @@ EOF
|
||||||
|
|
||||||
{{ $installPluginsCommand }} --verbose --latest {{ .LatestPlugins }} -f {{ .JenkinsHomePath }}/user-plugins.txt
|
{{ $installPluginsCommand }} --verbose --latest {{ .LatestPlugins }} -f {{ .JenkinsHomePath }}/user-plugins.txt
|
||||||
echo "Installing plugins required by user - end"
|
echo "Installing plugins required by user - end"
|
||||||
{{else}}
|
|
||||||
echo "Skipping installation if plugins"
|
|
||||||
echo "Checking if required base plugins are installed"
|
|
||||||
installedPlugins=$(jenkins-plugin-cli --list 2> /dev/null)
|
|
||||||
for plugin in {{ .RequiredBasePlugins }}; do
|
|
||||||
if ! echo "$installedPlugins" | grep -q "^$plugin "; then
|
|
||||||
echo "Required base plugin $plugin not installed, exiting"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "Found $plugin"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
{{end}}
|
|
||||||
`))
|
`))
|
||||||
|
|
||||||
func buildConfigMapTypeMeta() metav1.TypeMeta {
|
func buildConfigMapTypeMeta() metav1.TypeMeta {
|
||||||
|
|
@ -90,31 +73,22 @@ func buildInitBashScript(jenkins *v1alpha2.Jenkins) (*string, error) {
|
||||||
latestP = new(bool)
|
latestP = new(bool)
|
||||||
*latestP = true
|
*latestP = true
|
||||||
}
|
}
|
||||||
skipPlugins := jenkins.Spec.Master.SkipPlugins
|
|
||||||
if skipPlugins == nil {
|
|
||||||
skipPlugins = new(bool)
|
|
||||||
*skipPlugins = false
|
|
||||||
}
|
|
||||||
data := struct {
|
data := struct {
|
||||||
JenkinsHomePath string
|
JenkinsHomePath string
|
||||||
InitConfigurationPath string
|
InitConfigurationPath string
|
||||||
InstallPluginsCommand string
|
InstallPluginsCommand string
|
||||||
RequiredBasePlugins string
|
|
||||||
JenkinsScriptsVolumePath string
|
JenkinsScriptsVolumePath string
|
||||||
BasePlugins []v1alpha2.Plugin
|
BasePlugins []v1alpha2.Plugin
|
||||||
UserPlugins []v1alpha2.Plugin
|
UserPlugins []v1alpha2.Plugin
|
||||||
LatestPlugins bool
|
LatestPlugins bool
|
||||||
SkipPlugins bool
|
|
||||||
}{
|
}{
|
||||||
JenkinsHomePath: getJenkinsHomePath(jenkins),
|
JenkinsHomePath: getJenkinsHomePath(jenkins),
|
||||||
InitConfigurationPath: jenkinsInitConfigurationVolumePath,
|
InitConfigurationPath: jenkinsInitConfigurationVolumePath,
|
||||||
BasePlugins: jenkins.Spec.Master.BasePlugins,
|
BasePlugins: jenkins.Spec.Master.BasePlugins,
|
||||||
UserPlugins: jenkins.Spec.Master.Plugins,
|
UserPlugins: jenkins.Spec.Master.Plugins,
|
||||||
InstallPluginsCommand: installPluginsCommand,
|
InstallPluginsCommand: installPluginsCommand,
|
||||||
RequiredBasePlugins: strings.Join(requiredBasePlugins, " "),
|
|
||||||
JenkinsScriptsVolumePath: JenkinsScriptsVolumePath,
|
JenkinsScriptsVolumePath: JenkinsScriptsVolumePath,
|
||||||
LatestPlugins: *latestP,
|
LatestPlugins: *latestP,
|
||||||
SkipPlugins: *skipPlugins,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output, err := render.Render(initBashTemplate, data)
|
output, err := render.Render(initBashTemplate, data)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/plugins"
|
"github.com/jenkinsci/kubernetes-operator/pkg/plugins"
|
||||||
|
|
||||||
docker "github.com/distribution/reference"
|
docker "github.com/docker/distribution/reference"
|
||||||
stackerr "github.com/pkg/errors"
|
stackerr "github.com/pkg/errors"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ func (c *Configuration) Exec(podName, containerName string, command []string) (s
|
||||||
return stdout, stderr, stackerr.Wrap(err, "pod exec error while creating Executor")
|
return stdout, stderr, stackerr.Wrap(err, "pod exec error while creating Executor")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = exec.StreamWithContext(context.TODO(), remotecommand.StreamOptions{
|
err = exec.Stream(remotecommand.StreamOptions{
|
||||||
Stdin: nil,
|
Stdin: nil,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
Stderr: &stderr,
|
Stderr: &stderr,
|
||||||
|
|
@ -165,7 +165,7 @@ func (c *Configuration) Exec(podName, containerName string, command []string) (s
|
||||||
return stdout, stderr, stackerr.Wrapf(err, "pod exec error operation on stream: stdout '%s' stderr '%s'", stdout.String(), stderr.String())
|
return stdout, stderr, stackerr.Wrapf(err, "pod exec error operation on stream: stdout '%s' stderr '%s'", stdout.String(), stderr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
return stdout, stderr, nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetJenkinsMasterContainer returns the Jenkins master container from the CR.
|
// GetJenkinsMasterContainer returns the Jenkins master container from the CR.
|
||||||
|
|
|
||||||
|
|
@ -60,14 +60,6 @@ func (r *reconcileUserConfiguration) ReconcileOthers() (reconcile.Result, error)
|
||||||
return reconcile.Result{}, err
|
return reconcile.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := backupAndRestore.Backup(false); err != nil {
|
|
||||||
return reconcile.Result{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := backupAndRestore.EnsureBackupTrigger(); err != nil {
|
|
||||||
return reconcile.Result{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := r.ensureSeedJobs()
|
result, err := r.ensureSeedJobs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reconcile.Result{}, err
|
return reconcile.Result{}, err
|
||||||
|
|
@ -76,6 +68,13 @@ func (r *reconcileUserConfiguration) ReconcileOthers() (reconcile.Result, error)
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := backupAndRestore.Backup(false); err != nil {
|
||||||
|
return reconcile.Result{}, err
|
||||||
|
}
|
||||||
|
if err := backupAndRestore.EnsureBackupTrigger(); err != nil {
|
||||||
|
return reconcile.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
return reconcile.Result{}, nil
|
return reconcile.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,6 @@ func (s *seedJobs) EnsureSeedJobs(jenkins *v1alpha2.Jenkins) (done bool, err err
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil && !apierrors.IsNotFound(err) {
|
if err != nil && !apierrors.IsNotFound(err) {
|
||||||
|
|
||||||
return false, stackerr.WithStack(err)
|
return false, stackerr.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -237,7 +236,6 @@ func (s *seedJobs) EnsureSeedJobs(jenkins *v1alpha2.Jenkins) (done bool, err err
|
||||||
|
|
||||||
seedJobIDs := s.getAllSeedJobIDs(*jenkins)
|
seedJobIDs := s.getAllSeedJobIDs(*jenkins)
|
||||||
if !reflect.DeepEqual(seedJobIDs, jenkins.Status.CreatedSeedJobs) {
|
if !reflect.DeepEqual(seedJobIDs, jenkins.Status.CreatedSeedJobs) {
|
||||||
// @ansh-devs fixed : calls to Update and Patch will not alter its status.
|
|
||||||
jenkins.Status.CreatedSeedJobs = seedJobIDs
|
jenkins.Status.CreatedSeedJobs = seedJobIDs
|
||||||
return false, stackerr.WithStack(s.Client.Status().Update(context.TODO(), jenkins))
|
return false, stackerr.WithStack(s.Client.Status().Update(context.TODO(), jenkins))
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +303,6 @@ func (s *seedJobs) createJobs(jenkins *v1alpha2.Jenkins) (requeue bool, err erro
|
||||||
// Operator will able to watch any changes made to them
|
// Operator will able to watch any changes made to them
|
||||||
func (s *seedJobs) ensureLabelsForSecrets(jenkins v1alpha2.Jenkins) error {
|
func (s *seedJobs) ensureLabelsForSecrets(jenkins v1alpha2.Jenkins) error {
|
||||||
for _, seedJob := range jenkins.Spec.SeedJobs {
|
for _, seedJob := range jenkins.Spec.SeedJobs {
|
||||||
|
|
||||||
if seedJob.JenkinsCredentialType == v1alpha2.BasicSSHCredentialType || seedJob.JenkinsCredentialType == v1alpha2.UsernamePasswordCredentialType {
|
if seedJob.JenkinsCredentialType == v1alpha2.BasicSSHCredentialType || seedJob.JenkinsCredentialType == v1alpha2.UsernamePasswordCredentialType {
|
||||||
requiredLabels := resources.BuildLabelsForWatchedResources(jenkins)
|
requiredLabels := resources.BuildLabelsForWatchedResources(jenkins)
|
||||||
requiredLabels[JenkinsCredentialTypeLabelName] = string(seedJob.JenkinsCredentialType)
|
requiredLabels[JenkinsCredentialTypeLabelName] = string(seedJob.JenkinsCredentialType)
|
||||||
|
|
@ -347,7 +344,7 @@ func (s *seedJobs) credentialValue(namespace string, seedJob v1alpha2.SeedJob) (
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *seedJobs) getAllSeedJobIDs(jenkins v1alpha2.Jenkins) []string {
|
func (s *seedJobs) getAllSeedJobIDs(jenkins v1alpha2.Jenkins) []string {
|
||||||
ids := make([]string, 0, len(jenkins.Spec.SeedJobs))
|
var ids []string
|
||||||
for _, seedJob := range jenkins.Spec.SeedJobs {
|
for _, seedJob := range jenkins.Spec.SeedJobs {
|
||||||
ids = append(ids, seedJob.ID)
|
ids = append(ids, seedJob.ID)
|
||||||
}
|
}
|
||||||
|
|
@ -372,11 +369,11 @@ func (s *seedJobs) isRecreatePodNeeded(jenkins v1alpha2.Jenkins) bool {
|
||||||
|
|
||||||
// createAgent deploys Jenkins agent to Kubernetes cluster
|
// createAgent deploys Jenkins agent to Kubernetes cluster
|
||||||
func (s *seedJobs) createAgent(jenkinsClient jenkinsclient.Jenkins, k8sClient client.Client, jenkinsManifest *v1alpha2.Jenkins, namespace string, agentName string) error {
|
func (s *seedJobs) createAgent(jenkinsClient jenkinsclient.Jenkins, k8sClient client.Client, jenkinsManifest *v1alpha2.Jenkins, namespace string, agentName string) error {
|
||||||
_, err := jenkinsClient.GetNode(context.TODO(), agentName)
|
_, err := jenkinsClient.GetNode(agentName)
|
||||||
|
|
||||||
// Create node if not exists
|
// Create node if not exists
|
||||||
if err != nil && err.Error() == "No node found" {
|
if err != nil && err.Error() == "No node found" {
|
||||||
_, err = jenkinsClient.CreateNode(context.TODO(), agentName, 5, "The jenkins-operator generated agent", "/home/jenkins", agentName)
|
_, err = jenkinsClient.CreateNode(agentName, 5, "The jenkins-operator generated agent", "/home/jenkins", agentName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return stackerr.WithStack(err)
|
return stackerr.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,8 @@ func TestEnsureSeedJobs(t *testing.T) {
|
||||||
seedJobCreatingScript, err := seedJobCreatingGroovyScript(jenkins.Spec.SeedJobs[0])
|
seedJobCreatingScript, err := seedJobCreatingGroovyScript(jenkins.Spec.SeedJobs[0])
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
jenkinsClient.EXPECT().GetNode(context.TODO(), AgentName).Return(nil, nil).AnyTimes()
|
jenkinsClient.EXPECT().GetNode(AgentName).Return(nil, nil).AnyTimes()
|
||||||
jenkinsClient.EXPECT().CreateNode(context.TODO(), AgentName, 1, "The jenkins-operator generated agent", "/home/jenkins", AgentName).Return(testNode, nil).AnyTimes()
|
jenkinsClient.EXPECT().CreateNode(AgentName, 1, "The jenkins-operator generated agent", "/home/jenkins", AgentName).Return(testNode, nil).AnyTimes()
|
||||||
jenkinsClient.EXPECT().GetNodeSecret(AgentName).Return(agentSecret, nil).AnyTimes()
|
jenkinsClient.EXPECT().GetNodeSecret(AgentName).Return(agentSecret, nil).AnyTimes()
|
||||||
jenkinsClient.EXPECT().ExecuteScript(seedJobCreatingScript).AnyTimes()
|
jenkinsClient.EXPECT().ExecuteScript(seedJobCreatingScript).AnyTimes()
|
||||||
|
|
||||||
|
|
@ -128,10 +128,7 @@ func TestEnsureSeedJobs(t *testing.T) {
|
||||||
jenkins.Spec.SeedJobs = []v1alpha2.SeedJob{}
|
jenkins.Spec.SeedJobs = []v1alpha2.SeedJob{}
|
||||||
|
|
||||||
jenkinsClient := jenkinsclient.NewMockJenkins(ctrl)
|
jenkinsClient := jenkinsclient.NewMockJenkins(ctrl)
|
||||||
fakeClient := fake.NewClientBuilder().
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
WithRuntimeObjects(jenkins).
|
|
||||||
WithStatusSubresource(jenkins).
|
|
||||||
Build()
|
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -142,8 +139,8 @@ func TestEnsureSeedJobs(t *testing.T) {
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
}
|
}
|
||||||
|
|
||||||
jenkinsClient.EXPECT().GetNode(ctx, AgentName).AnyTimes()
|
jenkinsClient.EXPECT().GetNode(AgentName).AnyTimes()
|
||||||
jenkinsClient.EXPECT().CreateNode(ctx, AgentName, 1, "The jenkins-operator generated agent", "/home/jenkins", AgentName).AnyTimes()
|
jenkinsClient.EXPECT().CreateNode(AgentName, 1, "The jenkins-operator generated agent", "/home/jenkins", AgentName).AnyTimes()
|
||||||
jenkinsClient.EXPECT().GetNodeSecret(AgentName).Return(agentSecret, nil).AnyTimes()
|
jenkinsClient.EXPECT().GetNodeSecret(AgentName).Return(agentSecret, nil).AnyTimes()
|
||||||
|
|
||||||
seedJobsClient := New(jenkinsClient, config)
|
seedJobsClient := New(jenkinsClient, config)
|
||||||
|
|
@ -158,14 +155,13 @@ func TestEnsureSeedJobs(t *testing.T) {
|
||||||
|
|
||||||
// when
|
// when
|
||||||
_, err = seedJobsClient.EnsureSeedJobs(jenkins)
|
_, err = seedJobsClient.EnsureSeedJobs(jenkins)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
var deployment appsv1.Deployment
|
var deployment appsv1.Deployment
|
||||||
err = fakeClient.Get(ctx, types.NamespacedName{
|
err = fakeClient.Get(ctx, types.NamespacedName{Namespace: jenkins.Namespace, Name: agentDeploymentName(*jenkins, AgentName)}, &deployment)
|
||||||
Namespace: jenkins.Namespace,
|
|
||||||
Name: agentDeploymentName(*jenkins, AgentName),
|
|
||||||
}, &deployment)
|
|
||||||
assert.True(t, errors.IsNotFound(err), "Agent deployment hasn't been deleted")
|
assert.True(t, errors.IsNotFound(err), "Agent deployment hasn't been deleted")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -184,8 +180,8 @@ func TestCreateAgent(t *testing.T) {
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
jenkinsClient.EXPECT().GetNode(context.TODO(), AgentName).AnyTimes()
|
jenkinsClient.EXPECT().GetNode(AgentName).AnyTimes()
|
||||||
jenkinsClient.EXPECT().CreateNode(context.TODO(), AgentName, 1, "The jenkins-operator generated agent", "/home/jenkins", AgentName).AnyTimes()
|
jenkinsClient.EXPECT().CreateNode(AgentName, 1, "The jenkins-operator generated agent", "/home/jenkins", AgentName).AnyTimes()
|
||||||
jenkinsClient.EXPECT().GetNodeSecret(AgentName).Return(agentSecret, nil).AnyTimes()
|
jenkinsClient.EXPECT().GetNodeSecret(AgentName).Return(agentSecret, nil).AnyTimes()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import (
|
||||||
|
|
||||||
// ValidateSeedJobs verify seed jobs configuration
|
// ValidateSeedJobs verify seed jobs configuration
|
||||||
func (s *seedJobs) ValidateSeedJobs(jenkins v1alpha2.Jenkins) ([]string, error) {
|
func (s *seedJobs) ValidateSeedJobs(jenkins v1alpha2.Jenkins) ([]string, error) {
|
||||||
messages := []string{}
|
var messages []string
|
||||||
|
|
||||||
if msg := s.validateIfIDIsUnique(jenkins.Spec.SeedJobs); len(msg) > 0 {
|
if msg := s.validateIfIDIsUnique(jenkins.Spec.SeedJobs); len(msg) > 0 {
|
||||||
messages = append(messages, msg...)
|
messages = append(messages, msg...)
|
||||||
|
|
@ -88,30 +88,26 @@ func (s *seedJobs) ValidateSeedJobs(jenkins v1alpha2.Jenkins) ([]string, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.setSeedJobPushTriggers(seedJob, &messages, jenkins)
|
if seedJob.GitHubPushTrigger {
|
||||||
|
if msg := s.validateGitHubPushTrigger(jenkins); len(msg) > 0 {
|
||||||
|
for _, m := range msg {
|
||||||
|
messages = append(messages, fmt.Sprintf("seedJob `%s` %s", seedJob.ID, m))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if seedJob.BitbucketPushTrigger {
|
||||||
|
if msg := s.validateBitbucketPushTrigger(jenkins); len(msg) > 0 {
|
||||||
|
for _, m := range msg {
|
||||||
|
messages = append(messages, fmt.Sprintf("seedJob `%s` %s", seedJob.ID, m))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return messages, nil
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *seedJobs) setSeedJobPushTriggers(seedJob v1alpha2.SeedJob, messages *[]string, jenkins v1alpha2.Jenkins) {
|
|
||||||
if seedJob.GitHubPushTrigger {
|
|
||||||
if msg := s.validateGitHubPushTrigger(jenkins); len(msg) > 0 {
|
|
||||||
for _, m := range msg {
|
|
||||||
*messages = append(*messages, fmt.Sprintf("seedJob `%s` %s", seedJob.ID, m))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if seedJob.BitbucketPushTrigger {
|
|
||||||
if msg := s.validateBitbucketPushTrigger(jenkins); len(msg) > 0 {
|
|
||||||
for _, m := range msg {
|
|
||||||
*messages = append(*messages, fmt.Sprintf("seedJob `%s` %s", seedJob.ID, m))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *seedJobs) validateGitHubPushTrigger(jenkins v1alpha2.Jenkins) []string {
|
func (s *seedJobs) validateGitHubPushTrigger(jenkins v1alpha2.Jenkins) []string {
|
||||||
var messages []string
|
var messages []string
|
||||||
if err := checkPluginExists(jenkins, "github"); err != nil {
|
if err := checkPluginExists(jenkins, "github"); err != nil {
|
||||||
|
|
@ -129,7 +125,6 @@ func (s *seedJobs) validateBitbucketPushTrigger(jenkins v1alpha2.Jenkins) []stri
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPluginExists(jenkins v1alpha2.Jenkins, name string) error {
|
func checkPluginExists(jenkins v1alpha2.Jenkins, name string) error {
|
||||||
|
|
||||||
exists := false
|
exists := false
|
||||||
for _, plugin := range jenkins.Spec.Master.BasePlugins {
|
for _, plugin := range jenkins.Spec.Master.BasePlugins {
|
||||||
if plugin.Name == name {
|
if plugin.Name == name {
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, result)
|
assert.Nil(t, result)
|
||||||
})
|
})
|
||||||
t.Run("Invalid without id", func(t *testing.T) {
|
t.Run("Invalid without id", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
|
@ -178,7 +178,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, result)
|
assert.Nil(t, result)
|
||||||
})
|
})
|
||||||
t.Run("Invalid ed25519 private key in secret", func(t *testing.T) {
|
t.Run("Invalid ed25519 private key in secret", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
|
@ -261,7 +261,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, result)
|
assert.Nil(t, result)
|
||||||
})
|
})
|
||||||
t.Run("Invalid RSA private key in secret", func(t *testing.T) {
|
t.Run("Invalid RSA private key in secret", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
|
@ -508,7 +508,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, result)
|
assert.Nil(t, result)
|
||||||
})
|
})
|
||||||
t.Run("Invalid with empty username", func(t *testing.T) {
|
t.Run("Invalid with empty username", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
|
@ -715,7 +715,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, result)
|
assert.Nil(t, result)
|
||||||
})
|
})
|
||||||
t.Run("Invalid with empty app id", func(t *testing.T) {
|
t.Run("Invalid with empty app id", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
|
@ -914,7 +914,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, result)
|
assert.Nil(t, result)
|
||||||
})
|
})
|
||||||
t.Run("Invalid with set githubPushTrigger and not installed github plugin", func(t *testing.T) {
|
t.Run("Invalid with set githubPushTrigger and not installed github plugin", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
|
@ -984,7 +984,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, result)
|
assert.Nil(t, result)
|
||||||
})
|
})
|
||||||
t.Run("Invalid with set bitbucketPushTrigger and not installed bitbucket plugin", func(t *testing.T) {
|
t.Run("Invalid with set bitbucketPushTrigger and not installed bitbucket plugin", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
|
@ -1054,7 +1054,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
result, err := seedJobs.ValidateSeedJobs(jenkins)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, result)
|
assert.Nil(t, result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ const (
|
||||||
// SeedJobSuffix is a suffix added for all seed jobs
|
// SeedJobSuffix is a suffix added for all seed jobs
|
||||||
SeedJobSuffix = "job-dsl-seed"
|
SeedJobSuffix = "job-dsl-seed"
|
||||||
// DefaultJenkinsMasterImage is the default Jenkins master docker image
|
// DefaultJenkinsMasterImage is the default Jenkins master docker image
|
||||||
DefaultJenkinsMasterImage = "jenkins/jenkins:2.528.1-lts"
|
DefaultJenkinsMasterImage = "jenkins/jenkins:2.452.2-lts"
|
||||||
// DefaultHTTPPortInt32 is the default Jenkins HTTP port
|
// DefaultHTTPPortInt32 is the default Jenkins HTTP port
|
||||||
DefaultHTTPPortInt32 = int32(8080)
|
DefaultHTTPPortInt32 = int32(8080)
|
||||||
// DefaultSlavePortInt32 is the default Jenkins port for slaves
|
// DefaultSlavePortInt32 is the default Jenkins port for slaves
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func (g *Groovy) EnsureSingle(source, name, hash, groovyScript string) (requeue
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
||||||
appliedGroovyScripts := []v1alpha2.AppliedGroovyScript{}
|
var appliedGroovyScripts []v1alpha2.AppliedGroovyScript
|
||||||
|
|
||||||
for _, ags := range g.jenkins.Status.AppliedGroovyScripts {
|
for _, ags := range g.jenkins.Status.AppliedGroovyScripts {
|
||||||
if g.configurationType == ags.ConfigurationType && ags.Source == source && ags.Name == name {
|
if g.configurationType == ags.ConfigurationType && ags.Source == source && ags.Name == name {
|
||||||
|
|
@ -114,10 +114,7 @@ func (g *Groovy) WaitForSecretSynchronization(secretsPath string) (requeue bool,
|
||||||
func (g *Groovy) Ensure(filter func(name string) bool, updateGroovyScript func(groovyScript string) string) (requeue bool, err error) {
|
func (g *Groovy) Ensure(filter func(name string) bool, updateGroovyScript func(groovyScript string) string) (requeue bool, err error) {
|
||||||
secret := &corev1.Secret{}
|
secret := &corev1.Secret{}
|
||||||
if len(g.customization.Secret.Name) > 0 {
|
if len(g.customization.Secret.Name) > 0 {
|
||||||
err := g.k8sClient.Get(context.TODO(), types.NamespacedName{
|
err := g.k8sClient.Get(context.TODO(), types.NamespacedName{Name: g.customization.Secret.Name, Namespace: g.jenkins.ObjectMeta.Namespace}, secret)
|
||||||
Name: g.customization.Secret.Name,
|
|
||||||
Namespace: g.jenkins.ObjectMeta.Namespace,
|
|
||||||
}, secret)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +182,7 @@ func (g *Groovy) isGroovyScriptAlreadyApplied(source, name, hash string) bool {
|
||||||
func (g *Groovy) calculateHash(data map[string]string) (string, error) {
|
func (g *Groovy) calculateHash(data map[string]string) (string, error) {
|
||||||
hash := sha256.New()
|
hash := sha256.New()
|
||||||
|
|
||||||
keys := []string{}
|
var keys []string
|
||||||
for key := range data {
|
for key := range data {
|
||||||
keys = append(keys, key)
|
keys = append(keys, key)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
const configurationType = "test-conf-type"
|
const configurationType = "test-conf-type"
|
||||||
|
|
||||||
func TestGroovy_EnsureSingle(t *testing.T) {
|
func TestGroovy_EnsureSingle(t *testing.T) {
|
||||||
t.Skip("TODO: fix me, skipping the test suite temporarily")
|
|
||||||
log.SetupLogger(true)
|
log.SetupLogger(true)
|
||||||
emptyCustomization := v1alpha2.Customization{}
|
emptyCustomization := v1alpha2.Customization{}
|
||||||
hash := "hash"
|
hash := "hash"
|
||||||
|
|
@ -349,7 +348,6 @@ func TestGroovy_EnsureSingle(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGroovy_Ensure(t *testing.T) {
|
func TestGroovy_Ensure(t *testing.T) {
|
||||||
t.Skip("TODO: fix me, skipping the test suite temporarily")
|
|
||||||
log.SetupLogger(true)
|
log.SetupLogger(true)
|
||||||
groovyScript := "groovy-script"
|
groovyScript := "groovy-script"
|
||||||
groovyScriptName := "groovy-script-name.groovy"
|
groovyScriptName := "groovy-script-name.groovy"
|
||||||
|
|
@ -614,7 +612,6 @@ func TestGroovy_Ensure(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGroovy_isGroovyScriptAlreadyApplied(t *testing.T) {
|
func TestGroovy_isGroovyScriptAlreadyApplied(t *testing.T) {
|
||||||
t.Skip("TODO: fix me, skipping the test suite temporarily")
|
|
||||||
log.SetupLogger(true)
|
log.SetupLogger(true)
|
||||||
emptyCustomization := v1alpha2.Customization{}
|
emptyCustomization := v1alpha2.Customization{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ func Listen(events chan event.Event, k8sEvent k8sevent.Recorder, k8sClient k8scl
|
||||||
continue // skip the event
|
continue // skip the event
|
||||||
}
|
}
|
||||||
|
|
||||||
go func(notificationConfig v1alpha2.Notification, e event.Event) {
|
go func(notificationConfig v1alpha2.Notification) {
|
||||||
err = provider.Send(e)
|
err = provider.Send(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wrapped := errors.WithMessage(err,
|
wrapped := errors.WithMessage(err,
|
||||||
|
|
@ -75,7 +75,7 @@ func Listen(events chan event.Event, k8sEvent k8sevent.Recorder, k8sClient k8scl
|
||||||
logger.Error(nil, fmt.Sprintf("%s", wrapped))
|
logger.Error(nil, fmt.Sprintf("%s", wrapped))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}(notificationConfig, e)
|
}(notificationConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -75,11 +74,11 @@ func (s Slack) generateMessage(e event.Event) Message {
|
||||||
var messageStringBuilder strings.Builder
|
var messageStringBuilder strings.Builder
|
||||||
if s.config.Verbose {
|
if s.config.Verbose {
|
||||||
for _, msg := range e.Reason.Verbose() {
|
for _, msg := range e.Reason.Verbose() {
|
||||||
messageStringBuilder.WriteString(fmt.Sprintf("\n - %s \n", msg))
|
messageStringBuilder.WriteString("\n - " + msg + "\n")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, msg := range e.Reason.Short() {
|
for _, msg := range e.Reason.Short() {
|
||||||
messageStringBuilder.WriteString(fmt.Sprintf("\n - %s \n", msg))
|
messageStringBuilder.WriteString("\n - " + msg + "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package slack
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -81,7 +80,7 @@ func TestSlack_Send(t *testing.T) {
|
||||||
case "":
|
case "":
|
||||||
message := ""
|
message := ""
|
||||||
for _, msg := range e.Reason.Short() {
|
for _, msg := range e.Reason.Short() {
|
||||||
message = message + fmt.Sprintf("\n - %s \n", msg)
|
message = message + "\n - " + msg + "\n"
|
||||||
}
|
}
|
||||||
assert.Equal(t, field.Value, message)
|
assert.Equal(t, field.Value, message)
|
||||||
case provider.LevelFieldName:
|
case provider.LevelFieldName:
|
||||||
|
|
@ -149,7 +148,7 @@ func TestGenerateMessage(t *testing.T) {
|
||||||
|
|
||||||
var messageStringBuilder strings.Builder
|
var messageStringBuilder strings.Builder
|
||||||
for _, msg := range e.Reason.Verbose() {
|
for _, msg := range e.Reason.Verbose() {
|
||||||
messageStringBuilder.WriteString(fmt.Sprintf("\n - %s \n", msg))
|
messageStringBuilder.WriteString("\n - " + msg + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
mainAttachment := message.Attachments[0]
|
mainAttachment := message.Attachments[0]
|
||||||
|
|
@ -195,7 +194,7 @@ func TestGenerateMessage(t *testing.T) {
|
||||||
|
|
||||||
var messageStringBuilder strings.Builder
|
var messageStringBuilder strings.Builder
|
||||||
for _, msg := range e.Reason.Verbose() {
|
for _, msg := range e.Reason.Verbose() {
|
||||||
messageStringBuilder.WriteString(fmt.Sprintf("\n - %s \n", msg))
|
messageStringBuilder.WriteString("\n - " + msg + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
mainAttachment := message.Attachments[0]
|
mainAttachment := message.Attachments[0]
|
||||||
|
|
@ -241,7 +240,7 @@ func TestGenerateMessage(t *testing.T) {
|
||||||
|
|
||||||
var messageStringBuilder strings.Builder
|
var messageStringBuilder strings.Builder
|
||||||
for _, msg := range e.Reason.Verbose() {
|
for _, msg := range e.Reason.Verbose() {
|
||||||
messageStringBuilder.WriteString(fmt.Sprintf("\n - %s \n", msg))
|
messageStringBuilder.WriteString("\n - " + msg + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
mainAttachment := message.Attachments[0]
|
mainAttachment := message.Attachments[0]
|
||||||
|
|
@ -287,7 +286,7 @@ func TestGenerateMessage(t *testing.T) {
|
||||||
|
|
||||||
var messageStringBuilder strings.Builder
|
var messageStringBuilder strings.Builder
|
||||||
for _, msg := range e.Reason.Verbose() {
|
for _, msg := range e.Reason.Verbose() {
|
||||||
messageStringBuilder.WriteString(fmt.Sprintf("\n - %s \n", msg))
|
messageStringBuilder.WriteString("\n - " + msg + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
mainAttachment := message.Attachments[0]
|
mainAttachment := message.Attachments[0]
|
||||||
|
|
|
||||||
|
|
@ -72,19 +72,14 @@ func (s SMTP) generateMessage(e event.Event) *gomail.Message {
|
||||||
statusMessage.WriteString(reasons)
|
statusMessage.WriteString(reasons)
|
||||||
statusMessage.WriteString("</ul>")
|
statusMessage.WriteString("</ul>")
|
||||||
|
|
||||||
htmlMessage := fmt.Sprintf(
|
htmlMessage := fmt.Sprintf(content, s.getStatusColor(e.Level), provider.NotificationTitle(e), statusMessage.String(), e.Jenkins.Name, e.Phase)
|
||||||
content,
|
|
||||||
s.getStatusColor(e.Level),
|
|
||||||
provider.NotificationTitle(e),
|
|
||||||
statusMessage.String(),
|
|
||||||
e.Jenkins.Name, e.Phase,
|
|
||||||
)
|
|
||||||
message := gomail.NewMessage()
|
message := gomail.NewMessage()
|
||||||
|
|
||||||
message.SetHeader("From", s.config.SMTP.From)
|
message.SetHeader("From", s.config.SMTP.From)
|
||||||
message.SetHeader("To", s.config.SMTP.To)
|
message.SetHeader("To", s.config.SMTP.To)
|
||||||
message.SetHeader("Subject", mailSubject)
|
message.SetHeader("Subject", mailSubject)
|
||||||
message.SetBody("text/html", htmlMessage)
|
message.SetBody("text/html", htmlMessage)
|
||||||
|
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,23 +91,16 @@ func (s SMTP) Send(e event.Event) error {
|
||||||
usernameSelector := s.config.SMTP.UsernameSecretKeySelector
|
usernameSelector := s.config.SMTP.UsernameSecretKeySelector
|
||||||
passwordSelector := s.config.SMTP.PasswordSecretKeySelector
|
passwordSelector := s.config.SMTP.PasswordSecretKeySelector
|
||||||
|
|
||||||
err := s.k8sClient.Get(context.TODO(), types.NamespacedName{
|
err := s.k8sClient.Get(context.TODO(), types.NamespacedName{Name: usernameSelector.Name, Namespace: e.Jenkins.Namespace}, usernameSecret)
|
||||||
Name: usernameSelector.Name,
|
|
||||||
Namespace: e.Jenkins.Namespace,
|
|
||||||
}, usernameSecret,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.k8sClient.Get(context.TODO(), types.NamespacedName{
|
err = s.k8sClient.Get(context.TODO(), types.NamespacedName{Name: passwordSelector.Name, Namespace: e.Jenkins.Namespace}, passwordSecret)
|
||||||
Name: passwordSelector.Name,
|
|
||||||
Namespace: e.Jenkins.Namespace,
|
|
||||||
}, passwordSecret,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
usernameSecretValue := string(usernameSecret.Data[usernameSelector.Key])
|
usernameSecretValue := string(usernameSecret.Data[usernameSelector.Key])
|
||||||
if usernameSecretValue == "" {
|
if usernameSecretValue == "" {
|
||||||
return errors.Errorf("SMTP username is empty in secret '%s/%s[%s]", e.Jenkins.Namespace, usernameSelector.Name, usernameSelector.Key)
|
return errors.Errorf("SMTP username is empty in secret '%s/%s[%s]", e.Jenkins.Namespace, usernameSelector.Name, usernameSelector.Key)
|
||||||
|
|
@ -122,19 +110,15 @@ func (s SMTP) Send(e event.Event) error {
|
||||||
if passwordSecretValue == "" {
|
if passwordSecretValue == "" {
|
||||||
return errors.Errorf("SMTP password is empty in secret '%s/%s[%s]", e.Jenkins.Namespace, passwordSelector.Name, passwordSelector.Key)
|
return errors.Errorf("SMTP password is empty in secret '%s/%s[%s]", e.Jenkins.Namespace, passwordSelector.Name, passwordSelector.Key)
|
||||||
}
|
}
|
||||||
mailer := gomail.NewDialer(
|
|
||||||
s.config.SMTP.Server,
|
mailer := gomail.NewDialer(s.config.SMTP.Server, s.config.SMTP.Port, usernameSecretValue, passwordSecretValue)
|
||||||
s.config.SMTP.Port,
|
|
||||||
usernameSecretValue,
|
|
||||||
passwordSecretValue,
|
|
||||||
)
|
|
||||||
mailer.TLSConfig = &tls.Config{InsecureSkipVerify: s.config.SMTP.TLSInsecureSkipVerify}
|
mailer.TLSConfig = &tls.Config{InsecureSkipVerify: s.config.SMTP.TLSInsecureSkipVerify}
|
||||||
|
|
||||||
message := s.generateMessage(e)
|
message := s.generateMessage(e)
|
||||||
|
|
||||||
if err := mailer.DialAndSend(message); err != nil {
|
if err := mailer.DialAndSend(message); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,218 +1,214 @@
|
||||||
package smtp
|
package smtp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
//"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"mime/quotedprintable"
|
||||||
|
"net"
|
||||||
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
||||||
|
|
||||||
|
"github.com/emersion/go-smtp"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// testSMTPUsername = "username"
|
testSMTPUsername = "username"
|
||||||
// testSMTPPassword = "password"
|
testSMTPPassword = "password"
|
||||||
|
|
||||||
// testSMTPPort = 1025
|
testSMTPPort = 1025
|
||||||
|
|
||||||
// testFrom = "test@localhost"
|
testFrom = "test@localhost"
|
||||||
// testTo = "test.to@localhost"
|
testTo = "test.to@localhost"
|
||||||
// testSubject = "Jenkins Operator Notification"
|
testSubject = "Jenkins Operator Notification"
|
||||||
|
|
||||||
// // Headers titles
|
// Headers titles
|
||||||
// fromHeader = "From"
|
fromHeader = "From"
|
||||||
// toHeader = "To"
|
toHeader = "To"
|
||||||
// subjectHeader = "Subject"
|
subjectHeader = "Subject"
|
||||||
|
|
||||||
nilConst = "nil"
|
nilConst = "nil"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// testPhase = event.PhaseUser
|
testPhase = event.PhaseUser
|
||||||
// testCrName = "test-cr"
|
testCrName = "test-cr"
|
||||||
// testNamespace = "default"
|
testNamespace = "default"
|
||||||
// testReason = reason.NewPodRestart(
|
testReason = reason.NewPodRestart(
|
||||||
//
|
reason.KubernetesSource,
|
||||||
// reason.KubernetesSource,
|
[]string{"test-reason-1"},
|
||||||
// []string{"test-reason-1"},
|
[]string{"test-verbose-1"}...,
|
||||||
// []string{"test-verbose-1"}...,
|
)
|
||||||
//
|
testLevel = v1alpha2.NotificationLevelWarning
|
||||||
// )
|
|
||||||
// testLevel = v1alpha2.NotificationLevelWarning
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// type testServer struct {
|
type testServer struct {
|
||||||
// event event.Event
|
event event.Event
|
||||||
// }
|
}
|
||||||
|
|
||||||
// NewSession implements smtp.Backend.
|
// Login handles a login command with username and password.
|
||||||
// func (t *testServer) NewSession(c *smtp.Conn) (smtp.Session, error) {
|
func (bkd *testServer) Login(_ *smtp.ConnectionState, username, password string) (smtp.Session, error) {
|
||||||
// return testSession{}, nil
|
if username != testSMTPUsername || password != testSMTPPassword {
|
||||||
// }
|
return nil, errors.New("invalid username or password")
|
||||||
|
}
|
||||||
|
return &testSession{event: bkd.event}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// // TODO: @brokenpip3 fix me
|
// AnonymousLogin requires clients to authenticate using SMTP AUTH before sending emails
|
||||||
// func (bkd *testServer) Login(_ *smtp.Conn, username, password string) (smtp.Session, error) {
|
func (bkd *testServer) AnonymousLogin(_ *smtp.ConnectionState) (smtp.Session, error) {
|
||||||
// if username != testSMTPUsername || password != testSMTPPassword {
|
return nil, smtp.ErrAuthRequired
|
||||||
// return nil, errors.New("invalid username or password")
|
}
|
||||||
// }
|
|
||||||
// return &testSession{event: bkd.event}, nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
//
|
|
||||||
//// AnonymousLogin requires clients to authenticate using SMTP AUTH before sending emails
|
|
||||||
//func (bkd *testServer) AnonymousLogin(_ *smtp.ConnectionState) (smtp.Session, error) {
|
|
||||||
// return nil, smtp.ErrAuthRequired
|
|
||||||
//}
|
|
||||||
|
|
||||||
// A Session is returned after successful login.
|
// A Session is returned after successful login.
|
||||||
// type testSession struct {
|
type testSession struct {
|
||||||
// event event.Event
|
event event.Event
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // func (s testSession) Mail(from string, mop *smtp.MailOptions) error {
|
func (s *testSession) Mail(from string) error {
|
||||||
// // if from != testFrom {
|
if from != testFrom {
|
||||||
// // return fmt.Errorf("`From` header is not equal: '%s', expected '%s'", from, testFrom)
|
return fmt.Errorf("`From` header is not equal: '%s', expected '%s'", from, testFrom)
|
||||||
// // }
|
}
|
||||||
// // return nil
|
return nil
|
||||||
// // }
|
}
|
||||||
|
|
||||||
// // func (s testSession) Rcpt(to string, mop *smtp.RcptOptions) error {
|
func (s *testSession) Rcpt(to string) error {
|
||||||
// // if to != testTo {
|
if to != testTo {
|
||||||
// // return fmt.Errorf("`To` header is not equal: '%s', expected '%s'", to, testTo)
|
return fmt.Errorf("`To` header is not equal: '%s', expected '%s'", to, testTo)
|
||||||
// // }
|
}
|
||||||
// // return nil
|
return nil
|
||||||
// // }
|
}
|
||||||
|
|
||||||
// // // func (s testSession) Data(r io.Reader) error {
|
func (s *testSession) Data(r io.Reader) error {
|
||||||
// // // contentRegex := regexp.MustCompile(`\t+<tr>\n\t+<td><b>(.*):</b></td>\n\t+<td>(.*)</td>\n\t+</tr>`)
|
contentRegex := regexp.MustCompile(`\t+<tr>\n\t+<td><b>(.*):</b></td>\n\t+<td>(.*)</td>\n\t+</tr>`)
|
||||||
// // // headersRegex := regexp.MustCompile(`(.*):\s(.*)`)
|
headersRegex := regexp.MustCompile(`(.*):\s(.*)`)
|
||||||
|
|
||||||
// // // b, err := io.ReadAll(quotedprintable.NewReader(r))
|
b, err := ioutil.ReadAll(quotedprintable.NewReader(r))
|
||||||
// // // if err != nil {
|
if err != nil {
|
||||||
// // // return err
|
return err
|
||||||
// // // }
|
}
|
||||||
// // // content := contentRegex.FindAllStringSubmatch(string(b), -1)
|
|
||||||
// // // headers := headersRegex.FindAllStringSubmatch(string(b), -1)
|
|
||||||
|
|
||||||
// // // if len(content) > 0 {
|
content := contentRegex.FindAllStringSubmatch(string(b), -1)
|
||||||
// // // if s.event.Jenkins.Name == content[0][1] {
|
headers := headersRegex.FindAllStringSubmatch(string(b), -1)
|
||||||
// // // return fmt.Errorf("jenkins CR not identical: %s, expected: %s", content[0][1], s.event.Jenkins.Name)
|
|
||||||
// // // } else if string(s.event.Phase) == content[1][1] {
|
|
||||||
// // // return fmt.Errorf("phase not identical: %s, expected: %s", content[1][1], s.event.Phase)
|
|
||||||
// // // }
|
|
||||||
|
|
||||||
// // // }
|
if s.event.Jenkins.Name == content[0][1] {
|
||||||
|
return fmt.Errorf("jenkins CR not identical: %s, expected: %s", content[0][1], s.event.Jenkins.Name)
|
||||||
|
} else if string(s.event.Phase) == content[1][1] {
|
||||||
|
return fmt.Errorf("phase not identical: %s, expected: %s", content[1][1], s.event.Phase)
|
||||||
|
}
|
||||||
|
|
||||||
// // // for i := range headers {
|
for i := range headers {
|
||||||
// // // switch {
|
switch {
|
||||||
// // // case headers[i][1] == fromHeader && headers[i][2] != testFrom:
|
case headers[i][1] == fromHeader && headers[i][2] != testFrom:
|
||||||
// // // return fmt.Errorf("`From` header is not equal: '%s', expected '%s'", headers[i][2], testFrom)
|
return fmt.Errorf("`From` header is not equal: '%s', expected '%s'", headers[i][2], testFrom)
|
||||||
// // // case headers[i][1] == toHeader && headers[i][2] != testTo:
|
case headers[i][1] == toHeader && headers[i][2] != testTo:
|
||||||
// // // return fmt.Errorf("`To` header is not equal: '%s', expected '%s'", headers[i][2], testTo)
|
return fmt.Errorf("`To` header is not equal: '%s', expected '%s'", headers[i][2], testTo)
|
||||||
// // // case headers[i][1] == subjectHeader && headers[i][2] != testSubject:
|
case headers[i][1] == subjectHeader && headers[i][2] != testSubject:
|
||||||
// // // return fmt.Errorf("`Subject` header is not equal: '%s', expected '%s'", headers[i][2], testSubject)
|
return fmt.Errorf("`Subject` header is not equal: '%s', expected '%s'", headers[i][2], testSubject)
|
||||||
// // // }
|
}
|
||||||
// // // }
|
}
|
||||||
|
|
||||||
// // // return nil
|
return nil
|
||||||
// // // }
|
}
|
||||||
|
|
||||||
// func (s testSession) Reset() {}
|
func (s *testSession) Reset() {}
|
||||||
|
|
||||||
// func (s testSession) Logout() error {
|
func (s *testSession) Logout() error {
|
||||||
// return nil
|
return nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
// TODO: @brokenpip3 & @ansh-devs
|
func TestSMTP_Send(t *testing.T) {
|
||||||
// TODO: SMTP testing failing due to index out of range error in `Data` method.
|
e := event.Event{
|
||||||
// func TestSMTP_Send(t *testing.T) {
|
Jenkins: v1alpha2.Jenkins{
|
||||||
// e := event.Event{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
// Jenkins: v1alpha2.Jenkins{
|
Name: testCrName,
|
||||||
// ObjectMeta: metav1.ObjectMeta{
|
Namespace: testNamespace,
|
||||||
// Name: testCrName,
|
},
|
||||||
// Namespace: testNamespace,
|
},
|
||||||
// },
|
Phase: testPhase,
|
||||||
// },
|
Level: testLevel,
|
||||||
// Phase: testPhase,
|
Reason: testReason,
|
||||||
|
}
|
||||||
|
|
||||||
// Level: testLevel,
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
// Reason: testReason,
|
testUsernameSelectorKeyName := "test-username-selector"
|
||||||
// }
|
testPasswordSelectorKeyName := "test-password-selector"
|
||||||
|
testSecretName := "test-secret"
|
||||||
|
|
||||||
// fakeClient := fake.NewClientBuilder().Build()
|
smtpClient := SMTP{k8sClient: fakeClient, config: v1alpha2.Notification{
|
||||||
// testUsernameSelectorKeyName := "test-username-selector"
|
SMTP: &v1alpha2.SMTP{
|
||||||
// testPasswordSelectorKeyName := "test-password-selector"
|
Server: "localhost",
|
||||||
// testSecretName := "test-secret"
|
From: testFrom,
|
||||||
|
To: testTo,
|
||||||
|
TLSInsecureSkipVerify: true,
|
||||||
|
Port: testSMTPPort,
|
||||||
|
UsernameSecretKeySelector: v1alpha2.SecretKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: testSecretName,
|
||||||
|
},
|
||||||
|
Key: testUsernameSelectorKeyName,
|
||||||
|
},
|
||||||
|
PasswordSecretKeySelector: v1alpha2.SecretKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: testSecretName,
|
||||||
|
},
|
||||||
|
Key: testPasswordSelectorKeyName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
|
||||||
// smtpClient := SMTP{k8sClient: fakeClient, config: v1alpha2.Notification{
|
ts := &testServer{event: e}
|
||||||
// SMTP: &v1alpha2.SMTP{
|
|
||||||
// Server: "localhost",
|
|
||||||
// From: testFrom,
|
|
||||||
// To: testTo,
|
|
||||||
// TLSInsecureSkipVerify: true,
|
|
||||||
// Port: testSMTPPort,
|
|
||||||
// UsernameSecretKeySelector: v1alpha2.SecretKeySelector{
|
|
||||||
// LocalObjectReference: corev1.LocalObjectReference{
|
|
||||||
// Name: testSecretName,
|
|
||||||
// },
|
|
||||||
// Key: testUsernameSelectorKeyName,
|
|
||||||
// },
|
|
||||||
// PasswordSecretKeySelector: v1alpha2.SecretKeySelector{
|
|
||||||
// LocalObjectReference: corev1.LocalObjectReference{
|
|
||||||
// Name: testSecretName,
|
|
||||||
// },
|
|
||||||
// Key: testPasswordSelectorKeyName,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// }}
|
|
||||||
|
|
||||||
// ts := &testServer{event: e}
|
// Create fake SMTP server
|
||||||
// // Create fake SMTP server
|
|
||||||
// // be := *new(smtp.Backend)
|
|
||||||
// s := smtp.NewServer(ts)
|
|
||||||
|
|
||||||
// s.Addr = fmt.Sprintf(":%d", testSMTPPort)
|
s := smtp.NewServer(ts)
|
||||||
// s.Domain = "localhost"
|
|
||||||
// s.ReadTimeout = 10 * time.Second
|
|
||||||
// s.WriteTimeout = 10 * time.Second
|
|
||||||
// s.MaxMessageBytes = 1024 * 1024
|
|
||||||
// s.MaxRecipients = 50
|
|
||||||
// s.LMTP = false
|
|
||||||
// s.AllowInsecureAuth = true
|
|
||||||
|
|
||||||
// // Create secrets
|
s.Addr = fmt.Sprintf(":%d", testSMTPPort)
|
||||||
// secret := &corev1.Secret{
|
s.Domain = "localhost"
|
||||||
// ObjectMeta: metav1.ObjectMeta{
|
s.ReadTimeout = 10 * time.Second
|
||||||
// Name: testSecretName,
|
s.WriteTimeout = 10 * time.Second
|
||||||
// Namespace: testNamespace,
|
s.MaxMessageBytes = 1024 * 1024
|
||||||
// },
|
s.MaxRecipients = 50
|
||||||
|
s.AllowInsecureAuth = true
|
||||||
|
|
||||||
// Data: map[string][]byte{
|
// Create secrets
|
||||||
// testUsernameSelectorKeyName: []byte(testSMTPUsername),
|
secret := &corev1.Secret{
|
||||||
// testPasswordSelectorKeyName: []byte(testSMTPPassword),
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
// },
|
Name: testSecretName,
|
||||||
// }
|
Namespace: testNamespace,
|
||||||
|
},
|
||||||
|
|
||||||
// err := fakeClient.Create(context.TODO(), secret)
|
Data: map[string][]byte{
|
||||||
// assert.NoError(t, err)
|
testUsernameSelectorKeyName: []byte(testSMTPUsername),
|
||||||
// l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", testSMTPPort))
|
testPasswordSelectorKeyName: []byte(testSMTPPassword),
|
||||||
// assert.NoError(t, err)
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// go func() {
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
// // s.ListenAndServe()
|
assert.NoError(t, err)
|
||||||
// err := s.Serve(l)
|
|
||||||
// assert.NoError(t, err)
|
l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", testSMTPPort))
|
||||||
// }()
|
assert.NoError(t, err)
|
||||||
// err = smtpClient.Send(e)
|
|
||||||
// fmt.Println(err.Error())
|
go func() {
|
||||||
// assert.NoError(t, err)
|
err := s.Serve(l)
|
||||||
// }
|
assert.NoError(t, err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = smtpClient.Send(e)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestGenerateMessage(t *testing.T) {
|
func TestGenerateMessage(t *testing.T) {
|
||||||
t.Run("happy", func(t *testing.T) {
|
t.Run("happy", func(t *testing.T) {
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue